본문 바로가기
claudecode.to
문서 목록
Git과 팀 협업

잘못된 커밋·push 되돌리기

git revert reset 차이를 외우는 대신 '지금 어디까지 퍼졌는가' 한 가지로 고르는 판단표와, restore·reset·revert·reflog를 언제 쓰고 언제 쓰면 안 되는지 정리합니다.

20분2026-09-20 갱신

Git에서 되돌리는 명령은 여러 개지만, 고르는 기준은 하나입니다. "이 실수가 지금 어디까지 퍼졌는가." 내 작업 폴더에만 있는지, 커밋했지만 아직 push 전인지, 이미 push했는지, 남이 벌써 받아 갔는지에 따라 쓸 수 있는 명령이 달라집니다.

이 글은 그 판단표를 먼저 세우고, restore·reset·revert·reflog 를 각각 언제 쓰고 언제 쓰면 안 되는지 정리합니다. 커밋과 PR을 만드는 평소 조작은 Git 조작 자동화에 있습니다.

핵심 요약

  • 명령을 외우지 말고 "퍼진 범위"를 먼저 확인합니다. 범위가 명령을 정합니다.
  • push 전이라면 이력을 고쳐도 됩니다. push 후에는 새 커밋으로 되돌리는 방법만 안전합니다.
  • reset --hard 와 force push는 무언가를 확실히 없애는 명령입니다. 없어지는 대상이 무엇인지 먼저 말할 수 있어야 실행합니다.
  • 비밀값이 올라갔을 때는 이력 정리보다 키 폐기가 먼저입니다.
  • 충돌 화면에서 한쪽을 기계적으로 수락하면 남의 작업이 오류 없이 사라집니다.

어디까지 퍼졌는지로 고른다

퍼진 범위상황 예쓸 명령하면 안 되는 것
작업 디렉터리만엉뚱한 파일을 고쳤다git restore <파일>, 스테이징했다면 git restore --staged <파일>확인 없이 전체에 적용
커밋했지만 push 전메시지나 포함 파일이 틀렸다git commit --amend, git reset --soft HEAD~1이미 push한 커밋에 같은 명령 적용
내 작업 브랜치에 push, 리뷰 전커밋을 정리하고 싶다되도록 새 커밋으로 수정. 꼭 필요하면 내 브랜치에만 --force-with-lease공유 브랜치에 force push
main에 머지됨머지된 PR이 기능을 깨뜨렸다git revert 로 반대 변경 커밋 후 평소처럼 PRmain에 reset·force push
비밀값이 push됨키가 든 파일이 올라갔다키 폐기·재발급 먼저, 그다음 제거 커밋파일만 지우고 끝내기

이 표를 팀 문서에 그대로 옮겨 두면, 사고가 난 사람이 당황한 상태에서 검색하지 않고 한 줄을 짚을 수 있습니다.

작업 디렉터리만 바뀌었을 때 — restore

아직 커밋하지 않은 편집을 버리는 명령입니다.

git restore src/app.js              # 마지막 커밋 상태로 파일을 되돌린다
git restore --staged src/app.js     # 스테이징만 취소하고 편집은 남긴다

첫 번째 명령은 그 파일의 저장하지 않은 편집 내용을 완전히 버립니다. 커밋도 스태시도 없었다면 Git 어디에도 남지 않아 되찾을 수 없습니다. 실행 전에 git diff 로 무엇이 사라지는지 한 번 보는 습관을 권합니다.

두 번째 명령은 안전합니다. 스테이징 영역에서만 빼기 때문에 편집한 내용은 그대로 있습니다. "실수로 git add . 를 해서 .env 까지 올라갈 뻔했다" 같은 상황에 씁니다.

커밋했지만 push 전 — reset의 세 가지 모드

reset 은 브랜치가 가리키는 위치를 뒤로 옮기는 명령입니다. 옮기면서 작업 내용을 어디까지 남기느냐가 세 모드의 차이입니다.

모드커밋스테이징 영역작업 파일
--soft치워짐변경 내용이 남음그대로
--mixed(기본)치워짐비워짐그대로
--hard치워짐비워짐마지막 지점 상태로 덮어씀
git reset --soft HEAD~1    # 커밋만 취소, 변경은 스테이징에 남아 바로 다시 커밋 가능
git reset HEAD~1           # 커밋 취소, 변경은 파일에 남고 스테이징만 해제

--soft 가 가장 자주 쓰입니다. 커밋 하나를 잘못 묶었을 때 이 명령으로 풀고 둘로 나눠 다시 커밋하면 됩니다. 메시지만 고칠 때는 git commit --amend 한 줄이 더 간단합니다.

--hard 는 다릅니다.

git reset --hard HEAD~1

