Hoàn tác hợp nhất Git chưa được đẩy


3944

Trong nhánh chính của mình, tôi đã thực hiện một git merge some-other-branchđịa phương, nhưng không bao giờ đẩy các thay đổi sang bản 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 thực hiện git statussau 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 tin nhắn này với 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 mình đi trước bất kỳ số lượng cam kết nào. Làm thế nào để tôi trở lại điểm đó?


3
Nếu bạn cần lưu giữ lịch sử, nói cách khác, có một sự thay đổi mà bất cứ ai đã từng rút ra khỏi bạn hoặc bạn đã đẩy nó đi đâu đó, hãy sử dụng giải pháp trong câu trả lời của Yuri Ushakov dưới đây!
Sedrik

6
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ư nhiều người đã chỉ ra) mặc dù vẫn thu thập phiếu bầu. Đối với tôi "MBO" -s có vẻ tốt nhất, mặc dù nó có ít điểm hơn.
nhập

5
Nếu bạn cần lưu giữ lịch sử , hãy sử dụng giải pháp của Yuri bên dưới ! (chỉ cần thêm một liên kết đến bình luận @Sedrik)
cregox


3
Đâ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âu trả lời:


4460

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

git reset --hard commit_sha

Cũng có một cách khác:

git reset --hard HEAD~1

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

Xin lưu ý rằng mọi tệp được sửa đổi và không được cam kết / chưa được chỉnh sửa sẽ được đặt lại về trạng thái chưa sửa đổi . Để giữ chúng hoặc thay đổi stash đi hoặc xem --mergetùy chọn bên dưới.


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

git reset --hard ORIG_HEAD

có thể mang lại kết quả tốt hơn, vì nó sẽ bảo vệ những thay đổi của bạn. ORIG_HEADsẽ chỉ ra 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ự mình tìm kiếm nó.


Một mẹo nữa là sử dụng công --mergetắc thay vì --hardkhông thiết lập lại các tệp không cần thiết:

git reset --merge ORIG_HEAD

-

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


129
Tôi không nghĩ rằng điều này sẽ (luôn luôn?) Hoạt động - "một trước khi hợp nhất" sẽ là cam kết gần đây nhất được sáp nhập từ chi nhánh khác - nó sẽ không phải là cam kết gần đây nhất trên chi nhánh hiện tại . Đúng? (Đây có thể chỉ là kết quả của những gì được git logchọn hiển thị theo mặc định - có thể có một đầu ra khác git loghoặc git reflogcó thể được sử dụng cho việc này)
John Bachir

6
Tôi nghĩ rằng nó có thể phụ thuộc vào việc bạn hợp nhất squash.
Marcin Gil

29
@JohnBachir nói đúng. Trong git logđầu ra, bạn muốn xem xét hai cam kết cha mẹ. Một là cam kết mới nhất trong chi nhánh của bạn, một là cam kết mới nhất trong chi nhánh bạn sáp nhập. Bạn muốn git reset --hardcam kết cha mẹ trên chi nhánh bạn đã sáp nhập vào.
Justin

7
@ Johnohnach hợp nhất). Nếu bạn loại bỏ một cam kết hợp nhất này, thì tất cả các cam kết cũ hơn xuất hiện từ hợp nhất cũng sẽ biến mất. Tuy nhiên, để an toàn, sau khi thiết lập lại, git sẽ cho bạn biết vị trí của đầu mới: "Bây giờ đầu là 88a04de <thông báo cam kết>". Tôi luôn luôn nhìn vào đó để 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 sơ đồ đặt tên chi nhánh tiêu chuẩn để giữ cho mọi thứ đáng nhớ.
Đánh dấu E. Haase

44
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 chủ. Sau đó, hãy làmgit reset --hard <commit_sha>
Max Williams

1456

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

git reset --hard origin/master

Sau đó, masterchi nhánh địa phương của bạn sẽ trông giống hệt origin/master.


71
@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 chủ đị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 đó có thể không cho kết quả mong muốn
Dhruva Sagar

15
@ dhruva-sagar Có, nhưng miễn là git không nói bạn đứng sau và bạn không tìm nạp, bạn sẽ ổn thôi.
Kelvin

