Merge 충돌
Merge 충돌은 Merge Request의 두 브랜치(소스와 대상) 각각이 다른 변경 사항을 가지고 있을 때 발생하며, 어떤 변경 사항을 승인할지 결정해야 합니다. Merge Request에서 Git은 파일의 두 버전을 행 단위로 비교합니다. 대부분의 경우, GitLab은 변경 사항을 함께 Merge할 수 있지만, 두 브랜치가 동일한 행을 변경하는 경우 GitLab은 Merge을 차단하고 어떤 변경 사항을 유지할지 선택해야 합니다:
충돌이 있는 Merge Request은 다음 중 하나를 수행하기 전까지 Merge될 수 없습니다:
- Merge 커밋 생성
- 리베이스를 통한 충돌 해결
GitLab은 충돌을 해결하기 위해 소스 브랜치에 Merge 커밋을 생성하지만, 이를 대상 브랜치에 Merge하지는 않습니다. 그런 다음 Merge 커밋을 검토하고 테스트할 수 있습니다. 의도하지 않은 변경 사항이 포함되지 않았는지 확인하고 빌드를 망가뜨리지 않는지 확인하세요.
충돌 블록 이해
Git이 확인 필요한 충돌을 감지하면 충돌 블록의 시작과 끝을 충돌 마커로 표시합니다:
-
<<<<<<< HEAD
는 충돌 블록의 시작을 표시합니다. - 여러분의 변경 사항이 표시됩니다.
-
=======
는 여러분의 변경 사항의 끝을 표시합니다. - 대상 브랜치의 최신 변경 사항이 표시됩니다.
-
>>>>>>>
은 충돌의 끝을 표시합니다.
충돌을 해결할 때 다음을 삭제합니다:
- 유지하려는 충돌 라인의 버전.
- 충돌 마커 중에서 시작, 끝,
=======
라인 세 가지.
사용자 인터페이스에서 해결할 수 있는 충돌
Merge 충돌이 모두 아래 조건을 충족하면 GitLab 사용자 인터페이스에서 Merge 충돌을 해결할 수 있습니다:
- 파일이 텍스트이고 이진이 아닙니다.
- 파일이 UTF-8 호환 인코딩입니다.
- 파일에 이미 충돌 마커가 없습니다.
- 충돌 마커가 추가된 파일 크기가 200KB 미만입니다.
- 파일이 두 브랜치 모두 동일한 경로에 존재합니다.
만약 여러분의 Merge Request에 어떤 파일이 충돌을 포함하고 있지만, 모든 조건을 충족시키지 못하는 경우, 충돌을 매뉴얼으로 해결해야 합니다.
GitLab이 감지하지 못하는 충돌
GitLab은 두 브랜치가 파일명을 다른 이름으로 변경할 때 충돌을 감지하지 못합니다. 예를 들어, 다음 변경 사항은 충돌을 생성하지 않습니다:
-
one
브랜치가example.txt
를example1.txt
로 이름을 바꿉니다. -
two
브랜치가example.txt
를example_old.txt
로 이름을 바꿉니다.
이러한 브랜치가 Merge되면 example1.txt
와 example_old.txt
둘 다 존재하게 됩니다.
충돌 해결 방법
GitLab은 사용자 인터페이스에서 해결할 수 있는 충돌을 보여주며, 여러분은 명령 줄을 통해 로컬에서도 충돌을 해결할 수 있습니다:
- 대화형 모드: 수정 없이 유지할 행의 버전을 선택하는데만 필요한 충돌에 대한 UI 방법
- 인라인 편집기: 줄을 편집하고 변경 사항을 매뉴얼으로 혼합해야 하는 더 복잡한 충돌에 대한 UI 방법
- 명령 줄: 가장 복잡한 충돌에 대해 완전한 제어를 제공합니다.
대화형 모드
GitLab 사용자 인터페이스에서 Merge 충돌을 해결하려면:
- 왼쪽 사이드바에서 검색 또는 이동을 선택하고 프로젝트를 찾습니다.
- 코드 > Merge Request을 선택하고 Merge Request을 찾습니다.
- 개요를 선택하고 Merge Request 보고서 섹션으로 스크롤합니다.
-
Merge 충돌 메시지를 찾고 충돌 해결을 선택합니다. GitLab은 충돌이 있는 파일 디렉터리을 표시합니다. 충돌이 있는 라인은 강조 표시됩니다:
- 각 충돌에서 우리 것 사용 또는 그들 것 사용을 선택하여 유지하려는 충돌 라인의 버전을 표시합니다. 이 결정은 “충돌 해결”이라고 합니다.
- 모든 충돌을 해결한 후, 커밋 메시지를 입력합니다.
- 소스 브랜치에 커밋을 선택합니다.
충돌 해결은 Merge Request의 대상 브랜치를 소스 브랜치에 Merge하여 여러분이 선택한 텍스트의 버전을 사용합니다. 소스 브랜치가 feature
이고 대상 브랜치가 main
인 경우, 이 동작은 로컬에서 git switch feature; git merge main
을 실행하는 것과 유사합니다.
인라인 편집기에서
일부 Merge 충돌은 더 복잡하며, 충돌을 해결하기 위해 줄을 매뉴얼으로 수정해야 할 수 있습니다. Merge 충돌 해결 편집기는 이러한 복잡한 충돌을 GitLab 인터페이스에서 해결하는 데 도움을 줍니다:
- 왼쪽 사이드바에서 검색 또는 이동을 선택하고 프로젝트를 찾습니다.
- 코드 > Merge Request을 선택하고 Merge Request을 찾습니다.
- 개요를 선택하고 Merge Request 보고서 섹션으로 스크롤합니다.
- Merge 충돌 메시지를 찾고 충돌 해결을 선택합니다. GitLab은 충돌이 있는 파일 디렉터리을 표시합니다.
- 직접 편집하려는 파일을 찾고, 충돌 블록으로 스크롤합니다.
-
해당 파일의 헤더에서 편집하려면 인라인 수정을 선택하여 편집기를 엽니다. 이 예에서 충돌 블록은 1350행에서 시작하여 1356행에서 끝납니다:
- 충돌을 해결한 후, 커밋 메시지를 입력합니다.
- 소스 브랜치에 커밋을 선택합니다.
명령 줄에서
대부분의 충돌은 GitLab 사용자 인터페이스를 통해 해결할 수 있지만, 일부는 너무 복잡하기 때문에 로컬에서 명령 줄을 통해 해결하는 것이 더 좋습니다. 가장 복잡한 충돌은 각 변경 사항에 대한 최대한의 제어를 제공하기 위해 명령 줄로 고치는 것이 좋습니다.
전제 조건:
- 브랜치에 강제로 푸시할 권한이 있어야 합니다.
-
터미널을 열고 여러분의 기능 브랜치를 확인합니다. 예를 들어,
my-feature-branch
:git switch my-feature-branch
-
브랜치를 리베이스하고 (여기서
main
으로) 대상 브랜치에 대해 리베이스하여 Git이 여러분에게 충돌을 알려주기를 요청하십시오:git fetch git rebase origin/main
- 선호하는 코드 편집기에서 충돌 파일을 엽니다.
- 충돌 블록을 찾습니다.
- 파일을 수정합니다:
- 유지하려는 버전(또는
=======
이전 또는 이후)을 선택합니다. - 유지하지 않을 버전을 삭제합니다.
- 충돌 마커를 삭제합니다.
- 유지하려는 버전(또는
- 파일을 저장합니다.
- 충돌을 포함하는 각 파일에 대해이 프로세스를 반복합니다.
-
Git에서 변경 사항을 스테이징합니다:
git add .
-
변경 사항을 커밋합니다:
git commit -m "Merge 충돌 해결"
-
리베이스를 계속합니다:
git rebase --continue
여기까지는git rebase --abort
를 실행하여 프로세스를 중지할 수 있습니다. Git은 리베이스를 중단하고git rebase
를 실행하기 전의 상태로 브랜치를 되돌립니다.git rebase --continue
를 실행한 후에는 리베이스를 중단할 수 없습니다. - 변경 사항을 여러분의 원격 브랜치에 강제로 푸시합니다.