A git commit records a snapshot of the tracked files in the project. It consists of a git commit object, git tree objects and git blob objects.
Currently, I am curious to find out what Git will do for us behind the scene if we run the 'git commit' command. Below are the logs coming from my experiment.
Reference: Git Book
Preparation
Create a brand new folder and run the 'git init' command.
Step 1:
Create a file and run the 'git add' command.
$ echo 'test' > test.txt
$ git add .
Check the .git tree structure.
$ tree .git/
.git/
├── HEAD
├── branches
├── config
├── description
├── hooks
│ ├── applypatch-msg.sample
│ ├── commit-msg.sample
│ ├── fsmonitor-watchman.sample
│ ├── post-update.sample
│ ├── pre-applypatch.sample
│ ├── pre-commit.sample
│ ├── pre-merge-commit.sample
│ ├── pre-push.sample
│ ├── pre-rebase.sample
│ ├── pre-receive.sample
│ ├── prepare-commit-msg.sample
│ ├── push-to-checkout.sample
│ └── update.sample
├── index (a new file)
├── info
│ └── exclude
├── objects
│ ├── 9d (a new directory)
│ │ └── aeafb9864cf43055ae93beb0afd6c7d144bfa4 (a new file for git blob object)
│ ├── info
│ └── pack
└── refs
├── heads
└── tags
10 directories, 19 files
Run the 'git commit' command.
$ git commit -m 'first commit'
[master (root-commit) 002c253] first commit
1 file changed, 1 insertion(+)
create mode 100644 test.txt
The output '[master (root-commit) 002c253] first commit' means:
1. master(root-commit) => this is the first (root) commit in the master branch
2. There is a new git commit object '002c253'
Check the .git tree structure.
$ tree .git/
.git/
├── COMMIT_EDITMSG (a new file)
├── HEAD
├── branches
├── config
├── description
├── hooks
│ ├── applypatch-msg.sample
│ ├── commit-msg.sample
│ ├── fsmonitor-watchman.sample
│ ├── post-update.sample
│ ├── pre-applypatch.sample
│ ├── pre-commit.sample
│ ├── pre-merge-commit.sample
│ ├── pre-push.sample
│ ├── pre-rebase.sample
│ ├── pre-receive.sample
│ ├── prepare-commit-msg.sample
│ ├── push-to-checkout.sample
│ └── update.sample
├── index
├── info
│ └── exclude
├── logs (a new directory)
│ ├── HEAD (a new file)
│ └── refs (a new directory)
│ └── heads (a new directory)
│ └── master (a new file)
├── objects │ ├── 00 (a new directory)
│ │ └── 2c253e8b132d574074181a5b578ba3ea0145c6 (a new file for git commit object)
│ ├── 2b (a new directory)
│ │ └── 297e643c551e76cfa1f93810c50811382f9117 (a new file for git tree object)
│ ├── 9d
│ │ └── aeafb9864cf43055ae93beb0afd6c7d144bfa4
│ ├── info
│ └── pack
└── refs
├── heads │ └── master (a new file)
└── tags
15 directories, 25 files
Check the type of the git commit object '002c253'
$ git cat-file -t 002c253
commit
Check the content of the git commit object '002c253'
From the log, it provides the committing message, and a git tree object working with git blob objects to record the snapshot of the tracked files.
$ git cat-file -p 002c253
tree 2b297e643c551e76cfa1f93810c50811382f9117
author Frank <frank@demo.com>
committer Frank <frank@demo.com>
first commit
Check the type of the git tree object '2b297e'.
$ git cat-file -t 2b297e
tree
Check the content of the git tree object '2b297e'.
$ git cat-file -p 2b297e
100644 blob 9daeafb9864cf43055ae93beb0afd6c7d144bfa4 test.txt
According to the logs above, there are two files created after running the 'git commit' command.
1. commit object
It records the commit message, the author, the committer, the parent commit, and a git tree object.
2. tree object
It is the snapshot of the current file system.
Check the index file. (Check 'The Three Trees' chapter for more info)
$ git ls-files -s
100644 9daeafb9864cf43055ae93beb0afd6c7d144bfa4 0 test.txt
If it is the first commit, the master file will be created under .git/refs/heads/
Check the master branch info.
$ cat .git/refs/heads/master
002c253e8b132d574074181a5b578ba3ea0145c6
Step 2:
Add a new file and run the 'git add' command
$ echo 'test2' > test2.txt
$ git add .
Check the .git tree structure.
$ tree .git/
.git/
├── COMMIT_EDITMSG
├── HEAD
├── branches
├── config
├── description
├── hooks
│ ├── applypatch-msg.sample
│ ├── commit-msg.sample
│ ├── fsmonitor-watchman.sample
│ ├── post-update.sample
│ ├── pre-applypatch.sample
│ ├── pre-commit.sample
│ ├── pre-merge-commit.sample
│ ├── pre-push.sample
│ ├── pre-rebase.sample
│ ├── pre-receive.sample
│ ├── prepare-commit-msg.sample
│ ├── push-to-checkout.sample
│ └── update.sample
├── index
├── info
│ └── exclude
├── logs
│ ├── HEAD
│ └── refs
│ └── heads
│ └── master
├── objects │ ├── 00
│ │ └── 2c253e8b132d574074181a5b578ba3ea0145c6
│ ├── 18 (a new directory)
│ │ └── 0cf8328022becee9aaa2577a8f84ea2b9f3827 (a new file for git blob object)
│ ├── 2b
│ │ └── 297e643c551e76cfa1f93810c50811382f9117
│ ├── 9d
│ │ └── aeafb9864cf43055ae93beb0afd6c7d144bfa4
│ ├── info
│ └── pack
└── refs
├── heads │ └── master
└── tags
16 directories, 26 files
Run the 'git commit' command.
$ git commit -m 'second commit'
[master aea662f] second commit
1 file changed, 1 insertion(+)
create mode 100644 test2.txt
Check the .git tree structure.
$ tree .git/
.git/
├── COMMIT_EDITMSG
├── HEAD
├── branches
├── config
├── description
├── hooks
│ ├── applypatch-msg.sample
│ ├── commit-msg.sample
│ ├── fsmonitor-watchman.sample
│ ├── post-update.sample
│ ├── pre-applypatch.sample
│ ├── pre-commit.sample
│ ├── pre-merge-commit.sample
│ ├── pre-push.sample
│ ├── pre-rebase.sample
│ ├── pre-receive.sample
│ ├── prepare-commit-msg.sample
│ ├── push-to-checkout.sample
│ └── update.sample
├── index
├── info
│ └── exclude
├── logs
│ ├── HEAD
│ └── refs
│ └── heads
│ └── master
├── objects │ ├── 00
│ │ └── 2c253e8b132d574074181a5b578ba3ea0145c6
│ ├── 18
│ │ └── 0cf8328022becee9aaa2577a8f84ea2b9f3827
│ ├── 59 (a new directory)
│ │ └── 50f5c8ec9efcb96612f89264fd72994badb828 (a new file for git tree object)
│ ├── 2b
│ │ └── 297e643c551e76cfa1f93810c50811382f9117
│ ├── 9d
│ │ └── aeafb9864cf43055ae93beb0afd6c7d144bfa4
│ ├── ae (a new directory)
│ │ └── a662fe0a0621247fadb98f25a35b774343335a (a new file for git commit object)
│ ├── info
│ └── pack
└── refs
├── heads │ └── master
└── tags
18 directories, 28 files
Check the content of the git commit object 'aea662f'.
$ git cat-file -p aea662f
tree 5950f5c8ec9efcb96612f89264fd72994badb828
parent 002c253e8b132d574074181a5b578ba3ea0145c6
author Frank <frank@demo.com>
committer Frank <frank@demo.com>
second commit
Because it is not the first commit, the parent pointer will point to the first commit '002c253'.
Check the content of the git tree object '5950f5'.
$ git cat-file -p 5950f5
100644 blob 9daeafb9864cf43055ae93beb0afd6c7d144bfa4 test.txt
100644 blob 180cf8328022becee9aaa2577a8f84ea2b9f3827 test2.txt
Check the index file. (Check 'The Three Trees' chapter for more info)
$ git ls-files -s
100644 9daeafb9864cf43055ae93beb0afd6c7d144bfa4 0 test.txt
100644 180cf8328022becee9aaa2577a8f84ea2b9f3827 0 test2.txt
Step 3:
Create a new file 'test3.txt' under a new folder 'subfolder'
Run the 'git add' command.
$ mkdir subfolder
$ cd subfolder
$ echo 'test3' > test3.txt
$ cd ..
$ git add .
Check the .git tree structure.
$ tree .git/
.git/
├── COMMIT_EDITMSG
├── HEAD
├── branches
├── config
├── description
├── hooks
│ ├── applypatch-msg.sample
│ ├── commit-msg.sample
│ ├── fsmonitor-watchman.sample
│ ├── post-update.sample
│ ├── pre-applypatch.sample
│ ├── pre-commit.sample
│ ├── pre-merge-commit.sample
│ ├── pre-push.sample
│ ├── pre-rebase.sample
│ ├── pre-receive.sample
│ ├── prepare-commit-msg.sample
│ ├── push-to-checkout.sample
│ └── update.sample
├── index
├── info
│ └── exclude
├── logs
│ ├── HEAD
│ └── refs
│ └── heads
│ └── master
├── objects │ ├── 00
│ │ └── 2c253e8b132d574074181a5b578ba3ea0145c6
│ ├── 18
│ │ └── 0cf8328022becee9aaa2577a8f84ea2b9f3827
│ ├── 2b
│ │ └── 297e643c551e76cfa1f93810c50811382f9117
│ ├── 59
│ │ └── 50f5c8ec9efcb96612f89264fd72994badb828
│ ├── 9d
│ │ └── aeafb9864cf43055ae93beb0afd6c7d144bfa4
│ ├── ae
│ │ └── a662fe0a0621247fadb98f25a35b774343335a
│ ├── df (a new directory)
│ │ └── 6b0d2bcc76e6ec0fca20c227104a4f28bac41b (a new file for git blob object)
│ ├── info
│ └── pack
└── refs
├── heads │ └── master
└── tags
19 directories, 29 files
A blob file was created to track the new added file content, but without folder info.
Run the 'git commit' command.
$ git commit -m 'third commit'
[master d2633af] third commit
1 file changed, 1 insertion(+)
create mode 100644 subfolder/test3.txt
Check the .git tree structure.
$ tree .git/
.git/
├── COMMIT_EDITMSG
├── HEAD
├── branches
├── config
├── description
├── hooks
│ ├── applypatch-msg.sample
│ ├── commit-msg.sample
│ ├── fsmonitor-watchman.sample
│ ├── post-update.sample
│ ├── pre-applypatch.sample
│ ├── pre-commit.sample
│ ├── pre-merge-commit.sample
│ ├── pre-push.sample
│ ├── pre-rebase.sample
│ ├── pre-receive.sample
│ ├── prepare-commit-msg.sample
│ ├── push-to-checkout.sample
│ └── update.sample
├── index
├── info
│ └── exclude
├── logs
│ ├── HEAD
│ └── refs
│ └── heads
│ └── master
├── objects │ ├── 00
│ │ └── 2c253e8b132d574074181a5b578ba3ea0145c6
│ ├── 18
│ │ └── 0cf8328022becee9aaa2577a8f84ea2b9f3827
│ ├── 2b
│ │ └── 297e643c551e76cfa1f93810c50811382f9117
│ ├── 59
│ │ └── 50f5c8ec9efcb96612f89264fd72994badb828
│ ├── 96 (a new directory)
│ │ └── eb8e82f67bc50c83ea59bb1e993d559754784b (a new file for git tree object)
│ ├── 9d
│ │ └── aeafb9864cf43055ae93beb0afd6c7d144bfa4
│ ├── ae
│ │ └── a662fe0a0621247fadb98f25a35b774343335a
│ ├── d2 (a new directory)
│ │ └── 633af8288737f9c19cf4e69b12c6083f34646e (a new file for git commit object)
│ ├── df
│ │ └── 6b0d2bcc76e6ec0fca20c227104a4f28bac41b
│ ├── e1 (a new directory)
│ │ └── 452d77cf5821a8b20b8fba8add0c5804073a8f (a new file for git tree object)
│ ├── info
│ └── pack
└── refs
├── heads │ └── master
└── tags
22 directories, 32 files
Check the content of the git commit object 'd2633af'.
$ git cat-file -p d2633af
tree 96eb8e82f67bc50c83ea59bb1e993d559754784b
parent aea662fe0a0621247fadb98f25a35b774343335a
author Frank <frank@demo.com>
committer Frank <frank@demo.com>
third commit
Check the content of the git tree object '96eb8e'
$ git cat-file -p 96eb8e
040000 tree e1452d77cf5821a8b20b8fba8add0c5804073a8f subfolder
100644 blob 9daeafb9864cf43055ae93beb0afd6c7d144bfa4 test.txt
100644 blob 180cf8328022becee9aaa2577a8f84ea2b9f3827 test2.txt
Check the content of the git tree object 'e1452d'.
$ git cat-file -p e1452d
100644 blob df6b0d2bcc76e6ec0fca20c227104a4f28bac41b test3.txt
According to the logs above:
1. No git blob object for folders
2. New git tree object will be created for tracking folders
Check the index file.
It is similar with the git tree object, but it provide subfolder info.
$ git ls-files -s
100644 df6b0d2bcc76e6ec0fca20c227104a4f28bac41b 0 subfolder/test3.txt
100644 9daeafb9864cf43055ae93beb0afd6c7d144bfa4 0 test.txt
100644 180cf8328022becee9aaa2577a8f84ea2b9f3827 0 test2.txt
No comments:
Post a Comment