3
Cảm ơn! Điều này là hoàn hảo nếu (và chỉ khi) bạn có một kho lưu trữ từ xa.
tomc

2
Không, đó không phải là câu hỏi hoàn hảo cho câu hỏi này, hãy xem mệnh đề "giả định". Câu trả lời của MBO thực sự bao gồm 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.
nhập

2
Một lần nữa, có lẽ cảnh báo này sẽ đi vào câu trả lời: Luôn luôn tránh viết lại lịch sử git!
cregox

1175

Xem chương 4 trong cuốn sách Gitbài gốc của Linus Torvalds .

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

git revert -m 1 commit_hash

Hãy chắc chắn hoàn nguyên hoàn nguyên nếu bạn đang thực hiện lại chi nhánh, như Linus đã nói.


10
@perfectionist đồng ý :) Loại điều ước có một cách để chuyển câu trả lời này sang câu hỏi
khác--

để biết thêm thông tin về
Revert

1
Để tự tin rằng việc hoàn nguyên này đã hoạt động, bạn có thể thực hiện git diff hash1 hash2 trong đó hash1 là hoàn nguyên đã cam kết và hash2 là cam kết cũ có trạng thái mà bạn đang cố gắng quay lại. Không có đầu ra == thành công! Tôi đã có thể khôi phục nhiều cam kết bằng cách thực hiện nhiều lần, bắt đầu bằng cách hoàn nguyên việc hợp nhất gần đây nhất và làm việc ngược lại. git diff cho tôi thấy rằng tôi đã kết thúc trong trạng thái tôi muốn.
Robert Sinton

6
Lưu ý rằng điều này không thực sự giải quyết câu hỏi của người gửi ban đầu . Các poster ban đầu đã được sử dụng git revert -m 1 <commit>. Vấn đề là việc làm đó không xóa được sự hợp nhất ngẫu nhiên mà anh ta đã làm (và chưa được thúc đẩy). Các câu trả lời khác liên quan đến thiết lập lại cứng là tốt hơn cho vấn đề của người gửi ban đầu.

Đây là một 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

986

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 hoạt động, nhưng hoàn tác việc 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

Tham chiếu ORIG_HEADsẽ trỏ đến cam kết ban đầu từ trước khi hợp nhất.

( --mergeTùy chọn này không liên quan gì đến việc 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.)


17
Nếu bạn đã làm bẩn cây làm việc của mình kể từ đó, hãy git reset --merge ORIG_HEADbảo tồn những thay đổi đó.
kéo dài

1
Đây là câu trả lời đúng duy nhất (Tôi không nói đây là câu trả lời hay nhất - lưu ý sự khác biệt). Giả sử, về chủ, tôi đã thực hiện 3 lần cam kết tại t1, t3 và t5. Giả sử, trên nhánh1, tôi đã thực hiện 3 nhận xét tại t2, t4 và t6 (giả sử t1, t2, t3, t4, t5 và t6 theo thứ tự thời gian). Bất kỳ lệnh nào tương tự git reset --hard HEAD~5sẽ chỉ đặt lại CHÍNH (có thể loại bỏ các xác nhận trong cả chủ và nhánh1). Chỉ có --mergetùy chọn loại bỏ merge.
Manu Manjunath

@Manu --mergeTùy chọn không thực sự loại bỏ hợp nhất, bạn có thể sử dụng --hardnó cũng sẽ hoạt động tốt. Đây là tài liệu tham khảo ORIG_HEAD là đầu mối ở đây, nó được đặt trước khi bạn hợp nhất với nơi bạn đang đứng tại thời điểm đó. :)
odinho - Velmont

@yingted bạn có ý gì khi nói "Nếu bạn đã làm bẩn cây làm việc của mình kể từ đó, git reset --merge ORIG_HEAD sẽ duy trì những thay đổi đó." Bạn có nghĩa là thay đổi các tập tin sau khi hợp nhất? Dù sao tôi đã hợp nhất và sau đó đã giải quyết một số xung đột. Nhưng sau đó tôi muốn thiết lập lại hợp nhất và làm theo hướng dẫn trong câu trả lời này. Mọi thứ đều ổn và nó không bảo toàn những thay đổi của tôi được thực hiện sau khi hợp nhất. Repo địa phương của tôi chỉ tương tự như vị trí trước khi tôi thực hiện hợp nhất.
Samitha Chathuranga

