본문 바로가기
엘리스 AI 트랙 4기/elice AI track

[1주차] git branch

by _sweep 2022. 1. 17.

1월 15일 자 학습 내용 정리입니다.

 

 

 branch

버전 관리 시스템에서 branch는 독립적으로 어떤 작업을 진행하기 위한 개념이다.

개발을 하다 보면 코드를 여러 개로 복사해야 하는 일이 자주 생기는데 이때 브랜치를 이용해 코드를 통째로 복사하고 나서 원래 코드와는 상관없이 독립적으로 개발을 진행할 수 있다.

 

그 이유는 git이 데이터를 일련의 스냅샷으로 기록하기 때문이다.

 

어떤 파일을 커밋하면 git은 현재 Staging Area에 있는 데이터의 스냅샷에 대한 포인터, 메타데이터, 이전 커밋에 대한 포인터 등을 포함하는 commit object를 만들어 저장한다.

 

이때 데이터의 스냅샷에 대한 포인터와 이전 커밋에 대한 포인터를 저장한다는 점을 유의깊게 봐야 한다.

커밋을 한다는 점은 새로운 체크포인트를 만드는 것과 같으며 이전 커밋에 대한 포인터를 저장함으로써 현재 커밋이 무엇을 기준으로 바뀌었는지를 알 수 있다.

 

git의 브랜치는 커밋 사이를 이동할 수 있는 포인터와 같다.

브랜치는 두 가지로 나눌 수 있는데 메인 브랜치와 토픽 브랜치이다.

 

  • main branch : 배포할 수 있는 수준의 안정적인 브랜치
  • topic branch : 기능 추가나 버그 수정과 같은 단위 작업을 위한 브랜치

 

git repository를 생성하면 master라는 브랜치가 기본적으로 생성된다.

master 브랜치를 main branch라고 생각하면 된다.

 

커밋을 함에 따라 새 체크포인트가 생성되면 체크포인트의 마지막을 가리키는 HEAD 포인터가 이동해 현재 위치를 알린다.

 

기본적으로 master 브랜치가 존재하기 때문에 master 브랜치가 생성된 커밋을 가리키고 이후 여러 번 커밋 과정을 거치면 자동으로 가장 마지막 커밋을 가리킨다.

 

이때 새로 브랜치를 만들게 되면 하나 뿐이던 메인 줄기가 갈라지게 된다.

HEAD 포인터가 새로 만든 브랜치를 가리키게 하면 master 브랜치와 새로 만든 브랜치가 독립적으로 존재하게 된다.

새로 만든 브랜치가 topic 브랜치가 되는 것이다.

 

각 topic 브랜치에서 작업을 하다 배포 등의 작업이 필요하면 main 브랜치로 병합한다.

main 브랜치에 반해 topic 브랜치는 수시로 생겼다가 없어지는 것이 가능하다.

 

이처럼 각각의 브랜치는 다른 브랜치의 영향을 받지 않기 때문에 독립적으로 작업을 진행할 수 있다.

 

 

 git branch 명령어

git branch

branch를 생성하고 생성된 branch를 확인할 수 있는 명령어이다.

 

git branch <이름>

git branch

 

git branch <이름>을 입력하면 해당 이름을 가진 브랜치가 생성된다.

이름을 주지 않고 git branch만을 입력한다면 생성된 브랜치들을 확인할 수 있다.

 

git branch 명령어에는 다양한 옵션이 존재한다.

 

  • --merged : 병합된 브랜치를 확인한다.
  • -d : 브랜치를 삭제한다. 주로 topic branch의 개발이 끝나 병합한 후 삭제할 때 이용된다. 병합된 브랜치만 삭제할 수 있다.
  • -D : 병합 여부와 상관없이 브랜치를 강제로 삭제한다.

 

 

git checkout

branch를 전환하는 명령어이다.

 

git checkout <이름>

git checkout <snapshot hash>

 

git checkout <이름>을 입력하면 HEAD 포인터가 해당 이름의 브랜치를 가리키게 된다.

즉, 현재 작업을 할 브랜치가 해당 브랜치임을 나타낸다.

 

git checkout <snapshot hash>를 입력하면 과거의 파일 내용을 확인할 수 있다.

snapshot hash는 git log 명령어로 확인할 수 있다.

 

git merge

branch를 병합하는 명령어이다.

 

git merge <이름>

 

A 브랜치를 master 브랜치로 병합하고자 할 때 git checkout master로 master 브랜치로 이동한 후 git merge A 명령어로 master 브랜치에 A 브랜치를 병합할 수 있다.

 

즉, 토대가 되는 branch를 현재 브랜치로 설정한 후 merge 명령어로 병합할 브랜치를 병합하는 것이다.

 

 

 fast-forward 방식의 병합과 가지치기

fast-forward

새 브랜치를 만들면 새로운 체크포인트가 생성된다.

브랜치를 병합하면 병합된 브랜치가 이전에 만든 새 체크포인트로 이동하게 된다.

 

이를 그림으로 살펴보자면 다음과 같다.

 

 

c2라는 체크포인트를 가리키고 있는 master 브랜치가 있고 새로 생성된 hotfix 브랜치가 있다.

hotfix 브랜치는 생성되면서 새로운 체크포인트를 가지기 때문에 c4라는 체크포인트를 가리키고 있다.

 

이때 master 브랜치를 중심으로 hotfix 브랜치를 병합하면 다음과 같은 그림이 된다.

 

 

