a

Câu hỏi Hoàn tác hợp nhất Git chưa được đẩy


Trong nhánh chủ của tôi, tôi đã làm git merge some-other-branch tại địa phương, nhưng không bao giờ đẩy các thay đổi đến master gốc. Tôi không có ý định hợp nhất, vì vậy tôi muốn hoàn tác nó. Khi làm một git status sau khi hợp nhất, tôi nhận được thông báo này:

# On branch master
# Your branch is ahead of 'origin/master' by 4 commits.

Dựa trên một số hướng dẫn tôi tìm thấy, Tôi đã thử chạy

git revert HEAD -m 1

nhưng bây giờ tôi nhận được thông báo này git status:

# On branch master
# Your branch is ahead of 'origin/master' by 5 commits.

Tôi không muốn chi nhánh của tôi đi trước bởi bất kỳ số lượng cam kết nào. Làm thế nào để tôi quay trở lại điểm đó?


3088
2018-03-05 19:24


gốc


Nếu bạn cần phải bảo tồn lịch sử, nói cách khác có một sự thay đổi mà bất cứ ai đã bao giờ kéo từ bạn hoặc bạn đã đẩy nó một nơi nào đó sử dụng các giải pháp trong Yuri Ushakov câu trả lời xuống dưới đây! - Sedrik
Vui lòng bỏ chọn câu trả lời chiến thắng hiện tại, nó không an toàn (như được chỉ ra nhiều) mặc dù vẫn thu thập phiếu bầu. Với tôi "MBO" -s trông đẹp nhất, mặc dù nó có ít điểm hơn. - inger
Nếu bạn cần bảo tồn lịch sử, sử dụng Yuri's giải pháp xuống dưới đây! (chỉ cần thêm liên kết vào nhận xét @Sedrik) - cregox
Liên quan: Hoàn nguyên về cam kết Git trước đó.
Đây là một nguồn tài nguyên tuyệt vời trực tiếp từ Github: Cách hoàn tác (gần như) mọi thứ với Git - jasonleonhard


Các câu trả lời:


Với git reflog kiểm tra cam kết nào trước khi hợp nhất (git reflog sẽ là lựa chọn tốt hơn so với git log). Sau đó, bạn có thể đặt lại bằng:

git reset --hard commit_sha

Ngoài ra còn có một cách khác

git reset --hard HEAD~1

sẽ giúp bạn trở lại 1 cam kết.

Lưu ý rằng bất kỳ tệp đã được sửa đổi và không được cam kết / unstashed nào sẽ được đặt lại về trạng thái chưa sửa đổi của chúng. Để giữ cho chúng có thể thay đổi hoặc xem --merge tùy chọn bên dưới.


Như @Velmont đã đề xuất bên dưới trong câu trả lời của anh ấy, trong trường hợp trực tiếp này, hãy sử dụng:

git reset --hard ORIG_HEAD

có thể mang lại kết quả tốt hơn, vì nó nên bảo toàn các thay đổi của bạn. ORIG_HEAD sẽ trỏ đến một cam kết trực tiếp trước khi hợp nhất đã xảy ra, vì vậy bạn không phải tự săn lùng nó.


Một mẹo nữa là sử dụng --merge thay vì --hard vì nó không đặt lại các tệp không cần thiết:

- đập

Đặt lại chỉ mục và cập nhật các tệp trong cây đang hoạt động khác nhau giữa <commit> và HEAD, nhưng giữ cho các tệp khác nhau giữa chỉ mục và cây đang hoạt động (nghĩa là các thay đổi chưa được thêm).


3380
2018-03-05 19:34



Tôi không nghĩ công việc này sẽ luôn hoạt động - "trước khi hợp nhất" sẽ là cam kết gần đây nhất được hợp nhất từ ​​một nhánh khác - nó sẽ không là cam kết gần đây nhất trên nhánh hiện tại . Đúng? (Điều này có thể chỉ là kết quả của những gì git log chọn hiển thị theo mặc định - có thể có đầu ra khác git log hoặc là git reflog có thể được sử dụng cho điều này) - John Bachir
Tôi nghĩ rằng nó có thể phụ thuộc cho dù bạn squash hợp nhất. - Marcin Gil
@ JohnBachir là đúng. bên trong git log đầu ra, bạn muốn xem xét hai commit cha. Một là cam kết mới nhất trong nhánh của bạn, một là cam kết mới nhất trong nhánh bạn đã hợp nhất vào. Bạn muốn git reset --hard cho phụ huynh cam kết trên nhánh bạn đã hợp nhất vào. - Justin
@ JohnBachir: Miễn là "hợp nhất" không thực sự là một tiến nhanh, nó sẽ dẫn đến một cam kết mới ở đầu nhật ký, và cam kết này có hai cha mẹ (hoặc nhiều hơn 2 nếu bạn làm một con bạch tuộc hợp nhất). Nếu bạn loại bỏ cam kết hợp nhất này, thì tất cả các cam kết cũ đến từ quá trình hợp nhất cũng sẽ biến mất. Để được an toàn, tuy nhiên, sau khi một git đặt lại sẽ cho bạn biết nơi đầu mới là: "HEAD bây giờ là 88a04de <commit message>". Tôi luôn nhìn vào điều đó để chắc chắn rằng tôi đã kết thúc ở nơi tôi mong đợi. Dự án của tôi sử dụng một lược đồ đặt tên nhánh tiêu chuẩn để giữ cho mọi thứ đáng nhớ. - Mark E. Haase
Những gì tôi thấy hữu ích là nhìn vào "git reflog" và tìm kiếm cam kết cuối cùng mà tôi đã làm trong tổng thể. Sau đó làm git reset --hard <commit_sha> - Max Williams


