Skip to content

Latest commit

 

History

History
237 lines (144 loc) · 13.4 KB

브랜치 통합하기.md

File metadata and controls

237 lines (144 loc) · 13.4 KB

브랜치 통합하기

브랜치 통합에는 merge 를 사용하는 방법과 rebase를 사용하는 방법의 2가지 종류가 있다. 어느 쪽을 사용하느냐에 따라 통합 후의 브랜치의 이력이 크게 달라진다. 하나씩 어떤 의미인지 알아보자.


1. merge란?

merge를 사용하면 여러 개의 브랜치를 하나로 모을 수 있다. 예를 들어, 아래 그림과 같이 master브랜치에서 뻗어 나오는 bugfix라는 브랜치를 보자.

image

현재 상황은 master 브랜치에서 뻗어 나온 이후로 bugfix에서 커밋을 2번 해서 위의 그림과 같이 진행이 된 상황이다.


bugfix 브랜치를 master브랜치로 병합할 때, master 브랜치의 상태가 bugfix 브랜치를 만들었을 때의 상태와 같다면 매우 쉽게 merge할 수 있다. bugfix 브랜치는 master 브랜치의 이력을 모두 포함하고 있기 때문에, master 브랜치는 단순히 이동하기만 해도 bugfix 브랜치와 합쳐질 수 있다. 이 같은 병합을 fast-forward(빨리 감기)병합이라고 한다.

image

그러면 GitKrakenCLI를 이용해서 실습을 해보자.


실습

스크린샷 2020-10-26 오후 11 29 07

현재의 상황은 위의 그림과 같고 여기서 feature_jg라는 브랜치를 만들어서 브랜치에서 약간의 수정을 한 후에 커밋을 해보자.


스크린샷 2020-10-26 오후 11 32 11

위의 터미널은 master 브랜치에서 feature_jg 브랜치를 만들면서 이동하고 feature_jg 브랜치에서 fast.md라는 파일을 만들어 간단히 내용을 적어준 후에 commit까지 한 상태이다.

스크린샷 2020-10-26 오후 11 33 29

그리고 나서 GitKraken을 확인해보면 브랜치를 만들었음에도 불구하고 master 브랜치에서 가지처럼 뻗어나가는 것이 아니라 일자의 모양을 볼 수 있다.(일자 모양이라고 해서 브랜치가 없다고 생각하면 안된다.) 일자인 이유는 master 브랜치에 상태변화가 없기 때문이다. 만약 master 브랜치에도 커밋을 하고 feature_jg에도 커밋을 한다면 일반적인 가지치는 모양이 나올 것이다. 현재 상황이 가장 맨 위에 첫 번째 그림의 상황과 같다. 한마디로 여기서 master 브랜치와 feature_jg 브랜치를 merge 하면 fast-forward-merge가 되는 것이다.


그리고 master 브랜치를 돌아와서 feature_jg 브랜치와 merge를 하면 어떻게 되는지 확인해보자. 머지하는 명령어는 아래와 같다.

git merge 브랜치이름
ex) git merge feature_jg 
(현재는 feature_jg를 master에 merge하는 상황이기 때문에 master 브랜치로 와서 feature_jg와 병합을 해야 한다.)

스크린샷 2020-10-26 오후 11 37 37

그러면 위와 같이 merge가 성공한 것을 볼 수 있고, Fast-forward라는 것이 뜨는 것도 확인할 수 있다. 한마디로 master 브랜치를 feature_jg 브랜치가 있는 곳까지 빨리감기를 한 상황이다.


브랜치 병합: project level

예를들어 master 브랜치에는 A라는 파일을 만들고, feature_jg 브랜치에서는 B라는 파일을 만들어서 두 개의 브랜치를 merge 하면 어떻게 될까? 어떻게 되는지 바로 해보자.

스크린샷 2020-10-26 오후 11 49 37

위와 같이 feature_jg에서 새로운 파일을 하나 만들고 master 브랜치로 넘어가자.

스크린샷 2020-10-26 오후 11 52 09

