Branch 란 ?

Branch 란 우리말로 나뭇가지, 분기된 흐름 등의 뜻을 가진 단어이죠. 깃에서는 특정 커밋을 가리키는 '포인터'를 의미합니다. Branch는 최신 커밋을 가리키는 흐름이며, 하나의 프로젝트에서 특정 목적으로 서로 다른 개발 흐름을 병렬적으로 가져가기 위해 사용합니다. 이러한 브랜치를 통해 여러 개발자 혹은 여러 개발팀이 한 프로젝트의 세부 과제를 병렬적 진행하며, 각 목적에 맞는 개발 흐름을 관리할 수 있습니다.

 

이미지 출처 : 한국정보산업연합회

위의 그림처럼, master branch(기본으로 셋팅되는 main branch) 에서 개발 분야를 feature-A 와 feature-B로 나눠 각각의 팀이 개발을 진행하기로 했을 때, branch 를 나누어 관리할 수 있는 것이죠. branch는 나누거나 합치기가 가능합니다.

 git log를 입력할 때, HEAD -> master 라는 문구를 보셨을겁니다. master 란, 앞서 말했듯이 Master branch 의 master 이고, 현재 3번째 커밋을 가리키고 있는 것을 알 수 있습니다. HEAD 는 branch를 통해 특정 커밋을 가리킵니다. 즉, 여기서 master branch를 통해 3번째 커밋을 가리키는 것 입니다. 

지금 깃 랩 서버에 연동시키지 않은 상태라 보이지는 않지만, 깃 랩 서버(이름 : origin)에 연동하게 되면 origin/master 라는 붉은 단어가 뜨는데요, 이것은 깃 랩 서버에 존재하는 master 브랜치를 의미합니다. 만약, HEAD -> master, origin/master 라고 되어있디면 지금 컴퓨터의 master branch 와 gitlab 서버의 master 브랜치가 모두 3번째 커밋을 가리키고 있다는 의미이죠.

Branch 만들어보기

1. 한 갈래로 나누기

git branch {branch_name} 입력

git branch develop 를 입력해 develop branch를 생성해주도록 하겠습니다.

기존에 있던 master branch 에 더해, develop branch 가 생겼네요. branch 를 생성할 때는 나누기를 원하는 기점(커밋)으로 이동해 HEAD를 옮겨주고 생성해주면 됩니다. 

보통 master branch 에는 배포할 정도로 완성된 커밋들만 넣고, develop branch 에는 개발하는 중에 사용할 커밋들만 넣습니다.

커밋 간 HEAD를 옮기는 법은 살펴봤는데, 브랜치 간 HEAD를 옮기려면 어떻게 해야 할까요?

git checkout {branch_name} 을 입력해주면 됩니다.

git checkout develop 를 입력해주면,

HEAD 가 develop branch 를 가리키는 상태로 바뀐 것을 확인할 수 있지요. 이 상태에서 commit 하면 이제 새 커밋들을 develop 브랜치가 가리키게 됩니다.

지금까지 순서를 정리해보면, 분기점이 될 커밋으로 이동해 Branch 생성(git branch), 해당 Branch로 HEAD 이동(git checkout), Branch 에서 commit(git add, git commit) 로 정리할 수 있겠습니다. 위의 코드를 보면 분기점이던 세번째 커밋을 포함한 이전은 master branch 에, 이후의 커밋은 develop branch 에 속해있는 것을 볼 수 있죠. 나무의 기둥에서 뻗어나온 나뭇가지 같습니다. 이렇게, 병렬적으로 나눠서 개발할 필요가 있을때 각 작업에 별도의 브랜치를 할당해줌으로써 수행이 가능해집니다.

지금까지는 master branch 에서 다른 한 갈래로 뻗어나가는 branch를 다뤄봤는데요, master branch 에서 두 갈래로 나뉘어 버전관리를 하는 것도 실습해볼까요?

