본문 바로가기

IT

git merge가 1개도 아닌 2개.. 3ㄱㅐ?!?

제가 프로젝트를 하면서 많은 git용어에 대해서 많이 듣고 사용을 해봤는데, 기본적인 git 용어인 git push,

pull, checkout, status 등등 .. 많은 용어들이 존재를 하고 있지만 평소에는 거의 사용을 하지 않는 그러한

용어들이 있어서 실무에 적응하기 위해서 조금 더 자세히 공부하는 것이 좋을 것 같습니다. 그중에서 가장 먼저

알아볼 개념은 merge인데요 정말 정말 중요한 내용입니다. 

 

 

먼저 git이 무엇인지 모르는 분들도 있기 때문에 제 블로그에 있는 Git과 Github를 보시면 좋을 것 같습니다!!

 

Git과 GitHub 🐈‍⬛

많은 신입 개발자, 또는 개발자가 사용하는 버전관리인 git은 많은 사람들이 알고 있을 것이다. 하지만 생각 외로 Git과 GitHub의 차이를 잘 모르고 있는 사람이 되게 많은데 그 내용을 조금 다뤄볼

ltr2006.tistory.com


⭐️ Merge

그나마 많이 들어봤을 것 같은 용어인 merge이다.
merge는 한국어로 병합이라는 뜻을 가지고 실제로 A브랜치와 B브랜치를 병합함으로 합치는 것이다.

 

하지만 이러한 merge 방법에는 3가지로 나뉘게 된다.

  1. merge
  2. rebase merge
  3. squash merge

 

merge

 

먼저 가장 기본적인 merge는 어떠한 역할을 하고 있을까?

 

기본적으로 하나의 브랜치와 다른 브랜치의 변경 이력 전체를 합치는 개념을 이야기한다.

 

하지만 이러한 merge의 개념에는 2가지로 또 나뉘게 되는데 Fast-Forward3-Way-Merge로 나뉘게 된다.
최대한 쉽게 작성을 해보도록 하겠습니다. 

 

먼저 Fast-Forward라는 개념은 

가장 상위인 main 브랜치에서 A라는 브랜치를 만들었습니다.
이러한 A 브랜치에서 작업을 거쳐서 main 브랜치로 merge 과정을 거칠 때 바로 main으로 결합이 되죠.
이러한 과정에서 main과 A 브랜치에서 같은 commit을 base라고 부른다. 이러한 main과 A 브랜치는
동일한 선상에 위치하고 있습니다. 이러한 상태를 Fast-Foward 상태로 합니다.


➡️ Fast-Foward 관계에 있는 브랜치를 git merge를 입력하게 되면 새로운 commit이 생기지 않습니다.
예시로 협업을 하다가 보면 다른 팀원이 먼저 main에 작업한 B 브랜치를 merge를 했다면 A와 같은 브랜치는
Fast-Foward merge가 불가능하게 되는 것입니다.

이해가 되셨나요?

 

그러면 3-Way-Merge는 무엇일까?

 

3-Way-Merge라는 개념은

이전 상황과는 다르게 A 브랜치와 main 브랜치의 변경사항이 있을 경우에 사용하는 merge 방법입니다.
나의 브랜치에서 커밋을 하고 남의 브랜치에서 커밋을 하고 그러한 두 브랜치의 공통되는 base 커밋이 필요해요.

 

(다른 블로그의 자료가 좋아서 참고해서 작성해보았습니다.)

먼저 공통된 base 커밋이라고 하며 a, b, c, d라는 변경된 부분이 있습니다.

나의 브랜치와 다른 사람의 브랜치에서 변경이 된 표가 아래와 같습니다.

 

 

왼쪽과 같이 a라는 내 브랜치에서는 변경 사항이 없이 그대로 a로 되며 다른 사람도 같은 a'로 변경이 되었다.

그다음으로는 b 브랜치에서는 양쪽에서 변경 사항이 서로 없으며 같은 b로 통합이 되었다. 하지만 문제는 c 브랜치에서는 두 사람이 다른 내용으로 코드 내용을 변경하였으며,

d 브랜치 상황은 a랑 같은 상황이다.

 

 

 

이때 base 커밋이 되는 공통된 조상 커밋이 없고 나와 다른 사람의 브랜치만 비교해서 merge를 한다고 하면

 

다음 위과 같은 상황이 벌어진다.

공통으로 변경 사항이 없는 b 브랜치를 제외한 모든 브랜치에서 a가 a였는지 a'였는지 정확하지가 않다.

이로써 merge가 된 후에 어떤 브랜치가 merge가 됐는지 알 수가 없는 것이다.

 

 

but, 여기서 중요한 base 커밋을 기반으로 3-Way-Merge를 진행하면 보다 명확하게 결정할 수 있는 장점이 있다.

 

정리를 하자면 git은 merge를 할 때 각 브랜치의 마지막 커밋 2개, 브랜치의 base 커밋을 총 3개를

통하여서 병합을 수행한다.

 

수많은 블로그를 읽다가 예시가 자세히 나와있는 블로그가 있어서 한 번 소개하겠습니다!!
진짜 정말 좋은 자료인 것 같습니다!

 

[Git] 3-way merge와 rebase를 이용한 fast-forward merge

목차 LIST 3-way 병합하기 3-way merge는 쉽게 말해서 내 브랜치 커밋, 다른 브랜치 커밋을 병합해서 새로운 커밋을 생성하는 방법입니다. 어떤 상황에서 사용되는지 아래 예시로 살펴보겠습니다. 예

