기능 구현 후 README를 작성했는데, 중간에 실수로 revert
를 사용하여 기능 구현을 다 롤백했다. 이를 인지하지 못하고 README를 작성하여 커밋하였다. (기능 구현 - 롤백(실수) - README작성)
이에 중간의 롤백 커밋만 없애고 기능구현과 README 커밋만 남기고 싶은 상황이다.
수정 전
C - README.md 수정
...
B - revert: A에서 추가된 코드 제거 (문제상황)
A - feat: 로그인/로그아웃/회원가입 구현
수정 후
D(C랑 같은 내용) - cherry-pick: README.md 최종 수정
└─ A - feat: 로그인/로그아웃/회원가입 구현
1. cherry-pick을 원하는 커밋(C)의 해시를 복사한다.
2. 기능구현(A)를 기준으로 reset한다.
git reset --hard A
3. E를 cherry-pick으로 가져온다.
만약 reset을 해버려서 로그에서 커밋이 안 보이는 상황이더라도, reflog에서 이를 확인할 수 있다. (이러한 문제를 예방하기 위해 reset 전에는 항상 git log 또는 git reflog로 커밋 해시를 복사해두는 습관을 들이는 게 좋다고 한다.)
# 최근 브랜치 이동 내역 확인 (삭제된 커밋도 포함) git reflog git cherry-pick E
4. 충돌이 발생했다면 충돌하는 파일을 수정한 뒤 add하고 cherry-pick을 마무리한다.
git add README.md
git cherry-pick --continue
중단) 만약 cherry-pick을 중간에 취소하고 싶다면 아래의 명령어를 사용하면 된다.
git cherry-pick --abort
결과
우선 앞으로는 reset
과 revert
를 매우 신중하게 사용해야겠다. revert는
'커밋 삭제'가 아니라 '반대 커밋 추가'에 더 가깝다. (커밋 기록만 삭제되는 것이 아니라, 변경사항까지 다 롤백된다)
구분 | rebase | revert | reset |
---|---|---|---|
목적 | 히스토리 정리 (순서/병합/삭제 등) | 특정 커밋의 효과를 취소 | 커밋 자체를 과거 시점으로 되돌림 |
작동 방식 | 커밋을 재작성하고 새로 push (force 가능성 있음) | 되돌리는 새 커밋을 추가 | 커밋 포인터를 이전 커밋으로 이동 (옵션에 따라 워킹 디렉토리 영향) |
사용 상황 | 커밋 메시지 정리, squash, 충돌 해결 | 실수한 커밋 되돌릴 때, 협업 중 오류 수정 | 최근 커밋 자체를 없애고 싶을 때 (혼자 작업 시 주로 사용) |
히스토리 안전성 | ❌ 히스토리 바뀜 → force push 필요 | ✅ 히스토리 유지 안전 | ❌ 위험도 높음 (강제 push 필요, 기록 자체 삭제 가능) |
복구 가능성 | ✅ 백업 브랜치 있으면 가능 | ✅ 언제든 복구 가능 (되돌린 커밋은 남음) | ❌ 되돌린 커밋은 완전히 사라짐 (--hard 사용 시) |
중간 커밋 제어 | ✅ 가능 (순서 수정, squash 등 자유롭게) | 🔶 간접 가능 (여러 개 revert 가능하지만 순서 못 바꿈) | 🔶 불가능 (단순 이전 시점으로 이동) |
협업 상황 적합성 | 🔶 조심해야 함 (force push는 팀원과 충돌 가능) | ✅ 안전하게 공유 가능 | ❌ 협업 중 절대 금지 (reset 후 force push는 위험함) |