바이너리 파일과의 Git 충돌 해결


464

Windows에서 Git (msysgit)을 사용하여 수행 한 일부 디자인 작업의 변경 사항을 추적했습니다.

오늘 나는 다른 PC (원격 repo 사용 brian) 에서 일하고 있으며 오늘 수행 한 편집 내용을 랩톱의 일반 로컬 버전으로 다시 병합하려고합니다.

랩톱 git pull brian master에서 변경 사항을 로컬 버전으로 가져 왔습니다 . 기본 InDesign 문서와는 별개로 문제가 없었습니다. 이는 충돌로 나타납니다.

PC의 버전 ( brian)은 내가 유지하려는 최신 버전 이지만이 명령을 사용하라는 명령이 무엇인지 모르겠습니다.

파일을 랩톱에 직접 복사하려고 시도했지만 전체 병합 프로세스가 중단 된 것 같습니다.

누구든지 올바른 방향으로 나를 가리킬 수 있습니까?

답변:


854

git checkout이와 같은 경우 에는 --ours또는 --theirs옵션을 허용합니다 . 따라서 병합 충돌이 있고 병합하려는 지점에서 파일을 원한다는 것을 알고 있다면 다음을 수행 할 수 있습니다.

$ git checkout --theirs -- path/to/conflicted-file.txt

해당 버전의 파일을 사용합니다. 마찬가지로 (버전이 병합되지 않은) 버전을 원한다는 것을 알고 있다면

$ git checkout --ours -- path/to/conflicted-file.txt

47
--ours를 사용하기 전에 파일에서 'git reset HEAD path / to / conflicted-file.txt'를 실행해야했습니다. 그렇지 않으면 효과가없는 것 같습니다.
Zitrax

6
@Zitrax 당신은 실행 후 파일을 diff 했습니까 git checkout --ours? 매뉴얼 페이지에서 (IMHO) 체크 아웃은 --ours /-그들은 "수정, 병합 필요"목록에서 변경 사항을 제거하고 색인에 추가 할 것이라고 제안합니다. 나는 당신이 git add체크 아웃 후에 달릴 필요가 있다고 생각합니다 .
Tim Keating

15
참고 : 여전히 "git add conflicted-file.txt "및 "git commit" 을 수행하려고합니다 . 내가 시도했을 때 커밋 메시지는 충돌에 대한 메모와 함께 미리 채워졌습니다.
Edward Falk

2
"병합하고있는 지점"의 어구는 "병합하고있는 지점"에 가깝습니다. 전치사를 삭제하는 것이 더 좋을 것이라고 생각합니다 : "병합하고있는 지점", git 명령도 반영합니다 (즉 git merge branch_name).
andrybak

13
이 주제에 대한 설명에서 항상 누락되는 몇 가지 중요한 사항이 있습니다. 병합 대신 리베이스를 수행 할 때 의미 --their--ours교환됩니다. 즉 --their == 현재 체크 아웃 된 분기이며 --ours는 현재 분기로 병합하려는 분기, 일반적으로 원격 분기 또는 경로 사양입니다. 분기. 이 [space]--[space]옵션은 같은 이름으로 존재하는 분기 이름과 경로 사양 사이의 경로 사양을 명확하게합니다 (예 : 기존 분기 이름은 "abc"이고 디렉토리는 "abc"라고 함).
보이시 베이크

147

다음과 같이 충돌을 수동으로 해결하고 (파일 복사) 파일을 복사하거나 로컬 버전을 사용했는지에 관계없이 파일을 커밋해야합니다.

git commit -a -m "Fix merge conflict in test.foo"

Git은 일반적으로 병합 후 자동 커밋되지만 충돌을 감지하면 자체적으로 해결할 수 없으며 알아 낸 모든 패치를 적용하고 나머지는 수동으로 해결하고 커밋합니다. 힘내 병합 매뉴얼 페이지힘내 - SVN 크래시 코스 또는 블로그 항목은이 작업을 해야하는 방법에 대한 도움이 되거 수 있습니다.

편집 : 아래 게시물을 참조하십시오. 실제로 파일을 직접 복사 할 필요는 없지만 사용할 수 있습니다

git checkout --ours -- path/to/file.txt
git checkout --theirs -- path/to/file.txt

원하는 파일 버전을 선택하십시오. 파일을 복사 / 편집하려면 두 버전을 모두 혼합해야합니다.

mipadis 답변을 올바른 것으로 표시하십시오.


1
고마워 파일을 '올바른'파일로 표시하는 일종의 기본 제공 방법이 있는지 확실하지 않았습니다. 존재하지 않는 명령을 찾을 수없는 이유를 설명합니다!
Kevin Wilson

그래, 조금 직관적이지 않습니다-git resolve와 같은 것이 좋을 것이지만 추가 단계가 될 것입니다 ...
VolkA

120

당신은 또한이 문제를 극복 할 수 있습니다

git mergetool

