Published on

GitHub에서 실수로 PR을 승인했을 때 안전하게 되돌리는 방법

Authors

협업과정에서 Git을 사용한다면, Pull Request(PR)를 승인하고 병합(Merge) 하는 과정이 반드시 필요 합니다. 이번 글에서는 feature 브랜치라 하고(develop 과 1depth 차이인 작업브랜치)이를 예시로, develop 브랜치에 PR을 실수로 승인 처리 했을 때 깔끔하고 안전하게 되돌리는 과정을 기록합니다.

먼저, git log --oneline --graph --decorate 명령어를 사용하여 현재 상태를 확인합니다.

git log --oneline --graph --decorate

병합된 PR의 커밋과 develop 브랜치의 상태를 확인한 후, 실수로 병합된 PR의 커밋을 기록하거나 알아둡니다.

1. revert를 사용하여 병합 되돌리기

revertreset과 달리, 병합된 커밋을 삭제하는 것이 아닙니다.

핵심은 새로운 커밋을 생성하고 변경 사항을 원상복구 한다 는 것입니다.

1.1 origin (최신) develop 브랜치를 가져옵니다.

git checkout develop
git pull origin develop

1.2 병합된 커밋을 revert 합니다.

병합 커밋을 되돌리기 위해 -m 1 옵션을 사용하여 revert합니다.

git revert -m 1 (최근 병합 커밋)

git revert 란?

  • git revert는 특정 커밋의 변경 사항을 취소하는 새로운 커밋을 생성하는 명령어입니다.
  • 위에서 말했듯이 과거 상태로 단순히 "되돌리는" 것이 아닙니다. 취소된 변경 사항이 적용된 새로운 커밋이 추가됩니다.

즉!! git revert -m 1 (병합 커밋)을 실행하면, develop 브랜치를 기준으로 병합된 feature 브랜치의 변경 사항을 취소하는 새로운 커밋이 생성됩니다.

-> 기존 상태를 덮어쓰지 않고, 취소된 결과를 유지한 채 히스토리를 남긴다.

1.3 변경 사항을 develop 브랜치에 푸시합니다.

git push origin develop

이렇게 하면 revert 된 커밋과 함께 origin 에 반영 되었을 것 입니다. 이제 origin develop 브랜치는 (이전에 작업해서 반영했을)feature 브랜치가 병합되기 전 상태로 복구되었습니다.

2. feature 브랜치를 다시 PR하기

revert 까지만 수행했다면, develop 브랜치에는 feature 브랜치의 기존 작업 사항이 없는 예전 상태로 돌아 갔을 것입니다. 이 파트는 feature 브랜치를 최신 develop 브랜치에 맞추고, 다시 PR을 보내는 과정을 통해 이전 작업을 복구하는 방법입니다.

2.1 feature 브랜치로 이동해줍니다.

git checkout feature-branch

2.2 최신 develop 반영

이 때 feature 브랜치의 변경 사항을 최신 반영하는데, rebase를 사용합니다. 놓칠 수 있지만 핵심사실은 developrevert된 상태를 feature 브랜치에 반영하는 것입니다.

git pull origin develop
git rebase develop

merge VS rebase

git merge or rebase develop 를 수행할 때 어떤 차이가 있을지 정리했습니다. 저는 가장 큰 차이를 주동/수동으로 커밋이 합쳐지는 것으로 생각합니다. 어떤 것이 더 좋은지는 상황에 따라 다르겠지만, rebase를 사용하면 깔끔한 커밋 히스토리를 유지할 수 있습니다.

mergerebase
의미develop 브랜치의 변경 사항을 feature에 병합feature 브랜치의 커밋을 develop의 최신 상태 위로 다시 적용
히스토리병합 커밋이 생성됨 (Merge commit)커밋이 새로 만들어져 develop 위에서 다시 정렬됨
커밋 히스토리병합 커밋이 추가되므로 (아주약간)복잡해짐깔끔한 직렬 커밋 히스토리 유지
어떤 상황에서 사용되면 좋은지공동 작업 시 변경 사항을 합칠 때feature 브랜치를 최신 상태로 유지할 때

