Giải quyết xung đột hợp nhất Git có lợi cho những thay đổi của họ trong quá trình kéo


1226

Làm cách nào để giải quyết xung đột hợp nhất git có lợi cho các thay đổi được kéo?

Về cơ bản tôi cần loại bỏ tất cả các thay đổi xung đột khỏi cây làm việc mà không phải trải qua tất cả các xung đột git mergetooltrong một thời gian để giữ tất cả các thay đổi không xung đột. Tốt nhất là làm điều này trong khi kéo, không sau đó.



2
Bản sao của git pull từ xa .. tôi có thể buộc nó ghi đè thay vì báo cáo xung đột không? Bạn có thể thấy giải pháp tương tự ở đó.
Dan Dascalescu

3
@DanDascalescu Câu trả lời được chấp nhận ở đó không trả lời câu hỏi này, vì vậy rõ ràng nó không phải là một bản sao. Thêm vào đó, câu hỏi khác khá mơ hồ: rất khó để nói những gì được hỏi. Tất cả trong tất cả tôi không thể đồng ý với bạn. Bạn chỉ ra điều này là gì?
sanmai

2
@sanmai Bạn có hai câu trả lời - và bạn đã chấp nhận một trong số đó. Bạn có thể giải thích rõ hơn những gì bạn đang mong đợi trong một câu trả lời và bạn muốn chi tiết hơn bao nhiêu ở đây?
Edward Thomson

2
@EdwardThomson tốt, thực sự tôi đã suy nghĩ để mang lại danh tiếng này cho câu trả lời đầu tiên, nhưng nếu bạn hỏi, tôi có thể chờ xem liệu câu trả lời tốt hơn có xuất hiện không
sanmai

Câu trả lời:


1219
git pull -s recursive -X theirs <remoterepo or other repo>

Hoặc, đơn giản, cho kho lưu trữ mặc định:

git pull -X theirs

Nếu bạn đã ở trong trạng thái xung đột ...

git checkout --theirs path/to/file

40
Lưu ý rằng -s recursiveở đây là dư thừa, vì đó là chiến lược hợp nhất mặc định. Vì vậy, bạn có thể đơn giản hóa nó git pull -X theirs, về cơ bản là tương đương với git pull --strategy-option theirs.

5
Nếu tôi làm điều này, tôi sẽ trở lại trong MERGINGtiểu bang. Tôi có thể sau đó git merge --abortvà thử lại, nhưng mỗi lần tôi kết thúc với một sự hợp nhất xảy ra. Tôi biết rằng một cuộc nổi loạn đã được đẩy lên thượng nguồn của tôi, vì vậy có lẽ điều đó gây ra điều này?
Stewohn

22
Hãy cẩn thận với git checkout --theirs path/to/file. Sử dụng nó trong rebase và nhận được kết quả bất ngờ. Tìm thấy lời giải thích trong doc: Lưu ý rằng trong quá trình git rebase và git pull --rebase, chúng ta và chúng có thể bị tráo đổi; --ours cung cấp cho phiên bản từ chi nhánh các thay đổi được khởi động lại, trong khi --theirs cung cấp phiên bản từ chi nhánh giữ công việc của bạn đang bị từ chối.
Vuk Djapic

10
Lưu ý rằng git checkout --theirs/--ours pathtrang man nói rằng nó hoạt động cho các đường dẫn không được trộn . Vì vậy, nếu không có xung đột trong đường dẫn, nó đã được hợp nhất, lệnh này sẽ không làm gì cả. Điều này có thể xảy ra khi bạn muốn ví dụ phiên bản 'của họ' của toàn bộ thư mục con. Vì vậy, trong trường hợp như vậy sẽ an toàn hơn để làm git checkout MERGE_HEAD pathhoặc sử dụng hàm băm cam kết.
fsw

4
git pull -X theirstạo một cam kết hợp nhất nếu có xung đột (ví dụ: nếu một committer khác chạy git push -fđến điều khiển từ xa). Nếu bạn không muốn hợp nhất cam kết, thay vào đó hãy chạy git fetch && git reset --hard origin/master.
Dan Dascalescu

985

Bạn có thể sử dụng tùy chọn chiến lược "của họ" đệ quy :

git merge --strategy-option theirs

Từ người đàn ông :

