[TIL] git merge vs git rebase

swing·2021년 8월 8일
4

[TIL]

목록 보기
8/10
post-thumbnail

이 글은 학습한 내용을 본인의 생각을 통해 해석하고 정리한 TIL 입니다.
부족한 내용이나 틀린 사항은 언제든 댓글로 남겨주세요 !! 🙋‍♂️

📌 개요

개발을 하다보니, 자연스럽게 git을 접하게 되었고 이제는 항상 함께하는 친구가 되었다. 혼자 git을 쓸 때는 merge밖에 쓸 일이 없었는데, 슬슬 협업을 하다보니 자연스럽게 rebase라는 것도 접하게 되었다. 비슷해 보이는데 막상 써보니 너무 다르고 컨플릭트도 많이 나서 애를 꽤나 먹었다. 과연 뭐가 다르고 어떻게 사용해야 하는 것인가,,
자 이번에는, Git의 다양한 커맨드 중 git merge와 git rebase에 대해 박살을 내보자🔥


👉 요약

Merge는 말 그대로, 합병의 의미를 지닌다 ! 사실 rebase도 merge에서 파생된 녀석인 것 같다.
Re + Base, 즉 재설정이라고 생각하면 된다 !
다른 두 개의 브랜치를, 한 곳의 베이스에 깔끔하게 병합할 수 있는 방법, 그것이 rebase 이다.


👉 git merge

Merge는 기본적으로 3-way merge를 통해 각기 다른 브랜치를 병합하게 된다. 3-way merge는 각 브랜치의 마지막 커밋 2 개와 베이스의 커밋, 총 3개의 커밋을 이용하여 병합하는 방법이다.
❓❓❓ 자 당황하지말고, 아래의 표를 통해 이해해보자.

feature branch 1basefeature branch 2
A
B
C
D

자 위의 표는, base에 커밋되어서 변경된 부분이 A,B,C,D라고 가정해 본 표이다.

feature branch 1basefeature branch 2
AAA🔥
BBB
C🔥CC🌊
D🔥DD

자 여기서 🔥 과 🌊은 변경사항이 있다는 표시이다. 이 때 merge를 하게 되면 각 브랜치와 베이스를 비교하여 새로운 커밋을 결정하게 된다.
만약 여기서 베이스가 없다면! 비교할 대상이 없기 때문에 변경사항이 없는 B를 제외하곤 명확하게 커밋을 결정할 수가 없다.

feature branch 1basefeature branch 2Merge
AAA 🌊A 🌊
BBBB
C 🔥CC🌊Conflict!!!
D 🔥DDD 🔥

결국 3-way merge를 통해 각 브랜치의 마지막 커밋 2개와 베이스의 커밋을 비교해서 새로운 커밋을 만들어 내게 된다.


👉 git rebase

Rebase는 말 그대로, 재설정 한다는 의미이다. Rebase는 vi 명령어를 통해 다양하게 커밋 로그를 변경할 수 있기 때문에 편리하면서도 주의해서 사용을 해야한다.
feature 브랜치를 master에 rebase한다는 것은, feature 브랜치의 master에 대한 공통 조상인 base를 master로 재설정 한다는 의미이다.
❓❓❓ 자 또 당황하지 말고, 이번엔 실제 간단한 실습을 통해 이해해보자 !

실습은 Sourcetree를 통해, 가지를 보기 쉽게 했다.
최종적으로

이런 작업 상황을

이렇게 만들것이다 !

🚴‍♂️ step1

git switch feature/test
feature/test로 switch한다. 이 때 head가 feature/test를 가르킨 상태이다.

🚴‍♂️ step2

git rebase -i main
여기서 -i 명령어는 필요한 커밋만 남겨서 새로운 커밋을 만들 수 있는 명령어이다. 실습에선, 최종 커밋을 제외한 다른 커밋은 스쿼시를 하고 새로운 커밋을 만들어 rebase할 것이다.

또한 main대신에 @~3라고 쓰면, feature/test의 최근부터 3개 까지의 커밋을 rebase할 수 있다.

여기서 커밋들이 pick으로 되어있는 것을 확인할 수 있다. 스쿼시할 커밋을 pick -> s 로 바꿔주자.
이 때 가장 오래된 커밋이 vi편집기 상위에 위치한다.
가장 오래된 커밋을 중심으로 새로운 커밋을 만들어야 한다.
그렇지 않고 중간의 commit이나 그 다음 부터 하면 이전 commit이 무시되어 그 이력이 소실된다

pick 7ea4b9d feature/test 변경사항 첫번째
s c162e06 feature/test 변경사항 두번째
s e3b0ce0 feature/test 변경사항 최종

이런 식으로 가장 상위의 커밋을 pick해야 한다.

🚴‍♂️ step3

각 브랜치의 변경 사항을 원하는 데로 병합한다
실제 VSCode의 모습이다. 각 브랜치의 작업 내용을 비교해서 남길 작업 상황을 남긴다.

나는 두 브랜치에서 작업한 모든 상황을 병합하기 위해, Accept Both Changes를 했다.

🚴‍♂️ step4

git add . & git rebase --continue
변경사항을 저장하고 add한 후에, rebase를 이어서 하는 것이다.
이 때 vi편집기가 나오고 새로운 commit을 입력할 수 있게 된다.
필요없는 줄은 dd를 입력해서 지우고, 만약 커밋 로그를 다르게 남기려면 vi편집을 하는 것처럼 하면 된다.

이런 모습을

이렇게 만들었다.

🚴‍♂️ step5

git switch main & git merge feature/test
이렇게 하면 rebase가 완료되고 feature/test로 돌아오게 된다.
이제 main으로 head를 옮기고, fast-forward merge를 하여 완료하면 된다.
최종적으로 Sourcetree를 확인해보면, 아주 가지가 이쁘게 정렬된 것을 확인할 수 있다 !


👨🏻‍💻 끝으로,,

실제 실습을 하면서도, 굉장히 삽질을 많이 했다,, vi편집을 할때 가장 오래된 커밋을 남기고 편집했어야 하는데, 중간 커밋을 남기려고 하면 error가 나더라.
하지만 결론적으로는, 오히려 삽질을 통해 제대로 rebase를 알게 되었고 vi도 오랜만에 연습했다.
rebase의 주의 사항이 하나 있다 ! 그것은 다른 사람과 함게 쓰는 브랜치에는 rebase를 쓰지 않는 것이다. 내가 rebase한 내용을 다른 작업자가 pull땡겨버리면 엄청난 conflict를 마주하게 될 것이다 😰
local에서 작업하고 origin으로 push하기 전에, 깔끔하게 커밋을 정리하는 차원으로 이용하면 되겠다 !

참고

profile
if(기록📝) 성장🌱

1개의 댓글

크~~실습까지 아주 자세하게 작성해주셨네요!!

답글 달기