Thursday, June 22, 2023

git commit


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