C.W.K.
Stream
Lesson 02 of 05 · published

diff 뭉치가 아니라 snapshot

~20 min · snapshots, objects

Level 0Untracked 새싹
0 XP0/47 lessons0/14 achievements
0/100 XP to next level100 XP to go0% complete

Patch 가 아니라 snapshot

Git 에 대한 가장 흔한 오해는 'diff 를 저장한다' 는 거야. version N → N+1 의 차이만 보관한다고 생각하는데, 그건 SVN, CVS 모델이지. Git 은 본질적으로 달라. 모든 commit 은 모든 파일의 완전한 snapshot 이고, hash 로 주소지정돼.

두 commit 사이에 파일이 안 바뀌었으면 Git 은 두 번 저장 안 해. 같은 blob 을 가리키는 pointer 만 둬. 같은 내용은 항상 같은 hash 라서 dedup 이 자동이고, 1 bit 만 바뀌어도 완전히 다른 hash 라서 corruption 탐지가 돼. Git 의 history 연산이 빠른 이유가 이거야 — 어떤 version 보여줄 때 해당 snapshot 만 load 하면 되거든. 프로젝트 시작부터 diff 다 replay 할 필요가 없어.

세 가지 object type 으로 이걸 굴려. blob 은 파일 하나의 raw bytes. tree 는 directory listing — 이름/mode/그게 가리키는 blob hash. commit 은 tree hash + parent hash + author + committer + message 가 든 작은 object. 다 .git/objects/ 에 자기 SHA-1 이름으로 살아. branch 는 commit 하나 가리키는 41 byte. tag 는 아무 object 가리키는 41 byte. graph 전체가 content-addressable 이야.

git cat-file 매일 칠 일은 없어. 그래도 blob 하나, tree 하나, commit 하나 손으로 펼쳐보는 건 diff-기반 mental model 에 대한 백신이야. 한 번 보고 나면 branch 가 신비롭지 않고 merge 가 무섭지 않아져.

Code

commit 하나의 실제 object 들 들여다보기·bash
# 가장 최근 commit hash
HASH=$(git rev-parse HEAD)

# commit object 자체 (tree + parent + message)
git cat-file -p $HASH

# 그 commit 이 가리키는 tree
TREE=$(git cat-file -p $HASH | head -1 | awk '{print $2}')
git cat-file -p $TREE

# tree 한 줄은 (mode, type, hash, name) tuple
같은 파일은 한 번만 저장·bash
# 다른 위치에 같은 내용 파일 두 개 만들고 hash 찍어보기
echo 'hello' > a.txt
git hash-object a.txt
echo 'hello' > b.txt
git hash-object b.txt
# 둘 다 같은 hash — Git 은 blob 하나만 두고 tree 두 entry 가 같이 가리켜.

External links

Exercise

아무 작은 repo 에서 git rev-parse HEAD 찍고, 그 결과로 git cat-file -p <hash>. tree pointer 따라가서 또 git cat-file -p. blob hash 하나 골라 또 git cat-file -p <blob>. 그 출력에서 'snapshot 모델이라서 말이 되는데 diff 모델이라면 말이 안 되는' 점 세 가지 적어봐.

Progress

Progress is local-only — sign in to sync across devices.
이 페이지에서 버그를 발견하셨거나 피드백이 있으세요?문제 신고

댓글 0

🔔 답글 알림 (로그인 필요)
로그인댓글을 남기려면 로그인해 주세요.

아직 댓글이 없어요. 첫 댓글을 남겨보세요.