Làm lại một hợp nhất hoàn nguyên trong Git


231

Tôi đã gặp một chút vấn đề ở đây: Tôi có một nhánh cụ thể về vấn đề 28strong Git, mà tôi đã hợp nhất trong developnhánh chung . Hóa ra tôi đã thực hiện nó quá nhanh, vì vậy tôi đã sử dụng git-Revert để hoàn tác việc hợp nhất. Tuy nhiên, bây giờ đã đến lúc hợp nhất 28svào develop, nhưng lệnh git-merge nhìn thấy sự hợp nhất ban đầu và vui vẻ thông báo rằng tất cả đều ổn và các nhánh đã được hợp nhất. Tôi làm gì bây giờ? Tạo một 'Hoàn nguyên "Hoàn nguyên" 28s -> phát triển ""' cam kết? Có vẻ như không phải là một cách tốt để làm điều đó, nhưng tôi không thể tưởng tượng bất kỳ điều gì khác vào lúc này.

Cấu trúc cây trông như thế nào:

Đầu ra nhật ký Git


4
Đó là GitX ( gitx.frim.nl ).
Toms Mikoss

Câu trả lời:


169

Bạn phải "hoàn nguyên hoàn nguyên". Tùy thuộc vào bạn làm thế nào hoàn nguyên ban đầu, nó có thể không dễ dàng như âm thanh. Nhìn vào tài liệu chính thức về chủ đề này .

---o---o---o---M---x---x---W---x---Y
              /
      ---A---B-------------------C---D

cho phép:

---o---o---o---M---x---x-------x-------*
              /                       /
      ---A---B-------------------C---D

Nhưng tất cả có hoạt động không? Chắc chắn là có. Bạn có thể hoàn nguyên một sự hợp nhất, và từ góc độ kỹ thuật thuần túy, git đã làm điều đó rất tự nhiên và không có rắc rối thực sự.
Nó chỉ coi đó là một sự thay đổi từ "trạng thái trước khi hợp nhất" thành "trạng thái sau khi hợp nhất", và đó là nó.
Không có gì phức tạp, không có gì kỳ lạ, không có gì thực sự nguy hiểm. Git sẽ làm điều đó mà không cần suy nghĩ về nó.

Vì vậy, từ góc độ kỹ thuật, không có gì sai khi hoàn nguyên hợp nhất, nhưng từ góc độ công việc, đó là điều mà bạn thường nên cố gắng tránh .

Nếu có thể, ví dụ, nếu bạn thấy một vấn đề mà đã sáp nhập vào cây trồng chính, chứ không phải là phục hồi các hợp nhất, cố gắng thực sự khó có thể :

  • chia nhỏ vấn đề xuống nhánh bạn đã hợp nhất và chỉ sửa nó,
  • hoặc cố gắng hoàn nguyên các cam kết cá nhân đã gây ra nó.

Vâng, nó phức tạp hơn, và không có, nó không phải lúc nào công việc (đôi khi câu trả lời là: "oops, tôi thực sự không nên sáp nhập nó, bởi vì nó là chưa sẵn sàng, và tôi thực sự cần phải lùi lại tất cả các hợp nhất "). Vì vậy, sau đó bạn thực sự nên hoàn nguyên việc hợp nhất, nhưng khi bạn muốn thực hiện lại việc hợp nhất, bây giờ bạn cần thực hiện bằng cách hoàn nguyên việc hoàn nguyên.


10
Liên kết tốt (+1). Tôi đã tự do sao chép một phần tài liệu trong câu trả lời của bạn để cho phép người đọc thấy ngay các tùy chọn liên quan trong trường hợp này. Nếu bạn không đồng ý, hãy thoải mái hoàn nguyên.
VonC

5
Chúng tôi vừa gặp phải một trường hợp cần làm điều này và thấy rằng niềm vui không hoàn toàn dừng lại ở đây. Đó là một chi nhánh hoạt động lâu dài đã được sáp nhập, vì vậy chúng tôi cần tiếp tục cập nhật nó. Cách tiếp cận của tôi ở đây: tech.patronslikeme.com/2010/09/29/ Khăn
jdwyah

tôi đã theo dõi bài đăng trên blog của @ jdwyah và thật tuyệt vời (nghiêm túc, thật tuyệt vời khi nó chỉ hoạt động).
hellatan

