빌드노트
git add 뒤 git diff가 비었다면 --cached로 확인한다
git add 뒤 빈 diff는 변경이 사라졌다는 뜻이 아닐 수 있다. A 커밋·B 스테이징·C 작업 파일을 직접 비교하고, 다음 커밋에 넣을 내용은 --cached로 확인하는 이유를 설명한다.
수정한 파일을 git add한 뒤 git diff를 실행했는데 아무것도 나오지 않을 수 있다. 일반 git diff는 스테이징한 내용과 현재 파일을 비교한다. 두 내용이 같아졌다면 출력은 빈다. 다음 커밋에 넣어 둔 변경은 git diff --cached로 확인한다. Git diff 공식 문서 (새 탭에서 열림)
자기 저장소에서 확인할 때는 다음 명령을 사용한다. 첫 명령이 가리키는 최상위 경로가 확인하려던 저장소인지 먼저 본다. 이어지는 두 명령은 파일을 수정하지 않는다.
git rev-parse --show-toplevel
git diff --cached
git diff
--cached에는 커밋을 위해 준비한 변경이, 마지막 명령에는 아직 추가하지 않은 변경이 나온다. 일반 diff가 비어 있어도 --cached에 원하는 수정이 보인다면, 변경은 스테이징되어 있는 것이다. --staged도 --cached와 같은 옵션이다.
B를 추가하자 일반 diff가 비었다
비교 대상을 확인하려고 새 독립 저장소에서 한 줄짜리 note.txt로 실습했다. 실제 업무에서 발생한 사건이 아니라 Windows 11, Git 2.45.1.windows.1, PowerShell 7.6.6에서 만든 예제다.
따라 확인하려면 Git과 PowerShell 7을 준비하고, 기존 소스와 분리된 새 빈 폴더에서 시작한다. 아래 처음 두 명령으로 저장소를 만들고 최상위 경로가 그 폴더인지 확인한 뒤 나머지를 실행한다. 앞 명령이 실패하면 다음으로 넘어가지 않는다. Set-Content는 파일을 덮어쓰므로 기존 작업 파일에 적용하지 않는다. 이름과 이메일은 실습 커밋 한 번에만 전달한다.
git init --quiet --initial-branch=main
git rev-parse --show-toplevel
Set-Content -LiteralPath note.txt -Value 'A' -Encoding ascii
git add -- note.txt
git -c user.name='Diff Lab' -c user.email='diff-lab@example.invalid' commit -m 'Save A'
Set-Content -LiteralPath note.txt -Value 'B' -Encoding ascii
git diff -- note.txt
마지막 명령의 실제 출력에서 파일명과 해시 헤더를 제외하면 다음 부분이 남았다. -는 비교 기준에서 빠지는 줄이고, +는 비교 결과에 들어오는 줄이다. 끝의 -- note.txt는 비교할 경로를 이 파일로 제한한다.
@@ -1 +1 @@
-A
+B
이때 마지막 커밋에는 A가 있고, 디스크의 파일에는 B가 있다. 이어 B를 스테이징했다.
git add -- note.txt
git diff -- note.txt
git diff --cached -- note.txt
가운데 명령은 표준 출력과 오류 출력 모두 비어 있었다. 마지막 명령에는 앞서 본 -A, +B가 그대로 나왔다. 비교할 내용이 사라진 것이 아니라, 인덱스에도 B가 들어가서 일반 diff의 양쪽이 같아졌다.
여기서 인덱스는 다음 커밋에 넣을 내용을 준비하는 곳이며 스테이징 영역이라고도 부른다. 작업 트리는 현재 디스크에서 편집하는 파일들이다. 이 예제의 HEAD는 방금 만든 A 커밋을 가리킨다.
다시 수정하면 비교 결과가 셋으로 갈린다
B를 추가한 뒤 같은 파일을 C로 바꿨다. 이번에는 git add를 다시 실행하지 않고 세 명령을 비교했다.
Set-Content -LiteralPath note.txt -Value 'C' -Encoding ascii
git diff -- note.txt
git diff --cached -- note.txt
git diff HEAD -- note.txt
이제 HEAD의 파일은 A, 인덱스의 파일은 B, 작업 트리의 파일은 C다. 실제 출력의 변경 줄은 다음처럼 달랐다.
git diff:-B,+C. 인덱스 B를 기준으로 현재 파일 C가 얼마나 달라졌는지 보여 줬다.git diff --cached:-A,+B. HEAD의 A를 기준으로 다음 커밋에 준비한 B를 보여 줬다.git diff HEAD:-A,+C. HEAD의 A를 기준으로 현재 파일 C를 보여 줬다.
세 번째 명령만 읽으면 현재 파일이 C라는 것은 알 수 있지만, 인덱스에 B가 준비돼 있다는 사실은 알 수 없다. 커밋 직전 검토에 git diff HEAD만 사용하면 아직 추가하지 않은 수정까지 이번 커밋에 들어간다고 오해할 수 있다. 이 세 비교 방식은 Git 2.45.0의 diff 문서 (새 탭에서 열림)에도 구분되어 있다.
git add는 파일을 계속 따라가는 예약이 아니다. 실행 당시의 내용을 인덱스에 반영한다. 이후에 편집한 C까지 넣으려면 다시 추가해야 한다. Git add 공식 문서 (새 탭에서 열림)
커밋에 넣을 내용과 남길 내용을 나눠 확인한다
실습에서는 C를 추가하지 않은 채 -a나 파일 경로를 지정하지 않고 커밋했다. 새 커밋의 note.txt를 읽은 결과는 B였고, 디스크에는 C가 남았다. 커밋 뒤 --cached는 비었으며 일반 diff에는 여전히 -B, +C가 나왔다. 앞서 --cached로 읽은 내용이 실제로 커밋된 것이다.
자기 작업에서도 이번에 커밋할 내용은 git diff --cached, 아직 넣지 않은 내용은 git diff로 읽는다. B만 커밋하고 C를 다음 작업으로 남길 의도라면 두 출력이 모두 있는 상태도 맞다. 파일 전체의 현재 수정까지 이번 커밋에 넣을 의도라면 해당 파일을 다시 추가한 뒤 검토한다.
git add -- note.txt
git diff --cached -- note.txt
자기 파일에 적용할 때는 note.txt를 실제 경로로 바꾼다. 마지막에는 경로 제한 없는 git diff --cached도 읽어 다른 파일의 스테이징 내용을 함께 확인한다. 이 설명은 인덱스의 내용을 커밋하는 일반적인 경우를 다룬다. git commit -a나 파일 경로 지정처럼 커밋 대상을 달리 고르는 방식은 commit 공식 문서 (새 탭에서 열림)의 별도 조건을 확인해야 한다.
이번에 직접 확인한 것은 최초 커밋이 있는 저장소의 일반 추적 텍스트 파일이다. 부분 스테이징, 서브모듈, 외부 diff 도구는 시험하지 않았다. 실습에서는 줄바꿈 자동 변환을 껐으므로 사용자 설정에 따라 해시나 줄바꿈 경고는 달라질 수 있다. --cached까지 비어 있다면 이 글의 “수정이 스테이징된 상태”만으로는 설명할 수 없다. 먼저 최상위 경로와 명령 뒤에 제한한 파일 경로가 맞는지 확인한다.