메인 홈
home
사이트 맵 - 한눈에
home

깃 커밋 꼬였을 때? 당황하지 말고 이 방법들만 기억하세요 ( Git Commit )

프로젝트를 진행하다 보면 얘기치 않게 깃(Git) 히스토리가 꼬이는 상황을 마주하게 됩니다.
잘못된 파일을 커밋하거나, 다른 브랜치에 작업 내용을 올리거나, 심지어는 중요한 커밋을 실수로 날려버리는 아찔한 경험은 개발자라면 누구나 한 번쯤 겪을 수 있습니다.
이런 상황에서 당황하여 섣불리 명령어를 사용하다가는 상황을 더욱 악화시킬 수 있습니다. 다행히도 Git은 거의 모든 실수를 되돌릴 수 있는 강력한 기능들을 제공합니다.
지금부터 로컬 저장소의 가벼운 실수부터 원격 저장소의 복잡한 문제까지, 상황에 맞춰 현명하게 대처할 수 있는 방법들을 단계별로 상세히 알아보겠습니다.

1. 가장 최근 커밋, 가볍게 수정하기 (commit --amend)

가장 흔하게 발생하는 실수는 방금 완료한 커밋에 오타가 있거나 파일을 빠뜨린 경우입니다. 이럴 때는 새로운 커밋을 추가하는 대신, 마지막 커밋을 간단히 수정하는 것이 가장 깔끔합니다. git commit --amend 명령어는 바로 이런 상황을 위해 존재합니다.
1.
커밋 메시지만 수정할 때 방금 작성한 커밋 메시지에 오타가 있거나 내용을 보충하고 싶다면, 아래 명령어를 사용해 간단히 수정할 수 있습니다.
git commit --amend -m "수정된 새로운 커밋 메시지"
Shell
복사
2.
파일을 추가하거나 변경 내용을 덧붙일 때 커밋에 포함했어야 할 파일을 빠뜨렸거나, 일부 수정 사항을 추가하고 싶을 때 사용합니다. 먼저 원하는 파일을 스테이징 영역에 추가한 뒤, -no-edit 옵션을 사용하면 커밋 메시지는 그대로 둔 채 내용만 마지막 커밋에 덧붙일 수 있습니다.
# 빠뜨린 파일을 스테이징 영역에 추가합니다. git add 빠뜨린_파일.js # 기존 커밋 메시지를 유지하면서 마지막 커밋에 파일을 추가합니다. git commit --amend --no-edit
Shell
복사

2. 과거의 특정 상태로 돌아가기 (reset vs revert)

단순한 수정이 아니라 과거의 특정 시점으로 프로젝트 상태를 되돌려야 할 때가 있습니다. 이때는 git resetgit revert라는 두 가지 선택지가 있으며, 둘의 차이를 명확히 이해하고 사용하는 것이 매우 중요합니다.
1.
히스토리를 삭제하며 과거로 돌아가기: git resetreset은 브랜치가 가리키는 위치(HEAD)를 지정한 과거 커밋으로 강제로 이동시키는 강력한 명령어입니다. 즉, 지정한 과거 시점 이후의 모든 커밋 히스토리가 사라질 수 있어 주의가 필요합니다. 주로 원격 저장소에 공유되지 않은 로컬 커밋을 정리할 때 유용하며, 세 가지 옵션이 있습니다.
-soft: 커밋 기록만 취소하고, 변경했던 내용들은 모두 스테이징 영역(git add를 마친 상태)에 그대로 남겨둡니다.
# 가장 최근 커밋 1개를 취소하고, 변경 내용은 스테이징 상태로 유지합니다. git reset --soft HEAD~1
Shell
복사
-mixed (기본 옵션): 커밋 기록과 스테이징 내용까지 취소합니다. 변경했던 내용들은 작업 디렉토리(파일을 수정만 한 상태)에 남아있습니다.
# 가장 최근 커밋 2개를 취소하고, 변경 내용은 작업 디렉토리에 보존합니다. git reset --mixed HEAD~2
Shell
복사
-hard (매우 위험!): 커밋, 스테이징, 작업 디렉토리의 모든 변경 내용을 완전히 삭제하고 과거의 특정 상태로 돌아갑니다. 복구가 어려울 수 있으므로 사용에 각별한 주의가 필요합니다.
# 특정 커밋 해시의 상태로 모든 것을 되돌립니다. 이후의 모든 변경 내용은 영구 삭제됩니다. git reset --hard <되돌아가고_싶은_커밋_해시>
Shell
복사
2.
히스토리를 유지하며 변경 내용만 취소하기: git revertrevertreset과 달리 기존 히스토리를 삭제하지 않습니다. 대신, 특정 커밋에서 발생한 변경 사항을 되돌리는 새로운 커밋을 생성합니다. 이미 다른 팀원과 공유된 원격 저장소의 커밋을 안전하게 되돌려야 할 때 반드시 사용해야 하는 방법입니다.
# 문제가 된 커밋의 변경 사항을 취소하는 새로운 커밋을 생성합니다. git revert <문제가_된_커밋_해시>
Shell
복사
이 방법을 사용하면 "A라는 작업을 추가했다"는 커밋과 "A라는 작업을 다시 제거했다"는 커밋이 모두 히스토리에 남게 되어, 누가 언제 어떤 작업을 되돌렸는지 투명하게 추적할 수 있습니다.