이는 원인이 git충돌하는 바이너리 그들에 대한 기본 편집기 산란 로컬 복사본을 만들 수 :

  • {conflicted}.HEAD
  • {conflicted}
  • {conflicted}.REMOTE

분명히 텍스트 편집기에서 바이너리 파일을 유용하게 편집 할 수는 없습니다. 대신 편집기를 닫지 않고 새 {conflicted}.REMOTE파일 을 복사합니다 {conflicted}. 그런 다음 편집기 git를 닫으면 데코 레이팅되지 않은 작업 복사가 변경되었으며 병합 충돌이 일반적인 방식으로 해결되었음을 알 수 있습니다.


8
파일이 크거나 텍스트 편집기에서 바이너리를 열 위험을 감수하지 않으려면 mergetool 프롬프트 ( " Hit return to start merge resolution tool") 에서 ctrl + c를 누르면 git이 추가 파일을 그대로 둡니다. 그런 다음 LibreOffice / OpenOffice / MSWord와 같은 이진 문서 형식에 유용한 외부 도구로 수정하거나 병합하여 결과를 원래 파일 이름으로 다시 저장할 수 있습니다. git에게 충돌이 해결되었음을 알리기 git add위해 원래 파일 이름을 지정한 다음 병합 커밋을 마칠 수 있습니다.
Felix

18

현재 브랜치에 버전을 유지하여 해결하려면 (병합하려는 브랜치의 버전은 무시) 파일을 추가하고 커밋하십시오.

git commit -a

현재 브랜치의 버전을 병합하려는 브랜치의 버전으로 덮어 써서 해결하려면 먼저 해당 버전을 작업 디렉토리로 검색 한 다음 추가 / 커밋해야합니다.

git checkout otherbranch theconflictedfile
git commit -a

더 자세히 설명


1
특히 "저희"와 "-그들의"의 의미가 rebasing의 경우에 바뀐다는 점을 고려하면보다 직관적이기 때문에 허용 된 대답보다이 변형을 선호합니다.
Antony Hatchkins

11

mipadi의 답변이 저에게 효과적이지 않았습니다.이 작업을 수행해야했습니다.

git checkout-경로 /to/file.bin

또는 버전을 병합 상태로 유지하려면

git checkout-경로 /to/file.bin

그때

git add path / to / file.bin

그런 다음 "git mergetool"을 다시 수행하고 다음 충돌을 계속할 수있었습니다.


6

로부터 git checkout문서

git checkout [-f|--ours|--theirs|-m|--conflict=<style>] [<tree-ish>] [--] <paths>...

--ours
--theirs
인덱스에서 경로를 체크 아웃 할 때 병합되지 않은 경로에 대해 2 단계 ( ours) 또는 3 단계 ( )를 확인하십시오 theirs.

이전에 실패한 병합으로 인해 색인에 병합되지 않은 항목이 포함될 수 있습니다. 기본적으로 색인에서 이러한 항목을 체크 아웃하려고하면 체크 아웃 조작이 실패하고 체크 아웃되지 않습니다. 를 사용 -f하면 병합되지 않은 항목이 무시됩니다. 병합의 특정 측면에서 내용물을 사용하여 인덱스의 체크 아웃 할 수있는 --ours--theirs. 을 사용 -m하면 작업 트리 파일에 대한 변경 내용을 무시하여 원래 충돌 된 병합 결과를 다시 만들 수 있습니다.


4

비슷한 문제가 발생했습니다 (병합시 충돌을 일으킨 바이너리 파일이 포함 된 커밋을 가져와야 함) .git을 사용하여 완전히 수행 할 수있는 다른 솔루션을 발견했습니다 (즉, 수동으로 파일을 복사 할 필요가 없음). 나는 여기에 그것을 포함 시켜서 최소한 다음에 필요할 때 그것을 기억할 수 있다고 생각했습니다. :) 단계는 다음과 같습니다.

% git fetch

원격 저장소에서 최신 커밋을 가져 오지만 (설정에 따라 원격 브랜치 이름을 지정해야 할 수도 있음) 병합하지는 않습니다. 커밋을 FETCH_HEAD에 기록합니다.

% git checkout FETCH_HEAD stuff/to/update

이것은 내가 원하는 바이너리 파일의 사본을 가져 와서 작업 트리에있는 것을 원격 브랜치에서 가져온 버전으로 덮어 씁니다. git은 병합을 시도하지 않으므로 원격 지점에서 바이너리 파일의 정확한 사본으로 끝납니다. 완료되면 평소처럼 새 사본을 추가 / 커밋 할 수 있습니다.


4

이 절차는 Github에 풀 요청을 제출 한 후 이진 파일 충돌을 해결하는 것입니다.

  1. 따라서 Github에서 풀 요청이 바이너리 파일과 충돌하는 것을 발견했습니다.
  2. 이제 로컬 컴퓨터의 동일한 자식 분기로 돌아갑니다.
  3. (a)이 바이너리 파일을 다시 작성 / 다시 빌드하고 (b) 결과 바이너리 파일을이 동일한 git 브랜치에 커밋합니다.
  4. 그런 다음이 동일한 git branch를 다시 Github으로 푸시하십시오.

