본문 바로가기
Infra/GIT&GIT HUB

Git (9) : 병합 충돌 & n way-merge

by jaeaemin 2021. 7. 20.
Branch 충돌 해결

 

branch 간 merge 병합 중 충돌이 일어날 수 있는 상황은 같은 branch가 동일한 파일에 대해 같은 부분을 수정할 경우 일어납니다.

먼저 성공적인 병합의 예제로 아래 사진을 보면



각각의 master와 exp branch에는 자신의 이름을 가진 txt파일을 저장한 뒤에 commit하였습니다.

이제 이 파일들을 병합해보면 성공적으로 병합하여 Merge branch 'exp'로 master branch에 exp의 파일 내용들이 합쳐진 것을 확인할 수 있습니다

 

그 후 log 파일을 살펴보면 새롭게 병합된 commit이 생성된 것을 확인 할 수 있고 커맨드 창에서 파일 리스트를 살펴보면 master branch에서
exp branch에서 만들어졌던 exp.txt파일이 생성된 것을 확인 할 수 있습니다.

 

그렇다면 같은 파일에 다른 위치에 수정사항을 추가로 기입하면 어떻게 되는지 한번 살펴보겠습니다.

먼저 각 branch들의 위치에 common.txt 라는 파일에 common context 라는 내용의 텍스트 내용을 기입한 후 각각 commit한 뒤

master에서는 common context 내용 뒤에 this is master를 기입하고 exp에서는 common context 내용 앞에 common exp라는 내용을 기입한 뒤 exp를 master에 병합해 보면 병합이 성공적으로 이루어지는 것을 확인 할 수 있습니다.

 

그 후에 파일의 내용을 살펴보면 

파일의 내용이 합쳐져서 저장된 것을 확인 할 수 있습니다. common context 내용의 앞에 위치는 exp branch에서 수정된 내용이 common context 내용의 뒤에는 master branch에서 수정된 내용이 추가되어 각 branch에서 modified된 common.txt 파일이 합쳐저서 저장된 것 입니다.

이 경우에는 위의 그림처럼 정상적으로 병합이 완료 되는 것을 확인할 수 있습니다.

 

 

 

 

충돌

 

이제 우리가 제대로 인식해야하는 문제는 바로 같은 파일 같은 위치에서의 내용이 각 branch 마다 차이를 보일 때 발생합니다. 다시 common을 각 branch에서 같은 내용을 가지도록 초기화 하고 common conntext 뒤에  " : 각 branch 이름"을 붙인 뒤에 다시 commit을 하고 각 branch를 병합해 보겠습니다.

 

 

그 후에 merge를 진행하면 아래와 같이 경고 창이 뜨게되고 merge 진행 중 common.txt파일에서 충돌이 발생했다고 알려주게 됩니다.

common 파일의 내용을 확인하면 아래와 같습니다.

 

 

git 에서 파일을 병합하기 전에 살펴볼 때 같은 위치 상에 수정사항이 다르기 때문에 사용자에게 수정을 요구하는 메시지와 함께 각 branch에서 수정본을 합친 내용을 common파일에 저장하게 됩니다.

HEAD는 현재 위치한 branch이기 때문에 master이고 master에서 수정된 내용은 "common context : master"이고 같은 위치상에 exp에서 수정된 내용이 "common context : exp"라는 것을 의미합니다. 따라서 사용자는 git에서 제공한 이 메시지를 보고 소스코드를 적절하게 수정하여 다시 저장하여야 합니다.

 

 

 

 

3 way-merge

 

git에서는 어떤 branch와 다른 brnach 또는 commit 사이에서 어떤 파일을 병합할 때 3 way-merge나 2 way-merge를 사용하게 된다. 이 둘의 가장 큰 차이는 Base 즉 원본 코드를 참고 하는지의 여부이다.

 

예로 우리가 어떤 commit된 버전하나의 동일파일을 사용자1이 수정하고 사용자 2가 수정하여 그 파일들을 병합한다고 가정하자. 

f1.txt  사용자1 수정 f1.txt 수정 전 f1.txt파일 사용자2 수정 f2.txt 2 way-merge  3 way-merge
코드 0번째 줄 A A "null" "null"
코드 1번째 줄 B B B B B
코드 2번째 줄 1 C 2 ? ?
코드 3번째 줄 "null" D D ? "null"

 

이 표에서 Base는 당연히 수정 전 f1.txt파일로 A B C D라는 문자열을 줄마다 갖고 있었는데 각 사용자가 코드의 내용을 그대로 쓰거나 수정한 부분이 존재한다. 

이때 2 way-merge는 Base는 고려하지 않고 사용자 1,2의 f1.txt파일만 고려해서 병합하게 된다. 그러면 확실하게 통일된 코드 1번째 줄의 B를 제외하고는 나머지는 전부 충돌이 일어나서 우리가 위에서 알아본 대로 수정을 요구하는 메시지와 함께 합친 내용 전체를 코드에 추가하여 사용자가 자체적으로 수정해야한다.

 

3 way-merge의 경우에는 base를 포함해 총 3가지의 f1.txt파일을 비교하게 된다. 이 때 중요한 선행조건은 만약 파일의 내용이 통일되지 않는다면 수정이 일어난 쪽을 병합할 때 우선순위로 둔 다는 것이다. 즉 코드 0번째 줄을 보면 BASE에 A가 위치하는데 사용자 1은 수정하지 않고 그대로 두었고 사용자 2는 A를 삭제했다. 이때 사용자2의 f1.txt가 0번째 줄을 수정했으므로 3 way-merge에서는 A를 삭제한 것으로 병합하게 된다. 1번째 줄에 모두 통일된 부분은 당연히 통일시켜서 병합하게되고 나머지 부분은 방금 설명한 선행조건을 따라서 병합하게 된다. 이때 2번째 줄 처럼 각 파일에서 모두 다르게 수정되었다면 충돌을 발생시켜서 사용자가 직접 수정하도록 만든다.

 

반응형

'Infra > GIT&GIT HUB' 카테고리의 다른 글

Git (10) : reset  (0) 2021.07.22
Git (8) : stash (임시저장)  (0) 2021.07.18
Git (7) : branch & merge  (0) 2021.07.17
Git (6) : branch  (0) 2021.07.12
Git (5) : Reset , Revert 기초  (0) 2021.07.09