Các git reset --hard ORIG_HEADlệnh làm việc một cách hoàn hảo đối với tôi - nó có thể đã được giúp đỡ bởi thực tế là tôi đã không thực hiện bất kỳ thay đổi khác với kho sau khi địa phương git mergetôi đã cố gắng để hoàn tác. Lệnh chỉ cần đặt lại trạng thái của kho lưu trữ trở lại trạng thái trước khi hợp nhất. Cám ơn về tiền bo nhiều!
bluebinary

391

Với các 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 thực hiện:

git merge --abort

Từ man git merge:

[Điều này] chỉ có thể được chạy sau khi hợp nhất đã dẫn đến xung đột. git merge --abortsẽ 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.


8
Hợp nhất của anh ta được cam kết nhưng không được đẩy (xem tiêu đề), anh ta đã hợp nhất, lệnh của bạn chỉ hoạt động khi anh ta vẫn ở giữa một sự hợp nhất
JBoy

135

Bạn nên thiết lập lại cam kết trước đó. Điều này sẽ làm việc:

git reset --hard HEAD^

Hoặc thậm chí HEAD^^để hoàn nguyên cam kết đó. Bạn luôn có thể cung cấp một tài liệu tham khảo SHA đầy đủ nếu bạn không chắc chắn nên lùi lại bao nhiêu bước.

Trong trường hợp khi bạn gặp sự cố và chi 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.


5
Câu trả lời hay nhất IMHO, kết hợp câu trả lời của chính OP (giả sử chỉ có 1 bước để hoàn nguyên, dường như là trường hợp trong 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 ")
nhập

4
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ó đúng hơn. Chỉ cần đi lên TRƯỚC một bước thường là sai, và bạn thực sự phải tính xem bạn cần đi bao xa. Git đã thiết lập ORIG_HEADcho bạn, tại sao không sử dụng nó?
odinho - Velmont

nó cũng sẽ thiết lập lại những thay đổi cục bộ chứ? #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 nhiều so với một nửa câu trả lời ở đây.
Varda Elentári

ĐẦU ^ bằng cam kết trước TRƯỚC? và ^^ là hai cam kết trước? Đoán điều này sẽ không làm việc với sáp nhập nhanh về phía trước?
Marcus Leon

87

Gần đây, tôi đã sử dụng git reflogđể giúp đỡ 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 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 sự 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 chỉ đơn giản là git reset --hard 43b6032buộc chi nhánh này theo dõi từ trước khi hợp nhất và tiếp tục.


Câu trả lời tuyệt vời, cảm ơn bạn! Cần hoàn tác một sự hợp nhất nhưng các câu trả lời khác chỉ làm rối tung nó nhiều hơn, sử dụng reflogđể có được SHA và chuyển nó vào git resethoạt động.
Lankymart

51

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 ra, điều đáng chú ý git merge --abortlà chỉ tương đương với git reset --mergesự MERGE_HEADhiện diện. Đ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 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, vì vậy chúng không chỉ là cú pháp cũ và mới cho cùng một điều .

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


Làm việc tuyệt vời cho tôi. Mỗi bài đăng khác nói rằng điều này rất 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, 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 huống của OP và bỏ qua bối cảnh quan trọng.
Ben Wheeler

37

Được rồi, câu trả lời mà những người khác ở đây đưa ra cho tôi rất gần, nhưng nó không hoạt động. Đây là những gì tôi đã làm.

Làm điều này ...

git reset --hard HEAD^
git status

... đã cho tôi trạng thái sau đây.

# On branch master
# Your branch and 'origin/master' have diverged,
# and have 3 and 3 different commit(s) each, respectively.

Sau đó tôi phải gõ cùng một git resetlệnh nhiều lần. Mỗi lần tôi làm điều đó, tin nhắn thay đổi bởi một người như bạn có thể thấy bên dưới.

> git reset --hard HEAD^
HEAD is now at [...truncated...]
> git status
# On branch master
# Your branch and 'origin/master' have diverged,
# and have 3 and 3 different commit(s) each, respectively.
> git reset --hard HEAD^
HEAD is now at [...truncated...]
> git status
# On branch master
# Your branch and 'origin/master' have diverged,
# and have 2 and 3 different commit(s) each, respectively.
> git reset --hard HEAD^
HEAD is now at [...truncated...]
> git status
# On branch master
# Your branch and 'origin/master' have diverged,
# and have 1 and 3 different commit(s) each, respectively.
> git reset --hard HEAD^
HEAD is now at [...truncated...]
> git status
# On branch master
# Your branch is behind 'origin/master' by 3 commits, and can be fast-forwarded.

Tại thời điểm này, tôi thấy thông báo trạng thái đã thay đổi, vì vậy tôi đã thử thực hiện git pullvà dường như nó hoạt động:

> git pull
Updating 2df6af4..12bbd2f
Fast forward
 app/views/truncated |    9 ++++++---
 app/views/truncated |   13 +++++++++++++
 app/views/truncated |    2 +-
 3 files changed, 20 insertions(+), 4 deletions(-)
> git status
# On branch master

Câu chuyện dài quá ngắn, mệnh lệnh của tôi bắt nguồn từ đây:

git reset --hard HEAD^
git reset --hard HEAD^
git reset --hard HEAD^
git reset --hard HEAD^
git pull

19
hoặc bạn có thể đã sử dụngHEAD^^^^
Hasen

17
thậm chí có thể đặt lại thành origin/master;)
hasen

