본문 바로가기
TYLER SONGBlog
← Blog index
CS학습4 min read

Staging Area: 커밋할 변경 사항을 미리 골라 담는 Git의 중간 영역

스테이징 영역(Staging Area, Index)은 작업 디렉터리와 저장소 사이에서 다음 커밋에 포함할 변경 사항을 모아 두는 공간이다. `git add`로 파일이나 일부 변경 조각(hunk)만 골라 올리면, `git commit`은 그 상태만 스냅샷으로 기록한다. 이 구조 덕분에 한 번에 여러 작업을 했더라도 논리적 단위로 나누어 커밋할 수 있다.

By 송민성

1. 개념

스테이징 영역(Staging Area)은 다음 커밋에 들어갈 내용을 구성해 두는 공간이다. Git 내부에서는 인덱스(Index)라고 부르며, 실제로는 .git/index 파일에 저장된다.

Git은 파일이 세 가지 영역을 오간다고 볼 수 있다.

영역설명
작업 디렉터리(Working Directory)실제로 편집하는 파일들
스테이징 영역(Staging Area)다음 커밋에 포함하기로 한 변경 사항
저장소(Repository, .git)커밋으로 확정된 이력

2. 왜 사용하는가

  • 커밋 단위를 논리적으로 분리: 버그 수정과 리팩터링을 동시에 했더라도 각각 다른 커밋으로 남길 수 있다.
  • 커밋 전 검토: 올라간 내용을 git diff --staged로 확인한 뒤 확정할 수 있다.
  • 파일 내부의 부분 선택: 한 파일 안의 일부 변경만 커밋할 수 있다(git add -p).
  • 리뷰와 되돌리기 용이: 작은 커밋은 코드 리뷰, git revert, git bisect에서 다루기 쉽다.

3. 동작 원리

git add를 실행하면 Git은 다음 일을 한다.

  1. 파일 내용을 압축해 블롭(blob) 객체로 .git/objects에 저장한다.
  2. 인덱스에 "이 경로는 이 블롭을 가리킨다"는 항목(경로, 파일 모드, 객체 해시)을 기록한다.

git commit을 실행하면 인덱스의 내용으로 트리(tree) 객체를 만들고, 이 트리를 가리키는 커밋 객체를 생성한다. 커밋은 작업 디렉터리가 아니라 인덱스를 기준으로 만들어진다. 그래서 git add 이후에 파일을 다시 수정하면, 그 추가 수정은 스테이징되지 않은 상태로 남는다.

각 파일은 비교 기준에 따라 상태가 나뉜다.

  • Untracked: Git이 아직 추적하지 않는 파일
  • Modified: 마지막 커밋 대비 바뀌었지만 스테이징되지 않음
  • Staged: 다음 커밋에 포함되도록 인덱스에 올라감

4. 코드 예제

실습용 저장소를 만들어 흐름을 확인하는 셸 스크립트이다.

shell
#!/bin/sh set -e dir=$(mktemp -d) cd "$dir" git init -q git config user.name "demo" git config user.email "demo@example.com" # 1) 초기 커밋 printf 'line1\n' > app.txt git add app.txt git commit -q -m "init" # 2) 파일 수정 + 새 파일 추가 printf 'line1\nline2\n' > app.txt printf 'notes\n' > notes.txt git status --short # M app.txt # ?? notes.txt # 3) app.txt만 스테이징 git add app.txt git status --short # M app.txt # ?? notes.txt # 4) 스테이징 후 추가 수정 -> 같은 파일이 두 상태를 동시에 가짐 printf 'line1\nline2\nline3\n' >> app.txt git status --short # MM app.txt git diff # 작업 디렉터리 vs 인덱스 (line3만 보임) git diff --staged # 인덱스 vs HEAD (line2만 보임) # 5) 스테이징된 내용만 커밋 git commit -q -m "add line2" git status --short # M app.txt (line3은 아직 커밋되지 않음) # ?? notes.txt # 6) 스테이징 취소 예시 git add app.txt git restore --staged app.txt # 인덱스에서만 내림, 파일 내용은 유지 git status --short

파일 내부의 일부만 올리려면 대화형 모드를 쓴다.

shell
git add -p app.txt # y: 이 조각 스테이징, n: 건너뜀, s: 더 작게 분할, q: 종료

5. 시간 복잡도 또는 성능 특성

Git은 인덱스에 파일별 메타데이터(수정 시각, 크기 등)를 캐시해 둔다. git status는 이를 이용해 내용을 매번 전부 읽지 않고도 변경 여부를 빠르게 판단할 수 있다. 다만 변경된 파일은 새로 해시를 계산해야 하므로, 대용량 파일을 자주 git add하면 비용이 커진다. 정확한 소요 시간은 저장소 크기와 파일 시스템에 따라 달라지므로 일반적인 수치로 단정할 수 없다.

6. 실무 사용 사례

  • 기능 단위 커밋 분리: 한 번에 작업한 변경을 git add -p로 나눠 "버그 수정", "포맷팅", "테스트 추가"처럼 별도 커밋으로 만든다.
  • 커밋 전 자기 리뷰: git diff --staged로 디버깅용 console.log나 임시 코드가 섞이지 않았는지 확인한다.
  • 훅(hook) 연동: pre-commit 훅이나 lint-staged 같은 도구는 스테이징된 파일만 대상으로 린트와 포맷을 실행한다.
  • 직전 커밋 보완: 빠뜨린 파일을 git add한 뒤 git commit --amend로 마지막 커밋에 합친다.

7. 주의할 점

  • git add 후 다시 수정한 내용은 자동으로 반영되지 않는다. 커밋 전에 git status로 MM 표시가 없는지 확인한다.
  • git add .은 의도하지 않은 파일(.env, 빌드 산출물)까지 올릴 수 있다. .gitignore를 정비하고 git status로 확인한다.
  • 이미 추적 중인 파일은 .gitignore에 추가해도 무시되지 않는다. git rm --cached <파일>로 추적을 해제해야 한다.
  • 스테이징 취소에는 git restore --staged <파일>을 쓴다. 반면 git restore <파일>(옵션 없음)은 작업 디렉터리의 수정 내용을 버리므로 복구할 수 없다.
  • 시크릿을 한 번 git add하면 객체 저장소에 블롭이 남을 수 있다. 커밋하지 않았더라도 노출 가능성을 염두에 둬야 한다.

8. 핵심 정리

  • 스테이징 영역(인덱스)은 다음 커밋의 내용을 구성하는 중간 공간이다.
  • 커밋은 작업 디렉터리가 아니라 인덱스의 내용으로 만들어진다.
  • git add로 올리고, git restore --staged로 내리며, git diff --staged로 확인한다.
  • git add -p를 쓰면 한 파일 안에서도 변경 조각 단위로 골라 커밋할 수 있다.
  • git add 이후의 추가 수정은 다시 git add해야 커밋에 포함된다.