✅ Merge
실제 개발과정에서 겪을 만한 예제를 하나 살펴보겠습니다. 브랜치와 Merge는 보통 이런 식으로 진행합니다.
- 웹 사이트를 제작하기 위한 master 브런치가 있다.
- 새로운 이슈를 처리할 새 Branch를 하나 생성한다.
- 새로 만든 Branch에서 작업을 진행한다.
이때 중요한 문제가 생겨서 그것을 해결하는 Hotfix를 먼저 만들고 해결하는 과정도 있습니다.
- 새로운 이슈를 처리하기 이전의 운영(Production) 브랜치로 이동한다.
- Hotfix 브랜치를 새로 하나 생성한다.
- 수정한 Hotfix 테스트를 마치고 운영 브랜치로 Merge 한다.
- 다시 작업하던 브랜치로 옮겨가서 하던 일 진행한다.
✅ iss53
기존의 웹 사이트를 제작하기 위해 생성한 로컬 저장소의 master 브런치의 총 3번 커밋하였습니다. 이때 시스템의 이슈를 처리해야해서, 해당 이슈에만 집중할 수 있는 브런치를 새로 하나 만듭니다. 명령어는 다음과 같습니다.
#기존의 사용하던 명령어
git branch [new branch]
git checkout [new branch]
#위 두 명령어를 하나로 줄여놓은
git checkout -b [new branch]
#예시
git checkout -b iss53
기존 브런치에서 새 브런치를 생성하면 두 브런치는 동일한 커밋 객체를 가리키고 있습니다. iss53으로 Checkout 했기 때문에 현재 HEAD는 iss53 브런치의 가장 마지막 커밋인 C2를 가리키고 있게 됩니다. 이때 iss53 브런치에서 새로운 커밋을 작성하면 아래와 같이 iss53 브런치 포인트가 앞으로 나아갑니다.
#새로운 커밋을 하기 위한 준비
echo "iss53" >> iss53.txt
#새로운 커밋
git add iss53.txt
git commit -m "add iss53.txt"
#브런치 확인하기
git log --oneline --decorate --graph --all
위와 같이 서로 다른 커밋 객체를 가지고 있는 브런치 사이를 이동할 때는 아래와 같은 명령어를 사용하면 됩니다.
git checkout [브런치명]
git checkout master
git은 위의 명령어를 사용할 경우, branch를 이동하는 것은 물론 워킹 디렉토리(작업 공간)의 파일도 master 브런치가 가리키고 있는 커밋 객체의 시점으로 되돌아가게 됩니다. 그렇기에 만약 커밋하지 않은 파일이 존재하고 Checkout할 브랜치와 충돌이 날 경우 브랜치를 변경할 수 없습니다. 브랜치를 변경해야할 때에는 워킹 디렉토리를 깔끔하게 정리( 커밋이나 충돌날 일이 없게 파일 치우기)하는 것이 좋습니다.
✅ hotfix
위와 같은 상황에서 master 브랜치를 운영하던 중에 긴급한 문제가 생겨 hotfix 브런치를 만들고 해당 문제를 해결해야하는 상황일 때를 예로 들어보겠습니다.
master 브랜치로 돌아가 hotfix 브런치를 만들고 해당 문제를 처리하는 commit을 수행하면 아래와 같은 그림이 됩니다.
#master 브랜치로 이동 후 hotfix 브런치 생성
git checkout master
git checkout -b hotfix
#문제 처리 및 commit
echo "hotfix" >> hotfix.txt
git status
git add hotfix.txt
git commit -m "add hotfix.txt"
#브런치 확인
git log --oneline --decorate --graph --all
hotfix에서 문제를 해결하고 기존에 운영하던 master 브랜치에 합치려면 다음과 같은 명령어를 수행하면 됩니다. 이때 기존의 master 브랜치로 이동한 후 hotfix 브런치를 merge하면 됩니다.
git checkout master
git merge hotfix
Merge 메시지에서 “fast-forward” 가 보이나요? hotfix
브랜치가 가리키는 C4
커밋이 C2
커밋에 기반한 브랜치이기 때문에 브랜치 포인터는 Merge 과정 없이 그저 최신 커밋으로 이동합니다. 이런 Merge 방식을 “Fast forward” 라고 부릅니다. 다시 말해 A 브랜치에서 다른 B 브랜치를 Merge 할 때 B 브랜치가 A 브랜치 이후의 커밋을 가리키고 있으면 그저 A 브랜치가 B 브랜치와 동일한 커밋을 가리키도록 이동시킬 뿐입니다.
이후 더 이상 필요 없는 hotfix 브런치를 삭제하면 master 브런치는 급한 문제를 해결한 브랜치가 되고, iss53는 기존의 이슈를 처리하는 브런치로 여전히 남아있게 됩니다.
git branch -d hotfix
- master과 별개인 iss53
iss53은 아직 어떠한 작업도 수행하지 않았습니다. iss53에서 해당 이슈를 처리하고 새로운 commit을 생성해보겠습니다.
#이슈 처리하기 git checkout iss53 echo "iss53" >> iss53.txt git commit -a -m "modified iss53.txt" #확인 git log --oneline --decorate --graph --all
위에서 작업한
hotfix
가iss53
브랜치에 영향을 끼치지 않는다는 점을 이해하는 것이 중요합니다. master과 iss53은 두 개의 독립적은 브랜치로써 부모 커밋 객체는 C2에서 파생되었지만 이제 서로 어떠한 영향도 주지 않습니다.
✅ 3-way Merge
- iss53을 master에 merge 하기
53번 이슈를 다 구현하고 master 브랜치에 Merge 하는 과정을 살펴보겠습니다. 현재 브랜치( iss53 )가 가리키는 커밋이 Merge 할 브랜치( master )의 조상이 아니므로 Git은 'Fast-forward’로 Merge 하지 않습니다. 이 경우에는 Git은 각 브랜치가 가리키는 커밋 두 개와 공통 조상 하나를 사용하여 3-way Merge를 합니다.
git checkout master git merge iss53
단순히 브랜치 포인터를 최신 커밋으로 옮기는 게 아니라 3-way Merge 의 결과를 별도의 커밋으로 만들고 나서 해당 브랜치가 그 커밋을 가리키도록 이동시킵니다. 그래서 이런 커밋은 부모가 여러 개인 Merge 커밋이라고 부릅니다.
iss53 브랜치를 master에 Merge 하고 나면 더는 iss53 브랜치가 필요 없기 때문에 다음 명령으로 브랜치를 삭제하고 이슈의 상태를 처리 완료로 표시합니다.
git branch -d iss53
✅ 3-way Merge 충돌
가끔씩 3-way Merge가 실패할 때도 있습니다. Merge 하는 두 브랜치에서 같은 파일의 한 부분을 동시에 수정하고 Merge할 때 Git은 해당 부분을 Merge 하지 못 합니다. 예를 들어, master 브랜치와 conflict 브랜치가 같은 파일의 같은 부분을 수정할 경우를 예로 들어보겠습니다.
- conflictMerge 브랜치 생성
master에 conflict을 실험할 index.html을 추가하고 conflict 브랜치를 생성합니다.
#conflict에 사용할 파일 준비 echo "<div id="footer">contact : jhcode33@gmail.com</div>" >> index.html git add index.html git commit "add index.html" #conflict 브런치 생성 및 commit 추가 git checkout -b conflict echo "<div id="footer"> please contact us at jhcode33@gmail.com </div>" >> index.html git commit -a -m "modified index.html" #master 브런치에서 index.html 수정 git checkout master echo "add conflict" >> index.html git commit -a -m "modified index.html to master"
- merge 충돌
#merge 충돌 git merge conflic #충돌 확인 git status
Git은 자동으로 Merge 하지 못해서 새 커밋이 생기지 않습니다. 변경사항의 충돌을 개발자가 해결하지 않는 한 Merge 과정을 진행할 수 없습니다. Merge 충돌이 일어났을 때 Git이 어떤 파일을 Merge 할 수 없었는지 살펴보려면
git status
명령어를 사용합니다.충돌이 일어난 파일은 unmerged 상태로 표시됩니다. Git은 충돌이 난 부분을 표준 형식에 따라 표시해주고, 개발자는 해당 부분을 수동으로 해결합니다. 충돌 난 부분은 아래와 같이 표시됩니다.
<div id="footer">contact : jhcode33@gmail.com</div> 이 부분은 부모 커밋이 가지고 있던 코드이지만 아래 코드는 각각의 브런치에서 수정하고 커밋한 코드입니다.
- add conflict : master
- <div id=footer …..</div> : conflict
👉 충돌을 해결하기 위해서는 위쪽이나 아래쪽의 내용을 선택하거나 아예 새로 작성하여 commit하면 됩니다.
Notepad++ 오류가 난 파일을 열어 직접 수정했습니다. 충돌이 일어났을 때 사용할 수 있는 다양한 툴이 있습니다. 현재는 Merge 충돌이 일어났을 때 어떻게 하면 해결할 수 있는지 학습하는 과정일 뿐, 툴을 사용하면 더 쉽고 간편하게 해결할 수 있습니다. 아래와 같은 명령어를 입력하여 merge를 마무리 합니다.
git add index.html git commit -m "both modified complete"
🏷️이미지 출처 및 참고한 사이트
Uploaded by N2T