Git Cherry-pick vs Hợp nhất công việc


302

Giả sử tôi là người duy trì repo và tôi muốn thay đổi từ một người đóng góp, có một vài quy trình công việc có thể xảy ra:

  1. Tôi cherry-picktừng cam kết từ xa (theo thứ tự). Trong trường hợp này, git ghi lại các cam kết là không liên quan đến nhánh từ xa.
  2. Tôi mergelà chi nhánh, kéo theo tất cả các thay đổi và thêm một cam kết "xung đột" mới (nếu cần).
  3. Tôi mergetừng cam kết từ chi nhánh từ xa riêng lẻ (một lần nữa theo thứ tự), cho phép ghi lại xung đột cho từng cam kết, thay vì nhóm tất cả lại thành một.
  4. Để hoàn thiện, bạn có thể thực hiện rebase(giống như cherry-picktùy chọn?), Tuy nhiên sự hiểu biết của tôi là điều này có thể gây nhầm lẫn cho người đóng góp. Có lẽ điều đó loại bỏ tùy chọn 1.

Trong cả hai trường hợp 2 và 3, git ghi lại lịch sử chi nhánh của các xác nhận, không giống như 1.

Sự ủng hộ và lừa đảo giữa việc sử dụng một trong hai cherry-pickhoặc mergecác phương pháp được mô tả là gì? Sự hiểu biết của tôi là phương pháp 2 là chuẩn mực, nhưng tôi cảm thấy rằng việc giải quyết một cam kết lớn với một sự hợp nhất "xung đột", không phải là giải pháp sạch nhất.

Câu trả lời:


297

Cả rebase(và cherry-pick) và mergecó những lợi thế và bất lợi của họ. Tôi tranh luận mergeở đây, nhưng nó đáng để hiểu cả hai. (Xem ở đây để có một câu trả lời thay thế, tranh luận tốt, liệt kê các trường hợp rebaseđược ưu tiên.)

mergeđược ưa thích hơn cherry-pickrebasevì một vài lý do.

  1. Mạnh mẽ . Mã định danh SHA1 của một xác nhận xác định nó không chỉ trong và của chính nó mà còn liên quan đến tất cả các cam kết khác đi trước nó. Điều này cung cấp cho bạn một đảm bảo rằng trạng thái của kho lưu trữ tại một SHA1 đã cho là giống hệt nhau trên tất cả các bản sao. (Về lý thuyết) không có cơ hội ai đó đã thực hiện những gì trông giống như thay đổi nhưng thực sự là làm hỏng hoặc chiếm đoạt kho lưu trữ của bạn. Bạn có thể chọn cherry trong các thay đổi riêng lẻ và chúng có thể giống nhau, nhưng bạn không có gì đảm bảo. (Là một vấn đề thứ yếu nhỏ, các cam kết mới được chọn anh đào sẽ chiếm thêm không gian nếu người khác chọn anh đào trong cùng một cam kết, vì cả hai sẽ có mặt trong lịch sử ngay cả khi các bản sao làm việc của bạn kết thúc giống hệt nhau.)
  2. Dễ sử dụng . Mọi người có xu hướng hiểu mergequy trình làm việc khá dễ dàng. rebasecó xu hướng được coi là tiên tiến hơn. Tốt nhất là hiểu cả hai, nhưng những người không muốn trở thành chuyên gia kiểm soát phiên bản (mà theo kinh nghiệm của tôi đã bao gồm nhiều đồng nghiệp giỏi về những gì họ làm, nhưng không muốn dành thêm thời gian) thì dễ dàng hơn Thời gian chỉ hợp nhất.

Ngay cả với quy trình làm việc nặng rebasecherry-pickvẫn hữu ích cho các trường hợp cụ thể:

  1. Một nhược điểm mergelà lịch sử lộn xộn. rebasengăn chặn một loạt các cam kết bị phân tán trong lịch sử của bạn, như chúng sẽ xảy ra nếu bạn định kỳ hợp nhất trong các thay đổi của người khác. Thực tế đó là mục đích chính của nó khi tôi sử dụng nó. Những gì bạn muốn rất cẩn thận, là không bao giờ rebasemã mà bạn đã chia sẻ với các kho lưu trữ khác. Khi một cam kết được sửa pushđổi, một người khác có thể đã cam kết trên đó và việc phản đối sẽ gây ra sự trùng lặp tốt nhất ở trên. Tệ nhất là bạn có thể kết thúc với một kho lưu trữ rất bối rối và các lỗi tinh vi sẽ khiến bạn mất nhiều thời gian để thoát ra.
  2. cherry-pick là hữu ích để lấy mẫu một tập hợp nhỏ các thay đổi từ một nhánh chủ đề mà về cơ bản bạn đã quyết định loại bỏ, nhưng nhận ra có một vài phần hữu ích trên đó.

Đối với việc hợp nhất nhiều thay đổi trên một: nó đơn giản hơn nhiều. Có thể rất tẻ nhạt khi thực hiện việc hợp nhất các thay đổi riêng lẻ một khi bạn bắt đầu có nhiều thay đổi. Độ phân giải hợp nhất trong git (và trong Mercurial, và trong Bazaar) là rất rất tốt. Bạn sẽ không gặp phải vấn đề lớn khi sáp nhập các nhánh dài hầu hết thời gian. Tôi thường hợp nhất tất cả mọi thứ cùng một lúc và chỉ khi tôi nhận được một số lượng lớn các xung đột thì tôi mới sao lưu và chạy lại từng phần hợp nhất. Thậm chí sau đó tôi làm điều đó trong khối lớn. Như một ví dụ rất thực tế, tôi đã có một đồng nghiệp có 3 tháng thay đổi để hợp nhất và đã có 9000 xung đột trong cơ sở mã dòng 250000. Những gì chúng tôi đã làm để khắc phục là thực hiện hợp nhất giá trị một tháng tại một thời điểm: xung đột không xây dựng tuyến tính và thực hiện theo từng phần dẫn đến kết quả xaÍt hơn 9000 xung đột. Nó vẫn còn rất nhiều công việc, nhưng không nhiều bằng việc cố gắng thực hiện nó một lần.


