회사에서 다른 분이 작업했었던 브랜치가 master 에 병합이 되었는데 적용하지 말아야 하는 경우가 생겨서 이미 다른 사람들까지 병합이 된 상황에서 되돌려야 하는 경우가 생겼다.

$ git log --oneline --graph
*   f82c9d2 (HEAD -> master, tag: v1.16.7o, origin/master, origin/HEAD) Merge branch 'hotfix/EMTT-350' into 'master'
|\  
| * cf2113f (origin/hotfix/EMTT-350, hotfix/EMTT-350) feat: cache key 확인 후 없으면 api 호출하도록 수정
| * adb8f11 refact: 인자 수정
| * e1653bd refact: isset 은 null 확인까지 하므로 키 있는지만 확인하도록 수정
| * eb7cf72 feat: JSON 문자열 파싱 함수 수정
|/  
*   f030a02 Merge branch 'feature/TOP-14' into 'master'
|\  
| * bc363dd 주석 수정
| * 48b82b3 로그아웃 로그 오타 수정
| * d907051 로그인/아웃 로그 추가.
| * 081d7f0 sub account로 로그인 가능 하도록 수정
* |   b56d294 (tag: v1.16.4) Merge branch 'hotfix/HH2023-109' into 'master'
|\ \  
| |/  
|/|   
| * f26db3e intmon 상수 주석 추가.
| * cf82a6c org 한글 도메인 길이 체크 오류 수정.
|/

말하자면 위의 그래프에서 bc363dd 부터 081d7f0 까지 병합된 파일을 다시 되돌려서 적용이 되지 않도록 해야 했다. 커밋 이력과 함께 봤을 때 feature/TOP-14 브랜치에서 작업한 내용들만 되돌려야 했다.

 

위 문제를 해결하기 위해서는 해당 브랜치에서 작업한 파일들 기준으로 되돌리기를 진행해야 한다.

두 가지 방법이 있는데 하나는 커밋 하나하나를 여러 개를 한꺼번에 되돌리는 방법이고, 다른 하나는 브랜치 병합된 시점 기준으로 되돌리는 것이다.

 

첫 번째 방법은 아래처럼 하면 쉽게 해결할 수 있다. 근데 뭔가 빼먹었을 것 같은 찝찝함이 있을 것도 같다.

$ git revert bc363dd 48b82b3 d907051 081d7f0

 

두 번째 방법은 브랜치 병합 시점의 커밋 기준으로 해결하는 방법이다.

revert 는 특정 시점까지의 커밋 이력을 전부 되돌리는 것이 아니라 해당 시점에서의 커밋 이력을 되돌리는 것이기 때문에 b56d294 가 아니라 f030a02 를 보아야 한다.

그래서 단순히 해당 커밋을 기준으로 revert 를 하려고 하면 아래처럼 오류가 난다.

$ git revert f030a02
error: commit f030a02 is a merge but no -m option was given.
fatal: revert failed

이유는 트리를 보면 알 수 있는데 브랜치 2개가 하나로 합쳐지므로 어떤 브랜치를 기준으로 커밋 이력을 파악해야 하는지 알 수가 없기 때문이다.

 

여기서 해당 커밋을 상세히 보면 아래와 같은 정보들이 나타난다.

$ git cat-file -p f030a02
tree e80e557479b5af48245845ebcc76516bdd4cb70d
parent b56d294cc054b14cf43ac4d5f3b44b85805586e3
parent bc363ddd9f0bca685d95e783b4cc7da6727ba804
author {SOMEONE} <{SOMEEMAIL}> 1693989716 +0900
committer {SOMEONE} <{SOMEEMAIL}> 1693989716 +0900

Merge branch 'feature/TOP-14' into 'master'

기본 로그인 동작 로직 수정

See merge request {SOMEGIT}!113

부모가 두 개가 있다.

첫 번째 부모는 b56d294 이고, 두 번째 부모는 bc363dd 이다. 위 그래프에서 보면 알 수 있듯이 왼쪽부터 차례대로 보면 된다.

해당 시점의 커밋에서 변경된 파일들은 b56d294 커밋과 f030a02 커밋을 비교하면 그 차이를 알 수 있으므로 첫 번째 부모를 가지고 revert 를 실행해야 한다.

 

아래와 같이 -m 또는 --mainline 옵션을 이용하여 revert 를 해주면 된다. 숫자는 방금 위에서 말했던 부모들의 순서다(첫 번째 부모를 가지고 실행해야 하므로 1).

$ git revert -m 1 f030a02                                                                                                                                        ✔  10:21:16  
[revert aa6325e] Revert "Merge branch 'feature/TOP-14' into 'master'"
 7 files changed, 137 insertions(+), 355 deletions(-)
 ...(변경된 파일들)

 

revert 명령어를 실행할 때는 브랜치 관리를 위해 브랜치를 따로 만든 다음에 실행하도록 하자.