본문 바로가기
빌드노트 검색

빌드노트

git commit --amend로 메시지만 고쳤는데 다른 파일도 들어간 이유

메시지를 바꾸는 기본 amend도 staged 변경을 함께 담는다. 새 저장소에서 기본 amend·--only·--no-edit의 tree와 index를 비교하고, 메시지만 고친 뒤 파일 내용과 남은 스테이징을 확인하는 방법을 설명한다.

직전 커밋의 메시지 오타를 고치려고 git commit --amend -m 'Add guide'를 실행했는데, 다음 작업용으로 add해 둔 파일까지 그 커밋에 들어갈 수 있다. 기본 amend는 현재 인덱스의 내용으로 직전 커밋을 대체한다. -m은 새 메시지를 지정할 뿐, 커밋할 파일 내용을 고정하지 않는다. 메시지만 바꾸려면 파일 경로 없이 --amend --only를 사용한다. Git commit 공식 문서 (새 탭에서 열림)

인덱스는 다음 커밋에 담으려고 스테이징해 둔 내용이다. 따라서 메시지를 바꾸기 전에도 인덱스에 무엇이 들어 있는지 확인해야 한다. 아래는 Git과 PowerShell 7을 사용하는 절차다. 직전 커밋이 존재하고 충돌 처리가 진행 중이지 않은 저장소를 대상으로 한다. amend는 새 커밋을 만들므로 메시지만 바꿔도 커밋 ID가 달라진다. 여기서는 아직 공유하지 않은 로컬 커밋을 다룬다.

메시지를 고치기 전에 다른 변경이 준비돼 있는지 본다

저장소 루트에서 다음 명령으로 대상 위치와 스테이징한 변경을 확인한다. 첫 출력이 의도한 저장소인지 보고, 오류가 나면 다음 명령으로 넘어가지 않는다.

git rev-parse --show-toplevel
git diff --cached --name-status
git diff --cached

--name-status는 변경 종류와 파일명을, 마지막 명령은 실제 변경 줄을 보여 준다. --cached의 비교 기준은 기본적으로 현재 커밋인 HEAD다. amend에서는 기존 커밋의 파일 내용에 무엇이 더해지거나 바뀔지 읽는 데 쓴다. Git diff 공식 문서 (새 탭에서 열림)

새 독립 저장소에 guide.txt의 수정을 커밋하고, 별도 작업용 next.txt를 add한 실험에서는 두 번째 명령이 다음을 출력했다. A와 파일명 사이는 탭이다.

A	next.txt

마지막 명령에는 새 파일의 +next=staged 줄이 나왔다. 이 변경을 직전 커밋에 넣을 의도가 없다면 기본 amend를 그대로 실행할 상태가 아니다. 일반 git diff가 비어 있어도 이 판단은 달라지지 않는다. 실험에서도 디스크 파일과 인덱스의 내용이 같아 일반 diff는 비었지만, staged 변경은 남아 있었다.

같은 staged 파일을 두고 옵션을 바꿨다

Windows 11, Git 2.45.1.windows.1, PowerShell 7.6.6에서 조건마다 새 저장소를 만들었다. 실제 업무 사건이 아니라 합성 파일로 만든 비교다. 각 저장소의 직전 커밋 메시지는 오타가 있는 Add guied였고, 커밋에는 guide.txt만 있었다. 다음은 실행 전후 커밋의 파일 스냅샷인 tree와 인덱스를 비교한 결과다.

  • staged 변경이 없을 때 git commit --amend -m 'Add guide': 메시지는 고쳐졌고 tree는 같았다.
  • next.txt를 add한 뒤 같은 기본 amend: 메시지는 고쳐졌지만 tree에 next.txt도 들어갔다. 이후 cached diff는 비었다.
  • next.txt를 add한 뒤 git commit --amend --only -m 'Add guide': 메시지는 고쳐졌고 tree는 기존 커밋과 같았다. cached diff에는 A next.txt가 남았다.
  • next.txt를 add한 뒤 git commit --amend --no-edit: 메시지의 오타는 그대로였고 tree에는 next.txt가 들어갔다.