1
Trên thực tế, về mặt lý thuyết, có khả năng Mallory có thể làm hỏng kho lưu trữ của bạn bằng cách tạo các cam kết với cùng một SHA1 nhưng nội dung khác nhau, điều đó có lẽ sẽ không bao giờ xảy ra trong thực tế. :)
Bombe

1
Ha :) Tôi có nghĩa là "trên lý thuyết tỷ lệ cược thấp đến mức bạn có thể dựa vào nó không xảy ra", nhưng bạn đã đúng rằng nó đọc topsy-turvy.
quark

Bạn nghĩ gì về "merge --squash"?
cmcginty

@Bombe Nếu Mallory muốn thành công, cô ấy sẽ phải xây dựng cụ thể cam kết ban đầu và cam kết thứ hai với cùng SHA1. Vì vậy, một câu hỏi khác có thể là: tỷ lệ cược của hai (phần nào) cam kết không có thật xuất hiện và bạn không nhận thấy? ;)
João Portela

64
9000 xung đột? Tôi đã nghỉ việc và trở thành một người nuôi ong.
Sebastian Patten

95

Theo tôi, việc hái anh đào nên được dành riêng cho các tình huống hiếm khi cần thiết, ví dụ nếu bạn đã khắc phục trực tiếp trên nhánh 'chính' (thân cây, nhánh phát triển chính) và sau đó nhận ra rằng nó cũng nên được áp dụng cho 'duy trì '. Bạn nên căn cứ vào quy trình làm việc hoặc hợp nhất hoặc trên rebase (hoặc "git pull --rebase").

Xin nhớ rằng cam kết được chọn hoặc bị từ chối khác với quan điểm của Git (có định danh SHA-1 khác) so với cam kết ban đầu, vì vậy nó khác với cam kết trong kho lưu trữ từ xa. (Rebase thường có thể xử lý vấn đề này, vì nó kiểm tra bản vá id tức là các thay đổi, không phải là id xác nhận).

Ngoài ra trong git bạn có thể hợp nhất nhiều nhánh cùng một lúc: được gọi là hợp nhất bạch tuộc . Lưu ý rằng hợp nhất bạch tuộc phải thành công mà không có xung đột. Tuy nhiên, nó có thể hữu ích.

HTH.


19
+1 cho điểm rebase / cherry cherry thực sự "sao chép" các cam kết và do đó mất liên kết với cam kết ban đầu.
studgeek

1
Chúng tôi sử dụng cherry-pick theo cách này, dành riêng để di chuyển các cam kết sửa lỗi (có thể là các tính năng RẤT NHỎ) vào một nhánh phát hành hiện có để chuẩn bị một bản vá. Các tính năng trải rộng trên nhiều cam kết thường đảm bảo sẽ đi vào một nhánh phát hành dựa trên chủ.
foxxtrot

3
@foxxtrot: Một giải pháp khác là tạo một nhánh riêng cho một lỗi, dựa trên cam kết cũ nhất thể hiện lỗi này và hợp nhất nó thành 'duy trì' và thành 'chủ' ... mặc dù trong trường hợp này bạn cần biết rằng đó là lỗi. áp dụng cho cả hai chi nhánh.
Jakub Narębski

4
@Jakub Hai lệnh không thể thiếu để tạo và hợp nhất một nhánh bugfix: git blameđể tìm cam kết giới thiệu lỗi và git branch --containsxác định nơi hợp nhất nhánh. Được mô tả chi tiết hơn trong bài đăng này
gcbenison

-10

Rebase và Cherry-pick là cách duy nhất bạn có thể giữ sạch lịch sử cam kết. Tránh sử dụng hợp nhất và tránh tạo xung đột hợp nhất. Nếu bạn đang sử dụng gerrit, hãy đặt một dự án thành Hợp nhất nếu cần thiết và một dự án ở chế độ chọn cherry và tự mình thử.


không rõ ràng làm thế nào điều này trả lời câu hỏi, có thể một số ví dụ sẽ mang lại một số ánh sáng.
Adrian Nasui

1
Thực tế là lịch sử của bạn sẽ nhìn thẳng không có nghĩa là nó sẽ dễ hiểu hơn.
nicolimo86

Sáp nhập là cách thông thường để có một lịch sử trong sạch. Cherry-pick và rebase chủ yếu được sử dụng cho các tình huống mà bạn phải sửa đổi lịch sử. Điều gì có nghĩa là sáp nhập phải luôn là lựa chọn đầu tiên. Nguyên nhân khiến rebase thay đổi, điều rất nguy hiểm khi bạn làm việc với điều khiển từ xa và nhiều người.
Radon8472

Anh chàng này ngay tại đây xứng đáng với một huy chương. Anh ấy biết rằng anh ấy sẽ tiếp tục bỏ phiếu nhưng đó là câu trả lời đúng. Thanh danh.
PW Kad

Xin lỗi tôi đã không thấy những bình luận này cho đến bây giờ, Vui lòng thử trong môi trường thử nghiệm của bạn trước khi kết luận và làm những gì phù hợp với bạn! Tôi có khoảng 600 nhà phát triển đóng góp cho nhiều chi nhánh sản phẩm. FYI ... Tôi sử dụng Gerrit.
Nagaraj Magadum
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.