Tôi chạy vào một cuộc xung đột hợp nhất. Làm thế nào tôi có thể hủy bỏ hợp nhất?


2539

Tôi đã sử dụng git pullvà có một cuộc xung đột hợp nhất:

unmerged:   _widget.html.erb

You are in the middle of a conflicted merge.

Tôi biết rằng phiên bản khác của tệp là tốt và của tôi là xấu nên tất cả các thay đổi của tôi sẽ bị hủy bỏ. Tôi có thể làm cái này như thế nào?


30
Tôi nhận ra đây là một câu hỏi siêu cũ, nhưng bạn có muốn hủy bỏ toàn bộ hợp nhất và để lại nhánh bạn đang hợp nhất không bị trộn lẫn hoặc chỉ bỏ qua một tệp này như một phần của hợp nhất lớn hơn, cho phép tất cả các tệp khác hợp nhất thành bình thường? Đối với tôi, tiêu đề của bạn ngụ ý cái trước, cơ quan câu hỏi của bạn muốn cái sau. Các câu trả lời làm cả hai, mà không làm cho mọi thứ rõ ràng.
rjmunro

Tôi đã gặp trường hợp tương tự khi cam kết nói rằng hợp nhất tự động không thành công; khắc phục xung đột và sau đó cam kết kết quả:[rejected] gh-pages -> gh-pages (non-fast-forward)
Chetabahana

4
Gwyn, nó có thể hữu ích để chọn một câu trả lời được chấp nhận ở đây. Công cụ được bình chọn hàng đầu ít an toàn hơn một số giải pháp cập nhật hơn, vì vậy tôi nghĩ rằng nó sẽ giúp làm nổi bật những người khác về nó :)
Amitable

Câu trả lời:


2220

Vì bạn pullđã không thành công nên HEAD(không HEAD^) là cam kết "hợp lệ" cuối cùng trên chi nhánh của bạn:

git reset --hard HEAD

Một phần khác bạn muốn là để cho những thay đổi của họ vượt qua những thay đổi của bạn.

Các phiên bản cũ hơn của git cho phép bạn sử dụng chiến lược hợp nhất "của họ":

git pull --strategy=theirs remote_branch

Nhưng điều này đã bị xóa, như được giải thích trong tin nhắn này của Junio ​​Hamano (người duy trì Git). Như đã lưu ý trong liên kết , thay vào đó bạn sẽ làm điều này:

git fetch origin
git reset --hard origin

49
Thay vì thực hiện thiết lập lại cứng, bạn có thể đưa nó đến mức chi tiết hơn bằng cách thực hiện: git fetch origin -> git reset origin (soft reset, your changes are still present) -> git checkout file_to_use_their_version_of another_file (steamroll your own changes back to match the origin) Tôi không bao giờ sử dụng git pull nữa. Vì trong một cuộc chiến giữa mã mới nhất của tôi và nguồn gốc, nguồn gốc phải luôn luôn thắng, tôi luôn luôn git fetchgit rebase origin. Điều này thực sự làm cho sự hợp nhất và xung đột của tôi rất ít.
Kzqai

7
Tôi đồng ý. Tôi cũng muốn tìm nạp trước, và sau đó kiểm tra các thay đổi ngược dòng ( git log ..@{upstream}hoặc git diff ..@{upstream}). Sau đó, giống như bạn, tôi sẽ bắt đầu lại công việc của mình.
Pat Notz

162
Như đã lưu ý trong một câu trả lời gần đây hơn, kể từ phiên bản 1.6.1, có thể sử dụng 'git reset --merge'
Matt Ball

5
Tôi sử dụng git merge -X theirs remote_branchthay vì git pull --strategy=theirs remote_branchnhư theirstrông giống như một tùy chọnrecursive
MLT

14
git merge --abortlà thích hợp hơn nhiều.
Daniel Cassidy

1956

Nếu phiên bản git của bạn> = 1.6.1, bạn có thể sử dụng git reset --merge.

Ngoài ra, như @Michael Johnson đề cập, nếu phiên bản git của bạn> = 1.7.4, bạn cũng có thể sử dụng git merge --abort.

Như mọi khi, hãy đảm bảo bạn không có thay đổi không được cam kết trước khi bắt đầu hợp nhất.

Từ trang git merge man

git merge --aborttương đương với git reset --mergekhi MERGE_HEADcó mặt.

MERGE_HEAD có mặt khi tiến hành hợp nhất.

