빌드노트
잘못 git add한 파일, 수정은 남기고 스테이징만 취소하기
잘못 스테이징한 파일을 커밋 대상에서 빼면서 현재 수정은 남기는 방법이다. --staged 전후의 파일 해시와 두 diff를 비교하고, 작업 파일까지 복원하는 옵션과 결과를 구별한다.
이미 커밋된 파일을 고쳐 git add했는데 이번 커밋에서는 빼고 싶다. 파일에 쓴 내용은 그대로 남겨야 한다면 git restore --staged -- note.txt처럼 --staged만 지정한다. 다음 커밋에 준비한 내용을 담는 인덱스만 되돌리는 명령이다. 디스크에서 편집하는 파일, 즉 작업 트리는 건드리지 않는다. note.txt는 취소할 파일 경로로 바꾼다.
--source를 따로 지정하지 않은 --staged는 해당 경로의 인덱스를 HEAD, 즉 현재 커밋의 내용에 맞춘다. 파일의 추적을 끊는 것이 아니라 이번에 스테이징한 변경을 취소한다. 이 기본값과 복원 대상은 Git restore 공식 문서 (새 탭에서 열림)에 구분되어 있다.
먼저 취소할 파일의 두 diff를 읽는다
아래 명령은 Git이 설치된 PowerShell 7에서 사용한다. 현재 커밋에 이미 들어 있고, 충돌이 없으며, 수정 후 add한 일반 파일이 대상이다. 그 파일이 있는 저장소의 루트에서 실행하며, 모든 note.txt를 루트 기준의 실제 파일 경로로 바꾼다. 공백이 있으면 'docs/my note.txt'처럼 경로를 따옴표로 감싼다.
첫 명령이 출력하는 최상위 경로가 의도한 저장소인지 확인한다. 이 명령은 현재 폴더를 바꾸지 않는다. 하위 폴더에서 시작했다면 출력된 루트로 이동한 뒤 나머지를 실행한다. 앞 명령이 실패하면 그 지점에서 멈춘다.
git rev-parse --show-toplevel
git status --short -- note.txt
git diff --cached -- note.txt
git diff -- note.txt
--cached는 현재 커밋과 인덱스, 일반 diff는 인덱스와 작업 파일을 비교한다. --cached에 보이는 변경이 이번 커밋에서 뺄 내용인지 먼저 읽는다. 일반 diff에도 내용이 있다면 add한 뒤 다시 편집한 부분이 있다는 뜻이다. Git diff 공식 문서 (새 탭에서 열림)
Windows 11, Git 2.45.1.windows.1에서 새 합성 저장소로 이 절차를 확인했다. color=blue가 커밋된 파일을 color=green으로 고쳐 add한 상태였다. 상태는 M note.txt, cached diff의 변경 줄은 -color=blue, +color=green이었고 일반 diff는 비었다. 인덱스와 현재 파일이 같아도 커밋할 변경은 남아 있는 상태다.
--staged로 취소한 뒤 수정이 남았는지 확인한다
같은 파일에 다음 명령을 이어서 실행한다. -- 뒤의 경로로 대상을 한정하므로, 여기서는 해당 파일 전체의 스테이징을 취소한다.
git restore --staged -- note.txt
if ($LASTEXITCODE -ne 0) { throw '스테이징 취소에 실패했습니다.' }
git diff --cached -- note.txt
git diff -- note.txt
git status --short -- note.txt
실험에서 restore 자체는 아무 메시지도 출력하지 않았다. 이어 실행한 cached diff는 비었고, 일반 diff에는 앞서 본 -color=blue, +color=green이 나왔다. 따로 계산한 디스크 파일의 SHA-256도 실행 전후 같았다. Git 내부 식별자 대신 파일 바이트를 비교해, 디스크의 green이 보존됐음을 확인한 것이다.
마지막 상태 출력은 다음과 같았다. 맨 앞 공백도 출력의 일부다.
M note.txt
충돌이 없는 이 경우 첫 칸은 인덱스, 둘째 칸은 작업 트리 상태다. 처음의 M note.txt에서 M note.txt로 바뀌었다. 대상의 staged diff가 비고, 남겨야 할 수정이 일반 diff에 보이면 스테이징한 변경이 없어지고 작업 파일의 수정만 남은 것이다. 실제 파일 내용도 함께 확인한다. Git status의 짧은 출력 형식 (새 탭에서 열림)
다른 파일도 함께 스테이징한 별도 실험에서는 note.txt만 취소했고 다른 파일의 staged diff와 파일 해시는 유지됐다. 취소한 뒤 경로 제한 없는 git diff --cached도 읽으면 이번 커밋에 남아 있는 다른 변경을 확인할 수 있다.
add한 뒤 다시 편집했어도 현재 파일은 남는다
별도 저장소에서는 blue를 커밋하고 green을 add한 다음, 파일을 다시 red로 바꾸되 add하지 않았다. 취소 전에는 인덱스에 green, 작업 파일에 red가 있어서 상태가 MM note.txt였다.
여기에 같은 git restore --staged -- note.txt를 실행하자 파일 해시는 그대로였고 디스크에는 red가 남았다. 인덱스는 커밋의 blue로 돌아갔다. staged diff는 비었으며 일반 diff에는 -color=blue, +color=red가 나왔다. HEAD도 실행 전후 같은 커밋이었다.
이 명령은 현재 작업 파일을 보존하면서 그 파일의 스테이징을 통째로 취소한다. 인덱스에만 있던 중간 버전 green이나 기존의 스테이징 선택까지 따로 보관해 주지는 않는다. 파일의 일부 변경만 이번 커밋에서 빼려는 의도라면 파일 전체를 취소하는 이 절차와 구별해야 한다.
작업 파일까지 복원하는 옵션을 섞지 않는다
같은 blue 커밋·green 인덱스·red 작업 파일 상태를 각각 새로 만든 뒤, 다른 옵션도 비교했다. 다음은 별도 합성 파일에서 관찰한 결과다.
git restore -- note.txt: 인덱스의green을 작업 파일에 썼다. 파일 해시가 바뀌고 아직 add하지 않았던red가 사라졌다.green의 스테이징은 그대로였다.git restore --staged --worktree -- note.txt: 인덱스와 작업 파일이 모두 커밋의blue로 돌아갔다. 두 diff가 모두 비고 파일 해시도 바뀌었다.
옵션 없는 restore의 기본 대상은 작업 트리이고, 두 옵션을 함께 주면 두 곳을 복원한다. --staged가 있으면 기본 원본은 HEAD다. 이 차이는 설치한 버전이 속한 구간의 Git 2.43.0 restore 문서 (새 탭에서 열림)에서도 확인했다. 수정 보존이 목적이면 --staged만 선택해야 한다.
실행 전부터 staged diff가 비면 이미 취소됐거나 경로를 잘못 제한했을 수 있다. 명령이 오류를 내면 작업 위치·파일 경로와 현재 커밋의 존재를 확인한다. 취소 뒤에도 cached diff가 남거나 보관하려던 파일 내용이 달라졌다면, 실제로 실행한 옵션과 그 사이 다시 add하거나 저장했는지 확인한다.
이번에 직접 실행한 범위는 Windows의 커밋된 일반 텍스트 파일이며 줄바꿈 자동 변환을 껐다. 모든 대조 조건에서 HEAD는 같았다. 첫 커밋 전 저장소, 새로 추가하거나 삭제한 파일, 충돌, 부분 스테이징과 다른 운영체제는 시험하지 않았다.