2
@jdwyah dường như là một liên kết bị hỏng, nhưng nó có vẻ như là một bài đọc thú vị. Đây là một tấm gương.org.org nhưng nó thiếu các hình ảnh: web.archive.org/web/20111229193713/http://
Alex KeySmith

15
Bài đăng trên blog đã được phục hồi, cảm ơn: blog.jdwyah.com/2015/07/deals-with-git-merge-revutions.html
jdwyah 7/07/2015

53

Giả sử bạn có lịch sử như vậy

---o---o---o---M---W---x-------x-------*
              /                      
      ---A---B

Trong đó A, B không cam kết và W - là hoàn nguyên của M

Vì vậy, trước khi bắt đầu khắc phục sự cố, tôi thực hiện lệnh W cam kết với chi nhánh của mình

git cherry-pick -x W

Sau đó, tôi hoàn nguyên W cam kết trên chi nhánh của tôi

git revert W 

Sau khi tôi có thể tiếp tục sửa chữa.

Lịch sử cuối cùng có thể trông như:

---o---o---o---M---W---x-------x-------*
              /                       /     
      ---A---B---W---W`----------C---D

Khi tôi gửi PR, nó sẽ hiển thị rõ ràng rằng PR hoàn tác lại và thêm một số cam kết mới.


3
Điều này có vẻ hữu ích, nhưng rất ít về các chi tiết (C, D là gì trong sơ đồ cuối cùng) đến nỗi nó bực bội hơn là hữu ích
Isoyncous

4
@ Đồng bộ C và D dường như là các cam kết khắc phục các sự cố được giới thiệu bởi A và B.
Thomas

@Thomas chính xác
Maksim Kotlyar

Thật tốt khi bạn đã nhấn mạnh bằng cách sử dụng PR trong trường hợp này vì nó có thể cung cấp một 'kiểm tra vệ sinh' cuối cùng trước khi hợp nhất trở lại thành chủ.
Willem van Ketwich

sử dụng tại sao bạn khởi động lại chi nhánh của bạn từ W ban đầu? Tức là, hãy để chủ đề của bạn tiếp tục từ W, với W` tiếp theo là C và D? Điều đó loại bỏ một số trùng lặp
Erik Carstensen

12

Để hoàn nguyên hoàn nguyên mà không làm hỏng quá trình công việc của bạn quá nhiều:

  • Tạo một bản sao rác phát triển cục bộ
  • Hoàn nguyên cam kết hoàn nguyên trên bản sao phát triển cục bộ
  • Hợp nhất bản sao đó vào nhánh tính năng của bạn và đẩy nhánh tính năng của bạn đến máy chủ git của bạn.

Chi nhánh tính năng của bạn giờ đây có thể được hợp nhất như bình thường khi bạn sẵn sàng cho nó. Nhược điểm duy nhất ở đây là bạn sẽ có thêm một vài cam kết hợp nhất / hoàn nguyên trong lịch sử của mình.


Chỉ để ngăn chặn bất kỳ sự pha trộn nào nữa, tôi cũng đã tạo một bản sao 'rác' của nhánh tính năng của mình và hợp nhất sự phát triển hoàn nguyên vào nó.
jhhwilliams

Cảm ơn bạn! Đây là câu trả lời duy nhất thực sự giải thích cách thực hiện thay vì nói bạn không nên làm điều này. Thực sự hữu ích.
Emmy

Cảm ơn bạn, điều này thực sự giúp tôi. :)
Daniel Stracaboško

11

Để hoàn nguyên một hoàn nguyên trong GIT:

git revert <commit-hash-of-previous-revert>

1
Sử dụng điều này trong nhánh công việc của tôi để hoàn nguyên hoàn nguyên, sau đó PR mới để phát triển. Bây giờ git thấy tất cả các thay đổi trong PR trước đó đã được hoàn nguyên. Cảm ơn.
Danstan

3

Thay vì sử dụng, git-revertbạn có thể đã sử dụng lệnh này trongdevel nhánh để vứt bỏ (hoàn tác) cam kết hợp nhất sai (thay vì chỉ hoàn nguyên nó).

git checkout devel
git reset --hard COMMIT_BEFORE_WRONG_MERGE

