전제: reflog가 마지막 보루다
Git은 커밋을 곧바로 지우지 않는다. git reflog는 HEAD가 거쳐간 모든 위치를 최소 30일 보관한다. 대부분의 "잃어버렸다" 상황은 reflog로 복구된다.
1) 커밋하기 전 파일을 복구하고 싶다
git restore path/to/file # 워킹 트리 복구
git restore --staged path # 스테이징 해제
2) 직전 커밋 메시지만 수정
git commit --amend -m "새 메시지"
이미 push 했다면 강제 푸시 필요. 공유 브랜치면 새 커밋으로 정정하는 게 안전.
3) 직전 커밋에 파일 추가 빠뜨림
git add forgotten.txt
git commit --amend --no-edit
4) 잘못된 reset --hard 복구
git reflog
# 예: abcdef1 HEAD@{3}: commit: 내가 원하던 상태
git reset --hard abcdef1
5) rebase 충돌 중단
git rebase --abort # 처음부터 되돌림
git rebase --continue # 충돌 해결 후 이어가기
git rebase --skip # 현재 커밋 폐기하고 계속
6) push 했는데 되돌리고 싶다 (공유 브랜치)
git revert <commit> # 역방향 커밋으로 안전 되돌리기
# 복수 커밋
git revert --no-commit HEAD~3..HEAD
git commit -m "revert last 3"
public 브랜치에 force-push 금지. 팀 워크플로우가 깨진다.
7) 커밋 기록 꼬임 정리 (interactive rebase)
git rebase -i HEAD~5
# pick → squash: 합치기, reword: 메시지 수정, drop: 폐기
8) 충돌난 파일을 한쪽으로 강제 선택
git checkout --ours path # 현재 브랜치 쪽
git checkout --theirs path # 병합 대상 쪽
git add path && git commit
9) 커밋을 다른 브랜치로 옮기기 (cherry-pick)
git switch target-branch
git cherry-pick abcdef1
# 연속 커밋
git cherry-pick A^..C
10) 삭제된 브랜치 복구
git reflog | grep 'checkout.*branch'
# 마지막 HEAD 위치 확인 후
git branch recovered abcdef1
보너스: 스테이징 부분만 커밋
git add -p # hunk 단위 선택
git commit -m "logical change only"
예방 원칙
- 리스크 작업 전 브랜치 백업:
git branch backup/feature - 공유 브랜치에는
--force대신--force-with-lease - merge vs rebase는 팀 규칙으로 합의
- pre-commit 훅으로 실수 예방 (secrets 스캔, 린트)
자주 묻는 질문
reflog도 못 찾으면?
dangling object를 git fsck --lost-found로 탐색. 단, gc가 돌았으면 복구 불가하므로 30일 이내에 시도.
force-push가 필요한 정당한 경우?
본인 단독 작업 브랜치에서 rebase 정리 후 push. 공유 브랜치에서는 --force-with-lease로 안전장치 추가.
댓글 0