23

Bạn có thể sử dụng git reflogđể tìm kiểm tra trước. Đôi khi đó là một trạng thái tốt mà bạn muốn quay trở lại.

Cụ thể,

$ git reflog
$ git reset --hard HEAD@{0}

1
Cảm ơn bạn! Bạn đã tiết kiệm được nửa ngày làm việc của tôi. Tuy nhiên tôi không thể thoát chế độ reflog bằng bất kỳ lệnh nào.
Katarzyna

1
@Katarzyna sử dụng phím "q" để thoát khỏi reflog
Amjed Baig

21

Nếu bạn đang ở giữa một sự hợp nhất, bạn luôn có thể hủy bỏ nó git merge --abort


2
cảm ơn bạn và tôi đã làm điều đó đáng sợ câu trả lời chính xác. may mắn tôi đã cuộn xuống. tôi chỉ muốn xóa đầu hợp nhất
Nyuu

15

Tôi đã có thể giải quyết vấn đề này bằng một lệnh duy nhất không liên quan đến việc tìm kiếm id xác nhận.

git reset --hard remotes/origin/HEAD

Câu trả lời được chấp nhận không hiệu quả với tôi nhưng lệnh này đã đạt được kết quả mà tôi đang tìm kiếm.


Chính xác! Nó đặt lại các thay đổi của bạn vào đầu chi nhánh! Không làm từng cái một
Carlos Zinato

không làm việc cho tôi. thực sự cuối cùng đã gửi chi nhánh địa phương trở lại một hoặc hai tháng. Rất may đây là tất cả các địa phương vì vậy tôi luôn có thể phá hủy chi nhánh và lấy lại nó. Chỉ muốn chỉ ra rằng trong trường hợp những người khác đã thử điều này.
Matt Pengelly

@MattPengelly phương pháp này phần lớn không có giấy tờ và thường hoạt động nếu chi nhánh của bạn đồng bộ với chi nhánh từ xa trước khi bạn thực hiện hợp nhất. Đã được vài tháng kể từ khi chi nhánh của bạn đồng bộ với chi nhánh từ xa?
Ralph Ritoch

@MattPengelly nó cũng phụ thuộc vào nhánh nào được chỉ vào. Tôi đang sử dụng gitflow trên một trong các dự án của mình và mặc dù tôi đang ở nhánh phát triển, nhưng điều khiển từ xa / nguồn gốc được chỉ đến nguồn gốc / chủ vì vậy nếu tôi cần hoàn tác hợp nhất, có lẽ tôi cần phải thiết lập lại để từ xa / nguồn gốc / phát triển
Ralph Ritoch

14

Nếu bạn chưa cam kết, bạn chỉ có thể sử dụng

$ git checkout -f

Nó sẽ hoàn tác việc hợp nhất (và mọi thứ bạn đã làm).