그리고 master 브랜치에서도 새로운 파일을 하나 만들었다.

스크린샷 2020-10-26 오후 11 53 29

이번에는 두 개의 브랜치에서 모두 수정을 했기 때문에 GitKraken을 확인해보면 브랜치의 모양이 일자가 아니라 가지모양이 만들어진 것도 확인할 수 있다. 이제 master브랜치에서 두 개의 브랜치를 merge 해보자.

git merge feature_jg

스크린샷 2020-10-26 오후 11 56 05

그러면 위와 같이 머지가 되기 전 commit message를 입력할 수 있는 화면이 나올 것이다. 나는 기본으로 제공해주는 커밋 메세지로 merge를 하였다. (vi 에디터에서 저장하고 나오기처럼 하면 된다 ex) ESC + : + wq + Enter)

스크린샷 2020-10-26 오후 11 57 47

그러면 성공적으로 머지가 된 것을 확인할 수 있고, 각 브랜치에서 만들었던 새로운 파일들이 문제없이 잘 합쳐진 것도 확인할 수 있다.


충돌 해결, Conflict resolve

만약 두 개의 브랜치에서 동시에 같은 파일의 같은 곳을 수정하고, 그것을 병합 한다면 충돌(Conflict)이 발생한다. 그리고 충돌이 발생했을 때 해결하는 것을 Conflict resolve라고 한다. 지금은 충돌이 발생했을 때, CLI에서 해결 하는 법과 GitKraken을 이용해서 resolve 하는 법에 대해서 알아보자.

스크린샷 2020-10-27 오전 12 35 17

먼저 강제로 충돌을 일으켜보자. master 브랜치에서 본인이 원하는 파일을 원하는 대로 수정을 해보자!


그리고 feature_jg 브랜치로 가서 master 브랜치에서 수정했던 파일의 같은 라인을 다른 것으로 수정해보자.

스크린샷 2020-10-27 오전 12 38 54

나는 위와 같이 첫 번째 줄을 Gangnam!!에서 Git Study로 바꿨다. 그리고 다시 master 브랜치로 돌아와서 merge를 시도해보자.(master 브랜치에서 merge를 하는 이유는 master는 병합 할 브랜치이고, feature_jg 브랜치는 병합 될 브랜치이기 때문이다.)

스크린샷 2020-10-27 오전 12 42 28

그러면 위와 같이 충돌이 발생하는 것을 볼 수 있다.


1. CLI로 충돌 해결하기

스크린샷 2020-10-27 오전 12 44 44

충돌이 발생한 파일을 들어가보면 위와 같이 충돌이 일어난 부분을 표시해주는 것을 볼 수 있다.

  • 충돌이 발생한 부분의 시작 : <<<<<HEAD
  • 충돌 난 부분의 끝 : >>>>>feature_jg
  • 중간 경계선 표시 : =========

양 쪽의 브랜치에서 같은 파일의 같은 행을 수정했기 때문에 Git은 어떤 수정 사항을 선택할 것인지 사용자에게 맡기는 것이다. 이런 경우 충돌 난 두 브랜치 중 하나의 내용을 선택하거나, 두 수정 내역을 합치는 등 수동으로 충돌을 해결해야 한다. (Tip : vi 명령모드에서 x : 문자 하나 삭제, dd : 한줄삭제)


2. GitKraken 에서 충돌 해결

스크린샷 2020-10-27 오후 11 32 15

강제로 충돌이 일어나는 상황을 만든 후에 두 개의 브랜치를 병합하면 위와 같은 화면을 볼 수 있다. 그리고 오른쪽 위를 클릭한 후에 충돌이 일어난 파일을 클릭해보자.

스크린샷 2020-10-27 오후 11 35 26

그러면 위와 같이 master 브랜치의 파일에서 충돌이 일어난 부분을 표시해주고, feature_jg 브랜치의 파일에서 충돌이 일어난 부분도 표시해준다. 그리고 아래의 Output은 원래 원본 파일의 내용이다.


