git xóa cam kết hợp nhất khỏi lịch sử


97

Lịch sử Git của tôi trông như thế:

Lịch sử git

Tôi muốn ép những quả cam tím thành một chiếc duy nhất. Tôi không muốn nhìn thấy chúng lần nữa trong nhật ký cam kết của mình.

Tôi đã cố gắng làm điều đó git rebase -i 1, nhưng mặc dù 1đang ở trên cành màu xanh (xem hình), tôi vẫn thấy mọi cam kết trên cành màu tím của mình.

Làm cách nào để loại bỏ hoàn toàn nhánh màu tím (khỏi bản ghi cam kết)?


Repo của bạn có được đẩy đến bất cứ đâu mà người khác đã lấy từ đó không?
Schleis

Cả hai chi nhánh đều là địa phương thuần túy.
Benjamin Toueg

Câu trả lời:


100

Làm git rebase -i <sha before the branches diverged>điều này sẽ cho phép bạn loại bỏ cam kết hợp nhất và nhật ký sẽ là một dòng duy nhất như bạn muốn. Bạn cũng có thể xóa bất kỳ cam kết nào mà bạn không muốn nữa. Lý do khiến rebase của bạn không hoạt động là bạn đã không quay lại đủ xa.

CẢNH BÁO: Bạn đang viết lại lịch sử khi làm việc này. Thực hiện điều này với các thay đổi đã được đẩy vào kho lưu trữ từ xa sẽ gây ra sự cố. Tôi khuyên bạn chỉ nên làm điều này với các cam kết là địa phương.


4
Thậm chí nếu tôi chọn một sha trước các chi nhánh đã tách ra, tôi thấy tất cả các cam kết của chi nhánh tím -_-
Benjamin Toueg

1
Vâng, sau đó bạn xóa chúng trong trình chỉnh sửa đi kèm git rebasevà chúng sẽ bị xóa.
Schleis

4
Xóa các cam kết dẫn đến mất tất cả các sửa đổi của hợp nhất. Nhưng tôi đã thiết lập lại mềm và tôi đã có thể có một cái gì đó khá giống như tôi muốn (thứ tự không khớp với kỳ vọng ban đầu).
Benjamin Toueg

2
câu trả lời này không đầy đủ chi tiết, bạn khởi tạo rebase từ chi nhánh nào?
grgry

3
Khá chắc chắn rằng bạn không muốn 'xóa' các cam kết. 'remove' không phải là một tùy chọn trong rebase, nhưng delete thì có. nếu bạn xóa một cam kết, bạn sẽ mất những thay đổi mà nó đã giới thiệu. Bạn muốn phá vỡ các cam kết.
thecoshman

69

Bắt đầu với repo ở trạng thái ban đầu

Lịch sử repo gốc

Để loại bỏ cam kết hợp nhất và tách nhánh thành một cam kết duy nhất trong dòng chính

Cam kết cố định, không có cam kết hợp nhất

Sử dụng các lệnh này (thay thế 5 và 1 bằng SHA của các cam kết tương ứng):

git checkout 5
git reset --soft 1
git commit --amend -m '1 2 3 4 5'
git rebase HEAD master

Để giữ lại một cam kết hợp nhất nhưng bỏ nhánh cam kết thành một:

Cam kết thu gọn, cam kết hợp nhất được giữ lại

Sử dụng các lệnh sau (thay thế 5, 1 và C bằng SHA của các cam kết tương ứng):

git checkout -b tempbranch 5
git reset --soft 1
git commit --amend -m '1 2 3 4 5'
git checkout C
git merge --no-ff tempbranch
git rebase HEAD master

Để loại bỏ cam kết hợp nhất và thay thế nó bằng các cam kết riêng lẻ từ nhánh

Chi nhánh được chuyển vào dòng chính, không có cam kết hợp nhất

Chỉ cần làm (thay thế 5 bằng SHA của cam kết tương ứng):

git rebase 5 master

Và cuối cùng, để loại bỏ hoàn toàn nhánh