master 브랜치가 c2 체크포인트를 가리키는 것이 아니라 hotfix가 만든 체크포인트인 c4를 가리키게 되는 것이다.

 

master 브랜치와 hotfix 브랜치가 병합되었으니 hotfix의 모든 내용은 master 안에 존재한다.

즉, master 브랜치의 다른 부분은 변경 없이 hotfix 브랜치 안의 내용만이 새로 master 브랜치에 추가되는 것이다.

따라서 곧바로 병합되는 것을 볼 수 있다.

 

이와 같은 방식으로 병합이 이루어지는 방식을 fast-forward라고 한다.

 

가지치기

해당 repository에 대해 2개 이상의 다른 브랜치에서 따로 수정, 추가 등의 작업을 하게될 때의 병합을 말한다.

 

위의 그림에서 master는 c4 체크포인트를, iss53은 c3 체크포인트를 가리키고 있다.

master와 iss53이 각각 수정, 추가 등의 작업을 거쳐 각자 다른 체크포인트를 가지게 된 것이다.

 

이때 iss53 브랜치를 중심으로 master 브랜치를 병합하게 되면 다음의 그림이 된다.

 

 

이전의 fast-forward 방식처럼 이미 존재하는 체크포인트를 가리키게 되는 것이 아니라 새로운 체크포인트인 c5를 만든다.

 

 

충돌 해결

병합한 두 브랜치에서 같은 파일을 변경했을 때 충돌이 발생한다.

 

같은 repository에 대해 작업 내용은 다르지만 같은 파일을 건드리지는 않았을 경우에는 아무 문제 없이 정상적으로 병합이 진행된다.

그러나 같은 파일에 대한 수정 기록이 존재할 때에는 해당 파일에서 충돌이 발생한다.

 

충돌이 발생한 경우에는 자동으로 병합을 할 수 없으며 사용자가 직접 충돌을 해결하고 난 이후에 다시 병합을 진행할 수 있다.

 

충돌의 발생 여부는 git status 명령어로 확인할 수 있다.

병합이 진행되지 않고 에러가 발생한 경우에는 git status 명령어를 입력 시 충돌이 일어난 파일이 both modified 상태임을 알 수 있다.

 

이때 해당 파일을 열어보면 각 브랜치에서 어느 부분을 수정하였는지 표시가 되어있다.

따라서 코드를 수정한 후 저장을 하면 파일은 다시 modified 상태가 되고 add, commit 등의 작업을 거친 후 정상적으로 병합을 진행할 수 있다.

 

✏️ 예제

 

 

git repository를 생성하면 기본적으로 master 브랜치가 생성된다.

초기의 상태에서 git branch 명령어로 생성된 브랜치를 확인하면 위와 같이 master 브랜치만이 존재한다.

 

 

git branch 명령어로 temp라는 브랜치를 만들고 생성된 브랜치를 확인해 보았다.

temp라는 브랜치가 정상적으로 생성되었고 아직은 master 브랜치에 위치하는 것을 볼 수 있다.

 

 

git checkout 명령어를 통해 현재 브랜치를 temp로 바꾸었다.

* 기호와 글자색이 초록색으로 변한 것으로 보아 현재 브랜치가 temp로 변경되었음을 알 수 있다.

 

 

temp 브랜치 내에서 a.py의 내용을 변경한 후에 add, commit의 작업을 거쳤다.

git log --graph로 확인해본 결과 커밋이 정상적으로 진행된 것을 볼 수 있다.

 

 

이후 다시 master 브랜치로 이동한 후 a.py의 내용을 변경하였고 add, commit의 과정까지 거쳤다.

a.py라는 같은 파일을 temp 브랜치와 master 브랜치에서 각각 변경한 것이다.

 

 

master 브랜치에서 temp 브랜치와 병합하기 위해 git merge 명령어를 입력했더니 충돌이 발생했다는 문구와 함께 Automatic merge failed 라고 뜨며 병합이 실패했다.

git status 명령어를 입력하면 문제가 되는 파일인 a.py가 both modified 상태임을 알 수 있다.

 

 

이때 a.py를 열어보면 다음과 같은 표시가 되어있다.

=====를 기점으로 <<< HEAD 부분은 현재 HEAD 포인터가 가리키고 있는 브랜치인 master 브랜치에서 수정한 부분이고 >>> temp는 temp 브랜치에서 수정한 내용이다.

사용자는 이를 보고 a.py의 내용을 알맞게 수정한 후 저장하면 된다.

 

 

a.py의 내용을 알맞게 수정한 후 다시 add, commit의 과정을 거쳤다.

이후 git merge 명령어를 통해 temp 브랜치와 병합을 시도하면 아까와는 달리 정상적으로 병합이 실행되었음을 알 수 있다.

 

 

병합이 끝난 후 git log --graph로 확인해 보면 가지치기로 branch가 갈라져 각각 파일을 수정, 커밋한 기록이 있지만 병합이 끝난 후 정상적으로 합쳐진 가지를 볼 수 있다.

 

 

🔍 참조

git branch https://git-scm.com/book/en/v2/Git-Branching-Branches-in-a-Nutshell

 

 

 

 

 

'엘리스 AI 트랙 4기 > elice AI track' 카테고리의 다른 글

[2주차] JavaScript와 데이터 타입  (0) 2022.01.18
[1주차] git 원격 저장소  (0) 2022.01.17
[1주차] git 명령어  (0) 2022.01.17
[1주차] git  (0) 2022.01.17
[1주차] 미디어쿼리  (0) 2022.01.13

댓글