Git에서 병합 충돌을 해결하는 방법


4764

Git에서 병합 충돌을 어떻게 해결합니까?


31
다음 블로그 게시물은 Git과의 병합 충돌을 처리하여 올바른 방향으로 나아가는 방법에 대한 좋은 예를 보여줍니다. 취급 및 힘내에서 충돌 방지
mwilliams

4
병합 도구 (kdiff3 jebaird.com/2013/07/08/… )를 구성한 다음 git mergetool을 사용할 수 있습니다. 대규모 개발자 팀에서 작업 할 때는 항상 병합 충돌이 발생합니다.
Grady G Cooper

다운 스트림을 정기적으로 병합하여 대부분의 병합 충돌을 완화 할 수 있습니다.
앤트 P


8
흥미로운 질문 : 2008 년에 질문 한 100 % 공개는 실제로 무엇이 무엇인지에 대한 힌트가 전혀 없었습니다. 30 개의 답변이 있으며, 다른 diff3 및 병합 도구에 대해 거의 모든 것이 (간단히 보여지는 한) 받아들이지 않았습니다. 가장 투표가 많은 답변에는 기본 git설치로 즉시 작동하지 않는 명령이 언급되어 있습니다. 2017 년 현재 1.3m의 조회수와 수천 개의 투표로 SE 시작 페이지를 열었습니다. 매혹적인.
AnoE

답변:


2911

시험: git mergetool

충돌이 발생할 때마다 단계별로 안내하는 GUI가 열리고 병합 방법을 선택할 수 있습니다. 때로는 나중에 약간의 편집 작업이 필요하지만 일반적으로 충분합니다. 손으로 모든 일을하는 것보다 훨씬 낫습니다.

@JoshGlover 의견에 따라 :

명령

GUI를 설치하지 않으면 반드시 GUI를 열 필요는 없습니다. git mergetool나를 위해 달리는 결과 vimdiff가 사용되었습니다. 당신은 대신를 사용하려면 다음 도구 중 하나를 설치할 수 있습니다 : meld, opendiff, kdiff3, tkdiff, xxdiff, tortoisemerge, gvimdiff, diffuse, ecmerge, p4merge, araxis, vimdiff, emerge.

다음은 vimdiff병합 충돌을 해결하는 데 사용되는 샘플 절차 입니다. 이 링크를 기반으로

1 단계 : 터미널에서 다음 명령 실행

git config merge.tool vimdiff
git config merge.conflictstyle diff3
git config mergetool.prompt false

이렇게하면 vimdiff가 기본 병합 도구로 설정됩니다.

2 단계 : 터미널에서 다음 명령 실행

git mergetool

3 단계 : 다음 형식의 vimdiff 디스플레이가 표시됩니다

  ╔═══════╦══════╦════════╗
  ║       ║      ║        ║
  ║ LOCAL ║ BASE ║ REMOTE ║
  ║       ║      ║        ║
  ╠═══════╩══════╩════════╣
  ║                       ║
  ║        MERGED         ║
  ║                       ║
  ╚═══════════════════════╝

이 4 가지 견해는

LOCAL – 현재 지점의 파일입니다.

BASE – 공통 조상, 파일이 두 변경 전에 어떻게 보였는가

REMOTE – 브랜치에 병합 할 파일

MERGED – 병합 결과, 이것이 repo에 저장되는 것입니다

ctrl+를 사용하여 이러한보기를 탐색 할 수 있습니다 w. 직접 사용하여 병합 뷰에 도달 할 수 있습니다 ctrl+ w다음에 j.

여기여기 에 vimdiff 탐색에 대한 추가 정보

4 단계 . 다음과 같은 방법으로 MERGED보기를 편집 할 수 있습니다

REMOTE에서 변경 사항을 받으려면

:diffg RE  

BASE에서 변경 사항을 가져 오려면

:diffg BA  

LOCAL에서 변경 사항을 받으려면

:diffg LO 

5 단계 . 저장, 종료, 커밋 및 정리

:wqa vi에서 저장하고 종료

git commit -m "message"

git clean diff 도구로 만든 추가 파일 (예 : * .orig)을 제거하십시오.


54
참고 git mergetool -y로 한 번에 많은 파일을 병합하는 경우 몇 가지 키 입력을 저장하는 데 사용할 수 있습니다 .
davr

373
GUI를 설치하지 않으면 반드시 GUI를 열 필요는 없습니다. git mergetool나를 위해 달리는 결과 vimdiff가 사용되었습니다. 다음 도구 중 하나를 설치하여 대신 사용할 수 meld opendiff kdiff3 tkdiff xxdiff tortoisemerge gvimdiff diffuse ecmerge p4merge araxis vimdiff emerge있습니다..
Josh Glover

31
좋은 지적 조쉬. 우분투에서 meld와 함께 최고의 행운을 얻었습니다. 세 가지 방법으로 병합 디스플레이가 나쁘지 않습니다. OSX에서 git은 좋은 기본값을 선택했습니다.
피터 번즈

18
이것은 KDiff3을 열었습니다. 사용 방법에 대한 실마리가 전혀 없습니다.
David Murdoch 2016 년

7
Beyond Compare 3 now ( git mergetool -t bc3)를 사용할 수도 있습니다 .
AzP

1703

다음은 가능한 유스 케이스입니다.

몇 가지 변경 사항을 가져와야하지만 죄송합니다.

git fetch origin
git pull origin master

From ssh://gitosis@example.com:22/projectname
 * branch            master     -> FETCH_HEAD
Updating a030c3a..ee25213
error: Entry 'filename.c' not uptodate. Cannot merge.

따라서 최신 정보를 얻고 다시 시도하지만 충돌이 있습니다.

git add filename.c
git commit -m "made some wild and crazy changes"
git pull origin master

From ssh://gitosis@example.com:22/projectname
 * branch            master     -> FETCH_HEAD
Auto-merging filename.c
CONFLICT (content): Merge conflict in filename.c
Automatic merge failed; fix conflicts and then commit the result.

따라서 변경 사항을 살펴보기로 결정합니다.

git mergetool

오 마이, 오 마이, 업스트림은 몇 가지 사항을 변경했지만 내 변경 사항을 사용하려면