풀어서 정리하면 다음과 같습니다.

  • git merge developdevelop 브랜치의 변경 사항을 feature 브랜치에 새로운 병합 커밋을 만들어 반영합니다.

  • git rebase developfeature 브랜치의 커밋을 최신 develop 브랜치 위에 다시 적용하여 깔끔한 히스토리를 유지합니다.

  • 이 과정들에서 충돌이 발생하면 당연히&반드시 해결하고 진행해야 합니다.

2.3 기존 feature 브랜치의 작업을 다시 적용합니다.

잠깐 rebase와 merge를 알고왔다면, 기존 커밋을 한번 확인할 필요도 있습니다. 만약에 기존 작업이 사라진 것처럼 보이게 될 것 입니다. 이전 작업의 커밋주소를 확인해야하는데, 명령어로는 git reflog를 사용하여 기존 커밋을 확인할 수 있습니다.

git reflog

로그에서 원래 feature 브랜치 커밋을 찾고, 이를 다시 적용합니다. 작업간의 크게 충돌이 날수도 있고 꼬일 수 있기 때문에, 먼저 작성해둔 커밋 순서대로 cherry-pick을 사용하여 적용합니다.

git cherry-pick (작업의 첫 번째 커밋)
git cherry-pick (작업의 마지막 커밋)

git cherry-pick을 사용했나.

  • cherry-pick을 사용하면 feature 브랜치에서 원하는 커밋만 선택해서 적용할 수 있습니다.
  • rebase를 수행하는 과정에서 충돌이 발생할 수 있습니다. 충돌이 많을 것 같다면 직접 필요한 커밋만 cherry-pick으로 선택하는 것이 더 유리합니다.
  • 다시 순서를 정리하면 다음과 같습니다.
    1. 작업의 첫 번째 커밋 → 가장 기본적인 변경 사항이 적용됨
    2. 작업의 마지막 커밋 → 추가된 기능 및 수정 사항이 반영됨

이렇게 하면 코드가 충돌 없이 자연스럽게 적용됩니다.

2.4 강제 푸시하여 변경 사항을 반영합니다.

정상적으로 feature 브랜치에 변경 사항을 적용했다면, 강제 푸시를 통해 변경 사항을 반영합니다.

git push --force origin feature-branch

2.5 GitHub에서 새로운 PR을 생성합니다.

이제 모든 처리는 끝이 났습니다. 해당 원복된 커밋(작업)을 합치고자 한다면 다시 GitHub이나 사용하는 툴에서 feature 브랜치로 새로운 PR을 만들면 됩니다.

3. 회고 및 요약

작업자 간에 협업을 할 때, PR을 승인하고 병합하는 과정은 필수적이고 이런 과정에서 실수가 발생할 수 있습니다. 예전에는 실수로 PR을 승인했을 때 어떻게 해야할지 몰라 당황했던 기억이 있습니다. 이번 주에 작업도중에 실수로 PR을 승인했을 때, 간만에 당황했는데 비슷한 일을 겪고 당황하실 분들을 위해 이 내용을 기록합니다.

바쁜 사람을 위해, 요약하면 다음과 같습니다.

  • PR을 실수로 승인했을 경우 revert를 이용해 안전하게 되돌립니다.(삭제X / 새로운 복구커밋 생성O)
    • 병합된 커밋을 직접 삭제하는 것보다 revert 방식이 안전합니다.
  • git rebase develop을 수행하면 최신 develop 브랜치의 변경 사항을 반영하면서 깔끔한 커밋 히스토리를 유지할 수 있습니다.
  • 필요하면 git cherry-pick을 이용해 기존 커밋을 다시 적용합니다.
  • hongreat 블로그의 글을 봐주셔서 감사합니다!^^
  • 내용에 잘못된 부분이나 의문점이 있으시다면 댓글 부탁 & 환영 합니다~!
  • (하단의 버튼을 누르시면 댓글을 보거나 작성할 수 있습니다.)
Buy Me A Coffee