Ngoài ra, liên quan đến những thay đổi không được cam kết khi bắt đầu hợp nhất:

Nếu bạn có những thay đổi mà bạn không muốn cam kết trước khi bắt đầu hợp nhất, chỉ cần thay đổi git stashtrước khi hợp nhất và git stash popsau khi kết thúc hợp nhất hoặc hủy bỏ nó.


3
Thú vị - nhưng hướng dẫn sử dụng làm tôi sợ. Khi nào chính xác là nó thích hợp để sử dụng? Khi nào bạn sẽ phải chỉ định tùy chọn <commit>? #GitMoment: -o
Conny

1
Bạn thường sử dụng điều này khi bạn muốn làm lại việc hợp nhất từ ​​đầu. Tôi chưa bao giờ phải tự xác định cam kết tùy chọn, vì vậy mặc định (không có <commit> tùy chọn) là tốt.
Carl

44
Tôi muốn câu trả lời này có nhiều phiếu hơn! Tại thời điểm này, nó có vẻ như là giải pháp phù hợp nhất trong nhiều trường hợp.
Jay Taylor

1
Ngay cả với những thay đổi không được cam kết, git vẫn có thể khôi phục trạng thái trước khi hợp nhất. Đẹp!
T3rm1

2
git merge --abortchỉ là một từ đồng nghĩa với git reset --merge? Cái tên chắc chắn có ý nghĩa hơn, nhưng nó có cùng chức năng không?
Tikhon Jelvis

518
git merge --abort

Hủy bỏ quá trình giải quyết xung đột hiện tại và cố gắng xây dựng lại trạng thái hợp nhất trước.

Nếu có những thay đổi công việc không được cam kết xuất hiện khi hợp nhất bắt đầu, git merge --aborttrong một số trường hợp sẽ không thể tái cấu trúc những thay đổi này. Do đó, nên luôn luôn cam kết hoặc bỏ qua các thay đổi của bạn trước khi chạy git merge.

git merge --aborttương đương với git reset --mergekhi MERGE_HEADcó mặt.

http://www.git-scm.com/docs/git-merge


16
Điều này đã có sẵn kể từ git v1.7.4. Đó là một bí danh cho thiết lập lại git --merge.
Michael Johnson

162

Nó rất đơn giản.

git merge --abort

Git tự chỉ cho bạn giải pháp khi bạn gặp loại rắc rối này và chạy lệnh trạng thái git.

git status

Hy vọng điều này sẽ giúp mọi người.


97

Tôi nghĩ rằng đó là git resetbạn cần.

Coi chừng điều đó git revertcó nghĩa là một cái gì đó rất khác với svn revert- trong Subversion, Revert sẽ loại bỏ các thay đổi (không được cam kết) của bạn, trả lại tệp cho phiên bản hiện tại từ kho lưu trữ, trong khi git revert"hoàn tác" một cam kết.

git resetnên làm tương đương với svn revert, nghĩa là loại bỏ những thay đổi không mong muốn của bạn.


76

Trong trường hợp sử dụng cụ thể này, bạn không thực sự muốn hủy bỏ hợp nhất, chỉ giải quyết xung đột theo một cách cụ thể.

Không có nhu cầu cụ thể để thiết lập lại và thực hiện hợp nhất với một chiến lược khác. Các xung đột đã được đánh dấu chính xác bởi git và yêu cầu chấp nhận các thay đổi bên khác chỉ dành cho một tệp này.

Đối với một tệp không được trộn trong một git xung đột, làm cho có sẵn các phiên bản cơ sở chung, cục bộ và từ xa của tệp trong chỉ mục. (Đây là nơi chúng được đọc từ để sử dụng trong công cụ tìm khác biệt 3 chiều git mergetool.) Bạn có thể sử dụng git showđể xem chúng.

# common base:
git show :1:_widget.html.erb

# 'ours'
git show :2:_widget.html.erb

# 'theirs'
git show :3:_widget.html.erb

Cách đơn giản nhất để giải quyết xung đột để sử dụng nguyên văn phiên bản từ xa là:

git show :3:_widget.html.erb >_widget.html.erb
git add _widget.html.erb

Hoặc, với git> = 1.6.1:

git checkout --theirs _widget.html.erb

5
cảm ơn vì gợi ý Mặc dù vậy, đây không phải là một giao diện người dùng git kém?
Peter

@Peter: Tôi không bị thuyết phục. Kết quả mong muốn có thể đạt được với một vài lệnh cơ bản với các tùy chọn đơn giản. Những cải tiến nào bạn sẽ đề xuất?
CB Bailey