git checkout --ours filename.c
git checkout --theirs filename.c
git add filename.c
git commit -m "using theirs"

그리고 마지막으로 시도합니다

git pull origin master

From ssh://gitosis@example.com:22/projectname
 * branch            master     -> FETCH_HEAD
Already up-to-date.

타다!


19
바이너리 파일 (아트 애셋)과의 병합 오류가 많고 병합이 항상 실패하는 것처럼
보이므로 매우 유용했습니다. 따라서

188
꼼꼼한! 우리와 그들의 의미는 반대입니다. --ours == 리모컨. -그들의 == 지역. 참조git merge --help
mmell

57
필자의 경우 --thes = 원격 저장소, --ours = 내 로컬 저장소임을 확인합니다. @mmell 주석의 반대입니다.
Aryo

24
@mmell 분명히 rebase에서만 가능합니다. 참조this question
나빈

184
"우리"와 "그들"은 당신이 합병하고 있는지 아니면 저질인지에 관계됩니다. 당신이 경우 합병 후 "우리"수단이에 병합하고 지점 및 "그들의은"당신이 합병하고있는 지점입니다. 언제있는 거 리베이스 , 다음 "우리"수단 커밋 당신에게있는 거 리베이스를 위에 "그들의"는 리베이스하려는 커밋을 나타냅니다.

736

병합 도구를 사용하면 충돌이나 해결 방법을 이해하는 데 거의 도움이되지 않습니다. 나는 일반적으로 텍스트 편집기에서 충돌 마커를보고 git log를 보충으로 사용하는 것이 더 성공적입니다.

다음은 몇 가지 팁입니다.

팁 하나

내가 찾은 가장 좋은 것은 "diff3"병합 충돌 스타일을 사용하는 것입니다.

git config merge.conflictstyle diff3

다음과 같은 충돌 마커가 생성됩니다.

<<<<<<<
Changes made on the branch that is being merged into. In most cases,
this is the branch that I have currently checked out (i.e. HEAD).
|||||||
The common ancestor version.
=======
Changes made on the branch that is being merged in. This is often a 
feature/topic branch.
>>>>>>>

중간 부분은 공통 조상의 모습입니다. 이것은 각 브랜치에서 변경된 사항을 더 잘 이해할 수 있도록 상위 및 하위 버전과 비교할 수 있기 때문에 유용합니다. 그러면 각 변경의 목적이 무엇인지 더 잘 알 수 있습니다.

갈등이 몇 줄에 불과한 경우 일반적으로 갈등이 매우 분명합니다. (충돌을 해결하는 방법을 아는 것은 매우 다릅니다. 다른 사람들이 무엇을하고 있는지 알고 있어야합니다. 혼란 스러우면 상대방을 방으로 불러서 자신이보고있는 것을 볼 수 있도록하는 것이 가장 좋습니다 에서.)

충돌이 더 길면 세 섹션을 각각 잘라내어 "mine", "common"및 "thes"와 같은 세 개의 별도 파일로 붙여 넣습니다.

그런 다음 다음 명령을 실행하여 충돌을 일으킨 두 개의 diff hunk를 볼 수 있습니다.

diff common mine
diff common theirs

병합 도구는 충돌하지 않는 모든 diff hunk도 포함하므로 병합 도구를 사용하는 것과는 다릅니다. 주의가 산만 해지는 것을 알았습니다.

팁 2

누군가 이미 이것을 언급했지만 각 diff hunk의 의도를 이해하면 일반적으로 충돌이 발생한 위치와 처리 방법을 이해하는 데 매우 도움이됩니다.

git log --merge -p <name of file>

이것은 공통 조상과 병합하는 두 헤드 사이에서 해당 파일을 터치 한 모든 커밋을 표시합니다. (따라서 병합하기 전에 두 브랜치에 이미 존재하는 커밋은 포함되지 않습니다.) 이렇게하면 현재 충돌에 영향을 미치지 않는 다른 덩어리를 무시할 수 있습니다.

팁 3

자동화 된 도구로 변경 사항을 확인하십시오.

자동화 된 테스트가있는 경우 테스트를 실행하십시오. 보풀 이 있으면 실행하십시오. 빌드 가능한 프로젝트 인 경우 커밋하기 전에 빌드하십시오. 모든 경우에 변경 사항이 적용되지 않는지 확인하기 위해 약간의 테스트를 수행해야합니다. (충돌없이 병합하더라도 작업 코드가 손상 될 수 있습니다.)

팁 4

미리 계획하십시오. 동료들과 의사 소통합니다.

미리 계획하고 다른 사람들이 무엇을하고 있는지 알면 병합 충돌을 방지하고 더 일찍 해결하는 데 도움이 될 수 있습니다.

예를 들어, 귀하와 다른 사람이 모두 동일한 파일 세트에 영향을 줄 수있는 다른 리팩토링 작업을하고 있다는 것을 알고 있다면, 미리 서로 대화하고 각각의 변경 유형에 대해 더 잘 이해해야합니다. 만들기. 계획된 변경을 병렬로 수행하지 않고 순차적으로 수행하면 상당한 시간과 노력을 절약 할 수 있습니다.

많은 양의 코드를 처리하는 주요 리팩토링의 경우 직렬 작업을 강력히 고려해야합니다. 한 사람이 전체 리팩토링을 수행하는 동안 모든 사람이 해당 코드 영역에서 작업을 중지합니다.

시간 압력으로 인해 연속적으로 작업 할 수없는 경우 예상되는 병합 충돌에 대해 통신하면 최소한 세부 사항을 계속 염두에두고 문제를 더 빨리 해결하는 데 도움이됩니다. 예를 들어, 1 주일 동안 동료가 중단적인 일련의 커밋을 수행하는 경우 해당 주 동안 매일 1 ~ 2 회 해당 동료 지점을 병합 / 리베이스하도록 선택할 수 있습니다. 이렇게하면 병합 / 리베이스 충돌이 발견되면 몇 주 동안 기다렸다가 한 번에 모든 것을 병합하는 것보다 더 빨리 해결할 수 있습니다.

팁 5

병합이 확실하지 않은 경우 강제로 병합하지 마십시오.