2. 두 갈래로 나누기

우리가 지금까지 만든 코드에, attack method 와 defend method 를 추가 개발할 것이라 해봅시다. 그리고 각 method 는 다른 팀이 하나씩 맡아 개발하여 관리할 것입니다. 

그러면 분기점이 될 가장 최신 커밋으로 HEAD를 이동하고, feature-attack branch 와 feature-defend branch를 생성해주면 되겠지요. 그리고 attack method를 담당하는 팀은 HEAD를 feature-attack branch 에 이동시켜 attack method 소스코드를 커밋해 버전을 관리하고, defend method 를 담당하는 팀은 HEAD를 feature-defend branch 에 이동해서 defend method 소스코드를 커밋해 버전을 관리하면 될 것입니다. 

3. 모든 branch 확인하기

이 때, attack method를 맡아 작성하는 팀은 HEAD가 attack branch에 가있을때 defend branch 의 내용이 보이지 않습니다. defend method를 맡아 작성하는 팀도, HEAD가 defend branch에 가있을때 attack branch 의 내용이 보이질 않죠. (master branch의 내용을 보입니다.)

위의 코드를 보면, HEAD가 feature-defend 로 가있을때 master branch와 defend branch의 commit log는 보이지만, feature-attack branch가 보이지 않는 것을 확인할 수 있습니다. (현재 attack method 가 커밋된 상태입니다)

만약, 현재 내가 있는 branch 가 아닌 모든 branch를 보고싶다면 기존의 git log 에 다른 옵션을 추가해 명령해주어야 합니다.

git log --all --graph 입력

--all 은 HEAD 가 가리키는 branch 뿐 아니라 모든 branch를 보겠다는 명령어입니다.

--graph 은 브랜치와 커밋간의 관계를 그래프 형식으로 보여달라는 명령어 입니다.

해당 명령어를 입력해보니 왼편에 나무와 비슷하게 생긴 graph가 생긴 것을 볼 수 있습니다. develop branch 에서 두 갈래로 갈라져 있는 것을 확인할 수 있고, 모든 branch 가 보이지요.

개발 실무에서는 여러 작업을 분담해 처리하기 위해 보통 develop branch 에서 여러 개의 하부 branch 를 생성할때가 많습니다. 그리고 하나의 branch 위에서 팀이 버전을 관리하며 작업해가는 형식이지요.

4. branch 의 병합

이제 각 branch 의 개발이 끝나고, 각각의 feature 브랜치에서 했던 작업을 병합하고 싶습니다. (즉, develop branch에 작업의 결과를 모두 반영하고 싶다는 것입니다) 그러면 어떻게 병합해야 할까요?

먼저 develop branch(결과를 반영하고싶은 branch) 로 이동합니다.

git merge {합쳐주고싶은 branch이름} 입력

git merge feature-attack 을 입력합니다. 이 명렁어의 의미는, HEAD 가 가리키고 있는 브랜치(현재 develop)에 feature-attack 에서 했던 작업을 병합해달라는 것입니다. 보다 상세하게는, 1. 현재 HEAD 가 브랜치를 통해 가리키고 있는 커밋 과, 2. merge 뒤에 쓴 브랜치가 가리키고 있는 커밋을 합쳐달라는 것입니다.

HEAD 가 가리키던 develop branch 와 feature-attack bracnh 가 병합된 걸 알 수 있습니다. 특히 develop branch 의 위치가, six commit 에서 Add attach method 의 위치로 이동해온 것을 볼 수 있는데요, 이 경우를 Fast-Foward Merge 라고 합니다. 

Merge 로 branch 가 병합되는 경우에는, 두 가지의 경우가 있습니다. 

- 기존의 branch(develop)가 merge를 당하는 branch까지 쭉 당겨져 오는 경우

- 두 branch를 병합한 새로운 커밋이 생성되는 경우