3. 복잡한 히스토리, 마음대로 편집하기 (rebase -i)

여러 개의 커밋을 합치거나, 순서를 바꾸거나, 특정 커밋만 삭제하는 등 히스토리 자체를 정교하게 재구성하고 싶을 때가 있습니다. git rebase -i (대화형 리베이스)는 마치 Git의 타임머신처럼 과거의 커밋 목록을 자유자재로 편집할 수 있게 해줍니다.
1.
대화형 리베이스 시작하기 아래 명령어는 현재 브랜치의 최근 3개 커밋을 대상으로 대화형 리베이스를 시작합니다.
git rebase -i HEAD~3
Shell
복사
2.
커밋 편집하기 명령어를 실행하면 텍스트 편집기가 열리면서 지정한 커밋 목록과 함께 선택할 수 있는 작업들이 나타납니다.
pick (p): 해당 커밋을 그대로 사용합니다.
reword (r): 커밋은 그대로 두되, 커밋 메시지를 수정합니다.
squash (s): 바로 이전 커밋과 하나로 합칩니다. 두 커밋의 메시지를 합쳐 새로운 메시지를 작성할 수 있습니다.
fixup (f): squash와 동일하게 이전 커밋과 합치지만, 이 커밋의 메시지는 버리고 이전 커밋의 메시지를 사용합니다.
drop (d): 해당 커밋을 히스토리에서 완전히 삭제합니다.
이 기능들을 조합하여 지저분했던 커밋 기록을 의미 있는 단위로 깔끔하게 정리할 수 있습니다.

4. 브랜치 관련 실수, 깔끔하게 해결하기

때로는 작업 내용 자체보다 작업한 브랜치가 잘못된 경우가 있습니다. 이런 상황을 해결하는 유용한 명령어 두 가지를 소개합니다.
1.
다른 브랜치의 특정 커밋만 가져오기: cherry-pickfeature/A 브랜치에 작업해야 할 내용을 실수로 main 브랜치에 커밋했다면, cherry-pick을 사용하여 해당 커밋만 feature/A 브랜치로 쏙 가져올 수 있습니다.
# 올바른 브랜치로 이동합니다. git checkout feature/A # main 브랜치에 있던 특정 커밋을 현재 브랜치로 가져옵니다. git cherry-pick <main에_잘못_올린_커밋_해시>
Shell
복사
2.
작업 내용 임시로 저장하기: stash 아직 커밋하기는 애매한 작업 도중에 급하게 다른 브랜치로 이동해서 코드를 확인해야 할 때가 있습니다. 이때 git stash를 사용하면 현재 작업 내용을 임시로 저장하고 작업 디렉토리를 깨끗하게 만들 수 있습니다.
# 1. 현재 변경 내용을 임시 저장합니다. git stash # 2. 다른 브랜치로 이동하여 필요한 작업을 수행합니다. git checkout other-branch # ... 작업 수행 ... # 3. 원래 브랜치로 돌아와 저장했던 내용을 다시 불러옵니다. git checkout original-branch git stash pop
Shell
복사

5. 원격 저장소 강제 수정 (주의 필요!)