sunrise-min.tistory.com

 

⭐️ Rebase

 

 

다음으로는 Rebase에 관한 개념이다.

rebase merge는 공통 base를 가진 두 브랜치에서 하나의 브랜치의 base를 다른 브랜치의 최선 커밋을

base로 하여서 재정렬을 하는 것을 의미한다. 조금 더 쉽게 이야기하자면 이름 그대로 브랜치의 공통 조상

되는 base를 다른 브랜치의 커밋 지점으로 바꾸는 것이다.

 

나도 이렇게 들었을 때 무슨 내용인지 정말 헷갈리는데 다음과 같이 예시를 보면 이해하기가 편할 것 같다.

어떤 브랜치가 base인지, 또 어떤 브랜치가 합쳐지는 건지를 잘 알아야 한다.

예를 들어서 feature라는 브랜치에서 main 브랜치를 합쳐야 하는 상황을 들어보자.

$git checkout feature
$git rebase main

 

먼저 feature로 checkout을 해주고 feature에서 main 브랜치를 rebase marge를 하는 것이다.

그러면 아래와 같이 feature에 main을 합치는 것이다. ➡️ (rebase)

 

보이시나요? rebase는 main브랜치 끝에 feature 브랜치의 커밋을 이어서 붙이는 것입니다.

이렇게 rebase를 하게 된다면 main 브랜치 끝이랑 feature 브랜치의 시작이 이어집니다. main 브랜치 뒤에서

새로운 커밋으로 feature 브랜치의 커밋들이 생기는 것이죠.

 

하지만 이렇게 main 뒤에서 계속 커밋을 쌓아가면 commit마다 conflict가 발생할 수도 있습니다.
git merge보다 rebase의 변경 이력을 알기 훨씬 쉽기 때문에 그런 컨벤션으로 git rebase를 관리하는 것이 좋다.

 

위와 같은 기본적인 merge 방법을 보면 정말 이해하기 편하다 글을 작성하면서 헷갈렸지만..

사진을 보자마다 한 번에 이해를 해버렸다. 

 


그러면 조금 더 자세하게 알기 위해서 추가적으로 예제를 하나 더 추가해 보도록 하겠습니다.

위와 같은 상황은 rebase merge를 위한 사진이다.

 

우리가 rebase를 하려고자 하는 궁금적인 목표는 위에 사진과 같이 master 브랜치의 마지막인 m2라는

커밋 이후에 feature 브랜치의 변경 사항인 f1과 f2가 일어난 것처럼 보이게 하고 싶은 것이다.

위와 같은 상태로 만들고 싶은 것이다.

 

Rebase가 한국어로 재설정한다는 뜻인 거 아시죠? base를 b가 아니라 m2로 재설정한다는 것이다.

즉 feature를 master에 merge === feature의 master에 대하나 공통 조산인 base를 master로 변경

 

 

Rebase의 기본 전략

 

rebase를 하려고 하는 브랜치의 커밋들의 변경 사항을 Patch라는 것으로 만들어 임시 저장소에 저장합니다.

그다음 이를 master 브랜치로 rebase 하는 명령어를 사용하여 병합을 합니다.

 

 

 

그럼 간단하게 요약을 해보자면

 

방식 : rebase가 되는 base 브랜치에 합쳐질 브랜치들(feature)의 커밋이 새로운 커밋에 각각 기차 마냥 합쳐짐

장점 : 변경 이력을 알기 쉽다. (history 관리가 용이함)

단점 : 커밋마다 conflict가 빈번히 발생함 ➡️ 처음 접하는 사람들은 다소 어렵게 느껴질 수도 있음

 

⭐️ Squash 

 

마지막인 merge 방식 중 하나는 squash이다.


squas는 개발을 하다 보면 많은 커밋의 양이 생기는데 여러 개의 커밋을 하나로 합치는 기능을 말한다.

즉, 머지할 브랜치의 커밋을 전부 하나의 커밋으로 뭉쳐서 내가 머지하고자 하는 브랜치에 커밋을 하는 방식이다.

 

위와 같은 그림을 보면 조금 이해하기가 쉽나요??
commit a + b + c를 하나로 합쳐서 새로운 commit인 abc를 만들어내고 그걸 master 브랜치에 추가합니다.

abc는 하나의 parent(부모) 요소를 가지게 됩니다. feature 브랜치의 commit history를 합쳐서 깔끔하게 만들기

위해서 사용합니다.

$git checkout master
$git merge --squash (my-branch)
$git merge -m "~~~~"

 

이러한 squash방법은 머지가 된 브랜치의 사소한 커밋 사항을 남기지 않고 머지가 된다는 이점이 있고, 이로 인해

변경 사항을 관리하고 이해하기가 더 수월하다는 장점을 가지고 있습니다.

 

 

느낀 점

사실 지금도 너무 많이 헷갈린다. 아직 더 많은 자료가 있고 더 좋은 내용도 많이 존재하는데 20개를 넘는 자료를 보면서 정리하였다. merge 방법이 정말 여러 가지가 존재했다니 실무 가서 적용하라고 하면 정말 어려울 것 같다. 하지만 알아두면 좋은 git 개념이기 때문에 추가적으로 알게 된 내용이 있으면 추가를 할 것이다.