Github에서 풀 요청시 충돌이 사라집니다.


이것이 바로 내가 필요로하는 절차입니다.
Huifang Feng

2

바이너리가 dll 이상이거나 이미지와 같이 직접 편집 할 수있는 파일이거나 블렌드 파일 인 경우 (하나의 파일을 휴지통 / 선택하지 않아도 됨) 실제 병합은 다음과 같습니다.

바이너리 파일이 무엇인지에 대한 diff 도구를 검색하는 것이 좋습니다. 예를 들어 이미지 파일에 대한 무료 도구가 있습니다.

그것들을 비교하십시오.

파일을 비교할 수있는 diff 도구가 없다면 bin 파일 의 원래 생성기 (즉, 믹서기 3d와 같은 편집기 가있는 경우)를 수동으로 검사 할 수 있습니다. https://git-scm.com/book/es/v2/Git-Tools-Advanced-Merging#_manual_remerge를 사용 하여 로그를보고 다른 사람에게 무엇을 포함시켜야하는지 물어보고 파일을 출력 하십시오.

$ git show :1:hello.blend > hello.common.blend $ git show :2:hello.blend > hello.ours.blend $ git show :3:hello.blend > hello.theirs.blend


1

Windows에서 Git을 사용하여 이진 파일의 diff / merge를 관리하기위한 두 가지 전략을 살펴 보았습니다.

  1. Tortoise git를 사용하면 파일 확장자에 따라 다른 파일 형식으로 diff / merge 도구를 구성 할 수 있습니다. 2.35.4.3을 참조하십시오. Diff / Merge 고급 설정 http://tortoisegit.org/docs/tortoisegit/tgit-dug-settings.html . 물론이 전략은 사용 가능한 적절한 diff / merge 도구에 의존합니다.

  2. git 속성을 사용하면 도구 / 명령을 지정하여 이진 파일을 텍스트로 변환 한 다음 기본 diff / merge 도구가 작동하게 할 수 있습니다. http://git-scm.com/book/it/v2/Customizing-Git-Git-Attributes를 참조하십시오 . 이 기사는 메타 데이터를 사용하여 이미지를 비교하는 예제도 제공합니다.

소프트웨어 모델의 이진 파일로 작업하는 두 가지 전략을 모두 얻었지만 구성이 쉬우므로 거북이 git과 함께했습니다.


0

Excel 용 Git Workflow- https : //www.xltrail.com/blog/git-workflow-for-excel 응용 프로그램을 사용하여 대부분의 이진 파일 관련 병합 문제를 해결합니다. 이 오픈 소스 앱을 사용하면 너무 많은 시간을 소비하지 않고도 생산적으로 문제를 해결할 수 있으며 혼란없이 파일의 올바른 버전을 선택할 수 있습니다.


0

내 경우는 버그처럼 보인다 .... git 2.21.0 사용

나는 풀을했다 ... 바이너리 파일에 대해 불평했다.

warning: Cannot merge binary files: <path>
Auto-merging <path>
CONFLICT (content): Merge conflict in <path>
Automatic merge failed; fix conflicts and then commit the result.

그리고 여기에 어떤 대답에도 아무런 의미가없는 결과가 없었습니다.

내가 지금 가지고있는 파일을 보면 ... 내가 편집 한 파일입니다. 내가 한 경우 :

git checkout --theirs -- <path>
git checkout --ours -- <path>

나는 출력을 얻는다 :

Updated 0 paths from the index

그리고 여전히 내 파일 버전이 있습니다. 내가 rm하고 체크 아웃하면 대신 1이 표시되지만 여전히 내 버전의 파일을 제공합니다.

자식 병합 도구 말한다

No files need merging

자식 상태는 말합니다

    All conflicts fixed but you are still merging.
    (use "git commit" to conclude merge)

하나의 옵션은 커밋취소하는 것입니다 ...하지만 나는 운이 없었고 많은 커밋이 있었고이 나쁜 것이 첫 번째였습니다. 나는 그것을 반복하는 시간을 낭비하고 싶지 않습니다.

이 광기를 해결하려면 :

방금 도망 갔어

git commit

원격 버전을 잃어 버리고 여분의 이진 파일을 저장하는 공간을 낭비 할 것입니다 ...

git checkout <commit where the remote version exists> <path>

원격 버전을 다시 제공합니다.

그런 다음 파일을 다시 편집 한 다음 커밋하고 푸시하십시오. 이것은 아마도 이진 파일의 다른 사본으로 공간을 낭비하는 것을 의미합니다.


내 경우에 시도한 후 git checkout --ours <path>I 받았습니다 Updated 0 paths from the index . 나는 git add <path>명령으로 그것을 고쳤습니다.
Andriy
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.