Điều này cũng sẽ điều chỉnh nội dung của thư mục làm việc cho phù hợp. Hãy cẩn thận :

  • Lưu các thay đổi của bạn trong nhánh phát triển (vì hợp nhất sai) vì chúng cũng sẽ bị xóa bởi git-reset. Tất cả các cam kết sau khi bạn xác định là git resetđối số sẽ biến mất!
  • Ngoài ra, không làm điều này nếu các thay đổi của bạn đã được lấy từ các kho khác vì thiết lập lại sẽ viết lại lịch sử.

Tôi khuyên bạn nên nghiên cứu git-resetkỹ trang người đàn ông trước khi thử điều này.

Bây giờ, sau khi thiết lập lại, bạn có thể áp dụng lại các thay đổi của mình develvà sau đó thực hiện

git checkout devel
git merge 28s

Đây sẽ là một sự hợp nhất thực sự từ 28sthành develnhư ban đầu (hiện đã bị xóa khỏi lịch sử của git).


8
Đối với bất kỳ ai không quen thuộc với git và có thể muốn làm theo các hướng dẫn sau: cẩn thận với việc kết hợp reset --hardpush origin. Ngoài ra, hãy lưu ý rằng việc đẩy mạnh nguồn gốc có thể thực sự làm hỏng các PR mở trên GitHub.
funroll

Rất hữu ích để sửa một số vấn đề hợp nhất trên một máy chủ git riêng. Cảm ơn!
mix3d

1
+1 cho kỹ thuật này. Có khả năng phá hoại, nhưng có thể giúp bạn tiết kiệm rất nhiều đau đầu (và một lịch sử sai lầm) khi áp dụng một cách thận trọng.
siliconrockstar

1

Tôi chỉ tìm thấy bài viết này khi đối mặt với cùng một vấn đề. Tôi thấy đáng sợ đến mức đáng sợ khi phải thiết lập lại độ cứng, v.v ... Tôi sẽ kết thúc việc xóa thứ gì đó tôi không muốn và sẽ không thể lấy lại được.

Thay vào đó tôi đã kiểm tra cam kết mà tôi muốn chi nhánh quay trở lại, vd git checkout 123466t7632723. Sau đó chuyển đổi thành một chi nhánh git checkout my-new-branch. Sau đó tôi đã xóa chi nhánh mà tôi không muốn nữa. Tất nhiên điều này sẽ chỉ hoạt động nếu bạn có thể vứt bỏ nhánh bạn đã làm hỏng.


1
Các git reflogsẽ bảo vệ bạn trên hard reset cho một vài tháng trong trường hợp sau này bạn phát hiện ra rằng bạn cần có cam kết bị mất. Các reflog được giới hạn trong repo địa phương của bạn.
Todd

1

Tôi sẽ đề nghị bạn làm theo các bước dưới đây để hoàn nguyên hoàn nguyên, nói SHA1.

git checkout develop #go to develop branch
git pull             #get the latest from remote/develop branch
git branch users/yourname/revertOfSHA1 #having HEAD referring to develop
git checkout users/yourname/revertOfSHA1 #checkout the newly created branch
git log --oneline --graph --decorate #find the SHA of the revert in the history, say SHA1
git revert SHA1
git push --set-upstream origin users/yourname/revertOfSHA1 #push the changes to remote

Bây giờ tạo PR cho chi nhánh users/yourname/revertOfSHA1


1
  1. tạo chi nhánh mới theo cam kết trước khi hợp nhất ban đầu - gọi nó là 'cơ sở phát triển'
  2. thực hiện phản ứng tương tác của 'phát triển' trên đầu trang 'cơ sở phát triển' (mặc dù nó đã ở trên đỉnh). Trong quá trình rebase tương tác, bạn sẽ có cơ hội xóa cả cam kết hợp nhất và cam kết đảo ngược hợp nhất, nghĩa là xóa cả hai sự kiện khỏi lịch sử git

Tại thời điểm này, bạn sẽ có một nhánh 'phát triển' sạch sẽ mà bạn có thể hợp nhất tính năng của bạn như bạn thường làm.


Cách tiếp cận này sẽ tạo ra vấn đề nếu nhánh phát triển được chia sẻ với người khác.
PSR
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.