Kể từ thời gian git cherry-pick
được học để có thể áp dụng nhiều cam kết, sự khác biệt thực sự đã trở nên tranh cãi, nhưng đây là thứ được gọi là sự tiến hóa hội tụ ;-)
Sự khác biệt thực sự nằm ở mục đích ban đầu để tạo ra cả hai công cụ:
git rebase
Nhiệm vụ của nhiệm vụ là chuyển tiếp một loạt các thay đổi mà nhà phát triển có trong kho lưu trữ riêng tư của họ, được tạo dựa trên phiên bản X của một nhánh ngược dòng nào đó, sang phiên bản Y của cùng nhánh đó (Y> X). Điều này có hiệu quả thay đổi cơ sở của chuỗi cam kết đó, do đó "phục hồi".
(Nó cũng cho phép nhà phát triển ghép một loạt cam kết vào bất kỳ cam kết tùy ý nào, nhưng điều này ít rõ ràng hơn.)
git cherry-pick
là để mang lại một cam kết thú vị từ dòng phát triển này sang dòng phát triển khác. Một ví dụ cổ điển là sao lưu một bản sửa lỗi bảo mật được thực hiện trên một nhánh phát triển không ổn định sang một nhánh ổn định (bảo trì), điều này merge
không có ý nghĩa gì, vì nó sẽ mang lại rất nhiều thay đổi không mong muốn.
Kể từ lần xuất hiện đầu tiên, git cherry-pick
đã có thể chọn nhiều cam kết cùng một lúc, từng cái một.
Do đó, có thể sự khác biệt nổi bật nhất giữa hai lệnh này là cách chúng xử lý nhánh mà chúng hoạt động: git cherry-pick
thường đưa một cam kết từ một nơi khác và áp dụng nó trên nhánh hiện tại của bạn, ghi lại một cam kết mới , trong khi git rebase
lấy nhánh hiện tại của bạn và viết lại một loạt các cam kết về mẹo của riêng nó theo cách này hay cách khác. Đúng vậy, đây là một mô tả sâu sắc về những gì git rebase
có thể làm, nhưng nó có chủ đích, để cố gắng làm cho ý tưởng chung đi sâu vào.
Cập nhật để giải thích thêm một ví dụ về việc sử dụng git rebase
đang được thảo luận.
Trước tình hình này,
Sách nói:
Tuy nhiên, có một cách khác: bạn có thể lấy bản vá của thay đổi đã được giới thiệu trong C3 và áp dụng lại nó trên C4. Trong Git, điều này được gọi là phục hồi. Với lệnh rebase, bạn có thể thực hiện tất cả các thay đổi đã được cam kết trên một nhánh và áp dụng chúng cho nhánh khác.
Trong ví dụ này, bạn sẽ chạy như sau:
$ git checkout experiment
$ git rebase master
First, rewinding head to replay your work on top of it...
Applying: added staged command
"Điểm nổi bật" ở đây là trong ví dụ này, nhánh "thử nghiệm" (đối tượng phục hồi) ban đầu được tách ra khỏi nhánh "chính" và do đó nó chia sẻ cam kết từ C0 đến C2 với nó - một cách hiệu quả, "thử nghiệm" là " master "lên đến, và bao gồm, C2 cộng với cam kết C3 ở trên nó. (Đây là trường hợp đơn giản nhất có thể xảy ra; tất nhiên, "thử nghiệm" có thể chứa hàng chục cam kết trên cơ sở ban đầu của nó.)
Bây giờ git rebase
được yêu cầu căn cứ lại "thử nghiệm" vào mẹo hiện tại của "bậc thầy" và git rebase
diễn ra như sau:
- Chạy
git merge-base
để xem cam kết cuối cùng được chia sẻ bởi cả "thử nghiệm" và "chủ" (nói cách khác, điểm chuyển hướng là gì). Đây là C2.
- Lưu tất cả các cam kết đã thực hiện kể từ điểm chuyển hướng; trong ví dụ đồ chơi của chúng tôi, nó chỉ là C3.
- Tua lại HEAD (trỏ đến cam kết mẹo của "thử nghiệm" trước khi hoạt động bắt đầu chạy) để trỏ đến mẹo của "chủ" - chúng tôi đang phục hồi nó.
- Cố gắng áp dụng từng cam kết đã lưu (như thể với
git apply
) theo thứ tự. Trong ví dụ đồ chơi của chúng tôi, nó chỉ là một cam kết, C3. Giả sử ứng dụng của nó sẽ tạo ra một cam kết C3 '.
- Nếu mọi việc suôn sẻ, tham chiếu "thử nghiệm" sẽ được cập nhật để trỏ đến cam kết có được từ việc áp dụng cam kết đã lưu cuối cùng (C3 'trong trường hợp của chúng tôi).
Bây giờ trở lại câu hỏi của bạn. Như bạn có thể thấy, ở đây thực sự về mặt kỹ thuật git rebase
cấy ghép một loạt các cam kết từ "thử nghiệm" đến mẹo của "bậc thầy", vì vậy bạn có thể biết chính xác rằng thực sự có "một nhánh khác" trong quá trình này. Nhưng ý chính là cam kết mẹo từ "thử nghiệm" đã trở thành cam kết mẹo mới trong "thử nghiệm", nó chỉ thay đổi cơ sở của nó:
Một lần nữa, về mặt kỹ thuật, bạn có thể nói rằng git rebase
ở đây đã kết hợp một số cam kết nhất định từ "chủ" và điều này hoàn toàn chính xác.