공부 자료/Git

[Git] Branch & Conflict

뚜루뚜루세니 2021. 8. 29. 16:37
728x90

branch

branch란 같은 뿌리에서 나왔지만 서로 다른 역사를 써내려가고 있는 버전들을 의미한다.

즉, branch를 통해 하나의 프로젝트를 여러 갈래로 나눠서 관리할 수 있다. 각각의 독립된 브랜치에서 마음대로 소스코드를 변경하여 작업한 후에 원래 버전과 비교하여 또 하나의 새로운 버전을 만들어 낼 수 있다.

 

branch의 사용법

깃으로 버전 관리를 시작하면 기본적으로 master라는 브랜치가 만들어진다.

사용자가 커밋을 할 때마다, master 브랜치는 최신 커밋을 가리키게 된다.

브랜치는 커밋을 가리키는 포인터와 비슷하다고 생각하면 좋다.

 

기존에 저장한 파일을 master 브랜치에 그대로 유지하면서 기존 파일 내용을 수정하거나 새로운 기능을 구현할 파일을 만들 수 있은데, master 브랜치에서 뻗어 나오는 새로운 브랜치를 만드는 것을 branch "분기"한다고 한다.

새 브랜치에서 원하는 작업을 다 끝냈으면, 새 브랜치에 있던 파일을 원래 master 브랜치에 합칠 수 있는데 이러한 과정을 병합(merge)라고 한다.

서로 다른 파일 병합하기

1
2
3
4
5
6
7
8
9
10
11
12
# 브랜치 체크아웃
$ git checkout master
 
# 브랜치 병합
$ git merge <병합할 브랜치명>
# 브랜치 병합 - 편집기 창을 열지 않고 자동 커밋 메시지 그대로 사용
$ git merge <병합할 브랜치명> --no-edit
# 브랜치 병합 - 편집기 커밋 메시지를 추가하거나 수정
$ git merge <병합할 브랜치명> --edit
 
# 브랜치 병합 확인
$ git log --oneline --branches --graph
cs

다른 브랜치의 내용을 master 브랜치로 병합할 경우, master 브랜치로 체크아우싱 필요하다.

병합시 자동으로 커밋 메시지가 나타난다.

* master 브랜치에서 브랜치를 분기한 후 master 브랜치에 아무 변화가 없다면?

분기한 브랜치를 병합하는 것은 간단하기 때문에 빨리 감기 병합이라고 부른다. == 분기한 브랜치에서 만든 최신 커밋을 master 브랜치가 가리키게만 하면 되기 때문이다.

 

같은 문서의 같은 위치를 수정했을 때 병합하기

 

conflict는 병합과정에서 나타나는 문제이다.

각 브랜치에서 같은 파일의 이름의 같은 줄을 수정했을 때, 브랜치를 병합하면 브랜치 충돌이 발생하게 된다.

충돌이 발생할 경우, 해당 파일의 내용을 직접 수정해야한다.

 

병합이 끝난 브랜치 삭제하기

브랜치 병합한 후에 더이상 사용하지 않는 브랜치는 깃에서 삭제가 가능하다. 

삭제된 브랜치는 완전히 지워지는 것 X ->다시 같은 이름의 브랜치 만들면 예전 내용을 볼 수 있음

 

3 way merge

merge 를 하는 방식에는 fast-merge 와 3-way-merge 두 가지가 존재한다.

 

fast-forward merge

c는 커밋을 의미한다. 작업을 진행하며 위와 같은 커밋이 진행되어있고, 현재 c2에 master가 존재한다.

이슈가 생겨서 iss53라는 브랜치를 생성하면 위와 같은 그림 처럼 형성된다. iss53 브랜치에서 하는 행위의 어떤 것도 master에는 영향을 주지 못한다.

iss53의 브랜치의 이슈를 해결하고 커밋을 진행하면 커밋 히스토리는 위와 같이 존재할 것이다. 즉, master는 c2에 있지만 iss53는 c3를 가리키고 있다. 

c3 커밋에는 c2까지의 내용이 모두 담겨있게 된다. 이 상태에서 master로 merge하는 것은 master의 포인터를 최신 커밋이 가리키고 있는 c3로 옮기는 것을 의미하게 된다.

c3의 커밋이 c2 커밋에 기반한 브랜치 이기 때문에 브랜치 포인터는 merge 과정 없이 최신 커밋으로 이동하게 된다.

이러한 방식을 fast-forward 방식이라고 한다.

  • A와 B 브랜치가 있다.
  • A->B를 머지하려고 한다.
  • B가 A 이후의 커밋을 가리키고 있다. (B의 조상커밋이 A이다.)
  • A는 단순히 B와 동일한 커밋을 가리키도록 이동한다.

즉, 단순하게 포인터를 최신 커밋으로 옮기는 것

 

3-way-merge

만약에 이 상황에서 master 브랜치에서 급하게 해결해야할 이슈가 발생되었다고 가정하면,

master에서 hotfix 브랜치를 생성해서 급하게 생긴 이슈를 해결하고 커밋을 한 다음에 master에서 merge를 했다고 생각하자.

그렇다면, 위 그림과 같이 master는 c4에 있게 되고, 현재 포인터는 c4를 가리키게 된다. 

hotfix는 해결했기 때문에 해당 브랜치는 삭제해줘도 된다.

그러면 다시 개발하던 iss53로 돌아가서 작업을 완료 하고 커밋을 진행해 c5라는 커밋히스토리를 남기게 되면 fast-forward와는 다른 부분이 생기게 된다.

현재 가리키는 커밋(C4-master)가 merge할 브랜치(C5-iss53)의 조상 c3가 아니기 대문에 fast-forward로 merge를 해줄수가 없다.

즉, 3-way-merge는 각 브랜치가 가리키는 커밋 2개(C4,C5)와 공통의 조상 1개(C2)를 사용하는 것을 의미한다.

3-way-merge의 결과를 별도의 커밋으로 만들고 해당 브랜치가 그 커밋을 가리키도록 이동시킨다. 그 커밋은 c6이고, 해당 커밋의 부모는 여러개가 되는 것을 볼 수 있다.

이때, merge-conflic이 발생할 수 있게 된다.

merge하는 두 브랜치에서 같은 파일의 같은 부분을 동시에 수정하게 되면 git은 해당 부분을 merge하지 못하게 될 것 이다.

728x90