이 명령은 마지막 커밋과 함께, 커밋하지 않은 모든 편집을 지웁니다. 사라지는 것이 두 종류라는 점이 중요합니다. 커밋된 내용은 뒤에서 볼 reflog 로 되찾을 수 있지만, 커밋하지 않은 편집은 어디에도 기록이 없어 복구 불가입니다. 그래서 --hard 를 쓸 상황이라면 먼저 git stash 로 현재 편집을 대피시키거나, 임시 커밋을 하나 만들어 두는 편이 안전합니다.

그리고 이 세 모드 모두 push 전에만 쓰는 명령입니다. push한 커밋을 reset으로 치우면 내 이력과 원격 이력이 어긋나고, 그 상태를 맞추려면 force push밖에 남지 않습니다.

이미 push했을 때 — revert

revert 는 커밋을 지우지 않습니다. 그 커밋이 한 일의 반대 변경을 담은 새 커밋을 하나 더 쌓습니다.

git revert <되돌릴 커밋 해시>

이력이 늘어나는 것이 단점처럼 보이지만, 공유된 브랜치에서는 이것이 장점입니다. 남의 로컬에 있는 커밋은 그대로 두고 앞쪽에 한 줄을 더 얹는 방식이라, 다른 사람은 평소처럼 pull만 하면 됩니다. GitHub PR 화면의 되돌리기 버튼도 같은 일을 하고, 결과를 PR로 만들어 주므로 리뷰 기록까지 남습니다.

revert도 충돌이 날 수 있습니다. 되돌릴 커밋 이후에 같은 자리를 누군가 또 고쳤다면, Git은 반대 변경을 어디에 적용할지 몰라 멈춥니다. 이때는 평소 충돌과 똑같이 해소하면 되고, 중간에 그만두려면 git revert --abort 로 되돌리기 전 상태로 돌아갑니다. 이 명령은 revert 작업만 취소하므로 원래 이력에는 영향이 없습니다.

머지 커밋을 되돌릴 때는 어느 쪽 변경을 반대로 적용할지 지정해야 합니다. squash merge로 통일한 팀이라면 PR 하나가 커밋 하나여서 이 고민이 없어집니다. 이 선택을 왜 팀 차원에서 통일하는지는 팀 Git·GitHub 협업 규칙에서 다룹니다.

공유 브랜치의 force push가 왜 남의 작업을 지우나

force push는 "원격의 이력을 내 이력으로 덮어쓴다"는 명령입니다. 상황을 순서대로 보면 왜 위험한지 분명해집니다.

동료가 오후에 커밋 세 개를 공유 브랜치에 올렸습니다. 나는 오전에 받아 둔 상태에서 작업했으니 내 로컬에는 그 세 개가 없습니다. 이 상태에서 내가 이력을 정리하고 force push하면, 원격의 브랜치 끝은 내 로컬 상태가 됩니다. 동료의 커밋 세 개는 어느 브랜치도 가리키지 않는 상태가 되어 목록에서 사라집니다. 동료의 PC에는 아직 남아 있지만, 동료가 그 사실을 모르고 pull하거나 다시 clone하면 그대로 없어집니다.

그래서 두 가지를 씁니다. 첫째, 공유 브랜치에는 force push 금지를 보호 규칙으로 걸어 둡니다. 조심하겠다는 약속보다 플랫폼의 거부가 확실합니다. 둘째, 내 개인 브랜치에서 꼭 이력을 고쳐야 할 때는 --force 대신 --force-with-lease 를 씁니다.

git push --force-with-lease origin feature/my-branch

이 옵션은 "내가 마지막으로 본 원격 상태와 지금 원격 상태가 같을 때만 덮어쓴다"는 조건을 붙입니다. 그동안 누군가 무언가를 올렸다면 push가 거부되므로, 모르고 남의 커밋을 날리는 일을 막아 줍니다.

비밀값을 올렸다면 키 폐기가 먼저인 이유

파일을 지우고 이력까지 깨끗하게 정리하면 해결된 것처럼 보이지만, 그 사이에 값은 이미 여러 곳에 복제돼 있습니다. 다른 사람이 pull한 로컬 리포지터리, CI 실행 로그, 플랫폼의 캐시와 PR 화면, 알림 메일 본문까지 남을 수 있습니다. 이력을 지운다고 이 복제본들이 함께 사라지지는 않습니다.

그래서 순서를 고정합니다.

  1. 노출된 키를 즉시 폐기하고 새로 발급합니다. 이 단계만으로 노출의 피해가 끊깁니다.
  2. 리포지터리에서 파일을 제거하는 커밋을 만들고 .gitignore 에 해당 경로를 추가합니다.
  3. 새 키를 리포지터리가 아닌 환경 변수나 비밀 관리 도구에 넣습니다.
  4. 이력 재작성이 필요한지는 관리자가 판단합니다. 이력을 다시 쓰면 팀 전원이 다시 clone해야 하므로 영향이 큽니다.

