본문 바로가기
C.W.K.
Stream
Lesson 02 of 05 · published

diff 뭉치가 아니라 스냅샷

~20 min · snapshots, objects

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

Patch가 아니라 스냅샷

Git을 “diff를 차곡차곡 저장하는 도구”로 이해하기 쉬워. 버전 N에서 N+1로 바뀐 부분만 보관한다고 생각하는 거지. SVN이나 CVS는 그 그림에 가깝지만 Git은 달라. Commit 하나는 그 시점의 프로젝트 전체 스냅샷이고, 내용에서 계산한 hash로 찾아가.

그렇다고 안 바뀐 파일을 commit마다 또 저장하진 않아. 이전과 같은 파일은 같은 blob을 가리켜. 내용이 같으면 hash도 같으니 중복은 자연스럽게 합쳐지고, 1 bit만 달라져도 hash가 바뀌어서 손상도 알아챌 수 있어. 특정 시점을 보여줄 때는 그 스냅샷을 바로 읽으면 돼. 처음부터 diff를 전부 재생할 필요가 없어서 이력 탐색도 빨라.

이 구조의 중심에는 세 object가 있어. blob은 파일 하나의 raw bytes, tree는 이름과 mode, blob hash를 묶은 디렉터리 목록, commit은 tree hash와 parent hash, author, committer, message를 담은 작은 object야. 모두 .git/objects/ 아래에 자기 SHA-1 이름으로 살아. Branch는 commit 하나를 가리키는 41 byte짜리 이름표고, tag는 object 하나를 가리키는 41 byte짜리 이름표야. 그래프 전체가 내용으로 주소를 찾는 구조지.

git cat-file을 매일 쓸 필요는 없어. 그래도 blob, tree, commit을 한 번씩 직접 펼쳐보면 “Git은 diff 묶음”이라는 오해가 확실히 사라져. 그러면 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

작은 저장소에서 git rev-parse HEAD로 현재 commit hash를 구하고 git cat-file -p <hash>로 펼쳐봐. 거기서 tree를 따라가 다시 git cat-file -p를 실행하고, blob 하나는 git cat-file -p <blob>로 읽어. 출력에서 “스냅샷 모델이면 자연스럽지만 diff 모델로는 설명하기 어려운 점”을 세 가지 적어봐.

Progress

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

댓글 0

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

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