03-01 Git 내부 객체 모델

`.git` 안에서 실제로 무슨 일이 일어나는가 — blob/tree/commit 객체와 refs, packfile.


.git 안에서 실제로 무슨 일이 일어나는가 — blob/tree/commit 객체와 refs, packfile.

목표: Git을 “마법”이 아니라 단순한 내용 주소 저장소로 이해


🗄️ Git = 내용 주소 저장소

Git의 핵심은 키-값 저장소다. 내용을 넣으면 그 내용의 SHA-1 해시(키)를 돌려준다. 같은 내용은 항상 같은 해시 → 중복 자동 제거, 무결성 보장.

echo "hello" | git hash-object --stdin   # 내용 → 해시
# ce013625030ba8dba906f756967f9e9ca394464a

🧱 4가지 객체 타입

graph TB
    COMMIT["commit<br/>(스냅샷+메타)"] --> TREE["tree<br/>(디렉토리)"]
    TREE --> BLOB1["blob<br/>(파일 내용)"]
    TREE --> BLOB2["blob"]
    TREE --> TREE2["tree<br/>(하위 디렉토리)"]
    COMMIT --> PARENT["parent commit"]
    TAG["tag<br/>(주석 태그)"] --> COMMIT
객체저장 내용
blob파일의 내용(이름·권한 없음)
tree디렉토리 — blob/tree 목록 + 이름 + 권한
committree 1개 + 부모 커밋 + 작성자/커미터/메시지
tag주석 태그(커밋 가리킴 + 서명/메시지)

[!tip] 스냅샷의 실체 “커밋 = 스냅샷”은 곧 커밋이 최상위 tree를 가리키고, tree가 blob들을 가리킨다는 뜻. 안 바뀐 파일은 같은 blob을 재사용해 공간을 아낀다.


🔬 직접 들여다보기 (plumbing 명령)

git cat-file -t <hash>    # 객체 타입(blob/tree/commit)
git cat-file -p <hash>    # 객체 내용 출력
git cat-file -p HEAD      # 현재 커밋 객체

# 커밋이 가리키는 tree 탐색
git cat-file -p HEAD^{tree}

commit 객체 예시:

tree a1b2c3...           ← 이 커밋의 스냅샷(디렉토리)
parent 9f3a1c...         ← 부모 커밋
author Jongmin <..> 1717...
committer Jongmin <..> 1717...

feat: 로그인 추가

tree 객체 예시:

100644 blob e69de29...    README.md
040000 tree 4d5e6f7...    src

🔖 refs — 사람이 읽는 이름표

해시는 외우기 어렵다. ref는 해시를 가리키는 이름.

.git/refs/heads/main      → 9f3a1c2...   (브랜치)
.git/refs/tags/v1.0.0     → a1b2c3d...   (태그)
.git/HEAD                 → ref: refs/heads/main  (현재 위치)
git rev-parse HEAD        # HEAD가 가리키는 실제 해시
git rev-parse main        # 브랜치의 해시
cat .git/HEAD             # HEAD 내용
  • 브랜치 = 움직이는 ref(커밋하면 자동 전진)
  • HEAD = 현재 브랜치를 가리키는 ref(detached HEAD면 커밋을 직접 가리킴)

📦 packfile — 압축 저장

객체가 많아지면 Git이 비슷한 객체를 델타 압축해 .git/objects/pack/에 모은다.

git gc                    # 정리·압축(garbage collection)
git count-objects -vH     # 객체 수·크기 통계
git verify-pack -v ...    # packfile 내용 검사

느슨한(loose) 객체 → packfile로 묶여 디스크·전송 효율↑.


🩺 무결성 검사

git fsck                  # 객체 무결성·연결 검사
git fsck --lost-found     # 어디서도 참조 안 되는(dangling) 객체 찾기

dangling commit은 reflog·브랜치가 사라진 잃은 커밋일 수 있다 → 복구 단서.


📋 체크리스트

  • Git이 내용 주소 저장소임을 이해
  • blob/tree/commit/tag 역할
  • cat-file -p로 객체 탐색
  • 커밋 → tree → blob 그래프 그리기
  • refs와 HEAD의 의미
  • detached HEAD 개념
  • packfile·gc·fsck 용도

🔗 관련 노트

  • 02-06-대화형-리베이스와-히스토리-정리 — 이전
  • 03-02-bisect-worktree-submodule — 다음
  • 01-01-Git-개념과-동작원리 — 스냅샷 개념
  • 03-05-트러블슈팅과-재해-복구 — fsck로 복구

마지막 업데이트: 2026-06-02