Giả sử chủ nhân địa phương của bạn không đi trước nguồn gốc / chủ, bạn có thể làm

git reset --hard origin/master

Sau đó, địa phương của bạn master nhánh phải giống hệt nhau origin/master.


1290
2018-03-17 18:06



@Carter nó thực sự không phải là câu trả lời tốt nhất. Có thể nguồn gốc / chủ có thể đi trước tổng thể địa phương của bạn ngay trước khi hợp nhất bởi một số cam kết, trong trường hợp đó điều này có thể không cung cấp kết quả mong muốn - Dhruva Sagar
@ dhruva-sagar Có, nhưng miễn là git không nói bạn đang ở phía sau, và bạn không lấy, bạn nên ổn. - Kelvin
Cảm ơn! Điều này là hoàn hảo nếu (và chỉ nếu) bạn có một kho lưu trữ từ xa. - tomc
Không, đó không phải là câu trả lời hoàn hảo cho câu hỏi này, xem mệnh đề "giả định". Câu trả lời của MBO thực sự đề cập đến trường hợp này và trường hợp hợp nhất không phải là cam kết cục bộ duy nhất. - inger
Một lần nữa, có thể điều này cảnh báo nên đi vào chính câu trả lời: Luôn tránh viết lại lịch sử git! - cregox


Xem chương 4 trong sách Git và bài đăng gốc của Linus Torvalds.

Để hoàn tác hợp nhất đã được đẩy:

git revert -m 1 commit_hash

Hãy chắc chắn sẽ hoàn nguyên việc hoàn nguyên nếu bạn cam kết lại chi nhánh, như Linus nói.


1085
2018-06-02 16:31



^ - Câu trả lời đúng duy nhất ở đây là cách hoàn nguyên hợp nhất mà không vi phạm lịch sử. Điều này rất quan trọng nếu bạn làm việc với một repo được chia sẻ. - Ruslan Kabalin
Điều này đã không được bình chọn nhiều hơn bởi vì thay đổi chưa bao giờ được đẩy, vì vậy không có lý do gì để thêm sự hợp nhất ngẫu nhiên vào lịch sử. Xóa nó cục bộ và tiếp tục. - Justin
Hoàn nguyên một cam kết chưa được đẩy trông xấu xí trong lịch sử và làm cho nó trở nên khó hiểu hơn. Nếu bạn chưa đẩy nó, nó có ý nghĩa hơn để di chuyển HEAD của bạn về phía sau một vài cam kết, THEN đẩy. - Mark E. Haase
"Điều này đã không được upvoted nhiều hơn vì ..." - tuy nhiên, đối với những người như tôi đến câu hỏi này bởi vì chúng tôi / có / đẩy cam kết bổ sung, điều này là vô giá. - perfectionist
@perfectionist đã đồng ý :) Loại mong muốn có một cách để di chuyển câu trả lời này sang câu hỏi khác-- (có thể có?) - mikermcneil


Thật kỳ lạ khi lệnh đơn giản nhất bị thiếu. Hầu hết các câu trả lời đều hiệu quả, nhưng hoàn tác quá trình hợp nhất bạn vừa làm, đây là cách dễ dàng và an toàn:

git reset --merge ORIG_HEAD

Ref ORIG_HEAD sẽ trỏ đến cam kết ban đầu từ trước khi hợp nhất.

(Các --merge tùy chọn không có gì để làm với hợp nhất. Nó giống như git reset --hard ORIG_HEAD, nhưng an toàn hơn vì nó không chạm vào những thay đổi không được cam kết.)


833
2018-01-29 15:46



Vâng, đây là cách đơn giản nhất. Tôi tự hỏi tại sao nó lại có quá ít phiếu so với các câu trả lời khác. - Pablo Olmos de Aguilera C.
Nếu bạn đã làm bẩn cây làm việc của bạn kể từ đó, git reset --merge ORIG_HEAD bảo tồn những thay đổi đó. - yingted
Đây là câu trả lời cho tôi. Không cần git reflog hoặc bất cứ điều gì khác. Cảm ơn bạn. - crmpicco
Có, câu trả lời hay nhất. Đây là một ví dụ về cách hệ thống bỏ phiếu stackoverflow về cơ bản chỉ thưởng cho các câu trả lời được đăng sớm. - samthebest
Vâng, câu trả lời này đã đến gần ba năm sau khi được chấp nhận; nhưng tôi đồng ý, điều này làm việc tuyệt vời! - Mike Branski