특히 충돌하는 파일이 많고 충돌 마커가 수백 줄을 포함하는 경우 병합이 압도적으로 느껴질 수 있습니다. 종종 소프트웨어 프로젝트를 평가할 때 심하게 병합을 처리하는 등의 오버 헤드 항목에 충분한 시간을 포함하지 않기 때문에 각 충돌을 해체하는 데 몇 시간을 소비해야하는 실제 드래그처럼 느껴집니다.

장기적으로 미리 계획하고 다른 사람들이 무엇을하고 있는지 알고있는 것은 머지 충돌을 예상하고 더 짧은 시간 내에 올바르게 해결할 수 있도록 준비하는 가장 좋은 도구입니다.


6
diff3 옵션은 병합과 함께 사용할 수있는 훌륭한 기능입니다. 내가 찾은 유일한 GUI는 Perforce의 p4merge도구이며 Perforce의 다른 도구와 별도로 설치하여 사용할 수 있음 을 보여줍니다 (사용하지 않았지만 불만이 있음).
alxndr

3
리베이스 시도 후 병합 충돌이 발생했습니다 : $ git log --merge -p build.xml 출력 : 치명적 : MERGE_HEAD없이 병합?
Ed Randall

branch1에서 하나의 파일을 변경하고 branch2에서 해당 파일을 삭제하면 어떻게됩니까? 병합 충돌을 어떻게 해결할 수 있습니까? 하나의 브랜치의 변경 사항을 유지하여 병합 할 수있는 git을 사용하는 방법이 있습니까?
Honey

git config merge.conflictstyle diff3- 감사합니다. 이것은 놀랍고 좋은 3 웨이 병합 GUI를 찾고 (그리고 $$를 지불하려는) 자유롭게했습니다. IMO는 공통 조상뿐만 아니라 로컬 / 원격 보여주고 GUI가없는 (AFAIK) 마지막 커밋 로그 라인을 보여주기 때문에 더 좋습니다 . 커밋은 어떤 코드가 어떤 브랜치에 속하는지 식별하는 데 도움이됩니다.
ffxsam

때로는 diff3 충돌 스타일로 인해 거의 동일한 거대한 diff 덩어리가 생성되는 반면 기본적으로 더 작고 관리하기 쉬운 덩어리가 생성됩니다. 불행히도, 버그 보고서에 사용할 수있는 재생기가 없습니다. 그러나이 문제가 발생하면 옵션을 일시적으로 해제하는 것이 좋습니다.
Dave Abrahams

348
  1. 충돌하는 파일을 식별하십시오 (Git에서 알려야합니다).

  2. 각 파일을 열고 diff를 검사하십시오. 힘내는 그들을 구분합니다. 바라건대 각 블록의 버전을 유지하는 것이 분명 할 것입니다. 코드를 커밋 한 동료 개발자와 논의해야 할 수도 있습니다.

  3. 당신은 파일의 충돌을 해결하면 git add the_file.

  4. 모든 충돌을 해결 한 후 git rebase --continue또는 Git이 완료했을 때 수행 한 명령을 수행하십시오.


38
@Justin Git을 파일을 추적하기보다는 컨텐츠 를 추적 하는 것으로 생각 하십시오. 그런 다음 당신이 업데이트 한 내용이 있음을 쉽게 알 수 없는 저장소와 추가해야합니다. 이 생각 방식은 Git이 빈 폴더를 추적하지 않는 이유도 설명합니다. 기술적으로 파일이지만 추적 할 내용이 없습니다.
Gareth

7
콘텐츠가있는 경우 콘텐츠 버전이 2 개이므로 충돌이 발생합니다. 따라서 "git add"가 올바르게 들리지 않습니다. 충돌이 해결 된 후 하나의 파일 만 커밋하려는 경우 (git add, git commit) 작동하지 않습니다 ( "치명적 : 병합 중에 부분 커밋을 수행 할 수 없습니다")
Dainius

1
예, 기술적으로 이것은 요청 된대로 대답하지만 내 의견으로는 쓸만한 대답은 아닙니다. 미안합니다. 한 지점을 다른 지점과 동일하게 만드는 요점 은 무엇입니까 ? 물론 합병은 갈등이있을 것이다.
Thufir

5
툴 파이어 : 누가 한 지점을 다른 지점과 동일하게 만드는 것에 대해 말했습니까? "한 브랜치를 다른 브랜치와 동일하게 만들지 않고"병합해야하는 다른 시나리오가 있습니다. 하나는 개발 브랜치를 완료하고 변경 사항을 마스터 브랜치에 통합하려는 경우입니다. 그 후에 개발 브랜치를 삭제할 수 있습니다. 또 다른 하나는 최종 분기를 마스터로 통합하기 위해 개발 브랜치를 리베이스하려는 경우입니다.
Teemu Leisti

4
@JustinGrant git add는 색인에서 파일을 준비합니다. 저장소에 아무것도 추가 하지 않습니다 . git commit저장소에 항목을 추가합니다. 이 사용법은 병합에 적합합니다. 병합은 자동으로 병합 될 수있는 모든 변경 사항을 자동으로 준비합니다. 나머지 변경 사항을 병합하고 완료되면 색인에 추가해야합니다.
Mark E. Haase

105

스택 오버플로 질문에서 답변을 확인하십시오 .Git에서 병합 중단 , 특히 Charles Bailey의 답변 은 문제가있는 다른 버전의 파일을 보는 방법을 보여줍니다.

# Common base version of the file.
git show :1:some_file.cpp

# 'Ours' version of the file.
git show :2:some_file.cpp

# 'Theirs' version of the file.
git show :3:some_file.cpp

또한 "자식 체크 아웃 -m"에 "-m"옵션을 체크 아웃 - 당신이 다른 파리가 당신의 작업 공간으로 철회 추출 할 수 있습니다
qneill

이것은 나를 구했다. 각 파일을 개별적으로 살펴보면 각 지점에서 내가 뭘했는지 기억할 수있었습니다. 그런 다음 선택하기로 결정할 수있었습니다.
Rohmer

99

파일을 동시에 변경하면 병합 충돌이 발생합니다. 해결 방법은 다음과 같습니다.