ours
    This option forces conflicting hunks to be auto-resolved cleanly by 
    favoring our version. Changes from the other tree that do not 
    conflict with our side are reflected to the merge result.

    This should not be confused with the ours merge strategy, which does 
    not even look at what the other tree contains at all. It discards 
    everything the other tree did, declaring our history contains all that
    happened in it.

theirs
    This is opposite of ours.

Lưu ý: như trang man nói, tùy chọn chiến lược hợp nhất "của chúng ta" rất khác với chiến lược hợp nhất "của chúng ta" .


Dưới đây là lời giải thích chi tiết hơn: Lostechies.com/joshuaflanagan/2010/01/29/ trên
mPrinC

227
Ngoài ra git checkout --theirsđể hoạt động trên một tệp xung đột duy nhất
dvd

48
Điều này không hoạt động nếu bạn đã ở trong trạng thái giải quyết xung đột. Trong trường hợp đó tôi tin rằng cách tốt nhất để giải quyết là git checkout <ref to theirs> -- the/conflicted.file; và sau đó là git addnhững thay đổi của họ.
ThorSummoner

54
@ThorSummoner Trong trường hợp đó, có git checkout --theirs path / of / file. Bằng cách đó, bạn không phải tự tìm kiếm hàm băm chính xác.
Ikke

8
@Ikke Đó cơ bản nên là câu trả lời của riêng nó (và câu trả lời được chấp nhận tại đó) nếu bạn hỏi tôi.
ThorSummoner

473

Nếu bạn đã ở trong trạng thái xung đột và bạn muốn chấp nhận tất cả chúng:

git checkout --theirs .
git add .

Nếu bạn muốn làm ngược lại:

git checkout --ours .
git add .

Điều này khá quyết liệt, vì vậy hãy chắc chắn rằng bạn thực sự muốn xóa sạch mọi thứ như thế này trước khi thực hiện.


47
hoặc, không sử dụng .và chỉ định (các) tệp thay cho dấu chấm mà bạn muốn thanh toán. ít "quyết liệt" hơn và chính xác những gì bạn muốn làm, có lẽ.
manroe

10
điều này không hoạt động nếu tệp đã bị xóa khỏi nhánh khác: '<file>' không có phiên bản của chúng
Japster24

3
Sẽ upvote nhiều hơn nếu tôi có thể, tiếp tục trở lại câu trả lời này mọi lúc.
tarikki

6
Sử dụng git add -uthay thế để bỏ qua các tập tin không thuộc kiểm soát phiên bản.
Sudipta Basak

3
Trường hợp giả thuyết, ba thay đổi trong một tệp, một xung đột, hai không xung đột, liệu giải pháp này có áp dụng các thay đổi không xung đột và giải quyết thay đổi xung đột với chúng ta không? Hoặc sẽ chỉ mất phiên bản của chúng tôi bỏ qua những thay đổi không xung đột từ họ?
pedromarce

222

OK, hãy hình dung kịch bản tôi vừa tham gia:

Bạn cố gắng a merge, hoặc có thể a cherry-pick, và bạn đã dừng lại với

$ git cherry-pick 1023e24
error: could not apply 1023e24... [Commit Message]
hint: after resolving the conflicts, mark the corrected paths
hint: with 'git add <paths>' or 'git rm <paths>'
hint: and commit the result with 'git commit'

Bây giờ, bạn xem tệp bị xung đột và bạn thực sự không muốn giữ các thay đổi của mình. Trong trường hợp của tôi ở trên, tệp đã bị xung đột chỉ trên một dòng mới mà IDE của tôi đã tự động thêm vào. Để hoàn tác các thay đổi của bạn và chấp nhận thay đổi của họ, cách dễ nhất là:

git checkout --theirs path/to/the/conflicted_file.php
git add path/to/the/conflicted_file.php

Nghịch lý điều này (để ghi đè phiên bản đến với phiên bản của bạn) là

git checkout --ours path/to/the/conflicted_file.php
git add path/to/the/conflicted_file.php

Đáng ngạc nhiên, tôi không thể tìm thấy câu trả lời này rất dễ dàng trên mạng.


15
Lưu ý rằng, nếu một người thực hiện git statusgiữa checkoutadd, tệp vẫn hiển thị là "cả hai đã được sửa đổi".
giám mục

Bạn có biết có cách nào để làm điều này cho tất cả các tệp đang ở trạng thái xung đột không? Nếu vậy nó sẽ là một phần mở rộng tốt đẹp cho câu trả lời của bạn.
Drew Noakes

