브랜치(branch)
독립적인 작업 흐름을 브랜치라 한다. 부모 브랜치로부터 가지처럼 분기되어 새로운 작업 흐름을 만든다. 모든 프로젝트는 하나 이상의 브랜치를 가지고 있으며 각각의 브랜치는 다른 브랜치의 영향을 받지 않기에 여러 작업을 동시에 진행하고 나중에 다른 브랜치와 병합할 수 있다.
브랜치의 종류
브랜치는 조직, 개인 업무에 따라서 다양하게 구분되지만 크게 통합브랜치와 토픽브랜치로 나눌 수 있다.
- 통합 브랜치 : 배포되는 버전을 만드는 브랜치, 그렇기에 통합 브랜치가 가리키는 버전은 버그가 없고 모든 기능이 정상적으로 동작해야한다.
- 토픽 브랜치 : 토픽 브랜치는 버그 수정, 기능 추가 같은 단위 작업을 위한 브랜치이다. 협업을 할 때는 프로젝트 내에서 여러 작업이 동시에 진행되는데 이때 통합 브랜치로부터 토픽 브랜치를 만들어 토픽 브랜치에서 작업을 진행하고 작업이 완료되면 통합 브랜치로 병합한다.
Head 포인터
현재 체크아웃된,활성화된 브랜치를 가리키는 포인터이다. Head를 통해 git은 체크아웃된 브랜치를 알 수 있다. 브랜치 또한 특정 커밋 오브젝트를 가리키는 포인터일뿐이다.
브랜치의 원리
브랜치는 커밋 오브젝트(스냅샷)를 가리키는 포인터이다. 커밋 오브젝트 파일 안에는 트리 파일 포인터, 부모 커밋 객체의 포인터, 저자나 커밋 메세지 같은 메타데이터를 가진다. 트리 파일 안에는 트리 구조로 오브젝트 파일(Blob)의 포인터를 저장하고 있다.
브랜치 생성
master 브랜치만 있는 하나의 프로젝트가 있다. git branch 명령으로 브랜치를 생성한다.
git branch testing
위 명령을 실행하면 testing 브랜치가 생성되며 각 브랜치는 다음의 커밋을 가리킨다. 생성된 브랜치는 체크아웃된 브랜치(master)가 가리키고 있는 커밋을 가리킨다. git은 HEAD 포인터를 통해 어떤 브랜치가 체크아웃 되었는지 알 수 있다.
브랜치 전환하기
git checkout 명령으로 브랜치를 전환 할 수 있다.
git checkout testing
위 명령을 실행하면 HEAD포인터가 testing 브랜치를 가리키게 된다. 브랜치를 전환하면 워킹 디렉터리의 파일이 변경된다는 점을 기억해야 한다. 브랜치 전환 시 브랜치가 가리키고 있는 커밋 오브젝트를 기반으로 워킹 디렉터리에 체크아웃 된다. 따라서 커밋하지 않고 Index에만 변경 사항을 반영하면 브랜치 전환 시 변경 사항을 잃어버리게 된다. 만약 브랜치를 전환해야 하는데 아직 커밋해서는 안된다면 git stash 명령으로 변경 사항을 임시 저장 할 수 있다.
브랜치 확인
브랜치의 히스토리는 git log 명령으로 확인할 수 있다.
git log --decorate --graph --all
브랜치 병합
서로 다른 2개의 브랜치를 병합해야될때 git merge, git rebase 명령을 사용한다.
브랜치의 병합에는 fast-forward 방식과 3-way merge 방식이 있다.
- fast-forward 방식
fast-forward 병합은 그저 브랜치를 이동시키는 것이다. A와 B 브랜치가 있다. B의 커밋 오브젝트는 A의 커밋 오브젝트를 부모로 가지고 있고 A에서 B의 브랜치를 병합하면 fast-forward 병합이 일어나면서 A의 브랜치가 B의 커밋 오브젝트를 가리키게 된다. 사용이 끝난 브랜치는 git branch -d 명령어로 삭제하도록 하자.
git checkout master
git merge hotfix
- 3-way merge 방식
A와 B 브랜치가 있다. B의 커밋 오브젝트는 A의 커밋 오브젝트를 부모로 가지지 않고 A에서 B 브랜치를 병합하면 3-way merge가 일어나면서 별도의 커밋이 만들어진다. 이 커밋을 merge 커밋이라 한다. merge 커밋 오브젝트는 부모 커밋 오브젝트를 여러 개 가지고 있다.
git checkout master
git merge iss53
3-way merge시 충돌이 발생할 수 있다. 두 개의 브랜치에서 A라는 파일의 같은 부분을 수정한 뒤 병합하게 되면 git은 A라는 파일을 어떤 내용으로 채워야 할지 모르기에 충돌이 발생하게 된다. 충돌 발생 시 Git은 자동으로 Merge 하지 못해서 merge 커밋 생성에 실패한다. 이 경우 merge를 진행한 브랜치에서 충돌이 난 파일을 수정한 뒤 커밋해 merge 커밋을 직접 만들어야한다. 어떤 파일을 merge 할 수 없었는지 살펴보려면 git status 명령을 사용한다.
$ git status
On branch master
You have unmerged paths.
(fix conflicts and run "git commit")
Unmerged paths:
(use "git add <file>..." to mark resolution)
both modified: index.html
no changes added to commit (use "git add" and/or "git commit -a")
충돌이 일어난 파일은 unmerged 상태로 표시된다. Git은 충돌이 난 부분을 표준 형식에 따라 표시해준다. 그 부분을 개발자가 직접 수정하면 된다. 충돌 난 부분은 아래와 같이 표시된다.
<<<<<<< HEAD:index.html
<div id="footer">contact : email.support@github.com</div>
=======
<div id="footer">
please contact us at support@github.com
</div>
>>>>>>> iss53:index.html
====== 위쪽의 내용은 HEAD 브랜치(merge를 수행한 브랜치, master)의 내용이며 아래쪽은 merge 대상이 되는 브랜치(iss53)의 내용이다. 충돌을 해결하려면 위쪽이나 아래쪽 내용중에서 고르거나 새로 작성하면 된다.
'CM > Git' 카테고리의 다른 글
Git 히스토리 삭제 (0) | 2024.05.31 |
---|---|
Git 원격 저장소 (0) | 2022.08.04 |
Git 원리 (add,commit,status) (0) | 2022.08.01 |
Git 기초 (0) | 2022.07.31 |