Git

잘못한 Commit이 Github까지 올라갔을때?! - reset, force push... revert?

chattymin 2024. 10. 20. 16:53
728x90

내가 스토어에 올려둔 프로덕트를 사용하던 친구에게 제보가 들어왔다.

오류 상황 / 정상 상황

우측 gif처럼 필터를 클릭하면 리스트값이 변경되고 마커가 사라져야 하는데 좌측 gif에서는 해당 기능이 동작하고 있지 않다.

 

놀랍게도.. 좌측 gif가 1.0.2로 스토어에 올라간 버전이다.

 

 

문제는 1.0.1에서 1.0.2로 올라가며 내 실수로 코드가 누락된 것.

hotfix로 진행했다보니 PR이 없이 진행되었고, 그로인해 내 실수가 그대로 출시되었다.

 

 

물론 해결자체는 간단했기에 빠르게 수정 후 1.0.3으로 업데이트 진행하였고 심사도 무사히 통과해 릴리즈 되었다.

 

 


 

이제 여기서 문제가 발생한다.

 

hotfix브랜치 위로 main브랜치를 리베이스 하는 것은 문제가 없었다.

하지만 main위로 develop을 리베이스 하는 과정에서 잦은 hotfix로 인해 충돌이 정말 많이 발생하고 있었고, 리베이스 버튼을 누르자마자 100개가 넘는 confilct가 나를 반겼다.

 

그냥 merge로 안전하게 develop에 main의 변경사항을 넣자 

라는 생각을 해버렸고, git kraken에서 rebase버튼을 눌렀다는 것을 까먹은채 develop에 머지해버렸다.

 

그러고 메인을 봤는데...

?!?!?!?!?!?!?

왜 develop이 main에 머지된거지??!?!?!?

 

도저히 이해할 수 없는 상황에 main과 develop브랜치를 살펴보니 main에 있던건 develop으로 정상적으로 머지는 되었다.

근데 develop도 main으로 머지된것...

 

지금 develop은 2차 스프린트를 진행하며 아직 main으로 머지되면 안되는 코드들이 잔뜩이었다.

 

그래서... main을 원래대로 되돌려야 했다.

 

 

 

어떻게 해야하지???

사실 예전에 이것과 비슷한 경우를 만나 해결한 경험이 있기는 하다.

 

그때는 github에 무지하기도 했고, github에 대한 무서움이 가득 있어서 굉장히 보수적인 방법으로 진행했었다.

그 당시 실행했던 말도안되는 방법...

 

 

2연속 revert후 머지머지머지...

지금 생각하면 정말 별로인 방법이지만, 그때 당시에는 어떻게든 해결해야한다는 생각에 사용했었다.

처참했던 기억...

 

문제상황

친한 동생이 A브랜치에서 제출한 과제를 어떤 친구가 실수로 Merge를 해버렸고, 이를 복구하고자 Revert를 해버렸다.

 

이때 develop브랜치에는 A브랜치가 이미 머지된 기록이 있기 때문에 다시 머지를 하려고 하면 머지가 되지 않는다.

동생이 도와달라는 연락을 했고, 이 상황을 해결하고자 생각했던 것이 revert를 더 해버리자! 였다.

 

A -> develop 머지
develop을 revert

여기까지가 현재 진행된 상태이다.

 

이때 리버트 했다는 것을 리버트 해버린다면, 즉 머지 취소의 취소 를 한다면 머지한 적이 없어진다 라고 생각했다.

 

그래서 Main을 revert한 PR을 revert해버리면 되지 않을까? 라는생각에 아래와 같이 진행했다.

A -> develop머지
develop을 revert (revert1-A 브랜치가 생성됨)
revert1-A을 revert (revert2-revert1-A 브랜치가 생성됨) 
revert2-revert1-A -> revert1-A 머지
revert1-A -> A 머지
A -> develop 머지

 

결과적으로는 원하는대로 됐다.

 

develop에는 A의 코드가 들어간 적이 없게 되었고, A에서 develop으로 작성한 코드를 머지하려고 하면 정상적으로 되었다.

 

 

하지만 이 방법은 너무나 많은 merge가 필요하다.

그렇기에 더 좋은 방법이 있지 않을까 생각했고, reset이라는 것을 찾아 사용하게 되었다.

 

 

 

reset을 활용해서 돌려보자

우선 git log를 사용해서 지금까지 내가 작업한 기록을 확인한다.

여기서 내가 돌려야 하는 기록이 commit 6104b392e18fb46bb90478897db51051e63486fe 이다.

 

그렇다면 내가 기록해두어야 하는 정보는 해당 커밋의 바로 이전 commit 해시값이다.

즉, commit db3a9253f5e2d22d182d1b5a0026ad02782fef44 이 나에게 필요한 값.

 

이를 확인했다면 log 확인을 종료하면 된다.

여기서 깨알 정보

git log를 나가기 위해서는 q를 적으면 된다. 몰라서 한참 찾았거든...

 

 

 

그 후 우리가 사용해야 하는 것은 reset 기능이다.

 

이 때, reset에는 3가지 옵션이 존재한다.

 

--hard

  • hard 옵션을 사용하면 돌아간 커밋 이후의 변경 이력은 모두 삭제한다.
  • 커밋 반영 내용은 모두 사라지고 코드도 날아간다.

--mixed

  • 변경 이력은 모두 삭제하지만 변경 내용은 남아있다.
  • 이력은 날아가나 unStage 상태로 코드는 남아있다. 코드를 반영하려면 add 명령어로 stage에 반영하고 commit 하면 된다.

--soft

  • 변경 이력은 모두 삭제하지만 변경 내용은 남아있다. 그러나 stage 되어있다.
  • 즉, add명령어 필요없이 바로 commit 진행 가능하다

 

 

이 중 나에게 필요한 것은 hard 였다. 추후 develop에서 main으로 머지할 예정이었기 때문에 굳이 코드가 남아있지 않아도 된다.

git reset --hard db3a9253f5e2d22d182d1b5a0026ad02782fef44

이렇게 명령어를 작성한다면 해당 커밋의 이전으로 돌아올 수 있다.

 

 

이대로 마무리한다면 본인의 로컬만 해당 커밋으로 돌아왔을 것이다.

하지만 나는 사고를 거하게 쳐뒀기 때문에 github에도 반영이 되어있고, 이 또한 복구해야 했다.

 

 

그래서 내가 돌아온 commit으로 복구하려면 github로 push해야한다.

하지만, gihub가 판단하기에 최신기록 이전의 버전이기에 push가 아닌 최신 기록을 pull 받으라고 한다.

 

 

이를 위해서는 또 terminal로 push를 해주면 되는데

git push origin main

 

이렇게 해주면 터미널이 거부한다...

 

이유는 앞서 말한것 처럼 최신버전의 전 commit이기 때문.

 

 

 

이를 막아주기 위해 우리는 위험한 기능인 force push를 해줘야 한다.

 

force push란?

크래시가 나든 말든 무조건 push를 해달라는 위험한 요청이다.

그렇기 때문에 어지간하면 하지 않는 것을 권장한다.

 

 

하지만 이 경우에는 해야한다..

git push --force origin main

이렇게 코드를 작성하고 push를 한다면 무조건 push가 된다.

 

 

 

 

위와같은 험난한 과정을 거쳐 원래대로 돌아올 수 있었다.

와~ 조심스럽게 작업하느라 1시간은 날렸다

 

 

 

 

 

네.

이렇게 고생하기 싫으면 조심조심하는 안전한 github 생활 되세요들

728x90