Tôi cần bật lên và bỏ đi một cam kết "giữa" trong nhánh chính của mình. Tôi làm nó như thế nào?


94

Ví dụ: trong nhánh chính sau, tôi chỉ cần dọn rác cam kết af5c7bf16e6f04321f966b4231371b21475bc4da, là nhánh thứ hai do rebase trước đó:

commit 60b413512e616997c8b929012cf9ca56bf5c9113
Author: Luca G. Soave <luca.soave@gmail.com>
Date:   Tue Apr 12 23:50:15 2011 +0200

    add generic config/initializers/omniauth.example.rb

commit af5c7bf16e6f04321f966b4231371b21475bc4da
Author: Luca G. Soave <luca.soave@gmail.com>
Date:   Fri Apr 22 00:15:50 2011 +0200

    show github user info if logged

commit e6523efada4d75084e81971c4dc2aec621d45530
Author: Luca G. Soave <luca.soave@gmail.com>
Date:   Fri Apr 22 17:20:48 2011 +0200

    add multiple .container at blueprint layout

commit 414ceffc40ea4ac36ca68e6dd0a9ee97e73dee22
Author: Luca G. Soave <luca.soave@gmail.com>
Date:   Thu Apr 21 19:55:57 2011 +0200

    add %h1 Fantastic Logo + .right for 'Sign in with Github'

Tôi cần chú ý

  • cam kết đầu tiên 60b413512e616997c8b929012cf9ca56bf5c9113,
  • cam kết thứ ba e6523efada4d75084e81971c4dc2aec621d45530 và
  • cam kết cuối cùng 414ceffc40ea4ac36ca68e6dd0a9ee97e73dee22

"vứt bỏ" chỉ cam kết thứ hai af5c7bf16e6f04321f966b4231371b21475bc4da

Làm thế nào tôi có thể làm điều đó? Cảm ơn trước Luca

Câu trả lời:


98

Rebase hoặc hoàn nguyên là các tùy chọn. Rebase thực sự sẽ xóa cam kết khỏi lịch sử, vì vậy nó sẽ giống như cam kết thứ hai chưa bao giờ tồn tại. Đây sẽ là một vấn đề nếu bạn đã đẩy nhánh chính ra bất kỳ repo nào khác. Nếu bạn cố gắng đẩy sau một rebase trong trường hợp này, git sẽ cung cấp cho bạn lỗi hợp nhất từ ​​chối không tua đi nhanh .

Hoàn nguyên là giải pháp chính xác khi nhánh đã được chia sẻ với các repo khác. git revert af5c7bf16sẽ thực hiện một cam kết mới chỉ đơn giản là đảo ngược những thay đổi mà af5c7bf16 đã giới thiệu. Bằng cách này, lịch sử không bị viết lại, bạn duy trì một hồ sơ rõ ràng về sai lầm và các repo khác sẽ chấp nhận sự thúc đẩy.

Đây là một cách tốt để xóa: git rebase -i <commit>^ Điều đó sẽ đưa bạn đến cam kết ngay trước khi bạn muốn xóa. Trình chỉnh sửa tương tác sẽ hiển thị cho bạn danh sách tất cả các cam kết trở lại thời điểm đó. Bạn có thể chọn, bí, v.v. Trong trường hợp này, hãy xóa dòng cho cam kết mà bạn muốn xóa và lưu tệp. Rebase sẽ hoàn thành công việc của nó.


2
Trong trường hợp tôi chọn Rebase, cam kết phù hợp với rebase là gì? Tôi chỉ cần thả cái thứ hai ...
Luca G. Soave

@ BBJ3 Xem câu trả lời của mipadi.
Prajwal Dhatwalia

32

Nếu rebase là một tùy chọn, bạn có thể rebase và chỉ cần bỏ nó:

$ git rebase -i 414ceffc^

Nếu rebase không phải là một tùy chọn, bạn chỉ có thể hoàn nguyên nó:

$ git revert af5c7bf16

nếu tôi nhận được "git rebase 414ceffc" là cam kết cũ hơn, thì tôi cũng sẽ mất e6523 thứ ba và 60b41 đầu tiên?
Luca G. Soave

3
@Luca G. Soave: Bạn chỉ "mất" một cam kết nếu bạn yêu cầu cụ thể git rebasebỏ nó (bằng cách chạy rebaseở chế độ tương tác và xóa mục nhập của nó).
mipadi

Cảm ơn mipadi, tôi dành phiếu bầu của mình cho JCotton về cơ bản cho lời giải thích sâu rộng ngay cả khi hai bạn, đã nói điều tương tự ... cảm ơn một lần nữa.
Luca G. Soave

29

Mặc dù tất cả các tín dụng mà các câu trả lời ban đầu nhận được ở đây, tôi không hoàn toàn tìm thấy chúng để trả lời thỏa đáng câu hỏi. Nếu bạn thấy mình ở trong tình huống cần xóa một cam kết hoặc một tập hợp các cam kết từ giữa lịch sử, thì đây là những gì tôi đề xuất:

  • Tạo một nhánh mới từ phần đầu của nhánh chứa tất cả các cam kết và chuyển sang nhánh đó.
  • Hoàn nguyên chi nhánh mới trở lại điểm bạn muốn bắt đầu một cơ sở mới.
  • Sau đó, (đây là điểm chính) anh đào chọn các cam kết tiếp theo mà bạn thực sự muốn được áp dụng sau đó từ nhánh ban đầu sang nhánh mới và bỏ qua các cam kết bạn không muốn nữa (tức là những cam kết bạn đang xóa).
  • Nếu muốn, hãy đổi tên chi nhánh ban đầu thành một cái gì đó cho biết đó là mã cũ, sau đó đổi tên chi nhánh mới của bạn thành tên gọi ban đầu.
  • Cuối cùng, đẩy các thay đổi của bạn vào repo từ xa của bạn (nếu sử dụng repo). Có thể bạn sẽ cần phải sử dụng "ép buộc". Nếu cộng tác viên của bạn gặp sự cố khi kéo các bản sửa đổi, có thể dễ nhất là họ chỉ cần sao chép lại repo từ nguồn từ xa. Bằng cách này hay cách khác, bạn có thể sẽ muốn nói chuyện với họ nếu bạn đang gạt các cam kết ra khỏi lịch sử của mình!

Đây là thông tin về Hái Cherry: anh đào anh đào bằng git nghĩa là gì?

Đây là một số cách thực hiện với Tortoise Git (như tôi vừa làm). Chắc chắn sẽ dễ dàng hơn khi sử dụng tiện ích gui cho các loại thao tác này! Chọn cherry bằng TortoiseGit


6
Đây lẽ ra phải là câu trả lời hàng đầu!
MadOgre

Cách tốt để sử dụng cherry pick, giải pháp này thậm chí còn tốt hơn khi bạn muốn "bỏ qua" nhiều lần commit.
Johnny Willer

Không thực sự giải quyết câu hỏi ban đầu. Mặc dù giải pháp được đề xuất hoạt động nhưng tốn nhiều thời gian / khó xử hơn và IMO không mang lại bất kỳ lợi ích nào. Nếu nhánh đã được đẩy (và được sử dụng trong tự nhiên) thì chiến lược hoàn nguyên có lẽ là câu trả lời. Nếu không, rebase tương tác và xóa cam kết vi phạm là những gì tôi sẽ sử dụng. Nếu nó đã được đẩy nhưng chúng tôi biết nó không được sử dụng bởi bất kỳ ai, bạn vẫn có thể lấy đi với một rebase sau đó là một lực đẩy.
raduw
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.