Đã thử điều này và nó thực sự đã tăng số lượng cam kết mà chi nhánh địa phương của tôi đang ở phía trước.
barclay

14

Có câu hỏi này cũng đang tìm cách hoàn nguyên để phù hợp với nguồn gốc (nghĩa là KHÔNG cam kết trước nguồn gốc). Nghiên cứu sâu hơn, tìm thấy có một resetlệnh cho chính xác rằng:

git reset --hard @{u}

Lưu ý: @{u}là viết tắt cho origin/master. (Và, tất nhiên, bạn cần kho lưu trữ từ xa để làm việc này.)


14

Bạn phải thay đổi ĐẦU của bạn, Tất nhiên không phải của bạn nhưng git ĐẦU ....

Vì vậy, trước khi trả lời, hãy thêm một số nền tảng, giải thích đây là gì HEAD.

First of all what is HEAD?

HEADchỉ đơn giản là một tham chiếu đến cam kết hiện tại (mới nhất) trên nhánh hiện tại.
Chỉ có thể có một duy nhất HEADtại bất kỳ thời điểm nào. (không bao gồm git worktree)

Nội dung của HEADđược lưu trữ bên trong .git/HEADvà nó chứa 40 byte SHA-1 của cam kết hiện tại.


detached HEAD

Nếu bạn không tham gia vào cam kết mới nhất - có nghĩa HEADlà chỉ đến một cam kết trước đó trong lịch sử được gọi là cam kết detached HEAD.

nhập mô tả hình ảnh ở đây

Trên dòng lệnh, nó sẽ trông như thế này- SHA-1 thay vì tên chi nhánh vì HEADnó không trỏ đến đầu của nhánh hiện tại

nhập mô tả hình ảnh ở đây

nhập mô tả hình ảnh ở đây

Một vài lựa chọn về cách phục hồi từ một ĐẦU tách ra:


git checkout

git checkout <commit_id>
git checkout -b <new branch> <commit_id>
git checkout HEAD~X // x is the number of commits t go back

Điều này sẽ kiểm tra chi nhánh mới chỉ vào cam kết mong muốn.
Lệnh này sẽ kiểm tra một cam kết nhất định.
Tại thời điểm này, bạn có thể tạo một nhánh và bắt đầu làm việc từ thời điểm này.

# Checkout a given commit. 
# Doing so will result in a `detached HEAD` which mean that the `HEAD`
# is not pointing to the latest so you will need to checkout branch
# in order to be able to update the code.
git checkout <commit-id>

# create a new branch forked to the given commit
git checkout -b <branch name>

git reflog

Bạn luôn có thể sử dụng refloglà tốt.
git reflogsẽ hiển thị bất kỳ thay đổi nào đã cập nhật HEADvà kiểm tra mục nhập reflog mong muốn sẽ đặt HEADlại cho cam kết này.

Mỗi khi sửa đổi ĐẦU sẽ có một mục mới trong reflog

git reflog
git checkout HEAD@{...}

Điều này sẽ đưa bạn trở lại cam kết mong muốn của bạn

nhập mô tả hình ảnh ở đây


git reset --hard <commit_id>

"Di chuyển" ĐẦU của bạn trở lại cam kết mong muốn.

# This will destroy any local modifications.
# Don't do it if you have uncommitted work you want to keep.
git reset --hard 0d1d7fc32

# Alternatively, if there's work to keep:
git stash
git reset --hard 0d1d7fc32
git stash pop
# This saves the modifications, then reapplies that patch after resetting.
# You could get merge conflicts if you've modified things which were
# changed since the commit you reset to.
  • Lưu ý: ( Kể từ Git 2.7 ),
    bạn cũng có thể sử dụng git rebase --no-autostash.

git revert <sha-1>

"Hoàn tác" phạm vi cam kết hoặc cam kết đã cho.
Lệnh đặt lại sẽ "hoàn tác" mọi thay đổi được thực hiện trong cam kết đã cho.
Một cam kết mới với bản vá hoàn tác sẽ được cam kết trong khi cam kết ban đầu cũng sẽ vẫn còn trong lịch sử.

# add new commit with the undo of the original one.
# the <sha-1> can be any commit(s) or commit range
git revert <sha-1>

