지금까지 브랜치와 Fork로 Pull Request를 생성하고, 이를 머지하는 다양한 방법들에 대해서 다뤘습니다. 이 레슨에서는 머지시 충돌이 발생했을 때 해결하는 방법에 대해서 다루도록 하겠습니다.
충돌이란?
Git에서 충돌은 머지하는 과정에서 발생하는 현상입니다. 충돌은 동일한 파일 또는 동일한 부분에서 서로 다른 변경 사항이 생길 때 발생합니다. 이는 Git System이 어떻게 두 가지 변경 사항을 머지해야 할지 알 수 없을 때 발생하는 문제입니다.
일반적으로 두 브랜치를 머지하려고 할 때, Git은 자동으로 병합을 시도하는데요. 이 과정에서 두 브랜치가 동일한 파일 또는 동일한 부분을 수정한 경우, Git은 충돌이 발생했다고 판단합니다.
Git은 충돌이 발생한 파일을 특수한 형식으로 표시하여 사용자가 충돌을 해결할 수 있도록 도와줍니다. 일반적으로 충돌 부분은 <<<<<<<, =======, >>>>>>>와 같은 마커로 표시하고, 이 마커 사이에는 충돌을 발생시킨 변경 사항이 포함되어 있습니다.
충돌을 해결하기 위해서는 원인이 되는 파일을 열어 직접 수정해야 합니다. 수정된 파일은 변경 사항을 표시하는 적절한 코드로 수정되어야 합니다. 수정이 완료되면 충돌이 해결된 것으로 간주하고 변경 사항을 저장하고 커밋합니다.
충돌 해결 과정
여기서 충돌 해결에 대해 간단하게 설명드리도록 하겠습니다. 먼저 충돌을 발생시켜보는 것이 편하겠죠?
기존 repository로 이동하고, 다음 명령어를 따라서 입력해 보도록 합시다.
git checkout -b test/branch1
echo 'print("hello")' > test.py
git add test.py
git commit -m "feat: implement print hello"
git push origin
git checkout main
echo 'print("codeit")' > test.py
git add test.py
git commit -m "feat: implement print codeit"
git push origin
test/branch1을 push 했을 때 생성된 PR 링크로 들어가 봅시다.
push시에 아래와 같이 출력이 됐을 것입니다.
remote:
remote: Create a pull request for 'test/branch1' on GitHub by visiting:
remote: https://github.com/xxxxxxx/my-test-repository/pull/new/test/branch1
remote:
To github.com:xxxxx/my-test-repository.git
Pull Reqeust에서 충돌 해결하기
Pull Request의 구현 과정을 자세히 들여다 보면, 두 개의 서로 다른 브랜치를 병합하는 과정입니다. 그렇기 때문에 충돌이 발생할 수도 있는 것이죠. GitHub에서 생성한 Pull Request에서 충돌이 발생하면 다음과 같은 화면을 볼 수 있습니다.
Untitled
이렇게 충돌이 발생하게 되면 해결하는 방법은 크게 2가지입니다.
Resolve conflicts 버튼을 눌러 해결하기
로컬에서 충돌 해결 하기
이 두가지 방법은 근본적으로 같은 방법으로 충돌을 해결합니다.
Resolve Conflict 버튼을 눌러 해결하기
Resolve conflicts 버튼을 누르게 되면 GitHub에서 main을 test/branch1으로 병합하게 됩니다.
실제로 버튼을 누르게 되면 아래와 같은 UI를 확인할 수 있습니다.
Untitled
이제 우리에게는 4가지를 옵션이 있는데요.
현재 브랜치의 내용을 선택하는 것 (main, print("codeit")를 사용)
Accept Current
가져오는 브랜치의 내용을 선택하는 것 (test/branch1 print("hello")를 사용)
Accept Incomming
두 가지 모두를 선택하는 것
Accept Both
두 코드를 보고 직접 수정하는 것
<<< === >>> 를 삭제 후 직접 코드를 수정
충돌을 해결하고, Mark as resolved 버튼을 클릭해 볼게요. 다음과 같이 Commit merge라고 쓰인 녹색 버튼이 활성화 됩니다. 이 버튼을 누르면 변경 사항을 커밋할 수 있습니다.
Untitled
아래 커밋 내역을 보면 main을 test/branch1으로 브랜치로 머지했다는 것을 확인할 수 있습니다.
Untitled
이는 main으로 바로 병합할 수 없어서 main을 먼저 test/branch1로 병합하고(Resolve conflicts 버튼), 그 이후 Merge pull request 버튼을 통해 test/branch1을 main으로 병합하기 위함입니다.
로컬에서 해결하기
하지만 GitHub UI로 충돌을 해결하는 방식은 다소 위험할 수 있습니다. GitHub UI 상에서는 복잡한 코드의 흐름을 파악하기도 힘들고, 통합개발환경(IDE)이나 Editor의 지원이 없기 때문에 실수를 하거나 컴파일조차 되지 않는 커밋을 생성할 수도 있습니다. 복잡하게 얽힌 충돌의 경우 로컬에서 해결하는 것이 안전합니다.
가장 먼저 해당하는 브랜치로 이동합니다.
git checkout test/branch1
자 이제 checkout을 했으니 코드를 머지해야겠죠?
git merge main
이 명령어를 사용하면 충돌이 발생했을 것입니다. 우리는 이미 GitHub UI에서 해당 충돌을 해결해 보았습니다. 로컬에서도 같은 방식으로 진행하면 됩니다.
먼저 텍스트 편집기로 해당 파일을 열어서 <<<< ===== >>>> 로 표시 돼 있는 부분을 직접 수정합니다.
수정된 파일을 저장한 후, git add와 git commit을 사용하여 해당 파일의 병합이 완료되었음을 Git에 알릴 수 있습니다. 이렇게 하면 Git 시스템에 머지가 완료되었다는 정보가 기록됩니다.
git push를 수행하면 성공적으로 충돌을 해결할 수 있습니다.
머지를 위한 툴들
VS Code의 최신 버전에서는 머지툴을 제공합니다. 만약 아래 예제처럼 버튼 예제가 나오지 않는다면 VS Code를 업데이트해 보세요.
먼저 충돌을 발생시키고, 충돌이 발생한 파일을 VS Code로 켜보면 다음과 같은 버튼이 있습니다.
Untitled
Resolve in Merge Editor 버튼을 클릭하면 아래와 같은 UI가 나옵니다.
Untitled
왼쪽이 incoming이고, 오른쪽이 current입니다. 그리고 그 결과가 아래쪽에 나옵니다. 이는 VS Code에서 머지하는 방법을 편리하게 만들어 주는 것일 뿐인데요. 충돌을 해결한다는 본질은 텍스트 편집기에서 직접 편집하는 것과 크게 다르지 않습니다.
정리
이번 레슨에서는 Git, 특히 GitHub의 Pull Request에서 머지 과정에서 충돌이 발생했을 때 해결하는 방법에 대해서 다루었습니다. 충돌은 두 브랜치에서 같은 부분을 수정할 때 발생했는데요. Git은 충돌한 부분을 표시해 주고, 사용자가 해당 부분을 수동으로 수정하도록 도움을 줍니다. 사용자는 충돌을 해결한 후, 변경 사항을 저장하고 커밋하면 됩니다.
GitHub의 Pull Request에서 충돌이 발생했을 때 해결하는 방법 두 가지를 배웠는데요. 첫째로 GitHub의 Resolve conflicts 버튼을 사용하는 방법, 둘째로 로컬에서 충돌을 해결하는 방법입니다. 복잡한 충돌의 경우 로컬에서 해결하는 것이 바람직합니다.
충돌 해결에 도움을 주는 도구로는 VS Code의 머지툴이 있습니다. 이는 충돌 발생 부분을 시각적으로 표시해 주고, 수정 후 결과를 보여줘서 편리하게 충돌을 해결할 수 있습니다.