개발도구

Git 커밋을 잘못했을 때, push 전후로 reset과 revert 고르는 법

Hcode 2026. 10. 9.
반응형

커밋을 누른 뒤 빠뜨린 파일이나 잘못 넣은 코드를 발견했습니다. 다시 만들면 될 것 같지만, reset 옵션을 잘못 골라 작업 파일까지 잃을까 걱정됩니다. 먼저 다른 사람이 이미 이 커밋을 바탕으로 작업하는지, 변경한 파일은 남겨 둘 것인지 두 가지를 확인하세요.

아직 공유하지 않은 마지막 커밋은 reset으로 위치를 옮겨 다시 구성할 수 있습니다. 이미 공유된 이력은 revert로 반대 변경을 새 커밋에 남기는 편이 협업 흐름을 유지하기 쉽습니다. 여기서는 부모 커밋이 있는 일반 커밋 한 개를 다룹니다. 최초 커밋이나 merge 커밋은 같은 명령을 그대로 적용하지 않습니다.

아직 공유하지 않은 이력의 reset은 커밋 위치를 옮기고, 이미 공유한 이력의 revert는 기존 커밋 뒤에 되돌림 커밋을 추가한다. 코미가 공유 이력 끝에 새 커밋 카드를 끼운다.
파일을 어떻게 남길지와 다른 사람이 보는 이력을 어떻게 유지할지를 함께 결정합니다.

먼저 작업 파일과 되돌릴 커밋을 확인합니다

git status
git diff
git diff --cached
git log --oneline -5

미커밋 변경이 있다면 방금 만든 커밋의 변경과 섞여 있는지 확인합니다. git diff는 아직 stage하지 않은 변경을, git diff --cached는 stage한 변경을 보여 줍니다. 아래 reset·revert 예제는 별도로 보존해야 할 미커밋 작업을 먼저 정리한 상태를 전제로 합니다.

현재 커밋 위치를 남기고 싶다면 다음처럼 별도 브랜치를 만들 수 있습니다. 이 명령은 브랜치를 전환하지 않습니다.

git branch backup/before-undo

다만 백업 브랜치는 커밋 위치를 가리킬 뿐, 커밋하지 않은 파일까지 저장하지는 않습니다. 미커밋 작업은 별도 복사나 임시 커밋, 필요에 맞는 stash로 보존해야 합니다. git stash 공식 문서의 -u는 미추적 파일을 포함하지만 ignored 파일까지 포함하는 옵션은 아닙니다. 저장한 내용과 나중에 복원할 대상을 확인하세요.

push 전이라면 파일을 남긴 채 커밋을 다시 구성할 수 있습니다

직접 공유하지 않은 마지막 커밋을 취소하고 변경을 다시 묶고 싶다면 reset의 soft와 mixed 차이부터 고릅니다. 다음 두 방식 중 원하는 staging 상태에 맞는 하나를 사용합니다.

다시 커밋할 변경을 stage에 남기려면 soft

git reset --soft HEAD~1

현재 브랜치의 커밋 위치를 부모로 옮기고 index와 작업 파일은 그대로 둡니다. 깨끗한 상태에서 방금 만든 커밋을 되돌린 경우, 그 커밋의 변경이 stage된 상태로 남아 다시 커밋할 수 있습니다.

파일별로 다시 고르고 싶다면 mixed

git reset --mixed HEAD~1

커밋 위치와 index를 부모 커밋에 맞추되 작업 파일은 유지합니다. 변경이 unstaged 상태로 남으므로 필요한 파일이나 부분만 다시 git add할 수 있습니다. git reset HEAD~1에서 모드를 생략했을 때의 기본값도 mixed입니다.

직접 만든 임시 저장소에서 두 방식을 비교하니, 둘 다 파일의 최신 내용은 남았습니다. soft에서는 staged diff에, mixed에서는 unstaged diff에 변경이 나타났습니다. 파일이 보존된다는 점은 같지만 다음 커밋을 준비하는 상태가 달랐습니다.

--hard는 같은 선택지가 아닙니다. 작업 파일까지 대상 커밋에 맞추며 로컬 변경을 잃을 수 있습니다. 단지 커밋을 다시 만들려는 상황에서 붙일 옵션으로 생각하지 마세요.

