본문 바로가기
개발자/실무 개발 현장

Git 실수로 코드 날린 날 - 복구기

by 나무011 2026. 8. 23.
개발자 현직자 솔직 경험담

Git 실수로 코드 날린 날
— 복구기

git reset --hard 한 방에 3일치 작업이 사라진 그 날의 기록

Frontend Developer 2026년 6월 약 14분 읽기

그날 무슨 일이 있었나

금요일 오후 4시였다. 배포를 앞두고 브랜치 정리를 하고 있었다. main에서 작업 브랜치를 최신으로 맞추려고 했다. 명령어를 입력했다.

 
 
 
Terminal — 사건 발생 재현

git checkout main

Switched to branch 'main'

git pull origin main

Already up to date.

git checkout feat/payment-refactor

Switched to branch 'feat/payment-refactor'

# 여기서 실수 — rebase 하려다 reset --hard를 쳤다

git reset --hard origin/main

 

HEAD is now at a3f82c1 fix: 결제 모듈 에러 처리 수정

 

# 0.5초 침묵

# 그리고

!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

3일치 작업이 사라졌다

feat/payment-refactor 브랜치 전체가 main으로 덮어씌워졌다

커밋 안 된 변경사항 포함해서 전부

!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

3일 날아간 작업 기간
0.5초 실수에 걸린 시간
2시간 복구에 걸린 시간
95% 복구 성공률
Git 실수로 코드 날린 날
Git 실수로 코드 날린 날

처음 30분 — 패닉 상태

📍 사건 발생 직후 — 금요일 오후 4시 3분

화면을 보고 10초 동안 아무것도 못 했다. "내가 지금 뭘 한 거지." 손이 떨렸다. Ctrl+Z를 눌렀다. Git 명령은 되돌아가지 않았다. 당연히. 터미널을 닫았다가 다시 열었다. 브랜치는 그대로 main과 같은 상태였다.

팀장한테 말해야 하나. 배포가 내일인데. 3일 동안 만든 결제 리팩토링이 다 사라졌다. 눈앞이 하얘졌다. 5분 동안 아무것도 못 하고 앉아 있었다.

😰
패닉 상태에서 한 실수
패닉하면 실수가 실수 위에 쌓인다

당황해서 뭔가를 해야 한다는 생각에 명령어를 막 쳤다. git checkout으로 다른 브랜치를 갔다 왔다. git stash를 해봤다. git status를 스무 번 봤다. 이 과정에서 상황이 더 꼬일 뻔했다.

나중에 알게 됐다. Git 실수를 당했을 때 가장 먼저 해야 할 일은 아무것도 안 하는 것이다. 추가 명령어를 치면 복구 가능성이 줄어든다. 일단 멈추고 상황을 파악하는 게 먼저였다. 그때는 그 사실을 몰랐다.

🔴 Git 실수 직후 절대 하지 말아야 할 것

패닉해서 git push, git reset을 추가로 치는 것. 특히 git push --force는 원격 저장소도 덮어씌울 수 있다. 실수 직후에는 git status와 git log만 보고, 추가 변경 없이 상황을 파악하는 것이 최우선이다.

복구 과정 — 단계별 실제 기록

Step 1 — 멈추고 파악하기
일단 아무것도 안 한다. 상황을 이해한다.

15분 패닉 후 겨우 정신을 차렸다. 구글에 "git reset --hard 취소"를 검색했다. 가장 많이 나온 단어가 git reflog였다. reflog가 뭔지 알고는 있었는데 써본 적이 없었다. 일단 쳐봤다.

Step 2 — git reflog 확인
모든 Git 작업의 기록이 남아 있었다.

git reflog는 HEAD의 이동 기록을 전부 보여준다. reset --hard를 해도 이 기록은 남는다. 화면에 내가 했던 작업들이 나왔다. reset 하기 전의 커밋 해시가 보였다.

 
 
 
git reflog — 구원의 명령어

git reflog

 

a3f82c1 HEAD@{0}: reset: moving to origin/main ← 이게 실수

7e9d3b2 HEAD@{1}: commit: feat: 카드 결제 재시도 로직 추가 ← 이게 3일 전

4c1a8f5 HEAD@{2}: commit: feat: 결제 실패 에러 메시지 분기

b2e7d1c HEAD@{3}: commit: refactor: PaymentService 클래스 분리

8f3a9b4 HEAD@{4}: commit: chore: 타입 정의 추가

1d5c2e8 HEAD@{5}: commit: feat: 결제 모듈 초기 구조 ← 시작점

a3f82c1 HEAD@{6}: checkout: moving from main to feat/payment-refactor

 

