일반적인 Git 병합 충돌 해결: 단계별 문제 해결 가이드

이 필수 문제 해결 가이드를 통해 Git 병합 충돌을 마스터하세요. 충돌 마커(`<<<<<<<`, `>>>>>>>`)를 식별하고, 수동 해결 전략(로컬 유지, 원격 유지 또는 결합)을 적용하며, 병합 또는 리베이스를 안전하게 완료하는 방법을 배우세요. 충돌 해결을 위한 명확한 단계별 지침을 따라 좌절을 생산성으로 바꾸세요.

31 조회수

일반적인 Git 병합 충돌 해결: 단계별 문제 해결 가이드

Git에서 병합 충돌을 겪는 것은 특히 팀원 중 신입인 경우 개발을 중단시킬 수 있습니다. 종종 좌절스러운 장애물로 여겨지지만, 병합 충돌은 Git과 같은 분산 버전 관리 시스템에서 동시 개발의 자연스러운 결과입니다. 이는 Git이 두 브랜치 간의 차이점을 코드의 정확히 동일한 줄에서 자동으로 조정할 수 없음을 나타낼 뿐입니다.

이 가이드는 일반적인 Git 병합 충돌을 식별, 이해 및 체계적으로 해결하는 과정을 분석합니다. 이러한 구조화된 단계를 따르면 충돌을 신속하게 해결하고, 깨끗한 이력을 유지하며, 팀 내에서 원활한 협업을 복원할 수 있습니다.


Git 병합 충돌이란 무엇인가 이해하기

병합 충돌은 Git이 한 브랜치의 변경 사항을 다른 브랜치로 통합하려고 할 때(예: git merge 또는 git rebase 사용), 두 브랜치 모두 동일한 파일의 동일한 줄을 독립적으로 수정한 경우 발생하는 현상입니다. Git은 겹치지 않는 변경 사항을 결합하는 데는 뛰어나지만, 변경 사항이 직접적으로 겹칠 때는 사람의 개입이 필요합니다.

Git이 충돌을 알리는 방법

병합 중에 충돌이 발생하면 Git은 즉시 작업을 중단하고 병합이 실패했음을 알려줍니다. 영향을 받은 파일은 작업 디렉터리에서 충돌 상태로 표시됩니다. 다음을 사용하여 상태를 확인할 수 있습니다.

git status

출력에는 "Unmerged paths" 목록이 표시되며, 병합을 계속하려면 수동으로 해결해야 함을 나타냅니다.

1단계: 충돌 마커 식별

Git이 병합을 중단하면 충돌이 발생한 파일에는 충돌 영역을 구분하기 위해 Git이 삽입한 특수 마커가 포함됩니다. 이 마커는 어떤 변경 사항이 어느 브랜치에서 왔는지 정확히 확인하는 데 도움이 됩니다.

네 가지 충돌 마커

충돌이 발생한 파일에서 서로 다른 내용을 둘러싸고 있는 네 가지 뚜렷한 마커를 볼 수 있습니다.

  1. <<<<<<< HEAD:
    • 현재 브랜치(병합 대상 브랜치)의 변경 사항 시작을 표시합니다.
  2. =======:
    • 두 가지 충돌 변경 사항 세트 사이의 구분선 역할을 합니다.
  3. >>>>>>> branch-name:
    • 가져오는 브랜치(병합 출발 브랜치)의 변경 사항 끝을 표시합니다.

충돌 블록 예시:

feature/Amain으로 병합 중이며 두 브랜치 모두 config.js의 10번째 줄을 편집했다고 가정해 봅시다.

// config.js

function getTimeout() {
<<<<<<< HEAD
  return 5000; // Main 브랜치 기본값
=======
  return 10000; // Feature A 재정의
>>>>>>> feature/A
}

2단계: 수동으로 충돌 해결

충돌을 해결하려면 Git 마커를 제거하고 원하는 코드 조합을 선택하도록 파일을 편집해야 합니다. 세 가지 주요 해결 전략이 있습니다.

A. HEAD(현재 브랜치)의 변경 사항 유지

현재 브랜치(HEAD)의 버전이 올바르다고 판단되면, 가져온 변경 사항과 모든 마커를 제거합니다.

해결 조치:

// config.js

function getTimeout() {
  return 5000; // Main 브랜치 기본값
}

B. 가져오는 브랜치(Incoming Branch)의 변경 사항 유지

병합해 들어오는 브랜치의 변경 사항이 올바르다고 판단되면, 현재 브랜치의 변경 사항과 모든 마커를 제거합니다.

해결 조치:

// config.js

