빠른 비교
로컬 마지막 커밋 수정
git add <file>
git commit --amend
메시지만 수정
git commit --amend
이미 push한 내 작업 브랜치 갱신
git push --force-with-lease
피해야 할 기본값
git push --force히스토리 수정
amend는 마지막 commit 객체를 새 commit 객체로 다시 만든다
git commit --amend는 마지막 커밋에 변경을 덧붙이는 명령처럼 보이지만, 실제로는 새 commit 객체를 만들고 현재 브랜치가 그 새 커밋을 가리키게 합니다. 커밋 메시지만 바꿔도 커밋 해시는 달라집니다. 그래서 아직 push하지 않은 로컬 커밋을 다듬을 때는 편하지만, 이미 다른 사람이 가져간 커밋에 쓰면 히스토리 불일치가 생깁니다.
git status
git add src/auth.js
git commit --amend
git log --oneline -2amend 전에는 반드시 git status로 스테이징 상태를 확인합니다. 스테이징된 파일은 모두 새 커밋에 들어가므로, "메시지만 고치려던 amend"가 의도치 않은 파일 수정까지 포함할 수 있습니다. 메시지만 바꾸려면 작업트리가 깨끗한 상태에서 실행하는 편이 안전합니다.
force-with-lease는 원격이 내가 본 상태일 때만 덮어쓰는 push다
히스토리를 고친 브랜치를 이미 원격에 올린 적이 있다면 일반 git push는 non-fast-forward라며 거부될 수 있습니다. 이때 --force는 원격 브랜치를 그대로 덮어쓰므로 다른 사람이 새로 올린 커밋까지 지울 수 있습니다. --force-with-lease는 원격 ref가 내가 알고 있는 remote-tracking branch와 같을 때만 강제 갱신을 허용해, 내가 보지 못한 원격 변경을 덮어쓸 가능성을 낮춥니다.
git fetch origin
git log --oneline --decorate origin/feature..feature
git push --force-with-lease origin feature단, 공식 문서가 설명하듯 --force-with-lease도 remote-tracking 정보에 의존합니다. IDE나 백그라운드 작업이 자동으로 git fetch를 실행하면 "내가 직접 확인한 상태"와 remote-tracking branch가 어긋날 수 있습니다. 중요한 공유 브랜치에서는 강제 push 자체를 피하고, 꼭 필요하면 팀과 시간대를 맞춘 뒤 실행합니다.
선택 기준
| 상황 | 적합한 선택 |
|---|---|
| 아직 push하지 않은 마지막 커밋 수정 | git commit --amend |
| 커밋 메시지만 수정 | 깨끗한 작업트리에서 git commit --amend |
| PR 브랜치에서 내 커밋을 정리 후 갱신 | git push --force-with-lease |
| main, release 같은 공유 브랜치 | amend 후 force push 피하기 |
| 다른 사람이 이미 기반으로 삼은 커밋 | 새 커밋으로 수정 사항 추가 |
| 원격에 새 커밋이 생겼는지 불확실 | 먼저 git fetch와 log 비교 |
amend는 "내 마지막 커밋을 깔끔하게 만드는 도구"이고, force-with-lease는 "히스토리 재작성 결과를 원격에 반영할 때 최소한의 안전장치를 거는 push"입니다. 둘 다 협업 브랜치에서는 비용이 커지므로, 개인 작업 브랜치나 PR 브랜치 안에서 범위를 제한해 쓰는 편이 맞습니다.
주의할 점
--force-with-lease는 --force보다 안전하지만, 공유 브랜치를 마음대로 덮어써도 된다는 뜻은 아닙니다.
보호 브랜치, 릴리스 브랜치, 여러 사람이 작업 중인 브랜치에서는 새 커밋으로 수정하는 흐름이 더 안전합니다.
실패 예시
- main의 마지막 커밋을 amend한 뒤 force push함
- 자동 fetch가 켜진 환경에서 원격 상태를 직접 확인하지 않고 force-with-lease를 실행함
- 메시지만 바꾸려다 staging된 디버그 파일까지 amend에 포함함참고 링크
2 sources