# HEAD@{1}이 reset 직전의 상태다

# 해시 7e9d3b2으로 복구할 수 있다!

Step 3 — 커밋된 작업 복구
git reset --hard [해시]로 reset 이전 상태로 되돌린다

reflog에서 reset 직전 커밋 해시를 찾았다. 7e9d3b2이었다. 그 해시로 HEAD를 돌렸다. 파일들이 돌아왔다. 손이 떨렸다. 커밋된 내용 전부가 복구됐다. 3개의 커밋이 살아났다.

 
 
 
커밋된 작업 복구 — git reset

# reflog에서 찾은 해시로 되돌리기

git reset --hard 7e9d3b2

 

HEAD is now at 7e9d3b2 feat: 카드 결제 재시도 로직 추가

 

# 확인

git log --oneline -5

7e9d3b2 feat: 카드 결제 재시도 로직 추가

4c1a8f5 feat: 결제 실패 에러 메시지 분기

b2e7d1c refactor: PaymentService 클래스 분리

8f3a9b4 chore: 타입 정의 추가

1d5c2e8 feat: 결제 모듈 초기 구조

 

✓ 커밋된 작업 전부 복구 완료!

⚠️
아직 문제가 남았다
커밋 안 된 변경사항은 어디서 찾나

커밋된 것은 살아났다. 그런데 마지막 커밋 이후에 작업 중이던 것들이 있었다. 커밋을 안 한 상태였다. git stash도 안 했다. 그날 오후에 3~4시간 작업한 내용이었다.

이건 git reflog만으로는 못 찾는다. 커밋이 안 됐으니 커밋 해시가 없다. 여기서 다른 방법이 필요했다.

Step 4 — 커밋 안 된 작업 복구 시도
git fsck와 IDE 로컬 히스토리를 찾아본다

git fsck --lost-found 명령으로 dangling blob(고아 객체)을 검색했다. 운 좋게도 일부 객체가 남아 있었다. 또한 VSCode의 로컬 히스토리 기능이 파일별 변경 이력을 자동으로 저장하고 있었다. 이 두 가지를 조합해서 70% 정도를 복구했다.

 
 
 
커밋 안 된 작업 복구 시도

# 방법 1: git fsck로 고아 객체 찾기

git fsck --lost-found

Checking object directories: 100% done.

dangling blob 9f8c2a1e3b7d5f4e2c8b6a3d9f7e1c5b

dangling blob 3d7f9a2c8e1b5d6f4a9c2e8b7d3f1e5a

 

# 고아 객체 내용 보기

git cat-file -p 9f8c2a1e

// PaymentService.ts 내용이 나왔다!

 

# .git/lost-found/other/ 에 파일로 저장됨

ls .git/lost-found/other/

9f8c2a1e3b7d5f4e2c8b6a3d9f7e1c5b

3d7f9a2c8e1b5d6f4a9c2e8b7d3f1e5a

 

✓ 일부 작업 내용 발견! 복사해서 파일로 복원

 

# 방법 2: VSCode 로컬 히스토리

파일 우클릭 → 타임라인 → Local History 확인

→ 30분 단위 자동 저장 기록 발견!

→ 추가 30% 복구 완료

Step 5 — 최종 복구 완료
커밋 95%, 미커밋 70% 복구 — 2시간 후

2시간 작업 끝에 대부분을 살렸다. 커밋된 것은 100% 복구. 마지막 오후 작업분은 70% 정도. 나머지 30%는 다시 짰다. 배포일을 하루 미뤘다. 팀장에게 솔직하게 말하고 이해를 구했다.

git reset --hard를 치는 데 0.5초 걸렸다. 복구하는 데 2시간 걸렸다. 이 3.5초의 교훈이 이후 Git을 대하는 방식을 완전히 바꿨다.

Git 복구 치트시트 — 상황별 정리

🆘 Git 실수 복구 치트시트 — 상황별 명령어
## 상황 1: git reset --hard로 날린 경우 (커밋된 것) git reflog # 이동 기록 확인 git reset --hard HEAD@{N} # N번 전 상태로 복구 # 또는 해시로 직접 git reset --hard [복구할-해시]
## 상황 2: 커밋 안 된 변경사항이 날아간 경우 git fsck --lost-found # 고아 객체 찾기 git cat-file -p [해시] # 내용 확인 # .git/lost-found/other/ 에서 파일 찾기 # VSCode: 파일 → 타임라인 → Local History
## 상황 3: git branch -D로 브랜치 삭제한 경우 git reflog # 브랜치 최후 커밋 해시 찾기 git checkout -b [브랜치명] [해시] # 브랜치 재생성
## 상황 4: git commit --amend로 커밋 덮어쓴 경우 git reflog # amend 전 커밋 해시 찾기 git checkout [해시] -- . # 그 시점 파일만 복구
## 상황 5: git push --force로 원격 덮어쓴 경우 (최악) # 동료 로컬에 남은 브랜치가 있으면 git push origin [브랜치] # 동료 로컬에서 다시 올리기 # GitHub에서 Force Push 전 백업이 있으면 복원 가능
## 황금 원칙: git reflog는 90일간 기록을 보관한다 ## 대부분의 실수는 reflog로 복구 가능하다