Chi nhánh bị xóa hoàn toàn

Sử dụng lệnh này (thay thế C và D bằng SHA của các cam kết tương ứng):

git rebase --onto C D~ master

trong git rebase 5 mastertrường hợp, tại sao nó không phải là thứ tự "ABC 1 2 3 4 5 D ..."?
Roy

1
Lệnh đó nhận các cam kết masterkhông có điểm chung 5và đặt chúng lên trên 5. Cam kết Ckhông phải là một phần của dòng họ 5, nó là cam kết đầu tiên được chuyển lên trên 5.
Allen Luce

2
Nếu bạn muốn kết thúc với "ABC 1 2 3 4 5 D ..." bạn có thể làm:git rebase C 5; git rebase 5 master
Allen Luce

16

Có hai cách để giải quyết vấn đề này dựa trên những gì bạn muốn:

Giải pháp 1 : Xóa các cam kết màu tím, lưu giữ lịch sử (trong trường hợp bạn muốn quay trở lại)

git revert -m 1 <SHA of merge>

-m 1 chỉ định dòng mẹ để chọn

Các cam kết màu tím sẽ vẫn ở đó trong lịch sử nhưng vì bạn đã hoàn nguyên, bạn sẽ không thấy mã từ các cam kết đó.


Giải pháp 2 : Loại bỏ hoàn toàn các cam kết màu tím (thay đổi gián đoạn nếu repo được chia sẻ)

git rebase -i <SHA before branching out>

và xóa (bỏ dòng) tương ứng với các cam kết màu tím.

Điều này sẽ ít phức tạp hơn nếu các cam kết không được thực hiện sau khi hợp nhất. Cam kết bổ sung làm tăng nguy cơ xung đột trong revert/rebase.


Điều này nghe có vẻ không đúng. Bỏ qua một thực tế là rất khó để biết người đăng ban đầu muốn làm gì với các cam kết màu tím ngay từ đầu, nếu bạn hoàn nguyên hợp nhất, điều đó tốt, điều đó sẽ thực hiện một bản vá ngược các thay đổi từ cam kết đó và thêm nó vào một cam kết khác, hủy bỏ cam kết màu tím. Nó giống như 1 - 1 = 0. Nhưng nếu sau đó bạn căn cứ lại các cam kết màu tím, bạn sẽ để lại bản vá hoàn nguyên, trừ khi bạn cũng căn cứ lại đó. Nếu bạn không, nó giống như áp dụng -1vào lịch sử của bạn, không phải 0vậy, vì vậy bạn sẽ để lại những thay đổi mà bạn không muốn.

@Cupcake, được cung cấp là hai câu trả lời riêng biệt. Tôi đã sửa đổi câu trả lời cho được ít bối rối: P
Prem

AFAIK đây không phải là những gì OP đang yêu cầu. Anh ấy muốn giữ các thay đổi, nhưng loại bỏ tiếng ồn khỏi nhật ký của mình. Để làm được điều đó, anh ta cần xóa các cam kết xuống, việc xóa sẽ xóa các thay đổi.
thecoshman

Đúng, có vẻ như câu hỏi ban đầu đã được diễn đạt lại. Câu trả lời này không dành cho vấn đề OPs.
Prem

16

Để chỉ xóa một cam kết hợp nhất

Nếu tất cả những gì bạn muốn làm là xóa một cam kết hợp nhất (2) để nó giống như nó chưa từng xảy ra, thì lệnh đơn giản như sau

git rebase --onto <sha of 1> <sha of 2> <blue branch>

Và bây giờ nhánh màu tím không có trong bản ghi cam kết của màu xanh lam và bạn lại có hai nhánh riêng biệt. Sau đó, bạn có thể tách màu tím một cách độc lập và thực hiện bất kỳ thao tác nào khác mà bạn muốn mà không cần cam kết hợp nhất theo cách.


Trong tất cả các câu trả lời, tôi thấy đây là câu trả lời đơn giản nhất và dễ làm nhất. Cảm ơn bạn.
Roshambo
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.