[git] 강제 덮어 쓰기로 Git 병합

분기 demo와 병합해야하는 master분기가 있습니다. 다음 명령으로 원하는 결과를 얻을 수 있습니다.

git pull origin demo
git checkout master
git pull origin master
git merge demo
git push origin master

내 유일한 관심사는 병합 문제가있는 경우 병합 프롬프트를 표시하지 않고 분기의 git변경 사항을 덮어 쓰라고 말하고 싶습니다 master. 따라서 기본적으로 demo분기의 변경 사항은 분기의 변경 사항을 자동으로 덮어 써야합니다 master.

여러 옵션을 둘러 보았지만 병합에 대한 기회를 잡고 싶지 않습니다.



답변

정말이 대답과 관련,하지만 난 도랑 것 아니 git pull바로 실행이되는, git fetch다음에 git merge. 세 번의 병합을 수행하면 한 번의 가져 오기가 필요한 경우 Git에서 세 번의 가져 오기 작업을 실행하게됩니다. 그 후:

git fetch origin   # update all our origin/* remote-tracking branches

git checkout demo         # if needed -- your example assumes you're on it
git merge origin/demo     # if needed -- see below

git checkout master
git merge origin/master

git merge -X theirs demo   # but see below

git push origin master     # again, see below

가장 까다로운 병합 제어

여기서 가장 흥미로운 부분은 git merge -X theirs입니다. 으로 root545는 지적-X옵션은 병합 전략에 전달하고 기본 모두 recursive전략과 대안 resolve전략 포획 -X ours또는 -X theirs(둘 중 하나만). 하지만 그들이하는 일을 이해하려면 Git이 어떻게 병합 충돌을 찾고 처리하는지 알아야합니다 .

기본 버전 이 동일한 파일 의 현재 (로컬, HEAD 또는라고도 함 ) 버전 다른 (원격 또는이라고도 함 ) 버전 다를 때 일부 파일 1 내에서 병합 충돌이 발생할 수 있습니다 . 즉, 병합은 base, ours 및 theirs의 세 가지 개정 (세 개의 커밋)을 식별했습니다. “기본”버전은 커밋 그래프에서 볼 수 있듯이 커밋과 커밋 간의 병합 기반 에서 가져온 것 입니다 (이에 대한 자세한 내용은 다른 StackOverflow 게시물 참조). Git은 “우리가 한 일”과 “그들이 한 일”이라는 두 가지 변경 사항을 발견했습니다. 이러한 변경 사항은 (일반적으로) 한 줄씩 순전히 텍스트로 표시됩니다.--ours--theirs기초. Git은 파일 내용을 제대로 이해하지 못합니다. 단지 각 텍스트 줄을 비교하는 것입니다.

이러한 변경 사항은 git diff출력에서 볼 수 있으며 항상 그렇듯이 컨텍스트 도 있습니다. 변경 한 내용이 변경된 내용과 다른 줄에있을 수 있으므로 변경 내용이 충돌하지 않는 것처럼 보이지만 컨텍스트도 변경되었습니다 (예 : 변경 내용이 파일의 상단 또는 하단에 가까워짐에 따라 그래서 우리 버전에서는 파일이 다 떨어지지 만 그들의 버전에서는 상단이나 하단에 더 많은 텍스트를 추가했습니다).

변경 사항에 일어날 경우 다른 라인-에 대한 예, 우리는 변화 colorcolour라인 (17)에 그들이 변경 fredbarney줄에 71 다음 충돌이없는 : 힘내 간단합니다 모두 변경. 변경 사항이 동일한 줄에서 발생하지만 동일한 변경 사항 인 경우 Git은 변경 사항의 복사본 하나를 가져옵니다 . 변경 사항이 동일한 줄에 있지만 다른 변경 사항이거나 컨텍스트를 방해하는 특수한 경우에만 수정 / 수정 충돌이 발생합니까?

-X ours-X theirs우리, 또는 그들의 것을 : 옵션은 두 가지 변화 중 하나를 선택하여,이 충돌을 해결하는 방법을 망할 놈의 말. demo(그들의)를 master(우리의) 로 병합 하고에서 변경 사항을 demo원한다고 말 했으므로 -X theirs.

-X그러나 맹목적으로 적용하는 것은 위험합니다. 변경 사항이 줄 단위로 충돌하지 않았다고해서 변경 사항이 실제로 충돌하지 않는다는 의미는 아닙니다! 한 가지 고전적인 예는 변수 선언이있는 언어에서 발생합니다. 기본 버전은 사용되지 않는 변수를 선언 할 수 있습니다.

int i;

우리 버전에서는 컴파일러 경고를 없애기 위해 사용되지 않는 변수를 삭제하고, 버전에서는 i루프 카운터로 사용하여 몇 줄 후에 루프를 추가합니다 . 두 변경 사항을 결합하면 결과 코드가 더 이상 컴파일되지 않습니다. 이 -X옵션은 변경 사항이 다른 행 에 있으므로 여기서는 도움이되지 않습니다 .

자동화 된 테스트 스위트가있는 경우 가장 중요한 것은 병합 후 테스트를 실행하는 것입니다. 커밋 후에이 작업을 수행하고 필요한 경우 나중에 수정할 수 있습니다. 또는 커밋 하기 전에 명령 에 추가 --no-commit하여 수행 할 수 있습니다 git merge. 이 모든 세부 사항은 다른 게시물에 남겨 둘 것입니다.


1 “파일 전체”작업과 관련하여 충돌이 발생할 수도 있습니다. 예를 들어 파일에서 단어의 철자를 수정하여 (변경할 수 있도록) 전체 파일 을 삭제 합니다 ( 지우다). Git은 -X인수에 관계없이 이러한 충돌을 자체적으로 해결하지 않습니다 .