Với phiên bản Git mới hơn, nếu bạn chưa cam kết hợp nhất và bạn có xung đột hợp nhất, bạn chỉ cần làm:

git merge --abort

Từ man git merge:

[This] chỉ có thể chạy sau khi hợp nhất đã dẫn đến xung đột. git merge --abort sẽ hủy bỏ quá trình hợp nhất và cố gắng xây dựng lại trạng thái hợp nhất trước.


307
2018-02-12 02:13





Bạn nên đặt lại về cam kết trước đó. Điều này sẽ hoạt động:

git reset --hard HEAD^

Hoặc thậm chí HEAD^^ để hoàn nguyên cam kết hoàn nguyên đó. Bạn luôn có thể cung cấp toàn bộ tham chiếu SHA nếu bạn không chắc chắn bạn nên thực hiện bao nhiêu bước.

Trong trường hợp bạn gặp sự cố và nhánh chính của bạn không có bất kỳ thay đổi cục bộ nào, bạn có thể đặt lại thành origin/master.


104
2018-03-05 19:31



Câu trả lời hay nhất là IMHO, kết hợp bản thân của OP (giả sử chỉ có 1 bước để hoàn nguyên, có vẻ như là chữ Q), cũng như phím tắt của randomguy3 (hoạt động khi "nhánh chính của bạn không có bất kỳ thay đổi cục bộ nào" ") - inger
Tôi hoàn toàn đồng ý rằng đó là câu trả lời hay nhất ở đây !!! - Konstantin
Bạn bình luận, @Inger và @Konstantin, tại sao? Bạn đến đây sau khi câu trả lời của tôi được tạo ra, và nó chính xác hơn. Chỉ cần đi lên HEAD một bước thường là sai, và bạn sẽ phải thực sự đếm như thế nào đến nay bạn cần phải đi. Git đã đặt ORIG_HEAD cho bạn, tại sao không sử dụng nó? - odinho - Velmont
nó cũng sẽ thiết lập lại các thay đổi cục bộ? #Vui lòng cập nhật. - CoDe
Điều này làm việc hoàn hảo cho tôi, đặt lại đầu như thế có ý nghĩa hơn một nửa so với câu trả lời ở đây. - Varda Elentári


Gần đây, tôi đã sử dụng git reflog để giúp với điều này. Điều này chủ yếu chỉ hoạt động nếu JUST hợp nhất xảy ra, và nó đã được trên máy tính của bạn.

git reflog có thể trả về một cái gì đó như:

fbb0c0f HEAD@{0}: commit (merge): Merge branch 'master' into my-branch
43b6032 HEAD@{1}: checkout: moving from master to my-branch
e3753a7 HEAD@{2}: rebase finished: returning to refs/heads/master
e3753a7 HEAD@{3}: pull --rebase: checkout e3753a71d92b032034dcb299d2df2edc09b5830e
b41ea52 HEAD@{4}: reset: moving to HEAD^
8400a0f HEAD@{5}: rebase: aborting

Dòng đầu tiên chỉ ra rằng một hợp nhất đã xảy ra. Dòng thứ 2 là thời gian trước khi hợp nhất của tôi. Tôi đơn giản git reset --hard 43b6032 để buộc nhánh này theo dõi trước khi hợp nhất và thực hiện.


78
2017-12-19 17:51



Omigosh cuộc sống tiết kiệm :) - M.G.Palmer
Trời ơi. Cảm ơn bạn rất nhiều. - Ross Henderson
Tại sao đây không phải là câu trả lời hàng đầu mà tôi không biết. Điều này làm việc hoàn hảo. - Matt
Cảm ơn bạn vì điều này, tuyệt vời! - zooblin


Với Git hiện đại, bạn có thể:

git merge --abort

Cú pháp cũ hơn:

git reset --merge

Trường cũ:

git reset --hard

Nhưng thực sự, đáng chú ý là git merge --abort chỉ tương đương với git reset --merge cho rằng MERGE_HEAD là món quà. Điều này có thể được đọc trong trợ giúp Git cho lệnh hợp nhất.

git merge --abort is equivalent to git reset --merge when MERGE_HEAD is present.

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

Cá nhân tôi tìm thấy git reset --merge mạnh hơn và hữu dụng hơn trong công việc hàng ngày, vì vậy đó là thứ tôi luôn sử dụng.


42
2018-05-08 19:13



Làm việc tuyệt vời cho tôi. Mỗi bài viết khác nói điều này phức tạp, nhưng điều này đã làm chính xác những gì được mong đợi. Tôi cho rằng nó chỉ hoạt động vì có xung đột, điều này không trả lời chính xác câu hỏi ban đầu. - Jeremy
Câu trả lời này không tập trung vào tình hình của OP, và bỏ qua bối cảnh quan trọng. - Ben Wheeler