git을 사용하여 전체 파일에서 '자신의 수락'또는 '나의 수락'을위한 간단한 도구


399

시각적 병합 도구를 원하지 않고 충돌하는 파일을 viing하고 수동으로 HEAD (광산)와 가져온 변경 (그들)을 선택하고 싶지 않습니다. 대부분의 경우, 나는 그들의 모든 변화 또는 나의 모든 것을 원합니다. 일반적으로 이것은 변경으로 인해 혼란스러워지고 풀을 통해 다시 돌아 오지만 여러 곳에서 약간 수정 될 수 있기 때문입니다.

충돌 마커를 제거하고 내 선택에 따라 모든 방법을 선택할 수있는 명령 줄 도구가 있습니까? 또는 각 명령을 수행하기 위해 별명을 지정할 수있는 git 명령 세트.

# accept mine
alias am="some_sequence;of;commands"
alias at="some_other_sequence;of;commands"

이 작업은 다소 성가신 일입니다. '나를 받아들이십시오'에 대해 시도했습니다.

randy@sabotage ~/linus $ git merge test-branch
Auto-merging Makefile
CONFLICT (content): Merge conflict in Makefile
Automatic merge failed; fix conflicts and then commit the result.

randy@sabotage ~/linus $ git checkout Makefile 
error: path 'Makefile' is unmerged

andy@sabotage ~/linus $ git reset --hard HEAD Makefile 
fatal: Cannot do hard reset with paths.

이 변경 표시를 어떻게 제거해야합니까?

내가 할 수있는:

git reset HEAD Makefile; rm Makefile; git checkout Makefile

그러나 이것은 오히려 둥글게 보입니다. 더 나은 방법이 있어야합니다. 그리고이 시점에서 git이 병합이 발생했다고 생각하는지 확실하지 않으므로 이것이 반드시 작동한다고 생각하지는 않습니다.

다른 방법으로 가면 '수락을 받아들이는 것'도 엉망입니다. 내가 알아낼 수있는 유일한 방법은 다음과 같습니다.

git show test-branch:Makefile > Makefile; git add Makefile;

이것은 또한 엉망인 커밋 메시지를 제공합니다.이 메시지에는 Conflicts : Makefile이 두 번 있습니다.

누군가 위의 두 가지 행동을 더 간단한 방법으로 지적 할 수 있습니까? 감사


4
나는 이것을 3 년 이상 git 명령 줄 사용자로 제공해야합니다. 기본적으로 내장되어 있어야합니다.
Mauvis Ledford

답변:


602

해결책은 매우 간단합니다. indexgit checkout <filename> 에서 파일을 체크 아웃하려고 하므로 병합시 실패합니다.

당신이해야 할 일은 (즉, 커밋 체크 아웃 ) :

자신의 버전을 체크 아웃하려면 다음 중 하나 를 사용할 수 있습니다 .

git checkout HEAD -- <filename>

또는

git checkout --ours -- <filename>

또는

git show :2:<filename> > <filename> # (stage 2 is ours)

다른 버전을 체크 아웃하려면 다음 중 하나 를 사용할 수 있습니다 .

git checkout test-branch -- <filename>

또는

git checkout --theirs -- <filename>

또는

git show :3:<filename> > <filename> # (stage 3 is theirs)

또한 'add'를 실행하여 해결 된 것으로 표시해야합니다.

git add <filename>

31
나는 조금 이상한 것을 발견 --ours하고 --theirs수단 정확히이 명령을 시도 할 때 나는 직관적으로 생각했던 반대 ...
여호수아 Muheim

6
사용할 때주의하십시오 git show– 이것은 개행 정규화를 건너 뜁니다.
Chronial

2
이것은 약간의 파일에는 좋지만 (주석의 날짜가 변경 되었기 때문에) 많은 파일이 충돌하는 경우 어떻게합니까?
JhovaniC

4
@Santhos :는 --Git에서 경로 이름 (파일 이름, 디렉토리)과 수정본 (분기 이름 등)을 구분하는 데 사용됩니다. Git이 이름이 브랜치 이름인지 파일 이름인지 결정할 수없는 경우 중요합니다. 이것은 옵션을 인수 (파일 이름)와 구분하기 위해 이중 대시를 사용하는 POSIX (또는 GNU) 규칙을 따릅니다.
Jakub Narębski

3
@Sammaron @Joshua Muheim; theirs/는 ours당신이 REBASE 작업의 맥락에서 충돌을 해결하는 경우 교환 나타날 수 있습니다. rebase는 대상 분기를 체크 아웃하여 작동하므로 Cherry-picking은 "your"분기에서 대상으로 커밋하고, 들어오는 변경 ( "그들의")은 "your"분기에서, 현재 분기는 대상 분기 ( "ours")입니다. ).
RJFalconer

93

이 시도:

변경 사항을 승인하려면 다음을 수행하십시오. git merge --strategy-option theirs

당신을 받아들이려면 : git merge --strategy-option ours


5
이렇게하면 충돌하는 모든 파일에 대한 변경 내용이 유지되므로 예기치 않은 충돌이 발생할 경우 위험 할 수 있습니다.
John

3
또한 cherry-pick 및 rebase와 같은 다른 병합 명령에 사용할 수 있습니다.
idbrii

50

Jakub의 답변을 기반으로 편의를 위해 다음 git 별칭을 구성 할 수 있습니다.

accept-ours = "!f() { git checkout --ours -- \"${@:-.}\"; git add -u \"${@:-.}\"; }; f"
accept-theirs = "!f() { git checkout --theirs -- \"${@:-.}\"; git add -u \"${@:-.}\"; }; f"

선택적으로 하나 또는 여러 개의 파일 경로를 사용하여 해결하고 기본값이 없으면 현재 디렉토리 아래의 모든 것을 해결합니다.