reset이나 rebase로 로컬 히스토리를 수정한 후 원격 저장소에 반영하려면 일반적인 push로는 불가능합니다. 로컬과 원격의 히스토리가 달라졌기 때문입니다. 이때 강제로 원격 저장소를 덮어쓰는 명령어를 사용해야 하지만, 이는 팀원들과 함께 사용하는 공유 브랜치에서는 심각한 문제를 일으킬 수 있으므로 사용법을 정확히 알아야 합니다.
1.
원격 저장소 강제 덮어쓰기: push --force 이 명령어는 로컬 저장소의 히스토리를 기준으로 원격 저장소의 내용을 강제로 덮어씁니다. 만약 내가 모르는 사이에 다른 팀원이 원격 브랜치에 새로운 내용을 push 했다면, 그 내용이 사라질 수 있는 매우 위험한 명령어입니다.
# (경고!) 원격 저장소의 main 브랜치를 내 로컬 main 브랜치 상태로 강제 덮어씁니다. git push origin main --force
Shell
복사
2.
더 안전하게 강제 푸시하기: push --force-with-lease-force의 위험성을 보완한 더 안전한 대안입니다. 이 명령어는 push를 시도할 때, 내가 마지막으로 원격 저장소의 상태를 확인한 이후(fetch) 다른 누군가가 새로운 커밋을 올리지 않았는지 검사합니다. 만약 원격 브랜치에 변경 사항이 있다면 push를 거부하여 다른 사람의 작업을 덮어쓰는 위험을 막아줍니다. 개인 브랜치가 아니라면 force 대신 항상 이 명령어를 사용하는 습관을 들이는 것이 좋습니다.
# 원격 저장소에 내가 모르는 변경 사항이 없을 때만 강제 푸시를 실행합니다. git push origin main --force-with-lease
Shell
복사

6. 최후의 보루, 모든 것을 되돌리는 reflog

git reset --hard로 중요한 커밋을 날려버렸거나, rebase 도중 히스토리가 완전히 꼬여버려 어디서부터 잘못됐는지조차 알 수 없을 때가 있습니다. 이때 git reflog는 당신을 구해줄 최후의 보루입니다. 이 명령어는 브랜치, HEAD가 이동했던 모든 기록을 마치 블랙박스처럼 저장하고 있습니다.
1.
모든 이동 기록 확인하기git reflog를 입력하면 commit, reset, rebase, merge 등 내가 했던 모든 작업 기록과 해당 시점의 커밋 해시가 나타납니다.
git reflog
Shell
복사
a1b2c3d HEAD@{0}: reset: moving to a1b2c3d e4f5g6h HEAD@{1}: commit: 새로운 기능 추가 i7j8k9l HEAD@{2}: rebase -i (finish): returning to refs/heads/main ...
Plain Text
복사
2.
잃어버린 커밋으로 복구하기 로그에서 되돌아가고 싶은 상태의 커밋 해시(예: a1b2c3d)를 찾았다면, reset 명령어를 통해 해당 상태로 완벽하게 복구할 수 있습니다.
# reflog에서 찾은 해시로 상태를 완전히 복구합니다. git reset --hard a1b2c3d
Shell
복사

7. 특별 케이스: 외부 서비스 연동 문제 해결 (Vercel 예시)

때로는 Git 자체의 문제라기보다 Vercel과 같은 배포 자동화 서비스와의 연결이 꼬이는 경우도 있습니다. 이럴 때는 연결을 완전히 끊고 새로 설정하는 것이 가장 확실한 해결책이 될 수 있습니다.
1.
Vercel에서 프로젝트 연결 해제하기 Vercel 대시보드에서 해당 프로젝트의 Settings > Git 메뉴로 이동하여 'Disconnect' 버튼을 클릭합니다. 이렇게 하면 Git 저장소와의 연결이 해제되고 자동 배포가 중단됩니다.
2.
로컬 Git 저장소 원격 연결 정리하기 로컬 프로젝트 폴더에서 기존 원격 저장소 연결을 제거합니다.
# 기존 원격 저장소 연결을 제거합니다. git remote remove origin
Shell
복사
3.
Vercel에서 프로젝트 재연결하기 Vercel 대시보드에서 'New Project'를 클릭하고, 다시 연결하려는 Git 저장소를 선택하여 프로젝트를 새로 생성하고 배포 설정을 구성합니다.
Git은 복잡해 보이지만, 그만큼 다양한 상황에 대처할 수 있는 섬세하고 강력한 도구들을 갖추고 있습니다.
핵심은 reset, rebase처럼 히스토리를 변경하는 파괴적인 명령어와 revert처럼 히스토리를 보존하는 비파괴적인 명령어의 차이를 이해하고, 상황에 맞는 올바른 도구를 선택하는 것입니다.
특히 여러 사람과 함께 작업하는 공유 브랜치에서는 히스토리 변경에 매우 신중해야 하며, push --force와 같은 위험한 명령어 사용은 최소화해야 합니다.
문제가 발생했을 때 당황하지 않고 이 글에서 소개한 방법들을 차근차근 적용해본다면, 꼬여버린 Git 히스토리를 다시 깔끔하게 정리하고 안정적으로 프로젝트를 관리할 수 있을 것입니다.
이 글이 깃 문제 해결에 도움이 되셨다면, 동료에게 공유해보는 것은 어떨까요? 혹은 여러분이 겪었던 다른 깃 문제 상황이 있다면 댓글로 공유해주세요.