2010-10-13 26 views
93

Tôi là một chút mới cho toàn bộ tính năng rebasing trong git. Hãy nói rằng tôi đã thực hiện các cam kết sau:Làm cách nào để xóa hai cam kết không liên tiếp?

A -> B -> C -> D 

Sau đó, tôi nhận ra rằng D chứa một sửa chữa mà phụ thuộc vào một số mã mới được bổ sung trong A, và rằng những cam kết thuộc về nhau. Tôi làm cách nào để tự động làm tròn A & D và để lại B & C một mình?

Trả lời

120

Bạn có thể chạy git rebase --interactive và sắp xếp lại D trước khi B và bí D thành A.

Git sẽ mở ra một biên tập viên, và bạn thấy một tập tin như thế này:

pick aaaaaaa Commit A 
pick bbbbbbb Commit B 
pick ccccccc Commit C 
pick ddddddd Commit D 

# Rebase aaaaaaa..ddddddd onto 1234567 (4 command(s)) 
# 
# Commands: 
# p, pick = use commit 
# r, reword = use commit, but edit the commit message 
# e, edit = use commit, but stop for amending 
# s, squash = use commit, but meld into previous commit 
# f, fixup = like "squash", but discard this commit's log message 
# x, exec = run command (the rest of the line) using shell 
# 
# These lines can be re-ordered; they are executed from top to bottom. 
# 
# If you remove a line here THAT COMMIT WILL BE LOST. 
# 
# However, if you remove everything, the rebase will be aborted. 
# 
# Note that empty commits are commented out 

Bây giờ bạn thay đổi tập tin đó có vẻ như sau:

pick aaaaaaa Commit A 
squash ddddddd Commit D 
pick bbbbbbb Commit B 
pick ccccccc Commit C 

Và git giờ đây sẽ kết hợp các thay đổi của A và D với nhau thành một cam kết và đặt B và C sau đó. Khi bạn không muốn giữ thông điệp cam kết của D, bạn cũng có thể sử dụng từ khóa "sửa".

+3

Ban đầu, tôi đọc nó là "rebase D lên A, squash D thành A, sau đó rebase B lên DA". Nó không rõ ràng từ câu trả lời rằng điều này có thể được thực hiện bằng cách sắp xếp lại các dòng trong một trình soạn thảo văn bản. –

-1

$ git checkout chủ

$ git log --oneline

D 
C 
B 
A 

$ git rebase --onto ĐẦU ^^^ ĐẦU^

$ git log --oneline

D 
A 
+0

Tôi nghĩ bạn có nghĩa là '--oneline'? Và có vẻ như bạn đã bỏ 'C' và' B', đó không phải là ý định của OP. – bstpierre

+0

Không làm việc cho tôi. Nó di chuyển cả hai HEAD của tôi và làm chủ xuống A, nhưng không hợp nhất D thành A ('git show A') và D, C và B đã bị mất trong bản ghi nhật ký của tôi. Đã phải 'git rebase D' để quay lại. – Nate

38

Lưu ý: Bạn nên không thay đổi các cam kết đã được đẩy đến một repo khác theo bất kỳ cách nào trừ khi bạn biết số consequences.

git log --oneline -4

D commit_message_for_D 
C commit_message_for_C 
B commit_message_for_B 
A commit_message_for_A 

git rebase --interactive

pick D commit_message_for_D 
pick C commit_message_for_C 
pick B commit_message_for_B 
pick A commit_message_for_A 

Loại i (Đặt VIM trong chế độ chèn)

Thay đổi danh sách để trông như thế này (Bạn không cần phải loại bỏ hoặc bao gồm thông điệp cam kết). Đừng bỏ lỡ squash!:

pick C commit_message_for_C 
pick B commit_message_for_B 
pick A commit_message_for_A 
squash D 

Loại Esc sau đó ZZ (Lưu và thoát VIM)

# This is a combination of 2 commits. 
# The first commit's message is: 

commit_message_for_D 

# This is the 2nd commit message: 

commit_message_for_A 

Loại i

Thay đổi văn bản với những gì bạn muốn mới nhắn để trông giống như cam kết.Tôi khuyên bạn nên này là một mô tả về những thay đổi trong phạm AD:

new_commit_message_for_A_and_D 

Loại Esc sau đó ZZ

git log --oneline -4

E new_commit_message_for_A_and_D 
C commit_message_for_C 
B commit_message_for_B 

git show E

(You should see a diff showing a combination of changes from A and D) 

Bây giờ bạn đã tạo một cam kết mới E. Cam kết AD không còn trong lịch sử của bạn nhưng không bị mất. Bạn vẫn có thể khôi phục chúng tại thời điểm này và trong một thời gian bằng cách git rebase --hard D (git rebase --hard sẽ hủy mọi thay đổi cục bộ!).

3

Đối với những người đang sử dụng SourceTree:

Đảm bảo bạn chưa đẩy cam kết.

  1. Repository> Interactive rebase ...
  2. Kéo D (cam kết mới hơn) để được trực tiếp trên A (cam kết cũ)
  3. đảm bảo cam kết D được đánh dấu
  4. Bấm Squash with previous
Các vấn đề liên quan