Git의 원리] 2. git commit (tree, commit)
1. Staging Area에 add한 파일을 commit 해보자
$ git status
On branch master
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
new file: f1.txt
new file: f2.txt
new file: f3.txt
$ git commit -m 'first commit!'
[master bbaa106] first commit!
3 files changed, 3 insertions(+)
create mode 100644 f1.txt
create mode 100644 f2.txt
create mode 100644 f3.txt
$ git log
commit bbaa10614a8afcb2e938909e230583d0acf7146c (HEAD -> master)
Author: abc
Date: Thu Aug 25 16:04:20 2022 +0900
first commit!
'first commit!'이란 commit message를 입력하여 commit하였다.
git log로 commit history를 확인해보면, commit hash id를 확인할 수 있다.
2. commit object를 확인해보자.
hash id로 object type을 확인해보자.
$ git cat-file -t bbaa10614a8afcb2e938909e230583d0acf7146c
commit
$ git cat-file -p bbaa10614a8afcb2e938909e230583d0acf7146c
tree 9140095e1e126ebffad7dc660807e41a8411b352
author abc 1661411060 +0900
committer abc 1661411060 +0900
first commit!
bbaa10614a8afcb2e938909e230583d0acf7146c object type은 commit이고, 내용에는 tree, author, comitter, commit message를 포함하고 있음을 확인할 수 있다.
3. tree object를 확인해보자.
$ git cat-file -t 9140095e1e126ebffad7dc660807e41a8411b352
tree
$ git cat-file -p 9140095e1e126ebffad7dc660807e41a8411b352
100644 blob 2e65efe2a145dda7ee51d1741299f848e5bf752e f1.txt
100644 blob fa7af8bf5fdd704f73beb3adc5612682a98e1af5 f2.txt
100644 blob 2e65efe2a145dda7ee51d1741299f848e5bf752e f3.txt
tree에는 index에 있던 blob내용이 들어있다.
4. 생성된 tree/commit object 파일을 확인해보자.
git commit 시, tree object, commit object가 생성되며 이는 모두 .git\objects에 저장된다.
tree object : 9140095e1e126ebffad7dc660807e41a8411b352
commit object : bbaa10614a8afcb2e938909e230583d0acf7146c
hash 앞에 2글자의 directory가 생성됨을 확인하였다.
5. directory를 추가해서, f1.txt파일을 copy하여 commit해보자.
$ mkdir d1
$ cp f1.txt d1/f1.txt
$ git add d1/f1.txt
# index에 d1/f1.txt 파일이 추가가 되었다.
$ git ls-files --stage
100644 2e65efe2a145dda7ee51d1741299f848e5bf752e 0 d1/f1.txt
100644 2e65efe2a145dda7ee51d1741299f848e5bf752e 0 f1.txt
100644 fa7af8bf5fdd704f73beb3adc5612682a98e1af5 0 f2.txt
100644 2e65efe2a145dda7ee51d1741299f848e5bf752e 0 f3.txt
100644 d00491fd7e5bb6fa28c517a0bb32b8b506539d4d 0 test.html
$ git commit -m 'second commit!'
[master a710440] second commit!
1 file changed, 1 insertion(+)
create mode 100644 d1/f1.txt
# second commit이 추가되었다.
$ git log
commit a710440ebf93bb162541fec64e58a4fc78bd6869 (HEAD -> master)
Author: abc
Date: Fri Aug 26 08:58:54 2022 +0900
second commit!
commit bbaa10614a8afcb2e938909e230583d0acf7146c
Author: abc
Date: Thu Aug 25 16:04:20 2022 +0900
first commit!
6. first commit / second commit object 내용을 비교해보자.
$ git cat-file -p a710440ebf93bb162541fec64e58a4fc78bd6869
tree 1e0d717794850d631dcfad39d2b515b06eb02500
parent bbaa10614a8afcb2e938909e230583d0acf7146c
author abc 1661471934 +0900
committer abc 1661471934 +0900
second commit!
$ git cat-file -p bbaa10614a8afcb2e938909e230583d0acf7146c
tree 9140095e1e126ebffad7dc660807e41a8411b352
parent de836c5859bda4b0bfb9972dfb6cd195450da50f
author abc 1661411060 +0900
committer abc 1661411060 +0900
first commit!
second commit에는 parent commit object hash id가 포함되어 있다.
그리고 fist commit의 tree와 second commit의 tree는 다르다. commit이 발생한 시점의 파일의 snapshot을 저장하고 있기 때문에 다르다!
따라서 second commit상태에서 first commit상태로 파일을 되돌릴 수 있다.
7. second commit 의 tree object 내용을 확인해보자.
$ git cat-file -p 1e0d717794850d631dcfad39d2b515b06eb02500
040000 tree 82abd1f8af9029348fde85f30990d8810f0b97e5 d1
100644 blob 2e65efe2a145dda7ee51d1741299f848e5bf752e f1.txt
100644 blob fa7af8bf5fdd704f73beb3adc5612682a98e1af5 f2.txt
100644 blob 2e65efe2a145dda7ee51d1741299f848e5bf752e f3.txt
100644 blob d00491fd7e5bb6fa28c517a0bb32b8b506539d4d test.html
$ git cat-file -p 82abd1f8af9029348fde85f30990d8810f0b97e5
100644 blob 2e65efe2a145dda7ee51d1741299f848e5bf752e f1.txt
1e0d717794850d631dcfad39d2b515b06eb02500 tree 하위에는 82abd1f8af9029348fde85f30990d8810f0b97e5 tree가 포함되어 있고, 82abd1f8af9029348fde85f30990d8810f0b97e5 tree에는 f1.txt 파일명과 blob hash id내용이 들어있다.
결론
.git\object directory안에 저장되는 파일은 object 파일이고, object파일은 크게 3가지로 나눈다.
- blob : 파일의 내용
- tree : 파일명과 blob의 정보
- commit