이미 공유했다면 되돌림을 새 커밋으로 남깁니다

다른 사람이 받은 커밋을 reset으로 없앤 뒤 강제로 push하면 그 사람이 보는 이력과 달라질 수 있습니다. push 여부는 빠른 단서지만, 실제 기준은 이미 다른 작업의 바탕이 된 이력인지입니다. 공유된 일반 커밋의 변경을 취소할 때는 git revert가 새 커밋을 만듭니다.

git show --stat HEAD
git revert HEAD
git log --oneline -3
git status

위 예제는 최신 커밋 자체가 되돌릴 대상일 때입니다. 다른 커밋이라면 내용을 확인한 해당 커밋 ID를 사용해야 합니다. revert가 편집기를 열면 되돌리는 이유를 메시지에 남기고, 변경과 테스트 결과를 확인한 뒤 기존 업스트림에 일반 push로 반영할 수 있습니다.

로컬 bare 저장소를 원격처럼 연결한 실험에서는 원래 커밋이 이력에 남고 그 뒤에 되돌림 커밋이 추가됐습니다. 파일 내용은 이전 상태로 돌아왔고 강제 옵션 없이 push가 성공했습니다. GitHub나 사용자의 원격 저장소에 실험 커밋을 올린 것은 아닙니다.

revert가 언제나 자동으로 끝나는 것은 아닙니다. 이후 변경과 충돌하면 내용을 해결하고 필요한 파일을 stage한 뒤 git revert --continue로 이어갑니다. 그 revert 작업을 취소하려면 git revert --abort를 사용합니다. merge 커밋은 기준 부모를 선택해야 하므로 이 글의 일반 커밋 예제와 따로 판단해야 합니다.

reset을 잘못했다면 reflog에서 커밋 위치를 찾습니다

방금 reset한 커밋이 로그에서 사라졌더라도 로컬 참조 이동 기록에 남아 있을 수 있습니다. 먼저 기록과 커밋 내용을 확인한 뒤 새 복구 브랜치를 만들어 위치를 붙잡아 둘 수 있습니다.

git reflog --date=local
git show 복구할커밋ID
git branch rescue/before-reset 복구할커밋ID

복구할커밋ID는 reflog에서 찾고 내용을 확인한 실제 ID로 바꿉니다. 바로 또 다른 reset을 실행하기보다 새 브랜치로 커밋을 가리키면 현재 작업 파일을 바꾸지 않고 복구 대상을 남길 수 있습니다. 임시 저장소에서도 잘못된 mixed reset 뒤 이 방식으로 원래 커밋을 다시 참조했습니다.

reflog는 로컬 기록이며 만료될 수 있습니다. 영구 백업이 아니고, 커밋하지 않은 모든 파일을 복구해 주는 기능도 아닙니다. 특히 파일을 잃은 뒤에는 무엇이 커밋·stage·별도 백업돼 있었는지부터 구분해야 합니다.

실행 뒤에는 이력과 파일 상태를 함께 봅니다

  • soft를 썼다면: 원하는 변경이 staged diff에 남았는지 확인합니다.
  • mixed를 썼다면: 작업 파일이 남고 다시 stage할 변경이 보이는지 확인합니다.
  • revert를 썼다면: 원래 커밋과 새 되돌림 커밋이 모두 남았는지, 취소하려던 내용만 바뀌었는지 확인합니다.

선택의 출발점은 ‘커밋을 지운다’보다 ‘파일과 공유 이력을 어떤 상태로 남긴다’에 가깝습니다. 작업 상태를 먼저 보존하고 필요한 한 단계만 수행한 뒤 다시 확인하세요. 비밀 키처럼 민감한 내용이 커밋됐다면 revert만으로 과거 이력에서 사라지지 않으므로 키 폐기와 별도 이력 정리 절차가 필요합니다.

확인 기준: 2026년 10월 9일. Git 2.54.0에서 독립 임시 저장소와 로컬 bare 원격으로 검증했습니다. 복잡한 merge 이력과 여러 사람이 동시에 push하는 상황은 재현 범위에 포함하지 않았습니다.

반응형

댓글