Lược đồ này minh họa lệnh nào làm gì.
Như bạn có thể thấy có reset && checkoutsửa đổi HEAD.

nhập mô tả hình ảnh ở đây


Đây là kho báu
Jawand Singh

12

Câu trả lời đơn giản nhất là câu trả lời của odinho - Velmont

Đầu tiên làm git reset --merge ORIG_HEAD

Đối với những người đang tìm cách đặt lại sau khi thay đổi được đẩy, hãy làm điều này (Bởi vì đây là bài đăng đầu tiên được nhìn thấy cho bất kỳ câu hỏi hợp nhất git reset nào)

git push origin HEAD --force

Điều này sẽ thiết lập lại theo cách mà bạn sẽ không nhận được các thay đổi đã hợp nhất trở lại sau khi kéo.


10

Chỉ để có một tùy chọn bổ sung để xem xét, tôi chủ yếu theo mô hình phân nhánh được mô tả ở đây: http://nvie.com/posts/a-successful-git-branching-model/ và như vậy đã được hợp nhất với --no-ff(không chuyển tiếp nhanh) thường.

Tôi vừa đọc trang này vì tôi vô tình hợp nhất một nhánh thử nghiệm thay vì nhánh phát hành của tôi với chủ để triển khai (trang web, chủ là những gì đang hoạt động). Nhánh thử nghiệm có hai nhánh khác được hợp nhất với nó và tổng cộng khoảng sáu lần xác nhận.

Vì vậy, để hoàn nguyên toàn bộ cam kết tôi chỉ cần một git reset --hard HEAD^và nó hoàn nguyên toàn bộ hợp nhất. Vì các phép hợp nhất không được chuyển tiếp nhanh nên hợp nhất là một khối và lùi một bước là "nhánh không được hợp nhất".


10

Bạn chỉ có thể sử dụng hai lệnh để hoàn nguyên hợp nhất hoặc khởi động lại bằng một cam kết cụ thể:

  1. git reset --hard commitHash (bạn nên sử dụng cam kết mà bạn muốn khởi động lại, ví dụ: 44a587491e32eafa1638aca7738)
  2. git push origin HEAD --force (Gửi chi nhánh chính địa phương mới đến nguồn gốc / chủ)

Chúc may mắn và đi trước!


10

Nó có thể được thực hiện theo nhiều cách.

1) Hủy bỏ hợp nhất

Nếu bạn ở giữa một hợp nhất xấu (thực hiện sai với nhánh sai) và muốn tránh hợp nhất để quay lại nhánh mới nhất như sau:

git merge --abort

2) Đặt lại đầu vào nhánh từ xa

Nếu bạn đang làm việc từ chi nhánh phát triển từ xa, bạn có thể đặt lại CHÍNH về cam kết cuối cùng trên nhánh từ xa như sau:

git reset --hard origin/develop

3) Xóa chi nhánh hiện tại và kiểm tra lại từ kho lưu trữ từ xa

Xem xét, bạn đang làm việc về phát triển chi nhánh trong repo cục bộ, đồng bộ hóa với chi nhánh từ xa / phát triển, bạn có thể làm như sau:

git checkout master 
##to delete one branch, you need to be on another branch, otherwise you will fall with the branch :) 

git branch -D develop
git checkout -b develop origin/develop

rằng "1) Hủy bỏ hợp nhất" là khá đủ. Nâng cao.
CodeToLife

1
Hãy cẩn thận! git merge --abort "chỉ có thể được 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 trước khi hợp nhất"
Pedro García Medina

8

Nếu hợp nhất của bạn và các cam kết tương ứng chưa được đẩy, bạn luôn có thể chuyển sang một nhánh khác, xóa chi nhánh ban đầu và tạo lại nó.

Ví dụ, tôi vô tình hợp nhất một nhánh phát triển thành chủ và muốn hoàn tác điều đó. Sử dụng các bước sau:

git checkout develop
git branch -D master
git branch -t master origin/master

Voila! Master đang ở cùng giai đoạn với nguồn gốc, và trạng thái hợp nhất sai của bạn bị xóa.


1
Lưu ý: Điều này không chỉ hoàn tác việc hợp nhất mà còn bất kỳ cam kết cục bộ nào được thực hiện kể từ lần đẩy xuất xứ mới nhất.
Martijn Heemels