git CLI

충돌 상태가 될 때 수행 할 간단한 단계는 다음과 같습니다.

  1. 충돌하는 파일 목록은 다음과 같습니다 git status( Unmerged paths섹션 아래 ).
  2. 다음 방법 중 하나를 사용하여 각 파일의 충돌을 개별적으로 해결하십시오.

    • GUI를 사용하여 충돌을 해결하십시오 : git mergetool(가장 쉬운 방법).

    • 원격 / 기타 버전을 승인하려면 다음을 사용하십시오 git checkout --theirs path/file.. 해당 파일에 대한 로컬 변경 사항이 거부됩니다.

    • 로컬 / 당사 버전을 수락하려면 다음을 사용하십시오. git checkout --ours path/file

      그러나 어떤 이유로 인해 충돌하는 원격 변경이 수행되었으므로주의해야합니다.

      관련 : "우리"와 자식에 "그들의"의 정확한 의미는 무엇입니까?

    • 충돌 한 파일을 수동으로 편집하고 <<<<</ 사이의 코드 블록을 >>>>>찾은 다음 위 또는 아래에서 버전을 선택하십시오 =====. 충돌이 표시되는 방법을 참조하십시오 .

    • 경로와 파일 이름 충돌에 의해 해결 될 수있다 git add/ git rm.

  3. 마지막으로 다음을 사용하여 커밋 할 준비가 된 파일을 검토하십시오 git status.

    아래에 여전히 파일이 Unmerged paths있고 수동으로 충돌을 해결 한 경우 Git에 다음을 통해 해결했음을 알립니다 git add path/file.

  4. 모든 충돌이 성공적으로 해결되면 다음을 수행하여 변경 사항을 커밋하고 git commit -a평소처럼 원격으로 푸시하십시오.

참조 : GitHub 의 명령 줄 에서 병합 충돌 해결

실용적인 자습서를 보려면 Katacoda의 시나리오 5-수정 병합 충돌을 확인하십시오 .

DiffMerge

Windows, macOS 및 Linux / Unix에서 파일을 시각적으로 비교하고 병합 할 수있는 DiffMerge 를 성공적으로 사용했습니다 .

3 개의 파일 간 변경 사항을 그래픽으로 표시 할 수 있으며 자동 병합 (안전한 경우)하고 결과 파일 편집을 완벽하게 제어 할 수 있습니다.

DiffMerge

이미지 출처 : DiffMerge (Linux 스크린 샷)

간단히 다운로드하여 repo에서 다음과 같이 실행하십시오.

git mergetool -t diffmerge .

맥 OS

macOS에서는 다음을 통해 설치할 수 있습니다.

brew install caskroom/cask/brew-cask
brew cask install diffmerge

그리고 아마도 (제공되지 않은 경우) PATH에 다음과 같은 추가 간단한 래퍼가 있어야합니다 (예 :) /usr/bin.

#!/bin/sh
DIFFMERGE_PATH=/Applications/DiffMerge.app
DIFFMERGE_EXE=${DIFFMERGE_PATH}/Contents/MacOS/DiffMerge
exec ${DIFFMERGE_EXE} --nosplash "$@"

그런 다음 다음 단축키를 사용할 수 있습니다.

  • - Alt- Up/ Down이전 / 다음 변화로 이동합니다.
  • - Alt- Left/ Right왼쪽 또는 오른쪽에서 변경 내용을 적용합니다

또는 opendiff (Xcode Tools의 일부)를 사용하여 두 파일 또는 디렉토리를 병합하여 세 번째 파일 또는 디렉토리를 만들 수 있습니다.


79

자주 작은 커밋을 수행하는 경우로 커밋 주석을 살펴보십시오 git log --merge. 그런 다음 git diff갈등을 보여줄 것입니다.

몇 줄 이상이 관련된 충돌의 경우 외부 GUI 도구에서 진행중인 작업을보다 쉽게 ​​확인할 수 있습니다. 나는 opendiff를 좋아한다-Git은 vimdiff, gvimdiff, kdiff3, tkdiff, meld, xxdiff를 지원하며 다른 git config merge.tool "your.tool"도구를 설치할 수 있으며 다른 도구를 설치할 수 있습니다 git mergetool.

충돌을 해결하기 위해 파일을 편집 할 때마다 git add filename색인이 업데이트되고 diff는 더 이상 표시하지 않습니다. 모든 갈등의 처리와 그 파일이되었을 때 git add-ed, git commit병합을 완료합니다.


8
여기에 "git add"를 사용하는 것이 진짜 속임수입니다. 커밋하고 싶지 않을 수도 있지만 (아마 숨기고 싶을 수도 있음) 병합을 완료하려면 "git add"를 수행해야합니다. 나는 mergetool이 추가 기능을 제공한다고 생각하지만 (맨 페이지에는 없지만) 수동으로 병합을 수행하는 경우 "git add"를 사용하여 완료해야합니다 (커밋하지 않으려는 경우에도).
nobar

47

병합 충돌 마커가 무엇인지 이해하려면 충돌이 표시되는 방법 또는 Git의 git merge설명서를 참조하십시오 .

또한 충돌 해결 방법 섹션에서는 충돌을 해결 하는 방법에 대해 설명합니다.

충돌을 본 후 두 가지 작업을 수행 할 수 있습니다.

  • 병합하지 않기로 결정하십시오. 필요한 정리는 인덱스 파일을 HEAD커밋 으로 재설정하여 2를 반대로하고 2와 3으로 작성된 작업 트리 변경을 정리하는 것입니다. git merge --abort이것을 위해 사용될 수 있습니다.

  • 충돌을 해결하십시오. 힘내 작업 트리에서 충돌을 표시합니다. 파일을 모양으로 편집하고 색인으로 편집하십시오 git add. git commit거래를 봉인하는 데 사용 합니다.