이 사건 이후 바꾼 것들

🔀
위험한 명령 전 브랜치 확인 습관

reset, rebase, force push 전에 반드시 git status와 git branch로 현재 위치를 확인한다. 0.5초짜리 확인이 2시간을 아꼈을 것이다.

💾
자주 커밋하는 습관

WIP 커밋이라도 남긴다. "작업 중" 커밋이 나중에 구원이 된다. 커밋이 많으면 reflog에 더 많은 선택지가 생긴다.

🏷️
중요 작업 전 태그 생성

큰 리팩토링 전에 git tag backup-[날짜]를 만든다. 태그는 reflog와 달리 명시적으로 남아서 찾기 쉽다.

📚
VSCode Local History 켜두기

설정에서 files.localHistory.enabled를 true로. 커밋 안 해도 파일 변경을 자동 저장한다. 이번에 이게 30% 추가 복구를 도왔다.

🛡️ 위험한 Git 명령 전 안전장치 — 실제 사용 중인 alias
# ~/.gitconfig 또는 ~/.zshrc에 추가
# reset --hard 전 확인 강제 alias grh='echo "현재 브랜치: $(git branch --show-current)" && echo "진짜 reset --hard 할까요? (y/n)" && read -r yn && [ "$yn" = "y" ] && git reset --hard'
# 중요 시점 백업 태그 한 방에 alias gbackup='git tag backup-$(date +%Y%m%d-%H%M)'
# reflog 보기 좋게 alias grl='git reflog --format="%C(auto)%h %'\(20)%gd %s"'
# stash 자동 메시지와 함께 alias gs='git stash push -m "$(date +%Y%m%d-%H%M): wip"'
# 이 alias들이 생기고 나서 git 사고가 없어졌다

팀장에게 말하던 순간

💬
사건 해결 후
솔직하게 말했더니 생각보다 괜찮았다

2시간 복구 후 팀장한테 Slack 메시지를 보냈다. "git reset --hard 실수로 작업을 날렸고, 복구 작업 중입니다. 배포를 하루 미뤄야 할 것 같아요." 손이 떨렸다. 바로 답이 왔다. "고생했다. 나도 비슷한 경험 있어요. 내일 배포로 조정할게요."

말하기 전에 두려웠다. 혼날 것 같았다. 하지만 솔직하게 말하고 상황을 설명하니까 오히려 팀장이 비슷한 경험을 공유해줬다. 누구나 Git 실수를 한다는 걸 그때 알았다. 실수를 숨기는 것보다 빠르게 공유하고 해결하는 게 팀에 훨씬 낫다는 것도.

✅ Git 실수에서 살아남는 두 가지 원칙

첫째, 당황하면 아무것도 하지 않는다. git reflog를 열고 상황을 파악하는 것이 먼저다. 추가 명령어가 상황을 악화시킬 수 있다. 둘째, git reflog는 거의 모든 것을 복구할 수 있다. reset --hard, 브랜치 삭제, 잘못된 rebase — 커밋이 된 것은 reflog가 있는 한 살아난다. 90일 안에는.


그날 이후 git을 대하는 방식이 달라졌다. 두려움이 생긴 게 아니라 존중이 생겼다. reset --hard는 진짜 강력한 명령이다. 그 강력함을 이해하고 쓰는 것과 모르고 쓰는 것은 다르다. 이제는 위험한 명령 전에 항상 한 번 더 확인한다. 그 습관이 그날 사건이 남긴 가장 큰 유산이다.

그리고 git reflog는 반드시 외워두는 것을 권한다. 언젠가 반드시 필요한 날이 온다.

💬 Git 실수 경험담이 있으신가요?

reset --hard, force push, 브랜치 삭제 — 어떤 실수를 어떻게 복구했는지 댓글로 나눠주세요. 비슷한 상황에 처한 분들에게 가장 현실적인 도움이 될 것 같습니다.


소개 및 문의 · 개인정보처리방침 · 면책조항

© 2026 나무핀