2013-07-16 2 views
11

Tôi có một số cam kết trong kho của tôi:Git: loại bỏ sớm hơn cam kết nhưng giữ các thay đổi gần đây

như:

A - Added Feature A 
B - Removed Feature B 
C - Redesigned Feature C 
D - Added Feature D 
E - Added Feature D 

đâu E là gần đây nhất cam kết tôi đã thực hiện. Bây giờ tôi muốn loại bỏ những thay đổi tôi đã thực hiện với tính năng C nhưng tôi muốn giữ các thay đổi được thêm với D và E.

Tôi hy vọng bạn có thể giúp tôi.

Cảm ơn bạn

+2

thể trùng lặp của [Git: Xóa lựa chọn cam kết mục log cho một kho lưu trữ] (http://stackoverflow.com/questions/495345/git-removing-selected-commit-log-entries-for- a-kho lưu trữ) – jszakmeister

+1

@jszakmeister: Không hoàn toàn giống nhau, bài đăng được liên kết muốn xóa bí mật, trong khi OP muốn ở đây để xóa chúng – CharlesB

+1

@CharlesB Không hoàn toàn đúng. Squashing B và C là một lựa chọn, và do đó đã loại bỏ các cam kết trong câu hỏi của OP. Câu trả lời chứa các chỉ dẫn trên cả hai. – jszakmeister

Trả lời

7

Nếu bạn chỉ muốn "loại bỏ các thay đổi" (như được chỉ định trong phần câu hỏi của bạn) trái ngược với thực tế "xóa cam kết" (như được chỉ định trong tiêu đề), một tùy chọn dễ dàng là thêm cam kết, làm chính xác điều ngược lại với những gì cam kết trước đó đã làm.

Điều này không quá rõ ràng và có thể dẫn đến xung đột do thay đổi được thực hiện, nhưng nó không làm thay đổi lịch sử, cho phép bạn ghi lại sự đảo ngược và lý do của nó, và chơi tốt với các bản sao làm việc khác.

git revert là công cụ được sử dụng để làm cho cặp song sinh độc ác như vậy của một tập hợp các cam kết.

0

này được gọi là rebasing: bạn muốn -i switch.

đọc: https://www.atlassian.com/git/tutorial/rewriting-git-history#!rebase-i

cho một câu hỏi tương tự/câu trả lời xem: https://stackoverflow.com/a/2938393/2536029

+0

Cảm ơn bạn. Nhưng tôi đã sử dụng 'git revert C', loại bỏ tất cả các thay đổi được thực hiện với C. Điều đó thật dễ dàng. – Strernd

+1

đó sẽ là đề xuất đầu tiên trong câu trả lời được liên kết. – mnagel

0

để làm điều đó, hãy làm theo các bước sau:

git rebase -i HEAD~3 

sau đó di chuyển cam kết C để là người đầu tiên ở phía dưới , bạn sẽ có

D - Added Feature D 
E - Added Feature D 
C - Redesigned Feature C 

bạn sav e và xuất cảnh, sau đó

git reset HEAD^ 

này sẽ lùi lại cam C.

20

Interactive rebase là bạn của bạn!

Như những người khác đã nói:

$ git rebase -i HEAD~5 

... nơi -i là lá cờ tương tác, và HEAD~5 phương tiện bao gồm 5 cam kết cuối cùng trong rebase tương tác.

Khi bạn nhận được biên tập lên như là kết quả của việc ban hành trên, hãy nhìn vào những nhận xét trong file mở:

# 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 

Các bit chìa khóa cho bạn là Nếu bạn loại bỏ một dòng ở đây RẰNG COMMIT SẼ BỊ MẤT.

Vì vậy, hãy xóa các dòng tham chiếu các cam kết bạn muốn loại bỏ, lưu và đóng, và git sẽ xử lý phần còn lại (bạn có thể phải khắc phục một số xung đột tùy thuộc vào tính chất của cam kết và hoàn nguyên bạn đang cố xoá). Điều quan trọng cần lưu ý là nếu bạn đã đẩy mã của bạn và những người khác đã kéo nó, thì ở trên sẽ không hoạt động vì các cam kết sẽ tìm đường trở lại trong lần sau khi ai đó đã kiểm tra chi nhánh của bạn . Việc rebase tương tác xóa các cam kết trong phạm vi mà không có bản ghi của chúng, do đó, các bản sao khác không biết chúng đã bị xóa. Lần sau khi họ push, họ sẽ cố gắng và tái instate chúng như là các bản sao cục bộ "thấy" rằng nguồn gốc không có các đối tượng (cam kết) mà bạn đã xóa.

+1

Điều này được giải thích tốt hơn ở đây. Điều này nên được chấp nhận câu trả lời. –

+0

@CyrilCHAPON - trong khi tôi đồng ý rằng đây là câu trả lời hay (đối với tiêu đề câu hỏi), IMO không nhất thiết phải là câu trả lời đúng cho câu hỏi đã nêu (trong phần nội dung). Câu trả lời của IMO @ aib là câu trả lời được ưa thích nhất, bởi vì việc rebasing là phá hoại (viết lại lịch sử - như đã nói trong câu trả lời này, nhưng chưa được đánh dấu đủ IMO). Đôi khi đó là câu trả lời duy nhất, nhưng IMO rebase chỉ nên được sử dụng trên một nhánh master như là phương sách cuối cùng. –

1

Nếu bạn chỉ có các thay đổi cục bộ, có lẽ bạn tốt nhất nên theo dõi câu trả lời rebasing.Nếu bạn đã xuất bản các thay đổi ở bất kỳ đâu thì bạn không muốn rebase vì điều đó sẽ thay đổi lịch sử, có nghĩa là mọi người khác cũng sẽ phải rebase hoặc bạn sẽ nhận được commit cam kết sáp nhập lại.

Nếu người khác có các cam kết của bạn, điều cần làm là hoàn nguyên thay đổi vi phạm, không được miễn trừ hoàn toàn. Sử dụng git revert COMMIT_ID để tạo một cam kết mới hoàn tác các thay đổi bạn đã áp dụng trong COMMIT_ID.

0
git reabse -i HEAD~3 

bạn sẽ có danh sách 3 bạn cam kết cuối cùng thông điệp

C - Redesigned Feature C 
D - Added Feature D 
E - Added Feature D 

bạn chỉ cần chèn x git reset ĐẦU^trước khi cam kết bạn muốn phục hồi lại, bạn muốn phục hồi lại cam kết C, vì vậy nó sẽ như thế này là

C - Redesigned Feature C 
x git reset HEAD^ 
    D - Added Feature D 
    E - Added Feature D 

bảng điều khiển xuất phát lại, bạn sẽ thấy cam kết không còn trong nhật ký và tệp của chúng được tổ chức.

0

Nếu bạn sử dụng TortoiseGit trong Windows, bạn có thể nhấp chuột phải vào thư mục Git rồi nhấp TortoiseGit > Show log. Bạn có thể xem tất cả các cam kết được thực hiện trước và sau đó kiểm tra cam kết bạn muốn hoàn nguyên.

Nhấp vào cam kết và bạn có thể xem các tệp đã thay đổi bên dưới. Nhấp chuột phải vào các tệp cần hoàn nguyên và sau đó nhấp vào revert to parent revision.

How to revert commits