여러 도구와의 충돌을 통해 작업 할 수 있습니다.

  • mergetool을 사용하십시오. git mergetool병합 과정을 안내하는 그래픽 병합 도구를 시작합니다.

  • 차이점을보세요. 와 버전의 git diff변경 사항을 강조 표시하는 3 방향 차이를 표시 합니다.HEADMERGE_HEAD

  • 각 지점의 diff를보십시오. 버전에 git log --merge -p <path>대해 먼저 diff를 표시 HEAD한 다음 MERGE_HEAD버전을 표시합니다.

  • 원본을보십시오. git show :1:filename쇼 공통의 조상 git show :2:filename보여줍니다 HEAD버전 및 git show :3:filename표시 MERGE_HEAD버전을.

또한 통합 충돌 마커 및이를 해결하는 방법은 Pro Git 서적 섹션의 기본 병합 충돌 에서 읽을 수 있습니다 .


42

내 버전 또는 전체 버전을 원하거나 개별 변경 사항을 검토하고 각 변경 사항을 결정하려고합니다.

내 또는 그들의 버전을 완전히 수락하십시오 .

내 버전 (로컬, 로컬 버전)을 수락하십시오.

git checkout --ours -- <filename>
git add <filename>              # Marks conflict as resolved
git commit -m "merged bla bla"  # An "empty" commit

그들의 버전을 수락하십시오 (원격, 그들의 것) :

git checkout --theirs -- <filename>
git add <filename>
git commit -m "merged bla bla"

당신은하고 싶은 경우 모든 충돌 파일을 실행합니다 :

git merge --strategy-option ours

또는

git merge --strategy-option theirs

모든 변경 사항을 검토하고 개별적으로 승인

  1. git mergetool
  2. 변경 사항을 검토하고 각 버전에 대한 버전을 수락하십시오.
  3. git add <filename>
  4. git commit -m "merged bla bla"

기본값 mergetool명령 행 에서 작동 합니다 . 명령 행 mergetool을 사용하는 방법은 별도의 질문이어야합니다.

이를 위해 시각적 도구 를 설치할 수도 meld있습니다.

git mergetool -t meld

로컬 버전 (우리), "기본"또는 "병합"버전 (현재 병합 결과) 및 원격 버전 (그들의)이 열립니다. 완료되면 병합 된 버전을 저장하고 git mergetool -t meld"파일을 병합 할 필요가 없습니다"가 표시 될 때까지 다시 실행 한 다음 3 단계 및 4 단계로 이동하십시오.


git checkout --theirs-<filename>은 <filename>뿐만 아니라 모든 파일을 그들의 파일로 변경했습니다
Donato

실제로 나는 틀렸다. 지정된 파일 만 업데이트합니다.
도나 토

40

수동으로 병합 충돌을 해결하려는 Emacs 사용자의 경우 :

git diff --name-status --diff-filter=U

충돌 해결이 필요한 모든 파일을 표시합니다.

다음과 같이 각 파일을 하나씩 또는 한 번에여십시오.

emacs $(git diff --name-only --diff-filter=U)

Emacs에서 편집이 필요한 버퍼를 방문 할 때 다음을 입력하십시오.

ALT+x vc-resolve-conflicts

이렇게하면 3 개의 버퍼 (광산, 버퍼 및 출력 버퍼)가 열립니다. 'n'(다음 영역), 'p'(제공 영역)를 눌러 탐색하십시오. 'a'와 'b'를 눌러 광산 또는 해당 지역을 출력 버퍼에 각각 복사하십시오. 출력 버퍼를 직접 편집하십시오.

완료되면 : 'q'를 누르십시오. Emacs는이 버퍼를 저장할 것인지 묻습니다. 예. 버퍼를 완료 한 후 터미널에서 실행하여 해결 된 것으로 표시하십시오.

git add FILENAME

모든 버퍼 유형으로 완료되면

git commit

병합을 완료합니다.


33

보너스:

위의 답변에서 끌어 오기 / 가져 오기 / 병합에 대해 흥미롭고 생산적인 트릭을 공유하고 싶습니다.

git pull --rebase

이 위의 명령은 내 자식 생활에서 가장 유용한 명령으로 많은 시간을 절약했습니다.

새로 커밋 된 변경 사항을 원격 서버로 푸시하기 전에 git pull --rebase오히려 git pull수동으로 시도 merge하면 최신 원격 서버 변경 사항 (페치 + 병합)을 자동으로 동기화하고 로컬 최신 커밋을 git 로그의 맨 위에 놓습니다. 수동 풀 / 병합에 대해 걱정할 필요가 없습니다.

충돌이 발생할 경우

git mergetool
git add conflict_file
git rebase --continue

자세한 내용은 http://gitolite.com/git-pull--rebase를 참조하십시오.


32

리포지토리 중 하나의 변경이 중요하지 않다는 것을 잘 알고 있고 다른 변경 사항을 위해 모든 변경 사항을 해결하려면 다음을 사용하십시오.

git checkout . --ours

저장소에 유리하게 변경 사항을 해결 하거나

git checkout . --theirs

다른 저장소 나 주요 저장소 를 위해 변경 사항을 해결 합니다 .

또는 GUI 병합 도구를 사용하여 파일을 하나씩 단계별로 살펴 p4merge보거나 병합 도구라고 말 하거나 이미 설치 한 이름을 작성해야합니다.

git mergetool -t p4merge

파일을 완성한 후에는 저장하고 닫아야하므로 다음 파일이 열립니다.


2
git checkout. -그들은 내 문제 덕분에 해결
Ramesh Chand

충돌을 수동으로 해결하려면 Visual Studio Code에서 폴더를 열어보십시오. 파일마다 충돌 및 색상 충돌 선이 표시됩니다.
Mohamed Selim

31

Git에서 병합 충돌을 해결하려면 다음 단계를 따르십시오.

  1. 힘내 상태 확인 : 자식 상태

  2. 패치 세트 받기 : git fetch (Git 커밋에서 올바른 패치를 확인하십시오)

  3. 로컬 브랜치를 체크 아웃하십시오 (여기의 예제에서는 temp1) : git checkout -b temp1

  4. git pull --rebase origin master 에서 최근 내용을 가져옵니다.

  5. mergetool을 시작하고 충돌을 확인하고 수정하십시오 ... 현재 지점으로 원격 지점의 변경 사항을 확인하십시오 : git mergetool

  6. 상태를 다시 확인하십시오 : 자식 상태

  7. mergetool에 의해 로컬로 생성 된 원하지 않는 파일을 삭제하십시오. 일반적으로 mergetool은 확장자가 * .orig 인 추가 파일을 작성합니다. 중복 된 파일이므로 해당 파일을 삭제하고 로컬에서 변경 사항을 수정하고 올바른 버전의 파일을 추가하십시오. git add #your_changed_correct_files

  8. 상태를 다시 확인하십시오 : 자식 상태

  9. 동일한 커밋 ID로 변경 사항을 커밋하십시오 (이것은 새로운 별도의 패치 세트를 피합니다) : git commit --amend

  10. 마스터 브랜치로 푸시 : git push (Git 저장소로)