10
Tôi nghĩ rằng git 1.6.1lệnh có rất nhiều ý nghĩa, và là tốt. Đó chính xác là những gì tôi muốn. Tôi nghĩ rằng giải pháp trước 1.6.1 là không phù hợp và đòi hỏi kiến ​​thức về các phần khác của git cần được tách ra khỏi quy trình giải quyết hợp nhất. Nhưng phiên bản mới là tuyệt vời!
Peter

67

Đối với kịch bản như, tôi đã làm git fetchgit pullsau đó nhận ra rằng nhánh ngược dòng không phải là nhánh chính, dẫn đến xung đột không mong muốn.

git reset --merge 

Điều này trở lại mà không đặt lại các thay đổi địa phương của tôi.


45

Ý kiến ​​cho rằng đó git reset --mergelà một bí danh cho git merge --abort. Điều đáng chú ý git merge --abortlà chỉ tương đương với git reset --mergeviệc MERGE_HEADcó mặt. Điều này có thể được đọc trong trợ giúp git cho lệnh hợp nhất.

git merge --abort tương đương với git reset --merge khi có mặt MERGE_HEAD.

Sau khi hợp nhất thất bại, khi không có MERGE_HEAD, hợp nhất thất bại có thể được hoàn tác git reset --merge, nhưng không nhất thiết phải có git merge --abort. Chúng không chỉ là cú pháp cũ và mới cho cùng một thứ .

Cá nhân, tôi thấy git reset --mergemạnh mẽ hơn nhiều đối với các kịch bản tương tự như kịch bản được mô tả và nói chung là sự hợp nhất thất bại.


2
"Hợp nhất thất bại" ở đây thực sự có nghĩa là gì? Hợp nhất với xung đột hay cái gì khác? Hoặc để viết lại nó: khi nào MERGE_HEAD không có mặt? Câu hỏi tiếp theo của tôi là có để hiểu rõ hơn về cách sử dụng "git reset --merge".
Ewoks

@Ewoks git stash applyđã gây ra một cuộc xung đột hợp nhất với tôi nhưng git merge --abortkhông giúp được gì trong khi git reset --mergeđó.
nitzel

27

Nếu bạn kết thúc với xung đột hợp nhất và không có gì để cam kết, nhưng vẫn có một lỗi hợp nhất đang được hiển thị. Sau khi áp dụng tất cả các lệnh được đề cập dưới đây,

git reset --hard HEAD
git pull --strategy=theirs remote_branch
git fetch origin
git reset --hard origin

Vui lòng xóa

.git \ index.lock

Tập tin [cắt dán vào một số vị trí khác trong trường hợp khôi phục] và sau đó nhập bất kỳ lệnh nào dưới đây tùy thuộc vào phiên bản bạn muốn.

git reset --hard HEAD
git reset --hard origin

Mong rằng sẽ giúp !!!


19

Một thay thế, bảo tồn trạng thái của bản sao làm việc là:

git stash
git merge --abort
git stash pop

Tôi thường khuyên bạn nên chống lại điều này, bởi vì nó thực sự giống như hợp nhất trong Subversion khi nó loại bỏ các mối quan hệ chi nhánh trong các cam kết sau.


Tôi thấy cách tiếp cận này hữu ích khi tôi vô tình sáp nhập vào một chi nhánh git-svn, không xử lý tốt điều đó. Hợp nhất squash hoặc cherry picks sẽ tốt hơn khi làm việc với các nhánh theo dõi git-svn. Trong thực tế, giải pháp của tôi biến một sự hợp nhất thành một sự hợp nhất bí đao sau khi thực tế.
Alain O'Dea

Câu trả lời hay nhất cho câu hỏi
Fouad Boukredine

18

Vì Git 1.6.1.3 git checkoutđã có thể thanh toán từ một trong hai phía của hợp nhất:

git checkout --theirs _widget.html.erb

3

Tôi tìm thấy những điều sau đây làm việc cho tôi (hoàn nguyên một tệp về trạng thái hợp nhất trước):

git reset *currentBranchIntoWhichYouMerged* -- *fileToBeReset*

-5

Sourcetree

Bởi vì bạn không cam kết hợp nhất, sau đó chỉ cần nhấp đúp chuột vào một chi nhánh khác (có nghĩa là kiểm tra nó) và khi sourcetree hỏi bạn về việc loại bỏ tất cả các thay đổi thì đồng ý :)

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.