네 가지 object와 content-addressable store
Git이 아는 모든 것은 .git/objects/에 blob, tree, commit, tag 네 object 가운데 하나로 저장되고 내용의 SHA-1 hash로 주소를 얻어. repo 안에서 이 넷을 구분할 수 있으면 높은 수준의 Git 명령도 마법처럼 보이지 않아. 결국 네 모양을 만들고 연결하고 가리키는 일이거든.
Blob은 파일 하나의 raw byte만 저장해. 파일 이름도 permission도 없이 내용만 있어. 같은 내용을 가진 파일 둘은 같은 blob hash를 얻어 한 번만 저장돼. Tree는 directory listing을 저장해. 이름과 mode, 파일을 담은 blob 또는 하위 directory를 담은 tree의 hash가 있어. Tree가 blob에 이름과 구조를 부여하는 셈이야.
Commit은 root tree hash, parent commit hash, author와 committer 및 timestamp, message를 묶은 작은 object야. parent를 따라가면 이력을 거슬러 올라가고 tree를 열면 그 시점의 프로젝트 snapshot으로 들어가. Tag는 metadata가 있는 이름표 object로 annotated tag에 쓰여. Lightweight tag는 tag object가 아니라 ref일 뿐이야.
이 store는 내용으로 주소를 정해. echo "hello" | git hash-object --stdin은 hash를 계산하고 git cat-file -p <hash>는 object를 다시 읽어. Hash의 첫 두 글자는 .git/objects/ 아래 directory 이름, 나머지 38글자는 파일 이름이 돼서 .git/objects/3a/4f5d6e... 같은 모양이 나와. repo가 커지면 Git은 많은 object를 pack file로 압축하지만 mental model은 그대로야. hash → object → content야.