팀에서는 이 순서를 사고 대응표에 "알릴 사람"까지 포함해 적어 둡니다. 혼자 조용히 처리하려다 폐기 단계를 건너뛰는 것이 가장 흔한 실수입니다. 이 대응 순서를 팀이 같은 기준으로 공유하는 실습은 1일 과정에서 다룹니다.

충돌 화면에서 조용히 사라지는 변경

충돌은 두 사람이 같은 자리를 서로 다른 의도로 고쳤다는 신호입니다. 에디터가 보여 주는 "현재 변경 수락"이나 "들어오는 변경 수락" 버튼은 편리하지만, 기계적으로 누르면 한쪽 의도가 통째로 버려집니다.

이 유실이 위험한 이유는 아무 오류도 나지 않는다는 점입니다. 문법이 맞고 테스트가 통과하면 그대로 머지되고, 몇 주 뒤에 "내가 고친 문장이 왜 원래대로 돌아가 있지"라는 질문으로 발견됩니다.

그래서 세 가지를 습관으로 둡니다. 충돌 해소는 코드 선택이 아니라 의도 합치기라고 보고 두 변경을 모두 살리는 결과를 직접 만듭니다. 해소한 뒤에는 원래 작성자 양쪽에게 결과를 확인받습니다. 그리고 JSON이나 목록 데이터처럼 구조가 있는 파일은 해소 후 반드시 검사 스크립트를 한 번 돌립니다. 배열 끝에 항목을 동시에 추가하는 충돌은 쉼표 하나가 빠져 파일이 깨지기 쉽습니다.

git status                  # 아직 해소되지 않은 파일 목록 확인
git diff --check            # 충돌 표시가 남아 있는지 확인

충돌 자체를 줄이는 쪽이 더 효과적입니다. 작업 시작 전 pull, 짧게 사는 브랜치, 같은 파일을 만질 때 미리 알리기, 정렬 규칙이 있는 데이터는 끝이 아니라 정해진 위치에 추가하기 정도로 대부분 줄어듭니다.

reflog로 되찾는 절차

reflog 는 내 로컬에서 HEAD가 지나온 위치를 시간순으로 적어 둔 기록입니다. 브랜치에서 떨어져 나간 커밋도 여기에는 남아 있어서, reset으로 치운 커밋을 되찾을 수 있습니다.

git reflog
# a1b2c3d HEAD@{0}: reset: moving to HEAD~1
# e4f5g6h HEAD@{1}: commit: feat: 공지 목록 정렬 추가   ← 되찾고 싶은 지점

되돌아갈 지점을 찾았으면 그 위치에 브랜치를 새로 만듭니다. 현재 브랜치를 바로 옮기는 대신 새 브랜치를 만드는 쪽이 안전합니다. 잘못 짚었을 때 지금 상태를 잃지 않습니다.

git switch -c rescue e4f5g6h

내용을 확인한 뒤 필요한 커밋만 원래 브랜치로 가져오면 됩니다. 두 가지 한계는 알아 둡니다. reflog는 내 로컬 기록이라 다른 PC에서 일어난 일은 없고, 기본 보존 기간이 지나면 정리됩니다. 그리고 앞서 말한 대로 커밋하지 않은 편집은 reflog에도 없습니다. 이것이 "일단 커밋은 자주"라는 조언의 실질적인 이유입니다.

자주 겪는 문제

상황하기 쉬운 선택안전한 선택
push한 커밋을 지우고 싶다reset 후 force pushgit revert 로 새 커밋
커밋을 잘못 묶었다reset --hard 로 전부 지우고 다시reset --soft 로 풀고 나눠 커밋
브랜치가 원격과 어긋난다--force 로 덮어쓰기원격을 받아 합치거나 --force-with-lease
키가 올라갔다파일 삭제 커밋키 폐기·재발급 먼저
충돌이 났다한쪽 수락 버튼두 의도를 합친 뒤 검사 실행
커밋을 날렸다포기하고 다시 작업git reflog 로 지점 찾아 새 브랜치

정리

  • 명령을 고르기 전에 "어디까지 퍼졌는가"를 한 번 확인합니다. 그 답이 명령을 정합니다.
  • push 전이라면 restore·amend·reset --soft, push 후라면 revert 입니다.
  • reset --hard 와 force push는 무엇이 사라지는지 말할 수 있을 때만 실행합니다.
  • 비밀값은 키 폐기가 먼저, 이력 정리는 나중입니다.
  • 이런 판단을 팀 전체가 같은 표로 공유하는 방법은 팀 Git·GitHub 협업 규칙에 있고, Claude Code가 파괴적 명령을 실행하지 못하게 막는 설정은 권한 설정하네스 엔지니어링 예시에서 다룹니다.
  • 사고를 교실에서 먼저 내 보고 수습 절차를 팀 문서로 만들어 가는 실습은 기업 교육 1일 과정에 있습니다.

자주 묻는 질문

Gitrevertresetrestorereflog사고 수습