더 적은 병합 및 / 또는 더 스마트 한 병합 및 / 또는 리베이스 사용

두 명령 시퀀스 모두에 세 가지 병합이 있습니다. 첫 번째는 origin/demo로컬 로 가져 오는 demo것입니다 ( git pullGit가 매우 오래된 경우 업데이트에 실패 origin/demo하지만 동일한 최종 결과를 생성하는 사용자 사용). 두 번째는 가지고하는 것입니다 origin/master으로 master.

누가 업데이트 demo하고 있는지 명확하지 않습니다 master. 자신의 demo브랜치 에 자신의 코드를 작성 하고 다른 사람들이 코드를 작성하여에서 demo브랜치에 푸시하는 origin경우이 첫 번째 단계 병합은 충돌을 일으키거나 실제 병합을 생성 할 수 있습니다. 종종 병합보다는 rebase를 사용하여 작업을 결합하는 것이 좋습니다 (분명히 이것은 취향과 의견의 문제입니다). 그렇다면 git rebase대신 사용할 수 있습니다 . 당신이 당신의 자신의 커밋 중 하나가에하지 않을 경우 반면에 demo, 당신도하지 않습니다 필요demo 지점을. 또는 많은 것을 자동화하고 싶지만, 당신과 다른 사람들이 만든 커밋이있을 때주의 깊게 확인할 수 있다면,git merge --ff-only origin/demo: 이것은 가능한 경우 demo업데이트 된 것과 일치하도록 빨리 감기 origin/demo하고 그렇지 않은 경우 완전히 실패합니다 (이 시점에서 두 가지 변경 사항을 검사하고 적절하게 실제 병합 또는 리베이스를 선택할 수 있습니다).

이 동일한 논리가에 적용 master되지만에서 병합 수행 master하므로 반드시 master. 그러나 빨리 감기 비 병합으로 수행 할 수없는 경우 병합이 실패하기를 원할 가능성이 더 높으므로이 역시 git merge --ff-only origin/master.

.NET에서 직접 커밋을하지 않는다고 가정 해 봅시다 demo. 이 경우 이름을 demo완전히 버릴 수 있습니다 .

git fetch origin   # update origin/*

git checkout master
git merge --ff-only origin/master || die "cannot fast-forward our master"

git merge -X theirs origin/demo || die "complex merge conflict"

git push origin master

당신이 경우에 하는 자신의 일 demo지점 커밋이는 도움이되지 않습니다; 기존 병합을 유지 --ff-only하거나 (원하는 동작 에 따라 추가 할 수 있음) 리베이스로 전환 할 수도 있습니다. 참고 모든 세 가지 방법이 실패 할 수 있음 : 병합 충돌이 실패 할 수 있습니다와 병합 --ff-only빨리 감기를 할 수 없습니다 및 REBASE이 REBASE는 본질적으로 작동 (충돌이 실패 할 수 있습니다, 체리 따기 커밋, 병합을 사용하는 따라서 병합 충돌이 발생할 수 있습니다.


답변

비슷한 문제가있어서 변경 / 충돌이있는 파일을 다른 브랜치와 효과적으로 교체해야했습니다.

내가 찾은 해결책은 git merge -s ours branch.

이 옵션은 -s이고 아닙니다 -X. 는 최상위 병합 전략으로 -s의 사용을 나타내며 ours병합 전략에 옵션을 -X적용하는 것 입니다.oursrecursive

단계,은 ( oldbranch는) 덮어 쓰려는 분기입니다 newbranch.

  • git checkout newbranch 유지하려는 지점을 확인합니다.
  • git merge -s ours oldbranch 이전 브랜치에 병합되지만 모든 파일을 유지합니다.
  • git checkout oldbranch 덮어 쓰려는 브랜치를 체크 아웃합니다.
  • get merge newbranch 새 분기에 병합하여 이전 분기를 덮어 씁니다.


답변

이 병합 접근 방식은 충돌이나 다른 쓰레기에 대해 불평하지 않고 master에있는 모든 파일에 붙여 넣는 하나의 커밋을 추가 feature합니다.

여기에 이미지 설명 입력

아무것도 만지기 전에

git stash
git status # if anything shows up here, move it to your desktop

이제 마스터 준비

git checkout master
git pull # if there is a problem in this step, it is outside the scope of this answer

하기 feature모든 옷을 입고

git checkout feature
git merge --strategy=ours master

죽여라

git checkout master
git merge --no-ff feature


답변

git merge에서 “ours”옵션을 시도 할 수 있습니다.

git merge branch -X ours

이 옵션은 우리 버전을 선호하여 충돌하는 덩크를 자동 해결하도록 강제합니다. 우리 쪽과 충돌하지 않는 다른 트리의 변경 사항은 병합 결과에 반영됩니다. 바이너리 파일의 경우 전체 내용은 우리 쪽에서 가져옵니다.


답변

-X theirs및 기타 관련 명령 스위치를 사용하려고 할 때 병합 커밋이 계속 발생했습니다. 아마 제대로 이해하지 못했을 것입니다. 이해하기 쉬운 대안 중 하나는 분기를 삭제 한 다음 다시 추적하는 것입니다.

git branch -D <branch-name>
git branch --track <branch-name> origin/<branch-name>

이것은 정확히 “병합”이 아니지만이 질문을 발견했을 때 제가 찾고 있던 것입니다. 제 경우에는 강제로 푸시 된 원격 분기에서 변경 사항을 가져오고 싶었습니다.


답변