2011-07-30 35 views
53

Tôi có thói quen thực hiện một số lượng lớn các cam kết nhỏ và tôi ổn với nó. Nhưng tôi muốn, theo thời gian, có một loạt các cam kết tuyến tính và thu gọn chúng lại với nhau chỉ là một cam kết với khả năng viết một thông điệp cam kết mới.Thu gọn nhóm cam kết thành một trên Git

Tôi đã xem xét tài liệu nhưng có vẻ hơi khó hiểu với tôi. Có ai biết làm thế nào để làm điều đó?

+1

Xem câu hỏi này & câu trả lời http: // stackoverflow.com/questions/250238/collapsing-a-git-repositorys-history – iafonov

Trả lời

47

Giả sử bạn muốn viết lại lịch sử của cây sẽ trở lại cho đến khi (nhưng không bao gồm) cam kết a739b0d.

export EDITOR=vim # or your favorite editor 
git rebase a739b0d --interactive 

Hãy nhớ đọc trước interactive rebasing trước.

+2

Nhưng hãy nói rằng các cam kết mà tôi muốn "rebase" là cách trong quá khứ, trước khi một loạt các sáp nhập và chi nhánh ... vẫn hợp lệ? – Rodrogo

+1

Có. Trước tiên, bạn có thể sắp xếp lại các cam kết khi bạn rebase để các cam kết bạn muốn squash với nhau là trong một chuỗi sau tất cả các hợp nhất. Sau đó, bạn có thể squash những cam kết với nhau thành một cam kết. – yfeldblum

+1

Liên kết của bạn không đi bất cứ nơi nào cụ thể cho tôi. http://git-scm.com/book/en/Git-Branching-Rebasing là trang rebasing; http://git-scm.com/book/en/Git-Tools-Rewriting-History có nhiều tổng quan hơn. –

5

Bạn có thể dẹp bất kỳ số lượng cam kết thành một trong những đơn sử dụng

git rebase --interactive <commit> 
+3

Điều quan trọng là phải xem xét trường hợp bạn đã hoặc một số cộng tác viên của bạn đã đẩy vào kho lưu trữ của bạn trong Github. Xem http://stackoverflow.com/questions/5667884/how-to-squash-commits-in-git-after-they-have-been-pushed – e3matheus

+0

Đó là một điểm hợp lệ, nhưng vì '-i' giống như '--interactive', sự khác biệt duy nhất là' push'. –

+0

Mmm có. Nhưng tôi nhận xét rằng chỉ để làm rõ, rằng nếu bạn đã đẩy để làm chủ trước khi rebase, push này phải được thực hiện thông qua --force, phải không ?. Và rằng nếu một trong những cộng tác viên của bạn đã thúc đẩy, bạn không nên thực hiện việc rebase. – e3matheus

13

Sử dụng lệnh git rebase -i <commit> trong đó <commit> là SHA cho cam kết ổn định cuối cùng.

Thao tác này sẽ đưa bạn đến trình chỉnh sửa nơi bạn có thể thay thế nhãn pick bên cạnh mỗi cam kết từ <commit> mà bạn đưa vào làm đối số cho lệnh rebase tương tác của mình. Trên lệnh bạn muốn bắt đầu thu gọn, thay thế pick bằng reword và đối với mỗi cam kết sau đó bạn muốn thu gọn, hãy thay thế pick bằng fixup. Lưu và sau đó bạn sẽ được phép cung cấp thông báo cam kết mới.

+2

thực sự, giải thích tốt nhất mà tôi đã thấy chính xác và khớp nối ... –

+0

Đúng, cách dễ nhất. –

39

Giả sử bạn không quan tâm đến việc giữ lại bất kỳ thư cam kết hiện có nào, bạn có thể sử dụng công thức git tiện lợi (và nhanh). Trước tiên, hãy đảm bảo chi nhánh của bạn được kiểm tra:

git checkout <branch-to-squash> 

Vì lý do an toàn, hãy gắn thẻ cam kết hiện tại.

git tag my-branch-backup 

Tiếp theo, di chuyển các HEAD chi nhánh trở lại tốt nhất của bạn cam kết (không có sửa đổi không gian làm việc hoặc chỉ số):

git reset --soft <last-good-commit> 

Sử dụng git status, bạn sẽ nhận thấy rằng tất cả những thay đổi về chi nhánh tính năng của bạn bây giờ đã tổ chức. Tất cả những gì còn lại để làm là ...

git commit 

Phương pháp này là rất tốt để củng cố lịch sử gitly và phức tạp gnarly. Ngoài ra, không có xung đột hợp nhất/rebase để giải quyết!

Bây giờ, nếu bạn cần giữ lại bất kỳ thông điệp cam kết hiện có nào hoặc làm bất kỳ điều gì huyền ảo hơn mức cho phép ở trên, bạn sẽ muốn sử dụng git rebase --interactive.

Giải pháp có nguồn gốc từ: http://makandracards.com/makandra/527-squash-several-git-commits-into-a-single-commit

tham khảo: http://git-scm.com/docs/git-reset

tham khảo: http://git-scm.com/docs/git-rebase

+3

Đây là một câu trả lời tuyệt vời - có 310 cam kết để bí, dường như mọi cam kết đơn lẻ đều giới thiệu các lỗi rebase. Sử dụng cách tiếp cận của bạn nhanh chóng, không đau và chính xác. – tbm

+2

"Cam kết tốt cuối cùng" trong ngữ cảnh này là gì? –

+6

@MarceloMason Câu hỏi hay. Vui lòng giải thích "cam kết tốt cuối cùng" là "cam kết gần đây nhất trên chi nhánh của bạn mà bạn muốn giữ lại". Ví dụ, nếu bạn muốn đè bẹp lịch sử nhánh của chủ đề của bạn xuống tận nơi mà nó phân tách từ nhánh master, commit tốt nhất cuối cùng sẽ là 'merge-base' của master và nhánh chủ đề của bạn. Nếu bạn có mười commit trên nhánh của bạn và chỉ muốn củng cố top 5, commit tốt nhất cuối cùng sẽ là 'HEAD ~ 5'. –