28

3 단계가 있습니다.

  1. 명령으로 충돌을 일으키는 파일 찾기

    git status
    
  2. 다음과 같이 충돌이있는 파일을 확인하십시오.

    <<<<<<<<head
    blablabla
    
  3. 원하는 방식으로 변경 한 다음 명령으로 커밋

    git add solved_conflicts_files
    git commit -m 'merge msg'
    

나를 위해 일했다! 감사!
Nuwan Jayawardene

리베이스 중에이 작업을 수행 할 경우주의해야합니다. 당신은 사용해야 자식 REBASE --continue 대신 자식 커밋
사무엘 Dauzon

27

다른 방법과 같이 여러 가지 방법으로 병합 충돌을 해결할 수 있습니다.

진짜 열쇠는 로컬 및 원격 리포지토리에서 변경 사항이 어떻게 흐르는 지 아는 것입니다. 이것의 핵심은 추적 지점을 이해하는 것입니다. 나는 추적 지점이 내 로컬, 실제 파일 디렉토리와 원점으로 정의 된 원격 사이의 '중간에 누락 된 부분'으로 생각한다는 것을 알았습니다.

나는 이것을 피하기 위해 개인적으로 2 가지 습관을 들었습니다.

대신에:

git add .
git commit -m"some msg"

두 가지 단점이 있습니다-

a) 모든 새로운 / 변경된 파일이 추가되며 원치 않는 변경이 포함될 수 있습니다.
b) 먼저 파일 목록을 검토 할 수 없습니다.

대신에 나는 :

git add file,file2,file3...
git commit # Then type the files in the editor and save-quit.

이렇게하면 어떤 파일이 추가되는지 더 신중하게 알 수 있으며 메시지 편집기를 사용하는 동안 목록을 검토하고 조금 더 생각하게됩니다. -m옵션 대신 전체 화면 편집기를 사용하면 커밋 메시지가 향상됩니다 .

[업데이트-시간이 지남에 따라 더 전환했습니다 :

git status # Make sure I know whats going on
git add .
git commit # Then use the editor

]

또한 (그리고 당신의 상황과 더 관련이 있습니다), 나는 피하려고합니다 :

git pull

또는

git pull origin master.

pull은 병합을 의미하기 때문에 로컬에서 병합하지 않으려는 변경 사항이있는 경우 병합되지 않아야하는 코드에 대해 병합 된 코드 및 / 또는 병합 충돌로 쉽게 끝날 수 있습니다.

대신 나는 노력하려고

git checkout master
git fetch   
git rebase --hard origin/master # or whatever branch I want.

도움이 될 수도 있습니다.

자식 분기, 포크, 가져 오기, 병합, 리베이스 및 복제, 차이점은 무엇입니까?


이봐, 나는 당신의 대답을 이해했습니다. 그러나 github merge 충돌을 처음 사용했기 때문에 누락 된 것이 있다고 생각합니다. 무엇 당신이 할 때 로컬 수정에 발생 git checkout master하고 git fetchgit rebase --hard origin/master
Suhaib

해야 할 일에 대한 자세한 내용을 추가해야한다고 생각합니다. 나를 혼란스럽게하는 또 다른 예는 대답에서 언급 한 것입니다. 우리는 git add .로컬 수정 사항을 저장하여 후속 조치를 취할 수 git checkout master있습니까? 아니면 두 가지 다른 시나리오입니까?
Suhaib

@MichaelDurrant $ git rebase --hard origin/master b5a30cc159ba8dd error: unknown option hard '사용법 : git rebase [-i] [옵션] [--exec <cmd>] [--onto <newbase>] [<upstream>] [<branch>] 또는 : git rebase [-i] [ 옵션] [--exec <cmd>] [--onto <newbase>] --root [<branch>] 또는 : git rebase --continue | -중단 | -건너 뛰기 | --edit-할 일`
likejudo

24

CoolAJ86의 답변은 거의 모든 것을 요약합니다. 동일한 코드에서 두 가지 모두에 변경 사항이있는 경우 수동 병합을 수행해야합니다. 텍스트 편집기에서 충돌로 파일을 열면 다음 구조가 나타납니다.

(Code not in Conflict)
>>>>>>>>>>>
(first alternative for conflict starts here)
Multiple code lines here
===========
(second alternative for conflict starts here)
Multiple code lines here too    
<<<<<<<<<<<
(Code not in conflict here)

등호와 꺾쇠 괄호를 제거하면서 새 코드를 원하는 방식으로 대안 중 하나 또는 둘의 조합을 선택하십시오.

git commit -a -m "commit message"
git push origin master

17
git log --merge -p [[--] path]

항상 나를 위해 작동하는 것 같지 않으며 일반적으로 두 분기 사이에 다른 모든 커밋을 표시합니다 --. 이는 경로를 명령과 분리하는 데 사용할 때도 발생 합니다.

이 문제를 해결하기 위해해야 ​​할 일은 두 개의 명령 줄을 열고 한 번에 실행하는 것입니다.

git log ..$MERGED_IN_BRANCH --pretty=full -p [path]

그리고 다른

git log $MERGED_IN_BRANCH.. --pretty=full -p [path]

대체 $MERGED_IN_BRANCH내가와 합병 분기와 [path]충돌하는 파일. 이 명령은 ( ..) 두 커밋 사이의 모든 커밋을 패치 형식으로 기록합니다 . 위의 명령과 같이 한쪽을 비워두면 git이 자동으로 사용합니다 HEAD(이 경우 병합중인 분기).

