Reputation: 2596
I'm wondering that:
commit-tree
in plumbing?).I figured out blobs are made when I add files to index.
git init
mkdir test-dir
echo "File1" > test-dir/test.txt
git count-objects
# 0 objects, 0 kilobytes
git add test-dir/test.txt
git count-objects
# 1 objects, 4 kilobytes
git ls-files -s
# 100644 03f128cf48cb203d938805e9f3e13b808d1773e9 0 test-dir/test.txt
But I can't find tree object for test-dir
until commit.
git commit -m "my first commit"
# [master (root-commit) 48448a5] my first commit
# 1 file changed, 1 insertion(+)
# create mode 100644 test-dir/test.txt
git count-objects
# 4 objects, 16 kilobytes
git rev-list --all --objects
# 48448a5c6d04cbcd6ab25b64c4bbab9dec5fcf94
# 5f618720e3fc14d396086feb6ee1d869fbbf2e21
# 3bdfe0bec6b5140848283e5e55fc0edd9bb52b32 test-dir
# 03f128cf48cb203d938805e9f3e13b808d1773e9 test-dir/test.txt
git cat-file -t 3bdfe0
# tree
git cat-file -p 3bdfe0
# 100644 blob 03f128cf48cb203d938805e9f3e13b808d1773e9 test.txt
Now I get tree object for test-dir
directory.
Upvotes: 1
Views: 34
Reputation: 488183
The tree objects get built by git write-tree
. That is, git commit
consists of several sub-commands (see notes below):
git write-tree
git commit-tree <parents> <message> <tree-hash-ID>
git update-ref <full-ref> <commit-hash-ID>
The first command, which takes no parameters, turns the index (use git ls-files --stage
to view its contents) into a series of tree objects. The top level tree object's hash ID is printed to its standard output.
The second command needs parameters: -p
for each parent commit hash ID, -m
or -F
to supply the commit log message, and the tree hash ID printed by git write-tree
. It produces the commit object's hash ID as its standard output.
The last command also needs parameters: the full name of the current branch (e.g., refs/heads/master
), or the name HEAD
if HEAD
is currently detached from any branch, and the commit hash ID produced by the second command. It updates the given ref to hold the given hash ID. If the ref is a branch name, or HEAD
, the hash ID should be that of a commit.
Originally, git commit
was a small shell script that simply ran these three commands (with appropriate shell glue). At that time, git commit
did not have as many options and flags and modes as it does now.
Eventually git commit
became a single C program. It now does all these parts internally. It also handles locking, runs pre-commit hooks, and other such things; these can't be done properly in a shell script using the three individual commands. The three individual commands do still remain, however, so that you can use them to build your own scripts, if you like.
Upvotes: 2