그리고 이번에는 충돌 해결(Conflict Resolve)를 해보자.

스크린샷 2020-10-27 오후 11 40 49

충돌 해결을 하는 건 두 개의 파일의 내용이 중복 되어 하나의 파일 내용을 삭제해야 할 수도 있고, 둘 다 필요한 내용일 수도 있다. 그래서 위의 사진처럼 브랜치의 파일 코드 옆을 눌러 보면 초록색 체크가 나오는 것을 알 수 있다.


그와 동시에 아래 output에서도 순서가 정해져서 파일의 내용이 결정된다. (한마디로 코드의 순서가 중요하다면 순서에 맞게 선택해서 파일을 완성해야 한다는 뜻이다.) 이렇게 3개의 파일을 보여주는 이유는 Git에서 merge를 할 때 3-way merge를 사용하기 때문이다.


3-way merge란?

3-way merge는 Git에서 파일을 병합시킬 때 사용하는 것인데 어떤 것인지는 아래의 설명을 보면서 이해해보자.


먼저 아래 테이블의 의미는 각 열(세로)마다 하나의 파일이라고 생각하면 된다. 예를들어 1열은 master 브랜치의 A라는 파일, 2열은 A라는 파일의 원본, 3열은 feature_jg 브랜치의 A라는 파일이라고 생각하자. (그리고 테이블 안의 행은 파일안에 줄(line)이라고 생각하면 된다

master Base feature_jg
A A
B B B
1 C 2
D D

다시 정리하자면, A라는 파일의 원본 내용은 아래와 같다.

A
B
C
D

그리고 master 브랜치에서 A라는 파일을 아래와 같이 수정했다.

A
B
1

그리고 feature_jg 브랜치에서 A라는 파일을 아래와 같이 수정했다.


B
2
D

정리하자면 line1은 feature_jg 만 파일의 상태가 다르고, line2는 모두가 같고, line3은 master만 다르고, line4는 master만 파일의 상태가 다르다. 이제 feature_jg 브랜치를 master 브랜치로 병합(merge)하려고 할 때 어떻게 자동으로 병합(merge)이 되는지를 알아보자.


3-way merge를 보기 전에 먼저 2-way merge가 어떤 것인지 알고 가자.


2-way merge

master feature_jg 2-way merge
A master의 파일에는 line에 내용이 있고, feature_jg 파일의 line에는 내용이 없기 때문에 무엇을 채워야 할 지 모르기 때문에 Conflict 발생
B B master의 파일의 line과 feature_jg의 파일 line이 같기 때문에 그대로 B 유지
1 2 master의 파일의 line과 feature_jg의 파일 line이 다르기 때문에 Conflict 발생
D master의 파일에는 line에 내용이 없고, feature_jg 파일의 line에는 내용이 있기 때문에 무엇을 채워야 할 지 모르기 때문에 Conflict 발생

위와 같이 2-way merge는 master와 feature_jg 브랜치인 2개의 대상만 보고 병합(merge)를 하는 것이다. 이와 같이 2-way merge를 사용하면 2개의 파일로만 비교를 해야하기 때문에 병합을 할 때 Conflict가 더 많이 발생하게 된다.


3-way merge

master Base feature_jg 3-way merge
A A master에서는 파일의 내용이 원본과 같고, feature_jg에서는 파일의 내용이 원본에서 지워진 상태이기 때문에 이럴 때는 지워진 상태인 feature_jg 파일의 상태로 합쳐진다. (Conflict가 발생하지 않음)
B B B 3개의 파일 상태가 같기 때문에 B 유지
1 C 2 3개가 모두 다 다르기 때문에 Conflict 발생
D D 이것도 첫 번째 줄의 상태와 같다. (Conflict는 발생하지 않고 원본 파일에서 지워진 상태로 병합이 된다)

3-way merge는 master 브랜치의 파일, 원본파일, feature_jg의 파일 총 3개를 가지고 비교를 하기 때문에 2-way merge보다 훨씬 효율적으로 병합(merge)를 할 수 있다.