이를 통해 두 분기에서 커밋 된 파일이 분기 된 후에 확인할 수 있습니다. 일반적으로 충돌을 해결하기가 훨씬 쉽습니다.


16

사용 patience

나는 patience병합 재귀 전략을 사용하여 갈등을 해결하는 것에 대해 아무도 이야기하지 않은 것에 놀랐습니다 . 큰 병합 충돌의 patience경우 좋은 결과를 제공했습니다. 아이디어는 개별 라인이 아닌 블록을 일치 시키려고한다는 것입니다.

예를 들어 프로그램의 들여 쓰기를 변경하면 기본 Git 병합 전략 {이 다른 기능에 속하는 단일 중괄호와 일치 하는 경우가 있습니다. 이것은 피할 수 있습니다 patience:

git merge -s recursive -X patience other-branch

설명서에서 :

With this option, merge-recursive spends a little extra time to avoid 
mismerges that sometimes occur due to unimportant matching lines 
(e.g., braces from distinct functions). Use this when the branches to 
be merged have diverged wildly.

공통 조상과의 비교

병합 충돌이 발생하고 분기를 수정할 때 다른 사람들이 염두에두고있는 것을보고 싶다면 분기가 아닌 공통 조상과 분기를 직접 비교하는 것이 더 쉬운 경우가 있습니다. 이를 위해 다음을 사용할 수 있습니다 merge-base.

git diff $(git merge-base <our-branch> <their-branch>) <their-branch>

일반적으로 특정 파일에 대한 변경 사항 만보고자합니다.

git diff $(git merge-base <our-branch> <their-branch>) <their-branch> <file>

필자의 경우 병합 충돌을 잘 해결하지 못했습니다. 어떤 이유로 C # 프로젝트에서 구성 줄이 중복되어 유지 되었기 때문입니다. 전체 파일이 다른 것보다 더 친절했지만, 이전에 가지고 있었던
Mathijs Segers

15

2016 년 12 월 12 일부터 github.com에서 브랜치를 병합하고 충돌을 해결할 수 있습니다

따라서 이전 답변에서 제공되는 명령 줄 또는 타사 도구 를 사용하지 않으려면 GitHub의 기본 도구를 사용하십시오.

이 블로그 게시물 은 자세하게 설명하지만 기본 사항은 UI를 통해 두 가지 분기를 '병합'하면 이러한 충돌 충돌을 처리 할 수있는 편집기로 이동하는 '충돌 해결'옵션이 표시된다는 것입니다.

여기에 이미지 설명을 입력하십시오


이것은 github에 대해 묻지 않으므로 매우 열악한 답변이라고 생각하는 투표를했습니다.
mschuett

1
@ mschuett이 맞습니다. 문제는 "github에서 충돌을 해결하는 방법"이 아니라 "git에서 충돌을 해결하는 방법"입니다. 차이가 있고 git과 github가 같은 것이라고 생각하는 사람들이 이미 너무 많아서 그 느낌을 전파하는 것은 잘못입니다.
Patrick Mevzek

15

지점 (테스트)에서 마스터로 병합하려는 경우 다음 단계를 수행 할 수 있습니다.

1 단계 : 지점으로 이동

git checkout test

2 단계 :

git pull --rebase origin master

3 단계 : 충돌이있는 경우이 파일로 이동하여 수정하십시오.

4 단계 :이 변경 사항 추가

git add #your_changes_files

5 단계 :

git rebase --continue

6 단계 : 여전히 충돌이 있으면 3 단계로 다시 돌아가십시오. 충돌이 없으면 다음을 수행하십시오.

git push origin +test

7 단계 : 테스트와 마스터 사이에 충돌이 없습니다. 병합을 직접 사용할 수 있습니다.


13

나는 항상 충돌을 피하기 위해 아래 단계를 따릅니다.

  • 자식 체크 아웃 마스터 (마스터 지점에 오십시오)
  • git pull (최신 코드를 얻으려면 마스터를 업데이트하십시오)
  • git checkout -b mybranch (새 브랜치를 체크 아웃하고 그 브랜치에서 작업하기 시작하면 마스터는 항상 트렁크의 맨 위에 유지됩니다.)
  • git add. AND git commit 및 git push (변경 후 로컬 지점에서)
  • git checkout master (마스터에게 돌아 오십시오.)

이제 원하는 지역 지점과 동일한 작업을 수행하고 유지 관리하고 필요할 때 지점에 git checkout을 수행하는 동시에 작업 할 수 있습니다.


12

서로 다른 상황에서 병합 충돌이 발생할 수 있습니다.

  • "git fetch"를 실행 한 다음 "git merge"를 실행할 때
  • "git fetch"를 실행 한 다음 "git rebase"를 실행할 때
  • "git pull"을 실행할 때 (실제로 위에서 언급 한 조건 중 하나와 동일)
  • "git stash pop"을 실행할 때
  • git 패치를 적용 할 때 (예를 들어, 이메일로 전송할 파일로 내보내는 커밋)

충돌을 해결하려면 Git과 호환되는 병합 도구를 설치해야합니다. 나는 개인적으로 KDiff3를 사용하고 있으며 멋지고 편리하다는 것을 알았습니다. Windows 버전은 여기에서 다운로드 할 수 있습니다.

https://sourceforge.net/projects/kdiff3/files/

BTW Git Extensions를 설치하면 설정 마법사에 Kdiff3를 설치하는 옵션이 있습니다.

그런 다음 git configs를 설정하여 Kdiff를 mergetool로 사용하십시오.

$ git config --global --add merge.tool kdiff3
$ git config --global --add mergetool.kdiff3.path "C:/Program Files/KDiff3/kdiff3.exe"
$ git config --global --add mergetool.kdiff3.trustExitCode false

$ git config --global --add diff.guitool kdiff3
$ git config --global --add difftool.kdiff3.path "C:/Program Files/KDiff3/kdiff3.exe"
$ git config --global --add difftool.kdiff3.trustExitCode false

(경로를 Kdiff exe 파일의 실제 경로로 바꾸십시오.)

그런 다음 병합 충돌이 발생할 때마다이 명령을 실행하면됩니다.

$git mergetool

그런 다음 Kdiff3을 열고 먼저 병합 충돌을 자동으로 해결하려고 시도합니다. 대부분의 충돌은 자발적으로 해결되므로 나머지는 수동으로 수정해야합니다.

Kdiff3의 모습은 다음과 같습니다.

여기에 이미지 설명을 입력하십시오

그런 다음 파일을 저장하면 파일이 저장되고 충돌이 발생한 다음 파일로 이동하여 모든 충돌이 해결 될 때까지 동일한 작업을 다시 수행합니다.

모든 것이 성공적으로 병합되었는지 확인하려면 mergetool 명령을 다시 실행하면 다음과 같은 결과가 나타납니다.

$git mergetool
No files need merging

8

이 답변은 편집기 내에서 모든 작업을 선호하는 VIM 사용자를위한 대안을 추가하는 것입니다.


TL; DR

여기에 이미지 설명을 입력하십시오


Tpope는 VIM 용 fugitive 라는 훌륭한 플러그인을 개발했습니다 . 일단 설치되면 :Gstatus충돌하는 파일을 확인하고 :Gdiff3 가지 방법으로 Git을 열 수 있습니다.

3 웨이 병합에서 비산 하면 다음과 같은 방식으로 병합하려는 분기의 변경 내용을 얻을 수 있습니다.

  • :diffget //2, 원래 ( HEAD ) 브랜치 에서 변경 사항 가져 오기 :
  • :diffget //3병합 지점에서 변경 사항을 가져옵니다.

파일 병합을 마치면 병합 :Gwrite된 버퍼를 입력 하십시오. Vimcasts는 이 단계를 자세히 설명 하는 훌륭한 비디오를 발표했습니다 .


6

VS 코드를위한 Gitlense

Gitlense for VS Code를 사용해 볼 수 있습니다. 주요 기능은 다음과 같습니다.

3. 갈등을 쉽게 해결하십시오.

나는 이미이 기능을 좋아한다 :

여기에 이미지 설명을 입력하십시오

2. 현재의 라인 비난.

여기에 이미지 설명을 입력하십시오

3. 거터 비난

여기에 이미지 설명을 입력하십시오

4. 상태 표시 줄 비난

여기에 이미지 설명을 입력하십시오

여기에서 확인할 수있는 많은 기능이 있습니다 .


5

git fetch
git check 브랜치
git rebase 마스터

이 단계에서는 선호하는 IDE를 사용하여 충돌을 해결하려고합니다.

이 링크를 따라 https://help.github.com/articles/resolving-a-merge-conflict-using-the-command-line/ 파일에서 충돌을 해결하기 위해 ho를 확인할 수 있습니다.

git add
git rebase
-git commit 계속
-git push origin HEAD : refs / drafts / master 수정 (초안처럼 누름)

이제 모든 것이 잘되고 gerrit에서 커밋을 찾을 수 있습니다.

이것이이 문제에 관한 모든 사람들에게 도움이되기를 바랍니다.


3

Visual Studio Code를 아직 편집하지 않은 경우 편집 해보십시오. 병합을 시도한 후 병합 충돌이 발생하면 VS 코드는 병합 충돌을 자동으로 감지합니다.

원래 변경 사항이 무엇인지 표시하고 수락해야하는지 incoming또는

current change(병합 전 원본 의미) '?.

그것은 나에게 도움이되었고 그것은 당신을 위해 일할 수 있습니다!

추신 : 코드와 Visual Studio Code로 git을 구성한 경우에만 작동합니다.



2

Visual Studio를 사용하는 사람들 (내 경우에는 2015)

  1. VS에서 프로젝트를 닫습니다. 특히 큰 프로젝트에서 VS는 UI를 사용하여 병합 할 때 놀라게하는 경향이 있습니다.

  2. 명령 프롬프트에서 병합을 수행하십시오.

    git checkout target_branch

    자식 병합 source_branch

  3. 그런 다음 VS에서 프로젝트를 열고 팀 탐색기-> 분기로 이동하십시오. 이제 병합이 보류 중이며 충돌하는 파일이 메시지 바로 아래에 나열된다는 메시지가 나타납니다.

  4. 충돌하는 파일을 클릭하면 병합, 비교, 소스 가져 오기, 대상 가져 오기 옵션이 있습니다. VS의 병합 도구는 사용하기가 매우 쉽습니다.


매우 큰 프로젝트에서 VS Code 2017을 사용하고 있으며 프로젝트를 닫을 필요가 없습니다. 그것은 꽤 잘 처리 :)
protoEvangelion