2
Tôi làm điều này: git reset --hard và sau đó git pull [remote server name] [branch name] -Xtheirs(hoàn tác việc hợp nhất sau đó kéo công cụ mới lên trên công cụ của tôi) - không chắc đây có phải là điều bạn muốn không.
ssaltman

38

Các git pull -X theirscâu trả lời có thể tạo ra một cam kết hợp nhất xấu xí hoặc đưa ra một

lỗi: Thay đổi cục bộ của bạn đối với các tệp sau sẽ bị ghi đè bằng cách hợp nhất:

Nếu bạn muốn đơn giản bỏ qua mọi sửa đổi cục bộ đối với các tệp từ repo, ví dụ trên máy khách phải luôn là bản sao của nguồn gốc, hãy chạy cái này (thay thế masterbằng nhánh bạn muốn):

git fetch && git reset --hard origin/master

Làm thế nào nó hoạt động? git fetchkhông git pullnhưng không hợp nhất . Sau đó git reset --hardlàm cho cây làm việc của bạn phù hợp với cam kết cuối cùng. Tất cả các thay đổi cục bộ của bạn đối với các tệp trong repo sẽ bị loại bỏ , nhưng các tệp cục bộ mới sẽ bị bỏ lại một mình.


1
+1 - git fetch && git reset --hard {remote}/{branch}là những gì đã giải quyết vấn đề của tôi. Tôi cần phải hoàn toàn bỏ qua các thay đổi của riêng mình để ủng hộ trạng thái "của họ" của một chi nhánh, nhưng git pull -X theirsbị nghẹn trên một số tệp được di chuyển / đổi tên. Cảm ơn!
Ivaylo Slavov

23

Sau khi hợp nhất git, nếu bạn gặp xung đột và bạn muốn của họ hoặc của họ

git checkout --theirs .
git checkout --ours .

Làm thế nào tôi có thể làm điều này trên cơ sở chunk xung đột? Ở trên hoạt động ở cấp độ tệp, loại bỏ bất kỳ khối không xung đột nào mà tệp xung đột có thể có.
Jani

21

Để giải quyết tất cả các xung đột với phiên bản trong một chi nhánh cụ thể:

git diff --name-only --diff-filter=U | xargs git checkout ${branchName}

Vì vậy, nếu bạn đã ở trạng thái hợp nhất và bạn muốn giữ phiên bản chính của các tệp xung đột:

git diff --name-only --diff-filter=U | xargs git checkout master

Và đối với những người trên windows không có quyền truy cập vào ống xarg, làm thế nào để dịch?
tsTable

Nó sẽ không bỏ qua hoàn toàn thay đổi của bạn? Ngay cả những người không ở trong trạng thái xung đột?
Valentin Heinitz

Đây là những gì tôi đã làm. Thật không may, sau đó nó yêu cầu một git cherry-pick --continue hoặc một git commit --allow-emptylệnh để thực hiện các thay đổi này và dường như không có hệ thống nào đằng sau lệnh nào được yêu cầu, điều này khiến việc tự động hóa điều này trở nên khó khăn. Tôi hiện đang giải quyết vấn đề này bằng cách kiểm tra sự tồn tại của một .git/COMMIT_EDITMSGtập tin nhưng điều đó có vẻ khó hiểu và dễ vỡ, và tôi vẫn chưa tin rằng nó luôn hoạt động.
Konrad Rudolph

Điều này là tốt, có nghĩa là nếu bạn giải quyết thủ công một số (và làm git add) thì bạn có thể giải quyết hàng loạt phần còn lại thông qua việc này. git checkout --ours/ git checkout --theirscũng hữu ích.
RCoup

18

Xin lưu ý rằng đôi khi điều này sẽ không hoạt động :

kiểm tra git - đường dẫn / đến / tập tin

hoặc là

kiểm tra git - đường dẫn / đến / tập tin

Tôi đã làm điều này thay vào đó, giả sử CHÍNH là của chúng tôiMERGE_HEAD là của họ

git checkout HEAD -- path/to/file

hoặc là:

git checkout MERGE_HEAD -- path/to/file

Sau khi chúng tôi làm điều này và chúng tôi tốt:

git add .

Nếu bạn muốn hiểu thêm, hãy xem bài đăng tuyệt vời của torek tại đây: git checkout --ours không xóa các tệp khỏi danh sách tệp không được trộn


12

Người dùng IDE Mã VS (tích hợp Git):

