Git의 세 가지 트리: 작업 디렉토리, 스테이징, HEAD
Git이 파일 변경을 추적하는 세 개의 공간(작업 디렉토리, 스테이징 영역, HEAD)의 역할과 그 사이를 이동하는 명령어를 설명한다.
지난 글에서 원격 저장소를 로컬로 복제하는 방법을 살펴봤다. 이제 Git의 내부 구조 중 가장 핵심적인 개념을 다룰 차례다. Git의 **세 가지 트리(three trees)**를 이해하면 git add, git commit, git reset, git restore 같은 명령어들이 왜 그런 방식으로 동작하는지 명확하게 납득할 수 있다.
세 트리의 개념
Git은 파일의 변경 사항을 세 개의 별도 공간에서 관리한다.
작업 디렉토리(Working Directory): 실제 파일이 있는 공간이다. 에디터로 코드를 편집하면 이 공간이 변한다. Git이 추적하는지 여부와 관계없이 파일 시스템에 존재하는 모든 파일이 여기에 속한다.
스테이징 영역(Staging Area / Index): 다음 커밋에 포함시킬 변경 사항을 담아두는 공간이다. git add를 실행하면 변경 사항이 이 공간으로 이동한다. .git/index 파일에 저장된다.
저장소(HEAD): 커밋이 완료된 영구적인 이력이 저장된 공간이다. git commit을 실행하면 스테이징 영역의 내용이 여기로 이동해 새 커밋 객체가 된다.
세 트리의 상태가 달라지는 과정
코드 편집부터 커밋까지의 흐름을 따라가면 세 트리의 상태 변화를 이해할 수 있다.
# 초기 상태: 세 트리 모두 일치
git status
# nothing to commit, working tree clean
# 1. 파일 편집 → 작업 디렉토리만 변함
echo "hello" >> app.js
git status
# Changes not staged for commit:
# modified: app.js
# → 작업 디렉토리 ≠ 스테이징 ≠ HEAD
# 2. git add → 스테이징 영역에 반영
git add app.js
git status
# Changes to be committed:
# modified: app.js
# → 작업 디렉토리 = 스테이징 ≠ HEAD
# 3. git commit → HEAD에 저장
git commit -m "app.js 수정"
git status
# nothing to commit, working tree clean
# → 세 트리 모두 일치
각 단계에서 상태 확인하기
각 트리의 차이를 보는 전용 명령어가 있다.
# 작업 디렉토리 vs 스테이징 영역의 차이
git diff
# 스테이징 영역 vs HEAD(마지막 커밋)의 차이
git diff --staged # 또는 git diff --cached
# 작업 디렉토리 + 스테이징 전체 vs HEAD의 차이
git diff HEAD
세 트리 간 이동 명령어
앞으로 이동 (변경 사항 확정):
git add: 작업 디렉토리 → 스테이징 영역git commit: 스테이징 영역 → HEAD(저장소)
뒤로 이동 (변경 사항 취소):
git restore <file>: 스테이징 영역의 내용으로 작업 디렉토리 복원git restore --staged <file>: HEAD의 내용으로 스테이징 영역 복원git reset --soft HEAD~1: HEAD를 이전 커밋으로 이동 (스테이징·작업 디렉토리 유지)git reset --mixed HEAD~1: HEAD 이동 + 스테이징 초기화 (작업 디렉토리 유지)git reset --hard HEAD~1: 세 트리 모두 이전 커밋 상태로 되돌림
스테이징 영역이 존재하는 이유
SVN 같은 CVCS에는 스테이징 영역이 없다. 변경된 파일 전체가 한 번에 커밋된다. Git의 스테이징 영역은 의도적으로 설계된 기능이다.
논리적 커밋 단위: 10개 파일을 수정했더라도 관련된 3개만 골라서 하나의 커밋으로 만들 수 있다.
부분 변경 스테이징: 한 파일 안에서도 특정 변경만 골라 스테이징할 수 있다(git add -p).
# 수정 파일 중 일부만 커밋
git add feature-a.js
git commit -m "Feature A 구현"
git add bugfix.js
git commit -m "로그인 버그 수정"
# feature-b.js는 아직 작업 중이므로 스테이징하지 않음
세 트리 개념을 이해하면 이후에 다루는 git reset, git rebase, git stash 같은 고급 명령어를 훨씬 자연스럽게 이해할 수 있다.
지난 글: git clone: 원격 저장소 복제하기
다음 글: 스테이징 영역의 본질
읽어주셔서 감사합니다. 😊