[Git] History Rewrite로 실수한 커밋 정리하기
개발자라면 누구나 한 번쯤 겪는 상황이 있습니다. 커피 한 잔 마시고 돌아와서 기분 좋게 git push를 날렸는데, 커밋 메시지에 치명적인 오타가 있거나 파일을 하나 빼먹었을 때 말이죠.
심지어 더 최악의 상황도 존재합니다. AWS Secret Key나 DB Password가 적힌 환경 설정 파일(.env)을 실수로 커밋하고 푸시까지 해버린 순간입니다. 머릿속이 하얗게 변하는 이 순간, 우리는 Git의 시간을 되돌려야 합니다.
오늘은 이미 올라간 커밋을 수정하고, 실수를 흔적 없이 지우는 History Rewrite(기록 재작성) 기술을 깊게 파고들어 봅니다.
1. git commit –amend: 방금 한 커밋 덮어쓰기
가장 빈번하게 발생하는 ‘오타’나 ‘누락된 파일’을 수정할 때 사용하는 명령어입니다. 하지만 단순히 텍스트만 고치는 것이 아닙니다.
작동 원리: 새로운 해시값 생성
Git의 커밋은 불변(Immutable)입니다. 한 번 만들어진 커밋은 수정될 수 없어요. --amend를 사용하면 기존 커밋(A)을 수정하는 것이 아니라, 내용이 수정된 완전히 새로운 커밋(A’)을 생성하여 기존 커밋을 대체합니다.
# 1. 파일 누락 시: 파일을 Staging Area에 추가
git add missing_file.js
# 2. 커밋 덮어쓰기 (편집기 실행)
git commit --amend
# 3. (옵션) 메시지만 빠르게 수정하고 싶을 때
git commit --amend -m "Fix: 로그인 로직 수정 (누락 파일 추가)"
⚠️ 주의: 커밋의 ID인 SHA-1 해시값이 바뀝니다. 즉, 이미 원격 저장소(Remote)에 푸시된 커밋에
--amend를 사용하면 로컬과 원격의 히스토리가 달라져 충돌이 발생합니다.
2. git reset의 3가지 옵션 완벽 해부
“이 커밋은 아예 없던 일로 하고 싶어.” 이때 사용하는 git reset은 뒤에 붙는 옵션에 따라 돌아온 후의 상태가 완전히 달라집니다. 이 3가지를 구분하는 것이 중급 개발자로 가는 첫걸음입니다.
–soft vs –mixed vs –hard
돌아갈 과거 시점(HEAD~1 등)을 지정했을 때, “그 이후에 작업했던 변경 사항들을 어디에 둘 것인가?”가 핵심 차이입니다.
| 옵션 | 변경 사항의 위치 | 추천 상황 (Use Case) |
|---|---|---|
--soft |
Staging Area (add 된 상태) | 커밋을 취소하고, 바로 다시 커밋(commit)하고 싶을 때. (여러 커밋을 하나로 합칠 때 유용) |
--mixed |
Working Directory (add 안 된 상태) | 기본값. 커밋은 취소하되, 코드는 살려서 다시 수정하고 싶을 때. |
--hard |
(삭제됨) | 위험! 작업 내용을 모두 날리고 깔끔하게 과거 상태로 돌아가고 싶을 때. |
# 가장 많이 사용하는 패턴 (작업 내용은 살리고 커밋만 취소)
git reset --mixed HEAD~1
# 현재 작업 내용이 마음에 안 들어서 싹 날릴 때
git reset --hard HEAD
3. git push -f: 협업 시 왜 위험한가?
위의 --amend나 reset을 사용하면 로컬 저장소의 역사가 바뀝니다. 이때 원격 저장소에 push 하려 하면 Git은 거부(Reject)합니다. 로컬의 역사가 원격보다 뒤처지거나 갈라졌기 때문입니다.
이때 사용하는 것이 force push입니다.
git push origin [브랜치명] -f
# 또는 더 안전한 옵션 (추천)
git push origin [브랜치명] --force-with-lease
협업 시 위험성
내가 push -f를 하는 순간, 원격 저장소의 히스토리가 내 로컬 기준으로 강제로 덮어씌워집니다. 만약 동료 A가 그 사이에 커밋을 올렸다면? 동료의 커밋은 영구적으로 삭제되어 증발합니다.
유용한 사용처
- 나 혼자 쓰는 Feature 브랜치: PR을 올리기 전, 커밋 메시지를 예쁘게 정리(rebase)하거나 오타를 수정(amend)한 뒤에는 자유롭게 사용해도 됩니다.
- –force-with-lease: “누가 그 사이에 푸시하지 않았을 때만 강제 푸시해줘”라는 안전장치가 달린 옵션입니다. 실무에서는 이걸 습관화하는 것이 좋습니다.
결론
“실수는 누구나 한다. 하지만 흔적 없이 지우는 건 실력이다.”
Git은 강력한 타임머신 기능을 제공합니다. 오늘 다룬 amend, reset, force push를 이해한다면, 어떤 실수를 하더라도 당황하지 않고 우아하게 대처할 수 있을 것입니다.
궁금한 점이 있다면 댓글로 남겨 주세요.
참고 자료
- Git 공식 문서:
git commit --amend,git reset,git push - BFG Repo-Cleaner 공식 문서: 히스토리에서 민감한 파일 제거 예시
- Git Pro 2nd Edition: Rewriting History 장
댓글남기기