브랜치란 무엇인가?
파일을 Stage하면
- Git 저장소에 파일을 저장하고( Blob )
- Staging Area에 해당 파일의 체크썸을 저장한다.
$ git add README test.rb LICENSE
$ git commit -m 'The initial commit of my project'
git commit으로 커밋하면
- 먼저 루트 디렉터리와 각 하위 디렉터리의 트리 개체를 체크섬과 함께 저장소에 저장한다.
- 커밋 개체를 만들고 메타데이터와 루트 디렉터리 트리개체를 가리키는 포인터 정보를 커밋 개체에 넣어 저장한다. 그래서 필요하면 언제든지 스냅샷을 다시 만들 수 있다.
- 이 작업을 마치고 나면 Git 저장소에는 다섯개의 개체가 생긴다.
- 각 파일에 대한 Blob 3개 파일
- 디렉터리 구조가 들어있는 트리개체 하나
- 메타데이터와 루트 트리를 가리키는 포인터가 담긴 커밋 개체 하나
다시 파일을 수정하고 커밋하면
- 이전 커밋이 무엇인지도 저장한다.
- 커밋을 두번 더 하면 다음과 같다.
testing 브랜치를 만든다.
$ git branch testing
Git 은 'HEAD'라는 특수한 포인터가 있다. 이 포인터는 지금 작업 하는 로컬 브랜치를 나타낸다.
testing으로 체크아웃 하면 HEAD는 testing 브랜치를 가리킨다.
$ git checkout testing
커밋을 새로 하면 다음과 같다.
$ vim test.rb
$ git commit -a -m 'made a change'
다시 master 브랜치로 되돌아 가면 다음과 같다.
$ git checkout master
master 브랜치 상태에서 커밋을 하면 프로젝트 히스토리가 분리돼 진행된다.
$ vim test.rb
$ git commit -a -m 'made other changes'
브랜치와 Merge의 기초
브랜치와 Merge는 보통 이런식으로 진행된다.
- 작업 중인 웹사이트가 있다.
- 새로운 이슈 처리할 새 Branch를 하나 생성
- 새로 만든 Branch에서 작업중
이때 중요한 문제가 생겨서 그것을 해결하는 Hotfix를 먼저 만들어야 한다. 그러면 다음과 같이 할 수 있다.
- 새로운 이슈를 처리하기위해 이전의 운영(Production) 브랜치로 복원.
- Hotfix 브랜치를 새로 하나 생성
- 수정한 Hotfix 테스트를 마치고 운영 브랜치로 Merge
- 다시 작업 하던 브랜치로 옮겨가서 하던일 진행.
브랜치의 기초
다음과 같은 상태의 커밋 히스토리이다.
iss53 브랜치를 생성하고 체크아웃 한다.
#$ git branch iss53||git checkout iss53 와 같다.
$ git checkout -b iss53
Switched to a new branch "iss53"
iss53 브랜치에서 커밋한다.
$ vim index.html
$ git commit -a -m 'added a new footer [issue 53]'
master 브랜치로 체크아웃 하기전에 알아야 할 사항이 있다.
- 만약 iss53에서 아직 커밋 하지 않은 파일이 checkout할 브랜치와 충돌 나면 브랜치를 변경할 수 없다.
- 브랜치를 변경할 때에는 Working 디렉터리를 정리하는 것이 좋다.
- 정리 방법은 Stash 나 커밋 Amend이다.
master 브랜치로 체크아웃 한다.
- 이때 Working 디렉터리는 iss53 을 시작하기 이전 모습으로 되돌려지기 때문에 새로운 문제에 집중할 수 있는 환경이 만들어진다.
- Git은 자동으로 Working 디렉터리에 파일들을 추가하고, 지우고, 수정해서 Checkout한 브랜치의 스냅샷으로 되돌려 놓는다.
$ git checkout master
Switched to branch 'master'
hofix 브랜치를 생성 checkout 하고, 오류 수정 커밋을 한다.
$ git checkout -b hotfix
Switched to a new branch 'hotfix'
$ vim index.html
$ git commit -a -m 'fixed the broken email address'
[hotfix 1fb7853] fixed the broken email address
1 file changed, 2 insertions(+)
이후 master 브랜치로 체크아웃 하고 Merge 한다.
- Fast Forward : Merge 할 브랜치(hotfix)가 가리키고 있던 커밋이 현 브랜치(master)가 가리키는 것보다 '앞으로 진행한 커밋'이기 때문에 master 브랜치는 최신커밋으로 이동한다.
$ git checkout master
$ git merge hotfix
Updating f42c576..3a0874c
Fast-forward
index.html | 2 ++
1 file changed, 2 insertions(+)
merge 브랜치 위치에서 hotfix 브랜치를 삭제한다.
$ git branch -d hotfix
Deleted branch hotfix (3a0874c).
iss53 브랜치로 checkout 해서 처리하던 환경으로 되돌아가 하던일을 계속한다.
$ git checkout iss53
Switched to branch "iss53"
$ vim index.html
$ git commit -a -m 'finished the new footer [issue 53]'
[iss53 ad82d7a] finished the new footer [issue 53]
1 file changed, 1 insertion(+)
Merge의 기초
iss53에서 작업을 마쳤으면 master로 체크아웃하고 iss53을 Merge 한다.
- 3-way Merge : 브랜치가 가리키는 커밋 두 개(iss53, master) , 공통조상 하나(C2) 를 사용하여 머지하는 방식
- 3개의 머지 결과를 별도의 커밋으로 만들고 나서 해당 브랜치가 그 커밋을 가리키도록 이동시킨다.
- 이런 커밋은 부모가 여러개고 Merge 커밋이라고 부른다.
- 개발자가 직접 공통조상을 찾아야 하는 다른 CVS와는 달리, Git은 자동으로 최적의 공통조상을 찾아 Merge한다.
$ git checkout master
Switched to branch 'master'
$ git merge iss53
Merge made by the recursive
README | 1 +
1 file changed, 1 insertion(+), 0 deletions(-)
작업을 마치면 iss53 브랜치를 삭제한다.
$ git branch -d iss53
충돌의 기초
가끔씩 3-way Merge가 실패할 때도 있다. Merge하는 두 브랜치에서 같은 파일의 한 부분을 동시에 수정하고 Merge하지 못한다. 예를 들어, 53번 이슈와 hotfix가 같은 부분을 수정했다면 Git은 Merge하지 못하고 다음과 같은 충돌(Conflict) 메시지를 출력한다.
$ git merge iss53
Auto-merging index.html
CONFLICT (content): Merge conflict in index.html
Automatic merge failed; fix conflicts and then commit the result.
Merge 충돌이 일어났을 때 git status 명령을 이용한다.
- 충돌이 난 파일은 unmerged 상태로 표시된다.
$ git status
index.html: needs merge
# On branch master
# Changed but not updated:
# (use 'git add <file>...' to update what will be committed)
# (use 'git checkout -- <file>...' to discard changes in working directory)
#
# unmerged: index.html
#
충돌이 난 부분은 다음과 같이 표시된다.
- ======= 위쪽 내용은 HEAD버젼( merge 명령을 실행할 때 master 브랜치)
- 아래쪽은 iss53 브랜치의 내용이다.
<<<<<<< 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
다음은 아예 새로 작성하여 충돌을 해결하는 예제다.
- 충돌난 부분을 해결하고 git add 명령으로 다시 저장한다.
<div id="footer">
please contact us at email.support@github.com
</div>
git status 명령으로 다시 한번 확인해볼 수 있다.
$ git status
# On branch master
# All conflicts fixed but you are still merging.
# (use "git commit" to conclude merge)
#
# Changes to be committed:
#
# modified: index.html
충돌을 쉽게 해결하기 위해 git mergetool 명령도 있다.
$ git mergetool
git commit 명령으로 Merge 한 것을 커밋한다.
- 충돌을 해결하고 Merge할 때에는 커밋 메시지가 다음과 같다.
- 어떻게 충돌을 해결했고 좀 더 확인해야 하는 부분은 무엇을 어떻게 했는지 자세하게 기록한다.
Merge branch 'iss53'
Conflicts:
index.html
#
# It looks like you may be committing a merge.
# If this is not correct, please remove the file
# .git/MERGE_HEAD
# and try again.
#
'책 > 프로 Git' 카테고리의 다른 글
분산 환경에서의 Git-3 - 프로젝트에 기여하기 - 비공개 대규모 팀 (0) | 2020.07.28 |
---|---|
분산 환경에서의 Git-1 - 분산 환경에서의 Workflow (0) | 2020.07.28 |
Git 브랜치-2 (0) | 2020.07.27 |
Git의 기초 (0) | 2020.07.26 |
Git의 시작 (0) | 2020.07.24 |