2

intelliJ를 IDE로 사용하는 경우 다음 방법으로 부모를 지점에 병합하십시오.

git checkout <localbranch>
git merge origin/<remotebranch>

이 같은 모든 충돌을 보여줍니다

A_MBPro : 테스트 anu $ git merge origin / 자동 병합 src / test / java / com /.../ TestClass.java CONFLICT (콘텐츠) : src / test / java / com /.../ TestClass.java에서 병합 충돌

이제 TestClass.java 파일이 intelliJ에서 빨간색으로 표시됩니다. 또한 git status가 표시됩니다

Unmerged paths:
(use "git add <file>..." to mark resolution)
both modified:   src/test/java/com/.../TestClass.java

intelliJ에서 파일을 열면 섹션이 있습니다.

  <<<<<<< HEAD
    public void testMethod() {
    }
    =======
    public void testMethod() { ...
    }
    >>>>>>> origin/<remotebranch>

여기서 HEAD는 로컬 지점에서 변경되고 origin /은 원격 지점에서 변경됩니다. 여기에 필요한 물건을 보관하고 필요없는 물건을 제거하십시오. 그 후 정상적인 단계를 수행해야합니다. 그건

   git add TestClass.java
   git commit -m "commit message"
   git push

2

충돌을 해결하기 위해 Microsoft의 Visual Code를 사용하고 있습니다. 사용이 매우 간단합니다. 작업 공간에서 프로젝트를 열어 둡니다. 충돌을 감지하고 강조하며, GUI 또는 HEAD 또는 수신에서 변경하려는 항목을 선택할 수있는 GUI 옵션을 제공합니다. 여기에 이미지 설명을 입력하십시오

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.