Git 작업 내용은 유지하면서 커밋(Commit)만 취소하기

Git을 통해 버전관리를 하는 프로젝트에서 커밋(Commit) 완료 후 작업 오류를 발견했을 때 작업 내용들은 그대로 유지하면서 커밋 이력만 취소하는 방법을 정리했다.

커밋 이전 상태로 돌려야 하는 상황은 생각보다 자주 있다

구글 플레이 콘솔에 업로드된 앱의 버전 코드 정보
구글 플레이 콘솔에 업로드된 앱의 버전 코드 정보

개발 중이던 Trindex 프로젝트 0.37.2 업데이트 버전에 대해 커밋을 마쳤을 당시 출시 업로드를 하기 직전 버전 코드를 하나 건너뛴 것을 발견하게 된 적이 있었다. 구글 플레이 콘솔에 마지막 출시된 버전 코드는 4였지만 업로드하려는 빌드의 버전 코드는 6이었던 것. 버전 코드 중복이나 숫자가 줄어든 것이 아니어서 크게 문제 될 것을 없어 보였지만 그래도 깔끔하게 수정해 주기로 했다.

다시 말하자면 최종 커밋 직전의 커밋으로부터 변경된 내용은 유지한 채 최종 커밋 이력만 취소하고 오류를 수정해야 하는 상황이었다. 이러한 상황은 개발 과정에서 생각보다 자주 발생하므로 당시의 문제 해결 과정을 예시로 그 방법을 정리해 두기로 했다.

원격 저장소로 push 하여 보험을 들자

커밋 취소 전 원격 저장소에 push
커밋 취소 전 원격 저장소에 push

커밋 취소 커맨드를 입력하기 전 혹시 모를 사고에 대비하여 현 상태를 원격 저장소에 push 해 주었다. 가끔 사용하는 커맨드는 늘 헷갈리기 때문에 커맨드를 잘못 선택하는 불상사에 의해 작업 내용마저 모조리 날려버리는 상황을 모면하기 위해서였다. 그래서 이 글도 작성해 두는 것이지만 말이다.

작업 내용은 유지하면서 커밋(Commit)만 취소하기

터미널에서 커밋 로그 확인
터미널에서 커밋 로그 확인

커밋을 취소하기 위해서는 커밋 아이디가 필요하다. [git log]를 입력하여 취소할 커밋의 직전 커밋 아이디를 확인해 주고,

작업 내용은 놔두고 커밋만 취소하는 커맨드
작업 내용은 놔두고 커밋만 취소하는 커맨드

위와 같이 [git reset --soft ######]를 입력하여 작업한 내용은 유지한 상태로 지정한 커밋 아이디 이후의 커밋을 취소했다. 여기서 ######은 커밋 아이디에 해당하는 해시값 앞 6자리를 의미한다.

커맨드에서 핵심은 --soft 옵션이다. soft 대신 hard를 사용하면 기껏 작업해 둔 내용까지 모조리 원상 복구되므로 주의해야 한다.

로그를 통해 수행 결과 확인
로그를 통해 수행 결과 확인

다시 로그를 확인해 커밋이 잘 취소된 것을 확인했다.

작업 내용이 살아있음을 확인
작업 내용이 살아있음을 확인

[git status] 커맨드를 통해 작업했던 내용도 그대로 남아 있는 것을 확인할 수 있었다. 이제 발견했던 오류를 수정하고 다시 커밋해 주면 된다.

들어놓은 보험을 해약하고 마무리

오류 수정 후 다시 커밋을 진행한 결과
오류 수정 후 다시 커밋을 진행한 결과

build.gradle 파일에서 버전 코드를 5로 수정하고, [Sync]를 진행한 뒤 다시 터미널로 돌아와 [git add .] 커맨드를 입력하여 커밋을 마쳤다.

원격 저장소 push 시 오류 발생
원격 저장소 push 시 오류 발생

이제 앞서 사고 방지 차원에서 미리 원격 저장소에 push를 해 놓은 보험을 해약해야 한다. 그런데 늘 하던 대로 [git push origin master]를 입력하니 위와 같이 오류가 발생했다. 서로 다른 내용 때문에 충돌이 일어난 것이다. 이럴 때는...

원격 저장소에 강제 push 하는 것으로 해결
원격 저장소에 강제 push 하는 것으로 해결

[git push -u --force origin master]를 입력하여 강제로 덮어씌우기를 해버리면 된다.