function getTimeout() {
  return 10000; // Feature A 재정의
}

C. 변경 사항 결합 또는 재작성(하이브리드 접근 방식)

종종 가장 좋은 해결책은 양쪽의 논리를 통합하기 위해 새 버전을 수동으로 구성하거나, 원래의 두 수정 사항에 대한 요구 사항을 충족하기 위해 코드를 완전히 다시 작성하는 것입니다.

해결 조치(하이브리드 예시):

// config.js

function getTimeout() {
  // 환경 변수에 따라 시간 초과를 설정하여 로직 결합
  if (process.env.NODE_ENV === 'production') {
      return 10000;
  }
  return 5000; 
}

모범 사례: 충돌 블록을 해결한 후에는 항상 결과 코드가 컴파일되고 올바르게 작동하는지 확인하십시오. 이 단계에서 단위 테스트를 실행하는 것이 강력히 권장됩니다.

3단계: 해결된 파일 스테이징

모든 충돌 파일을 수동으로 편집하여 <<<<<<<, =======, >>>>>>> 마커를 모두 제거한 후에는 Git에 충돌이 처리되었음을 알리기 위해 이러한 변경 사항을 스테이징해야 합니다.

해결한 각 파일에 대해 표준 git add 명령을 사용합니다.

git add config.js
git add src/utils/helper.py
# ... 해결한 모든 충돌 파일에 대해 반복

Git이 해결을 인식하는지 확인하려면 git status를 다시 실행하십시오. 이전에 병합되지 않은 모든 경로는 이제 "커밋할 변경 사항" 아래에 나타나야 합니다.

4단계: 병합 또는 리베이스 완료

모든 충돌이 스테이징되면 원래 시작한 명령에 따라 작업을 완료합니다.

git merge 완료

표준 병합을 수행 중이었다면 커밋으로 완료합니다.

git commit

Git은 일반적으로 미리 채워진 병합 커밋 메시지와 함께 구성된 텍스트 편집기를 엽니다. 검토하고 저장 및 닫으면 병합이 완료됩니다.

git rebase 완료

리베이스 중이었다면, 해결된 상태 위에 후속 커밋을 적용하는 프로세스를 계속합니다.

git rebase --continue

리베이스 시퀀스 내의 후속 커밋도 충돌을 일으키는 경우, 발생하는 충돌마다 2단계부터 4단계까지 반복합니다.

어려운 충돌 문제 해결 팁

위 단계는 표준 해결 방법을 다루지만, 복잡한 시나리오에서는 대안적인 접근 방식이 필요할 수 있습니다.

1. 작업 중단

병합 또는 리베이스를 시작했는데 상황이 너무 복잡하거나 팀원과 상의해야 한다고 판단되면, 명령을 실행하기 전 상태로 언제든지 되돌릴 수 있습니다.

git merge --abort  # 'git merge'로 시작한 경우
git rebase --abort  # 'git rebase'로 시작한 경우

2. 시각적 Diff 도구 사용

많은 변경 사항이 겹치는 복잡한 파일의 경우, 전용 3방향 병합 도구(VS Code의 내장 병합 편집기, KDiff3 또는 Meld와 같은)를 사용하는 것이 강력히 권장됩니다. 구성된 도구를 직접 실행할 수 있습니다.

git mergetool

이 인터페이스는 일반적으로 로컬 버전, 원격 버전 및 기본 공통 조상을 보여주어 수동 선택을 훨씬 더 명확하게 만듭니다.

3. 바이너리 파일 처리

Git은 이미지나 컴파일된 자산과 같은 바이너리 파일을 자동으로 병합할 수 없습니다. 두 브랜치가 동일한 바이너리 파일을 수정한 경우 Git은 충돌을 보고합니다. 이 경우 선호하는 파일을 작업 디렉터리로 복사하고, 스테이징하고, 커밋/계속하여 수동으로 어느 버전을 유지할지 선택해야 합니다.

# 예시: 바이너리 파일에 대해 가져오는 브랜치의 버전 유지
cp .git/rebase-apply/patch /path/to/conflicted/image.png 
# OR 사용 가능한 파일 선택 유틸리티 사용
git add image.png
git rebase --continue

요약

병합 충돌은 협업 개발에서 관리 가능한 마찰 지점입니다. <<<<<<<, =======, >>>>>>> 마커를 이해하고, 원하는 결과를 얻기 위해 파일을 신중하게 편집하고, git add로 해결을 스테이징하고, 작업을 완료(git commit 또는 git rebase --continue)하면 충돌을 신속하게 해결하고 워크플로우를 효율적으로 계속 진행할 수 있습니다.