4

Nếu bạn muốn một giải pháp dòng lệnh, tôi khuyên bạn chỉ nên đi với câu trả lời của MBO.

Nếu bạn là người mới, bạn có thể thích phương pháp đồ họa:

  1. Bắt đầu gitk(từ dòng lệnh hoặc nhấp chuột phải trong trình duyệt tệp nếu bạn có)
  2. Bạn có thể dễ dàng phát hiện ra cam kết hợp nhất ở đó - nút đầu tiên từ trên cùng có hai cha mẹ
  3. Theo liên kết đến cha mẹ đầu tiên / bên trái (cái trên nhánh hiện tại của bạn trước khi hợp nhất, thường là màu đỏ đối với tôi)
  4. Trên cam kết đã chọn, nhấp chuột phải vào "Đặt lại chi nhánh tại đây", chọn thiết lập lại cứng ở đó

4

Chiến lược: Tạo một chi nhánh mới từ nơi mọi thứ đều tốt.

Đặt vấn đề: Hoàn nguyên hợp nhất là khó. Có quá nhiều giải pháp, tùy thuộc vào nhiều yếu tố, chẳng hạn như bạn đã cam kết hay đẩy mạnh việc hợp nhất của mình hay nếu có những cam kết mới kể từ khi hợp nhất. Ngoài ra, bạn vẫn cần có một sự hiểu biết tương đối sâu sắc về git để điều chỉnh các giải pháp này cho trường hợp của bạn. Nếu bạn mù quáng làm theo một số hướng dẫn, bạn có thể kết thúc bằng một "hợp nhất trống", nơi không có gì sẽ được hợp nhất và các nỗ lực hợp nhất tiếp theo sẽ khiến Git nói với bạn "Đã cập nhật".

Giải pháp:

Giả sử bạn muốn hợp nhất devvào feature-1.

  1. Tìm bản sửa đổi mà bạn muốn nhận hợp nhất:

    git log --oneline feature-1
    a1b2c3d4 Merge branch 'dev' into 'feature-1' <-- the merge you want to undo
    e5f6g7h8 Fix NPE in the Zero Point Module <-- the one before the merge, you probably want this one
    
  2. Kiểm tra xem nó (quay ngược thời gian):

    git checkout e5f6g7h8
    
  3. Tạo một chi nhánh mới từ đó và kiểm tra xem nó:

    git checkout -b feature-1
    

Bây giờ bạn có thể khởi động lại hợp nhất của bạn:

  1. Hợp nhất: git merge dev

  2. Khắc phục xung đột hợp nhất của bạn.

  3. Cam kết: git commit

  4. Khi bạn hài lòng với kết quả, hãy xóa chi nhánh cũ: git branch --delete feature-1


2

Chỉ cần tạo chi nhánh mới, sau đó chọn cherry cam kết với nó.

Trình tiết kiệm và đơn giản hơn sau đó đặt lại được mô tả trong nhiều câu trả lời ở trên


1
Tôi đồng ý với đề xuất này, đặc biệt nếu bạn không hoàn toàn thoải mái với các lệnh git được liệt kê. Điều này có thể chậm hơn với nhiều "công việc" hơn, nhưng nếu nó không xuất hiện nhiều và bạn lo ngại về việc mất công việc của mình, điều đó đáng để nỗ lực.
Greg

1

Tôi nghĩ rằng bạn có thể làm git rebase -i [hash] [branch_name] ở đâu [hash]là băm xác định cho tuy nhiên xa trở lại bạn muốn tua lại cộng thêm một (hoặc tuy nhiên nhiều cam kết sao bạn muốn đi) và sau đó xóa các dòng cho các cam kết trong trình soạn thảo mà bạn không muốn nữa . Lưu các tập tin. Lối ra. Hãy cầu nguyện. Và nó nên được tua lại. Bạn có thể phải làm một git reset --hard, nhưng nó sẽ tốt ở điểm này. Bạn cũng có thể sử dụng điều này để rút các cam kết cụ thể ra khỏi ngăn xếp, nếu bạn không muốn giữ chúng trong lịch sử của mình, nhưng điều đó có thể khiến kho lưu trữ của bạn ở trạng thái mà bạn có thể không muốn.


