Khi tôi hiểu, cam kết là ảnh chụp nhanh của tệp vì vậy nếu tôi thực hiện thay đổi A và sau đó thay đổi B, thay đổi cam kết B tệp đã bao gồm các thay đổi trong thay đổi A, sẽ không sắp xếp lại thay đổi.Tại sao sắp xếp lại các cam kết bằng cách sử dụng git rebase -i không làm hỏng lịch sử?
Trả lời
Đó là, trên thực tế, một câu hỏi rất hay, vì cam kết là ảnh chụp nhanh.
Lý do rebase hoạt động là do rebase thực sự được lặp lại git cherry-pick
(với một chút gói ở mặt trước để tìm ra những gì để chọn, và nhiều hơn nữa ở cuối để di chuyển nhãn chi nhánh), và git cherry-pick
hoạt động bằng cách cam kết thành một tập hợp thay đổi.
Giả sử ví dụ mà bạn có chuỗi này cam kết:
A--B--C <-- topic
/
...--o--*--o--o <-- mainline
Để rebase topic
vào mainline
chúng ta cần phải (1) tìm ra cam kết rằng đang trên topic
nhưng không phải trên mainline
(mà là C
, B
và A
dọc theo hàng trên cùng, kết thúc tại cam kết được đánh dấu *
) và sau đó (2) sao chép chúng vào các cam kết mới, chúng tôi sẽ thêm vào bên dưới đầu của mainline
.
rebase đầu tiên tìm thấy ba hậu *
cam kết và đặt chúng vào một (đảo ngược lệnh: A
, B
, C
) danh sách (nó cũng bỏ qua sáp nhập cam kết theo mặc định nhưng không có hòa trộn ở đây). Sau đó nó thực hiện một lựa chọn anh đào cho mỗi cam kết.
Để chọn cherry A
, Git diffs A
chống lại *
. Điều này biến hai ảnh chụp nhanh thành các changesets. Git sau đó áp dụng các thay đổi đối với mũi-hầu hết các cam kết của mainline
và làm cho một mới cam kết, chúng ta hãy gọi nó A'
, trên một nhánh vô danh:
A--B--C <-- topic
/
...--o--*--o--o <-- mainline
\
A' <-- HEAD
Để anh đào-chọn B
, Git diffs B
chống A
. Áp dụng các thay đổi này cho A'
sẽ tạo một cam kết khác B'
. Lặp lại cho C
để có được C'
:
A--B--C <-- topic
/
...--o--*--o--o <-- mainline
\
A'-B'-C' <-- HEAD
ngoái, Git bị lột nhãn topic
xa C
và chỉ nó để C'
để thay thế. Chuỗi cũ đang bị bỏ rơi (mặc dù bạn vẫn có thể tìm thấy nó qua reflogs, và rebase
bản sao ID của C
với tên đặc biệt ORIG_HEAD
cũng):
A--B--C [abandoned]
/
...--o--*--o--o <-- mainline
\
A'-B'-C' <-- topic
và bây giờ rebase hoàn tất.
Lưu ý rằng mỗi bản sao được thực hiện bằng cách sử dụng cơ chế hợp nhất của git nếu cần (nếu các khác biệt không áp dụng ngay lập tức). Mỗi người có thể dẫn đến xung đột hợp nhất, yêu cầu phải ngừng lại và nhận trợ giúp từ bạn. (Hoặc, tệ hơn, bạn có thể bị kết hợp sai, mặc dù điều này hiếm gặp trong thực tế.Và tất nhiên, nếu bạn sắp xếp lại các cam kết (bằng cách di chuyển pick
đường xung quanh trong một lần rebase tương tác), chúng tôi chỉ thay đổi thứ tự mà chúng tôi chọn và áp dụng từng cam kết. Các hoạt động pick-cherry vẫn hoạt động theo cùng một cách: so sánh cam kết đã chọn với cha mẹ của nó (C
vs B
, A
vs *
, B
vs A
).
Nhưng dữ liệu khác biệt phụ thuộc vào nội dung của tệp trong cam kết trước đó, điều này sẽ thay đổi sau khi sắp xếp lại chúng. Hay liệu thứ tự này chỉ là mỹ phẩm? –
Các bản sao mới là * bản sao mới *, với tất cả những điều này ngụ ý. Giả sử, ví dụ, trong khi anh đào chọn 'B' bạn nhận được một cuộc xung đột hợp nhất vì đầu của' đường chính 'có một sự thay đổi mâu thuẫn. Khi bạn sửa chữa xung đột và tiếp tục rebase, commit mới 'B'' bây giờ có một sự thay đổi khác so với commit ban đầu' B'. Cả 'B' và' B'' vẫn còn trong kho, và lựa chọn cherry-pick tiếp theo (giả sử nó là cho 'C') so sánh' C' với 'B' trước khi cố gắng áp dụng thay đổi đó cho' B'' (có thể nhận được xung đột hợp nhất khác vì 'B'' giờ đã khác!). – torek
Tôi nghĩ rằng tôi thấy nó ngay bây giờ sau khi đọc bình luận của bạn và đọc lại câu trả lời của bạn. Có vẻ như tôi bị ném ra bởi thuật ngữ. Như tôi thấy nó bây giờ, chắc chắn, các cam kết có thể được sắp xếp lại nhưng kết quả cam kết sau khi một rebase là hoàn toàn mới cam kết cho dù bạn sắp xếp lại chúng hay không. Kết quả cam kết này cũng có một "tệp ảnh chụp nhanh" khác nhau, đó là kết quả của việc chỉ áp dụng sự khác biệt từ việc chọn anh đào đến đầu dòng chính. Theo cách đó, việc sắp xếp lại là mỹ phẩm vì các cam kết ban đầu được sắp xếp lại không thay đổi. Vui lòng cho tôi biết nếu tôi đúng. –
- 1. Làm cách nào để sắp xếp lại/kết hợp các cam kết bằng cách sử dụng Git rebase?
- 2. Lỗi khi sắp xếp lại các cam kết với git rebase -i
- 3. git: viết lại lịch sử: sắp xếp lại và hợp nhất cam kết
- 4. Sắp xếp lại git commit lịch sử theo ngày
- 5. ghi lại hiệu quả (rebase -i) rất nhiều lịch sử với git
- 6. Cách thực hành tốt nhất để ghép vào NEXT cam kết trong git rebase -i?
- 7. git rebase bằng cách sử dụng sourcetree
- 8. Làm thế nào để sử dụng git rebase -i sau khi git merge mà không làm rối tung mọi thứ?
- 9. Tại sao git svn dcommit mất lịch sử kết hợp các cam kết cho các chi nhánh địa phương?
- 10. Tại sao tôi muốn làm git rebase?
- 11. Tại sao git pull --rebase thất bại khi phát lại các cam kết hiện có?
- 12. Git - Xóa cam kết khỏi lịch sử
- 13. git rebase và git push: không nhanh về phía trước, tại sao lại sử dụng?
- 14. Git loại bỏ lịch sử cam
- 15. git cam kết múi giờ bị hỏng
- 16. Git: Cách xóa tệp khỏi cam kết lịch sử?
- 17. Git rebase cam kết lựa chọn
- 18. Git rebase: Kết hợp cam kết không tiếp theo
- 19. Sử dụng lịch sử cam kết git để tìm các điểm nóng của dự án?
- 20. Làm cách nào để "mở lại" một cam kết git?
- 21. Git rebase tương tác n cuối cùng cam kết
- 22. Giảm Git cũ cam kết từ lịch sử?
- 23. Lịch sử Git bao gồm/sublodule submodule cam kết
- 24. Làm thế nào để sửa lỗi cam kết trong yêu cầu kéo GitHub, bị hỏng bởi git rebase?
- 25. Tự động bỏ qua các cam kết trống khi sử dụng git rebase
- 26. git rebase một cam kết duy nhất
- 27. Giữ lịch sử cam kết sau khi 'hợp nhất git'
- 28. Không thể đặt lại tệp cho một cam kết cụ thể bằng cách sử dụng Git
- 29. Xóa tất cả Lịch sử Cam kết Git
- 30. Lặp lại sử dụng git-filter-branch để ghi lại các cam kết mới
Git có sự khác biệt khi cần thiết; rebase áp dụng khác với nội dung cơ sở mới. – jthill