기본 amend 뒤 cached diff가 비었다고 파일이 제외된 것은 아니다. 실험에서는 인덱스의 파일 내용은 그대로였고, 새 커밋이 그 내용을 담으면서 비교 양쪽이 같아졌다. 반대로 --only 뒤 cached diff가 남은 것은 다음 작업이 아직 커밋되지 않았다는 뜻이었다.

--no-edit는 선택된 메시지를 편집기 없이 사용하는 옵션이다. 이 실험처럼 다른 메시지를 지정하지 않은 amend에서는 기존 메시지를 유지한다. 파일 내용을 보존하는 옵션으로 고르면 안 된다. 경로 없는 --amend --only의 지원과 이 차이는 Git 2.45.0 commit 문서 (새 탭에서 열림)에서도 확인했다.

메시지만 바꾼 뒤에는 두 커밋을 직접 비교한다

현재 커밋을 가리키는 값을 저장한 뒤, 파일 경로를 붙이지 않고 메시지만 바꾼다. 'Add guide'는 실제로 남길 메시지로 교체한다. 같은 PowerShell 세션에서 이어 실행해야 뒤의 비교에 $before를 쓸 수 있다.

$before = git rev-parse HEAD
if ($LASTEXITCODE -ne 0) { throw 'Cannot read HEAD' }
git commit --amend --only -m 'Add guide'
if ($LASTEXITCODE -ne 0) { throw 'Amend failed' }

여기서 파일 경로를 지정하지 않는 조건이 중요하다. --only에 경로를 주면 해당 경로의 작업 트리 내용을 가져오는 방식이므로, 메시지만 바꾸는 위 명령과 용도가 달라진다. 이번 비교에서는 경로를 지정한 amend는 실행하지 않았다.

성공한 다음에는 커밋의 파일 내용, 남은 스테이징, 새 메시지를 각각 확인한다.

git diff --name-status $before HEAD
git diff --cached --name-status
git log -1 --format=%s

--only 실험에서 첫 명령은 아무것도 출력하지 않았고, 둘째는 앞서 본 A next.txt, 셋째는 Add guide를 출력했다. 별도로 비교한 tree ID도 전후 같았고 디스크 파일의 바이트도 보존됐다. 커밋 ID가 바뀌었다는 사실과 파일 내용이 바뀌었다는 사실은 따로 확인해야 한다.

amend 직후의 커밋 요약에는 1 file changed가 나왔지만, 그것만으로 이전 커밋보다 파일이 달라졌다고 판단하지 않았다. 이전 커밋과 새 커밋을 직접 비교한 첫 명령에서는 차이가 없었다. 일반 커밋처럼 HEAD와 그 부모만 비교하면, 원래 그 커밋이 담고 있던 수정까지 보게 된다.

메시지만 바꾸려던 상황에서 첫 명령에 파일이 나오면 기대와 다른 결과다. 실행한 옵션과 훅의 동작, 그 사이 다른 작업이 있었는지 확인한다. staged 변경을 남겨 두려던 상황에서 둘째 출력이 사라졌다면 단순히 정리가 잘됐다고 넘기지 말고 첫 비교에서 그 파일이 새 커밋에 들어갔는지 본다. 명령 자체의 오류는 빈 diff로 해석하지 않는다.

반대로 준비한 변경을 직전 커밋에 실제로 포함할 목적이라면, 경로 제한 없는 git diff --cached 전체가 의도에 맞는지 읽은 뒤 기본 amend를 고를 수 있다. 메시지도 고치면 -m, 기존 메시지를 그대로 쓰면 --no-edit를 선택한다. 인덱스에 무관한 변경이 섞여 있으면 먼저 커밋할 범위를 정리한다.

직접 실행한 범위는 충돌 없는 일반 텍스트 파일과 새 staged 파일이다. 훅과 커밋 서명, 줄바꿈 자동 변환을 끈 환경이며, 부분 스테이징·병합 커밋·다른 운영체제는 시험하지 않았다. 원격 저장소나 공유된 커밋의 재작성 절차도 검증하지 않았다.

← 전체 글 보기