[이전 포스트]
[Git] 버전 관리의 꽃, 브랜치(branch)
[이전 포스트] [Git] Git 내부 구조 알아보기, objects - commit, blob, tree[ 이전 포스트 ] [Git] 개발자 필수 도구, Git이 뭔데?Git이란?Git은 소스코드나 파일의 변화를 추적하는 버전 관리 시스템(VCS, Versio
300-29-1.tistory.com
Git - 브랜치와 Merge 의 기초
Merge 시에 발생한 충돌을 다루는 더 어렵고 요상한 내용은 뒤에 고급 Merge 에서 다루기로 한다.
git-scm.com
'깃북 3.2 브랜치와 Merge 기초'에 대한 발췌 및 정리입니다.
Merge는 언제 쓸까
브랜치와 Merge는 보통 아래와 같은 상황에서 적용합니다.
- 운영중인 서비스가 존재하고, 뭔가 작업을 진행하고 있습니다.
- 새로운 이슈를 처리할 새 Branch(ex. #issue 53)를 하나 생성합니다.
- 새로 만든 Branch에서 작업을 진행합니다.
이 때,
중요한 문제가 하나 생겨서
이를 해결하는 Hotfix를 먼저 만들고 처리해야 합니다.
이를 위해,
- 새로운 이슈를 처리하기 이전의 운영(Production) 단계 브랜치로 이동합니다.
- Hotfix 브랜치를 새로 하나 생성합니다.
- 수정한 Hotfix에 대해, 테스트를 마치고 이를 운영 브랜치로 Merge 합니다.
- 다시 #iss 43 브랜치로 돌아가 하던 일을 마저 진행합니다.
이 때 2번 상태의 커밋 히스토리와 브랜치를 표현하면 다음과 같습니다.
운영 단계의 브랜치를 master이라 하면,
이처럼 운영 단계의 브랜치,
즉 커밋 C2에서
#iss53 이슈를 해결하기 위해 iss53 브랜치를 만들고
핫픽스 해결을 위해 hotfix 브랜치도 만든 상태입니다.
Fast forward merging
3번 과정에 대해 설명하겠습니다.
master 브랜치에서 갈라져 나온 hotfix에 대해,
문제를 제대로 고쳤는지 테스트하고 이를 운영환경에 반영 및 배포하려면
테스트 이후 hotfix 브랜치를 master 브랜치와 합쳐야 합니다.
이를 branch merging이라 하며, git merge 명령으로 실행합니다.
merge를 수행할 브랜치로 checkout(이동) 한 뒤,
merge 당할 브랜치를 인자로 전해주면 됩니다.
$ git checkout master
$ git merge hotfix
Updating f42c576..3a0874c
Fast-forward
index.html | 2 ++
1 file changed, 2 insertions(+)
hotfix 브랜치가 가리키는 C4 커밋은,
C2 커밋에 기반해있습니다.
따라서 이 때의 merge는 딱히 무언가 병합하는 과정 없이
브랜치를 그저 최신 커밋으로 옮기게 됩니다(정확히는 hotfix의 head로).
이런 merge 방식을
“Fast forward” 라고 부릅니다.
단지 master 브랜치가 hotfix의 HEAD를 가리키게 했을 뿐입니다.
이후 다시 #iss53 을 해결하러 브랜치를 변경해야 하는데,
그 전에 더 이상 필요 없는 hotfix 브랜치는 삭제합니다.
git branch 명령에 -d 옵션을 주고 브랜치를 삭제합니다.
$ git branch -d hotfix
Deleted branch hotfix (3a0874c).
자 이제 이슈 53번을 처리하던 환경으로 되돌아가서 하던 일을 계속 합니다.
$ 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(+)
위에서 작업한 hotfix 브랜치가 iss53 브랜치에 영향을 미치지 않는다는 점을 이해하는 게 중요합니다.
Merge의 기초, 3-way merge
53번 이슈를 다 구현하고 master 브랜치에 Merge 하는 과정을 살펴봅시다.
iss53 브랜치를 master 브랜치에 Merge 하는 것은
앞서 살펴본 hotfix 브랜치를 Merge 하는 것과 비슷합니다.
git merge 명령으로 합칠 브랜치에서 합쳐질 브랜치를 Merge 하면 됩니다.
$ git checkout master
Switched to branch 'master'
$ git merge iss53
Merge made by the 'recursive' strategy.
index.html | 1 +
1 file changed, 1 insertion(+)
hotfix 를 Merge 했을 때와 메시지가 다릅니다.
현재 브랜치가 가리키는 커밋이 Merge 할 브랜치의 조상이 아니므로,
Git은 'Fast-forward’방식으로 Merge 하지 않습니다.
이 경우에는 Git은 각 브랜치가 가리키는 커밋 두 개와
공통 조상 하나를 사용하여 3-way Merge를 합니다.
Fast forward 처럼 단순히 브랜치 포인터를 최신 커밋으로 옮기는 게 아니라,
3-way Merge의 결과를 별도의 커밋으로 만들고 나서
Merge를 진행한 해당 브랜치가 그 커밋을 가리키도록 이동시킵니다.
따라서
이런 커밋은 부모가 여러 개 이며,
Merge 커밋이라고 부릅니다.
정상적으로 Merge가 끝났다면, 더 이상 iss53 브랜치는 필요없으니 삭제합니다.
이후 #iss53 이슈의 상태를 처리 완료로 표시합니다.
$ git branch -d iss53
충돌, Conflict
가끔씩 3-way Merge가 실패할 때도 있습니다.
바로 Merge 하는 두 브랜치에서,
같은 파일의 동일한 부분을 동시에 다르게 수정하고
Merge 하면 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.
일단 Conflict 되면, Git은 자동으로 Merge를 진행하지 못해
새 커밋이 생기지 않습니다.
변경 사항의 충돌을 개발자가 해결하지 않는 한 Merge 과정을 진행할 수 없습니다.
이 때 Git이 어떤 파일을 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의 내용이고,
아래쪽은 병합당하는 iss53 브랜치의 내용입니다.
충돌을 해결하려면 위쪽이나 아래쪽 내용 중에 하나를 고르거나,
새로 작성해 Merge 해야 합니다.
이후 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
충돌을 해결한 이후 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.
# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.
# On branch master
# All conflicts fixed but you are still merging.
#
# Changes to be committed:
# modified: index.html
#
어떻게 충돌을 해결했는지,
좀 더 확인해야 하는 부분은 무엇인지,
왜 그렇게 해결했는지에 대해 자세하게 기록해야 합니다.
자세한 기록은 나중에 이 Merge 커밋을 이해하는데 도움을 줍니다.
[다음 포스트]
[Git] 버전 관리의 꽃 3, 기본이자 유용한 전략
Git - 브랜치 워크플로Git은 꼼꼼하게 3-way Merge를 사용하기 때문에 장기간에 걸쳐서 한 브랜치를 다른 브랜치와 여러 번 Merge 하는 것이 쉬운 편이다. 그래서 개발 과정에서 필요한 용도에 따라 브
300-29-1.tistory.com
Ref.
Git - 브랜치와 Merge 의 기초
Merge 시에 발생한 충돌을 다루는 더 어렵고 요상한 내용은 뒤에 고급 Merge 에서 다루기로 한다.
git-scm.com
git merge — Key Puncher
Git 7: Merging
www.keypuncher.net
'프로젝트 생산성' 카테고리의 다른 글
[Git] 협업 필수, 원격 브랜치(remote branch) (0) | 2024.09.14 |
---|---|
[Git] 버전 관리의 꽃 3, 기본이자 유용한 전략 (0) | 2024.09.14 |
[Git] 버전 관리의 꽃, 브랜치(branch) (3) | 2024.09.14 |
[Git] Git 내부 구조 알아보기, objects - commit, blob, tree (0) | 2024.09.12 |
[Git] 개발자 필수 도구, Git이 뭔데? (1) | 2024.09.11 |