git squash merge

lamPolar·2024년 10월 7일
0

github

목록 보기
4/4
post-thumbnail

사건의 발단 - merge 방식의 변경

이번 프로젝트에서 merge 방식을 바꿔보기로 했다.
SJ 님의 의견이었는데, back 레파지토리에서 하는 대로 front 레파지토리에도 적용해보기로 했다.
기존 merge 방식과 다른 두가지 merge 방식인 reabse, squash merge방식을 사용해보고 싶었기 때문이다.
세가지 merge 방식의 차이는 -> 3-way merge 이 블로그에 잘 정리되어 있다.

우리가 정한 merge 룰은 다음과 같았다.
1. deploy는 main 브랜치 작업물로 하고,
2. dev브랜치에서 main브랜치로의 merge는 rebase방식을 사용하고,
3. 그 외 다른 브랜치에서 dev브랜치로의 merge는 squash방식을 사용하기로 했다.
간단한 git-flow를 따르기로 한 것이다.

사건의 전개 - PR commit log 폭탄

깃헙에 KS 님의 PR이 올라와서 리뷰를 하러갔더니 commit log 폭탄이 있었다.
알고보니 브랜치 구분을 안하고 올리셨던 것..!
이때는 초반 PR이어서 내용에 대한 comment만 남기고 Approve를 드렸다.
이 결정을 아주 후회 했다ㅎ

그리고 이 커밋들은 feature -> dev로의 PR이라 하나의 커밋으로 squash 되어 merge되었다.

사건의 위기 - 또 다시 나타난 폭탄

다른 기능을 위한 KS님의 PR이 다시 올라왔다.
그런데 그 PR의 commit log가 뭔가 이상했다.

몇가지 commit이 추가된것 말고는 거의 모든 커밋이 다시 올라온 것이다.
그래서 나는 해당 이슈에 대해서 피드백을 남겼다.

풀리퀘 커밋 로그와 file changed가 맞지 않습니다. 확인 한번만 부탁드려요!

그리고 KS님의 답변이 달렸다.

파일 자체는 문제가 없는데 로그가 이상하네요. 수정해서 올리겠습니다!

그리고 다음 날 회의에서 우리는 1시간 30분동안 이 커밋로그가 왜 그런것인지 토의했다. 회의 좋잖아 한잔해~


KS님이 작업하신 branch graph는 위와 같았다.
Feature 1 에서 작업한 A, B, C 커밋이 squash merge 된 이후 인데,
분기된 Feature 2 브랜치에서 PR할 때 A, B, C, D, E, F가 모두 올라간 것이다.

해결 방법

회의에 참석한 SJ님이 rebase를 하면 해결할 수 있다고 하셨다.

git checkout [pr branch]
git pull origin dev
git reset --hard HEAD^
git rebase dev

이 방식으로 진행했더니 dev브랜치에서 갈라져 나온 순간부터의 모든 commit에 대해서 commit 한개마다의 conflict를 해결하라는 경고 문구가 떴다.

왜 그랬을까?

현재 local은 git pull origin dev로 인해서 origin dev의 상태를 갖고 있었다.
그런데 rebase가 진행되면서 feature2의 첫 커밋과 현재 dev 브랜치(= origin dev)가 가지고 있는 파일의 변경 사항이 충돌을 일으킨 거였다.

rebase과정의 실수...!

중복된 커밋을 제거하고 싶은 경우, conflict 해결 과정에서 중복된 내용이 들어간 커밋에 대해서는 incoming(dev)을 선택했어야 한다.
하지만 KS님은 rebase conflict 해결 과정에서 계속 incoming이 아닌 current를 선택했다.
왜냐하면 결론적으로 dev상태의 코드를 만들고 싶었기 때문이다. 하지만, 커밋의 incoming을 쭉 따라가면 현재 dev상태가 되는거였기 때문에 incoming을 누르는게 우리의 의도와 맞는 rebase conflict 해결과정이었다.

그래서 우리는 결론적으로, 약 커밋이 4개 정도 줄어든 commit log를 force push 하게 되었다. ㅎㅎㅎㅎㅎ

의문 1. 왜 dev에 merge를 했는데 중복된 log를 탐지하지 못하는걸까?

왜냐하면, squash merge과정에서 commit log와 무관한 새로운 commit id가 만들어졌기 때문에, dev브랜치 입장에서는 전혀 다른 commit이라고 인식하는 것.

의문 2. 그렇다면 rebase과정을 통하면 중복된 log가 사라지는데, 그건 어떻게 가능한걸까?

그건 사람이 수동으로 각 커밋마다의 변경점을 보고 확인해서 중복된 내용이라는 것을 확인해주니까 가능한거! git이 자동으로 해줄 수는 없다 ㅠㅠ

의문 3. squash merge가 아닌 merge를 사용했다면 이런 일이 발생하지 않았을까?

YES!! merge를 했을 경우 dev브랜치에 merge를 위한 커밋이 하나 추가될 뿐, 내가 올린 PR의 모든 commit log 가 dev에 포함되게 된다.
dev브랜치 입장에서는 똑같은 commit id에 대해서 다시 반영해달라고 하는 것이므로, 중복된 commit id를 제외하고 PR에 보여졌을 것이다.

의문 4. PR에서 보여주는 commit log는 결국 dev branch와 변경점이 있으니까 보이는거 아닌가? 근데 왜 file changed와 일치하지 않을까?

이건 우리가 rebase과정에서 실수를 범했기 때문이다. 결론적으로는 dev branch와 같은 코드를 갖게 되기 때문에 file changed에는 보이지 않지만, 각 commit 마다는 변경점이 있다고 판단하기 때문에 PR에서 해당 commit을 보여주는것!

사건의 결론 - cherry pick 으로 해결해보자

이 풀리퀘에 남은 commit log 가 약 30개에 달했기 때문에 우리는 조금 더 쉬운 방식을 다시 시도해보기로 했다.
새로운 브랜치를 만들고, PR 에 올라가야하는 5개의 커밋에 대해서 cherry-pick명령을 통해 새로운 브랜치로 옮기는 것이다.

cherry pick 명령어 - 블로그 참고

이 사건에서 배운것

  1. PR이 올라간 후에는 꼭 dev 브랜치를 rebase하거나 merge하고 작업을 이어가자.
  2. commit log는 죄가 없다. 대부분은 HUMAN ERROR다.
  3. 이런 문제를 방지하려면 그냥 dev브랜치에서 다시 분기를 하자.
  4. rebase와 squash merge가 동작하는 방식을 제대로 이해하게 된것 같다.
  5. 모르는 것을 서로 나누는 회의는 즐겁다.하핳
profile
불안을 안고 구르는 작은 모난 돌

0개의 댓글