[alias]당신 의 섹션에 추가 ~/.gitconfig하거나 실행

git config --global alias.accept-ours '!f() { git checkout --ours -- "${@:-.}"; git add -u "${@:-.}"; }; f'
git config --global alias.accept-theirs '!f() { git checkout --theirs -- "${@:-.}"; git add -u "${@:-.}"; }; f'

1
나를 위해 작동하지 않습니다 ... 이것들은 bash 또는 다른 쉘입니까?
user456584

이들은 git 별칭 입니다. [alias]섹션에 추가 ~.gitconfig하거나 사용하십시오 git config --global accept-ours "...". 내 답변을 수정했습니다.
kynan

2
이 별명이 얼마나 많은 시간을 절약했는지 알 수 없습니다. 엄지 손가락!
Adam Parkin

1
@hakre 별명을 인용했는지 확인하십시오. 그렇지 않으면 쉘이 별명을 해석하려고 시도합니다. 또는을 수동으로 수정하십시오 ~/.gitconfig.
kynan

1
기본값을위한 쉘 문법 :!f() { git checkout --ours -- "${@:-.}" git add -u "${@:-.}; }; f
jthill

17

kynan의 답변을 바탕으로 파일 이름에서 공백과 초기 대시를 처리 할 수 ​​있도록 수정 된 동일한 별칭이 있습니다.

accept-ours = "!f() { [ -z \"$@\" ] && set - '.'; git checkout --ours -- \"$@\"; git add -u -- \"$@\"; }; f"
accept-theirs = "!f() { [ -z \"$@\" ] && set - '.'; git checkout --theirs -- \"$@\"; git add -u -- \"$@\"; }; f"

0

충돌을 해결하기위한 이상적인 상황은 충돌을 해결하려는 방법을 미리 알고 재귀 적 병합 전략 옵션을 통과 할 수있는 -Xours경우 -Xtheirs입니다. 이 외에도 세 가지 시나리오가 있습니다.

  1. 파일의 단일 버전 만 유지하려고합니다 (이 파일은 병합 할 수없는 이진 파일에서만 사용해야합니다. 그렇지 않으면 충돌하거나 충돌하지 않는 파일이 서로 동기화되지 않을 수 있음).
  2. 특정 방향으로 모든 충돌을 간단히 결정하려고합니다.
  3. 일부 충돌을 수동으로 해결 한 다음 나머지는 모두 특정 방향으로 해결해야합니다.

이 세 가지 시나리오를 해결하기 위해 .gitconfig파일에 다음 줄을 추가 할 수 있습니다 .

[merge]
  conflictstyle = diff3
[mergetool.getours]
  cmd = git-checkout --ours ${MERGED}
  trustExitCode = true
[mergetool.mergeours]
  cmd = git-merge-file --ours ${LOCAL} ${BASE} ${REMOTE} -p > ${MERGED}
  trustExitCode = true
[mergetool.keepours]
  cmd = sed -I '' -e '/^<<<<<<</d' -e '/^|||||||/,/^>>>>>>>/d' ${MERGED}
  trustExitCode = true
[mergetool.gettheirs]
  cmd = git-checkout --theirs ${MERGED}
  trustExitCode = true
[mergetool.mergetheirs]
  cmd = git-merge-file --theirs ${LOCAL} ${BASE} ${REMOTE} -p > ${MERGED}
  trustExitCode = true
[mergetool.keeptheirs]
  cmd = sed -I '' -e '/^<<<<<<</,/^=======/d' -e '/^>>>>>>>/d' ${MERGED}
  trustExitCode = true

get(ours|theirs)도구는 파일의 각 버전을 유지하고 다른 버전의 모든 변경 사항을 버립니다 (병합이 발생하지 않음).

merge(ours|theirs)도구는 파일의 로컬, 기본 및 원격 버전에서 3 방향 병합을 다시 수행하여 지정된 방향의 충돌을 해결하도록 선택합니다. 여기에는 몇 가지주의 사항이 있습니다. 특히 병합 명령 (예 : 알고리즘 및 공백 처리)에 전달 된 diff 옵션은 무시합니다. 원본 파일에서 병합을 깔끔하게 수행합니다 (따라서 파일에 대한 수동 변경 사항은 무시되므로 좋거나 나쁠 수 있음). 파일에 있어야하는 diff 마커와 혼동 될 수 없다는 이점이 있습니다.

keep(ours|theirs)도구는 단순히 diff 마커와 닫힌 섹션을 편집하여 정규 표현식으로 감지합니다. 이는 merge 명령의 diff 옵션을 유지하고 일부 충돌을 수동으로 해결 한 다음 나머지를 자동으로 해결할 수 있다는 이점이 있습니다. 파일에 다른 충돌 마커가 있으면 혼동 될 수 있다는 단점이 있습니다.

이것들은 모두 제공되지 않은 git mergetool -t (get|merge|keep)(ours|theirs) [<filename>]경우 실행 되어 <filename>모든 충돌 파일을 처리 하여 사용됩니다 .

일반적으로 말하면 정규 표현식을 혼란스럽게하는 diff 마커가 없다는 것을 가정하면 keep*명령 의 변형이 가장 강력합니다. mergetool.keepBackup옵션을 설정하지 않거나 true로 두면 병합 후에 *.orig파일을 병합 결과와 비교하여 해당 파일이 의미가 있는지 확인할 수 있습니다. 예를 들어, mergetool커밋하기 전에 변경 사항을 검사하기 위해 다음을 실행합니다 .

for f in `find . -name '*.orig'`; do vimdiff $f ${f%.orig}; done

참고 : merge.conflictstyle이 아닌 경우 규칙 diff3/^|||||||/패턴 sed/^=======/대신 필요합니다 .

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