이것저것 공부한 기록

[Git] rebase & merge 잘못 했다 본문

Others

[Git] rebase & merge 잘못 했다

블랜디 2022. 11. 15. 14:10

저번에 remote에서 개발 브랜치 하나를 통으로 날린 적이 있는데, 그 때 이후 또 새로운 실수를 해서 정리한다.. ^^

(위 실수는 local에 개발 브랜치 최신버전을 갖고있던 팀원분이 있어서 해결함)

 

 

 

현재 하고 있는 프로젝트가 Sprint 진행중이라서, 2주에 한번씩 Sprint 브랜치를 main에서 생성한 후 rebase해서 합치고 있다.

근데 또.. 외부 릴리즈가 있는 프로젝트라, 릴리즈 때 마다 릴리즈 브랜치도 따로 따고 있다.

 

이번에 역시 Sprint 진행중에 릴리즈 브랜치를 따로 따게 되어 브랜치 두 개를 동시에 main branch로 합치게 되었다.

 

1. Sprint 브랜치 A rebase 후 merge ( 이력 통합 )
2. 릴리즈 브랜치 B merge ( 이력 유지 )

 

위 순서로 진행했는데, 이슈 패치와 신규 구현건으로 동시에 수정된 파일이 꽤 많았다.

때문에 conflict가 굉장히 많이 났는데,

 

그걸 대충 해결하고 remote에 push를 한 후 (그러면 안됐는데)

merge한 A branch를 remote에서 삭제하고 (그러면 안됐는데2)

새 SPRINT 브랜치를 따서 팀에 공지를 했다. (그러면 안됐는데3)

 

그러고 나서 새 SPRINT 브랜치에서 작업하려고 build를 해봤더니 build error가 났다... ^^

 

급히 확인해보니 conflict난 파일을 합치는 과정에서, 두 군데서 동시에 수정된 파일들을 하나로 밀어버려서 발생한 문제였다.

다행히 아직 아무도 commit한건 없어서 팀에 잠깐 브랜치 다시 merge해야하니 작업사항 있으신분은 기다려달라는 공지를 한 후 복구에 돌입...

 

머리를 싸매고 내가 해야 하는 일의 순서를 생각해봄....

 

1. main branch를 이 모든 일이 일어나기 전으로 reset (revert하는게 나았을것 같다)
2. A branch 다시 복구해서 재 rebase
3. B branch 다시 merge

 

1. main branch reset

reflog 확인해서 rebase하기 전으로 HEAD를 돌리래서 또 냅다 reflog만 확인해서 돌렸다가, 영 이상한걸 깨닫고...

다시 읽어보니 reflog 뒤에 branch를 붙여줘야 깔끔하게 해결이 가능하단 것을 확인. 

 

$git reflog main(branch 명)

 

해서 main에다가 A branch merge 하기 전 마지막 내역을 찾고,

reset해서 main branch의 head를 돌려줬다.

........그런데 이거 revert했어야 했다. 이미 내가 새 Sprint 브랜치 땄다고 한 시점에 main pull한 팀원이 있어서...

 

$git reset --hard {log number} or {HEAD위치} (ex: e31dr5 or main@{4})

 

... 이력 유지를 해주려면 revert하셔야 합니다.

저는 reset을 때리고 냅다 push 때려 버려서 팀원에게 main branch삭제하시고 다시받으라는 공지를 또..

 

 

무튼 이력을 깔끔하게 정리했다면 remote로 push 해준다 

 

$git push -f origin main

 

 

main branch 정리는 완료.

 

 

2. A branch 다시 복구

A branch의 현재 상태는..

  • remote : main에 rebase된 후(내역사라짐) 삭제됨
  • local : main에 rebase된 상태, local에는 남아있음

 

그래서 일단 main branch와 같은 방법으로 rebase 전 이력까지 돌려줬다.

같은 방법으로 git push -f origin A(브랜치이름) 하려고 했는데 

 

error: src refspec A(브랜치이름) matches more than one
error: 레퍼런스를 'github.com:--/----.git'에 푸시하는데 실패했습니다

 

에러가 떴다... 

뭐지? 하고 찾아보니 remote랑 local의 같은 이름 branch에 대한 내용이 완전 달라서 문제가 생긴 듯.

해결 방법을 찾아보니 git init해서 새로 세팅을 하거나, 아예 새 directory에 repository전체를 받으라는데, 나는 commit 내역을 유지한 채로 브랜치를 합쳐야해서 이걸 어떻게 해야할지 고민하다가 결국...

마지막 내역에서 브랜치를 새로 따서 그 브랜치를 rebase하기로 했다. ㅎㅎ

 

$git checkout -b 새 브랜치 명

 

여기까지 완성 !

 

 

3. 다시 merge

이 사달이 난 이유에 대해서 좀 생각해보다가...

rebase와 merge순서를 바꿔보면 좀 conflict가 덜 날것 같다는 근거없는 확신이 생겨서, 작업에 착수했다.

 

1. 릴리즈 브랜치 B merge

2. Sprint branch A rebase 후 merge

 

이렇게 했더니 파일 하나만 신경쓰면 됐다.

 

4. 최종 확인 후 push

빌드 에러 있는지, 다른 이슈 있는지 확인해보니 빌드 에러도 안나고 conflict 걱정되었던 파일들도 각 수정사항이 잘 반영되어있는 것을 확인..!

 

그대로 main branch push 후 Sprint branch를 삭제 !

(release branch는 그대로 남겨놓았다)

 

5. 기타 사후처리

하지만 위에 말했던대로 merge 후 ~ reset 사이에 remote main을 한번 pull했던 사람을 대상으로,

local의 main branch를 삭제하고 다시 checkout 받으라는 공지가 추가로 필요하다.

그대로 pull 땡길경우 local의 commit 내역이 그대로 유지되어 push할 수 있게 되어버리기 때문...

 

그리고 새로 만들었던 다음 Sprint 브랜치는 얄짤없이 내 local과 remote에서 동시 삭제 후,

다시 main에서 뽑아줬다.

물론 이 브랜치도 팀원들에게 local의 새 Sprint 브랜치 삭제 후 다시 checkout 받으라고 공지해줘야한다...!!^^

 

 

 


 

정말 진땀나는 오전이였다.. ^^...

이제 또 일해야지....