Nếu bạn muốn chấp nhận tất cả các thay đổi đến trong tệp xung đột thì hãy thực hiện các bước sau.

1. Go to command palette - Ctrl + Shift + P
2. Select the option - Merge Conflict: Accept All Incoming

Tương tự, bạn có thể làm cho các tùy chọn khác như Chấp nhận cả hai, Chấp nhận tất cả hiện tại, v.v.


2
Điều đó dường như chỉ hoạt động cho một tệp duy nhất, không phải tất cả các tệp có xung đột.
Yoryo

1

Tôi đã có một next-versionnhánh hoạt động lâu dài với hàng tấn xóa các tệp đã thay đổi develop, các tệp đã được thêm vào ở những nơi khác nhau trên cả hai nhánh, v.v.

Tôi muốn đưa toàn bộ nội dung của next-versionchi nhánh vào develop, tất cả trong một cam kết hợp nhất lớn.

Sự kết hợp của các lệnh trên làm việc cho tôi là:

git merge -X theirs next-version
# lots of files left that were modified on develop but deleted on next-version
git checkout next-version .
# files removed, now add the deletions to the commit
git add .
# still have files that were added on develop; in my case they are all in web/
git rm -r web

Không phải là một câu trả lời mới, chỉ cần kết hợp các bit từ nhiều câu trả lời, một phần để trấn an rằng bạn có thể cần tất cả các câu trả lời này.


1

Nếu bạn đã ở trong trạng thái xung đột và không muốn kiểm tra từng đường một. Bạn có thể thử

git merge --abort
git pull -X theirs

-1

từ https://git-scm.com/book/en/v2/Git-Tools-Avised-Merging

Điều này về cơ bản sẽ làm một sự hợp nhất giả. Nó sẽ ghi lại một cam kết hợp nhất mới với cả hai nhánh là cha mẹ, nhưng nó thậm chí sẽ không nhìn vào nhánh bạn đang hợp nhất. Nó sẽ chỉ ghi lại như là kết quả của việc hợp nhất mã chính xác trong nhánh hiện tại của bạn.

$ git merge -s ours mundo

Hợp nhất được thực hiện bởi chiến lược 'của chúng ta'.

$ git diff HEAD HEAD~

Bạn có thể thấy rằng không có sự khác biệt giữa nhánh chúng tôi đã ở và kết quả của sự hợp nhất.

Điều này thường có thể hữu ích để về cơ bản lừa Git nghĩ rằng một nhánh đã được hợp nhất khi thực hiện hợp nhất sau này. Ví dụ: giả sử bạn đã phân nhánh một nhánh phát hành và đã thực hiện một số công việc trên đó mà bạn sẽ muốn hợp nhất trở lại vào nhánh chính của mình tại một số điểm. Trong khi đó, một số lỗi trên bản gốc cần được nhập vào nhánh phát hành của bạn. Bạn có thể hợp nhất nhánh bugfix vào nhánh phát hành và cũng hợp nhất nhánh của chúng ta vào nhánh chính của bạn (mặc dù đã có bản sửa lỗi) nên khi bạn hợp nhất nhánh phát hành lại, không có xung đột từ bugfix.

Một tình huống tôi thấy hữu ích nếu tôi muốn chủ nhân phản ánh những thay đổi của một nhánh chủ đề mới. Tôi đã nhận thấy rằng -Xtheir không hợp nhất mà không có xung đột trong một số trường hợp ... ví dụ:

$ git merge -Xtheirs topicFoo 

CONFLICT (modify/delete): js/search.js deleted in HEAD and modified in topicFoo. Version topicFoo of js/search.js left in tree.

Trong trường hợp này, giải pháp tôi tìm thấy là

$ git checkout topicFoo

từ topicFoo, lần đầu tiên hợp nhất trong tổng thể bằng cách sử dụng chiến lược -s của chúng tôi, điều này sẽ tạo ra cam kết giả mạo chỉ là trạng thái của topicFoo. $ git merge -s chủ của chúng ta

kiểm tra cam kết hợp nhất đã tạo

$ git log

bây giờ kiểm tra chi nhánh

$ git checkout master

hợp nhất nhánh chủ đề trở lại nhưng lần này sử dụng chiến lược đệ quy -Xtheirs, giờ đây nó sẽ hiển thị cho bạn một nhánh chính với trạng thái topicFoo.

$ git merge -X theirs topicFoo
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.