1

Nếu bạn đã cam kết hợp nhất:

git reset HEAD~1
# Make sure what you are reverting is in fact the merge files
git add .
git reset --hard

1
  1. Trước tiên, hãy chắc chắn rằng bạn đã cam kết mọi thứ.

  2. Sau đó đặt lại kho lưu trữ của bạn về trạng thái làm việc trước đó:

    $ git reset f836e4c1fa51524658b9f026eb5efa24afaf3a36
    

    hoặc sử dụng --hard( điều này sẽ xóa tất cả các thay đổi cục bộ, không cam kết! ):

    $ git reset f836e4c1fa51524658b9f026eb5efa24afaf3a36 --hard
    

    Sử dụng hàm băm đã có trước khi cam kết hợp nhất sai của bạn.

  3. Kiểm tra những cam kết nào bạn muốn cam kết lại trên đầu phiên bản chính xác trước đó bằng cách:

    $ git log 4c3e23f529b581c3cbe95350e84e66e3cb05704f
    
    commit 4c3e23f529b581c3cbe95350e84e66e3cb05704f
    
    ...
    
    commit 16b373a96b0a353f7454b141f7aa6f548c979d0a
    
    ...
    
  4. Áp dụng các cam kết đúng của bạn trên đầu phiên bản bên phải của kho lưu trữ của bạn bằng cách:

    • Bằng cách sử dụng cherry-pick (những thay đổi được giới thiệu bởi một số cam kết hiện có)

          git cherry-pick ec59ab844cf504e462f011c8cc7e5667ebb2e9c7
      
    • Hoặc bằng cách chọn anh đào phạm vi cam kết bằng cách:

      • Đầu tiên kiểm tra các thay đổi đúng trước khi hợp nhất chúng:

        git diff 5216b24822ea1c48069f648449997879bb49c070..4c3e23f529b581c3cbe95350e84e66e3cb05704f
        
      • Đầu tiên kiểm tra các thay đổi đúng trước khi hợp nhất chúng:

        git cherry-pick 5216b24822ea1c48069f648449997879bb49c070..4c3e23f529b581c3cbe95350e84e66e3cb05704f
        

        trong đó đây là phạm vi của các cam kết chính xác mà bạn đã cam kết (không bao gồm hợp nhất cam kết sai).


1
  1. git stash

  2. git branch -d the_local_branch

  3. git checkout -t <name of remote>

  4. git stash apply

Điều này làm việc cho tôi .. !!


0

Nếu bạn nhận thấy rằng bạn cần hoàn nguyên ngay lập tức sau khi hợp nhất và bạn chưa làm gì khác sau nỗ lực hợp nhất, bạn chỉ có thể ban hành lệnh này: git reset --hard HEAD@{1} .

Về cơ bản, hợp nhất của bạn shasẽ được trỏ đến HEAD@{0}nếu không có gì khác được cam kết sau khi hợp nhất và do đó HEAD@{1}sẽ là điểm trước khi hợp nhất.


0

Đơn giản nhất của cơ hội đơn giản nhất, đơn giản hơn nhiều so với bất cứ điều gì đã nói ở đây:

Xóa chi nhánh địa phương của bạn (cục bộ, không phải từ xa) và kéo lại. Bằng cách này, bạn sẽ hoàn tác các thay đổi trên nhánh chính của mình và bất kỳ ai cũng sẽ bị ảnh hưởng bởi thay đổi mà bạn không muốn thúc đẩy. Bắt đầu lại


0

Trong trường hợp này, bạn sẽ muốn đặt lại chi nhánh của mình với git reset --hard <branch_name>. Nếu bạn muốn lưu các thay đổi của mình trước khi đặt lại chúng, hãy chắc chắn tạo một nhánh mới và git checkout <branch_name>.

Bạn cũng có thể thiết lập lại trạng thái thành một cam kết cụ thể git reset --hard <commit_id>.

Nếu thay đổi đã được đẩy, bạn có thể sử dụng git revert <branch_name>thay thế. Hãy chắc chắn kiểm tra cách sử dụng git Revert và git checkout trong các tình huống khác.

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.