이 중 전자의 경우를 Fast-Foward Merge 라고 하는 것이지요.

 

Comfilict 발생시 대처

feature-attack branch의 병합을 완료했으니, 이제 feature-defend branch 도 병합해줍니다.

그런데, 이런! 병합 중에, 오류가 발생했습니다.

Auto-merging myfile.txt CONFLICT (content): Merge conflict in myfile.txt Automatic merge failed; fix conflicts and then commit the result.

이러한 오류 문구가 발생한 이유는, merge 중 충돌이 발생했기 때문입니다.

그림을 보면, feature-attack branch 와 feature-defend branch 의 일부 소스코드(attack 와 defend) 가 같은 라인에 위치해있다는 것을 볼 수 있지요. 여기서 문제가 발생합니다. 파이썬이 같은 라인에 다른 코드를 병합하려다보니, 어떤 라인을 선택해야 할 지 모르겠다는 것입니다. 이게 conflict 오류 발생의 원인이 됩니다. 이 경우에 파이썬은 각 파일에 표시를 남겨줍니다. 

해결법은 간단한데요, 파일에 파이썬이 남겨준 오류 코드를 확인하고, 이 파일이 가졌으면 하는 최종 코드를 남겨두면 되는 것입니다. 예시의 경우처럼 둘 다 남기고 싶다면, 필요없는 부분을 지우고 원하는 코드의 모습으로 고쳐주면 됩니다. (괄호 수정)

코드의 수정이 완료되었다면, git add . 와 git commit 명령어를 사용해 커밋하면 되는 것이지요.

 

 이제 각 branch 들이 develop branch로 합쳐지면서 새로운 커밋이 만들어진 것을 볼 수 있습니다. merge를 할 때, 새로운 커밋이 만들어지느냐 Fast-Forward merge가 발생하느냐는 대개 "흐름의 분기"의 차이에서 발생합니다. 가령, 기존 branch 와 병합하고픈 최신 branch 의 로그가 직선 모양으로 앞뒤로 위치한다면 merge를 할 때 최신 커밋을 가리키는 쪽으로 이동합니다.(Fast-Forward) 그러나 흐름이 중간에 갈라진 branch 끼리를 merge하면 새로운 commit 이 하나 더 생기는 것입니다.

point

저번에 branch 관련 내용이라며 넘어간 코드를 한번 살펴보죠.

git push -u origin master

이 명령어를 기억 하시나요? gitlab 서버에 프로젝트를 올리라며 push 해주는 명렁어라고 했었지요.

사실 이 명령어를 더 자세히 설명하자면, master branch 를 origin 이 의미하는 gitlab 서버 프로젝트에 올리라는 뜻입니다. push 나 pull 은 "branch 단위"로 작업이 이루어집니다. 즉, push 나 pull 뒤에는 branch 의 이름이 적혀집니다.

가령 git push -u origin develop 하면 gitlab origin 서버에 develop 브랜치가 올라갑니다.

-u 는 "--set-upstream" 의 약자로, 내 컴퓨터의 master branch가 항상 gitlab서버의 master 브랜치를 바라보게 하라는 의미입니다. 그래서 처음에 저렇게 적어주면, 이후 push를 할 때 git push 라는 간단한 명령어만 사용하면 되는 것이죠.


오늘 살펴본 branch 는 깃 전체를 관통하는 내용입니다.

branch가 무엇일까? 왜 필요할까? 어떻게 병합할까? 어떻게 외부 저장소에 올릴까?  등을 잘 알고 있어야 합니다.

생각보다 글이 조금 길어져서 원래 쓰려고 한 다른 내용을 못 썼네요.. 글이 너무 길면 읽기 부담스러우니..^^;

다음 글에서는 프로젝트의 전반적인 과정에서 git과 gitlab 을 어떻게 쓰는지, Fork/Clone, MergeRequest하는 법 등 실전편을 가져오도록 하겠습니다.

 

+ Recent posts