Git은 분산 버전 관리와 4대 오브젝트 시스템으로 병렬 개발을 가능하게 한다

Git을 오래 써도 내부 동작을 모르고 쓰는 경우가 많다. git commit, git push 정도로 쓰다가 cherry-pick이나 rebase 충돌 앞에서 멘붕이 오는 게 그 증거다. 내부 구조를 알면 Git이 이상하게 행동할 때 원인을 찾기 훨씬 쉬워진다.

Git이 분산 버전 관리인 이유

중앙집중식 VCS(SVN 등)는 서버가 단일 장애점이다. 서버가 죽으면 아무것도 할 수 없다. Git은 모든 사용자가 전체 히스토리를 가진 완전한 저장소를 로컬에 갖는다. 서버 없이도 커밋, 브랜치 생성, 히스토리 탐색이 가능하다. 서버는 팀 동기화 포인트일 뿐이다.

4대 오브젝트

Git의 핵심은 단 4종류의 오브젝트다. 모든 Git 동작이 이 4개의 오브젝트 생성·연결로 이루어진다.

Blob (파일 내용)

파일 내용만 저장한다. 파일 이름이나 경로는 포함되지 않는다. 내용이 같으면 다른 경로에 있어도 같은 blob을 공유한다. SHA-1 해시로 식별된다. 이 덕분에 중복 파일이 두 번 저장되지 않는다.

Tree (디렉토리 구조)

디렉토리 구조를 나타낸다. 파일 이름과 권한, 그리고 각 파일(blob)이나 하위 디렉토리(tree)에 대한 포인터를 담는다. 하나의 tree는 해당 시점의 디렉토리 스냅샷이다.

Commit (스냅샷 + 메타데이터)

특정 시점의 프로젝트 상태를 기록한다. 루트 tree에 대한 포인터, 부모 commit(들)에 대한 포인터, 작성자·작성 시간·커밋 메시지를 담는다. 커밋은 변경 사항이 아닌 스냅샷이다. 이게 SVN과 Git의 근본적인 차이다.

Tag (커밋에 붙이는 라벨)

특정 커밋을 가리키는 이름이다. v1.0.0 같은 릴리즈 태그가 대표적이다. 브랜치와 달리 이동하지 않는다.

작업 영역과 파일 상태

Git은 파일을 세 영역에서 관리한다:

영역설명
Working Directory실제 파일이 있는 공간
Staging Area (Index)git add한 변경 사항 대기열
Repository (.git)git commit된 스냅샷 저장소

파일 상태 흐름:

Untracked → Staged (git add) → Committed (git commit)
Modified  → Staged (git add) → Committed (git commit)

HEAD와 브랜치의 관계

HEAD는 현재 작업 중인 위치를 가리키는 포인터다. 보통은 브랜치를 가리키고, 브랜치는 특정 commit을 가리킨다.

HEAD → main → commit_abc

git checkout feature-branch를 실행하면:

HEAD → feature-branch → commit_xyz

Detached HEAD 상태는 HEAD가 브랜치가 아닌 commit을 직접 가리킬 때다. 이 상태에서 커밋하면 어느 브랜치에도 속하지 않는 orphan commit이 생긴다.

왜 이걸 알아야 하나

merge 충돌이 났을 때, rebase가 어떻게 동작하는지, reset --hardreset --soft의 차이가 뭔지. 이 개념들이 “4대 오브젝트 + 포인터” 모델로 설명된다. 내부 구조를 알면 명령어를 외우지 않아도 원리에서 동작을 추론할 수 있다.

출처