Anh đào chọn một cam kết với Git có nghĩa là gì?


2339

Gần đây, tôi đã được yêu cầu cherry-pickmột cam kết.

Vì vậy, anh đào chọn một cam kết trong git có nghĩa là gì? Bạn làm nó như thế nào?


13
Thay vì hợp nhất, với việc chọn lại anh đào từ một nhánh sang nhánh đích (ví dụ: master) sẽ dễ dàng hơn.
Levent Divilioglu

Câu trả lời:


2858

Chọn anh đào trong Git có nghĩa là chọn một cam kết từ một chi nhánh và áp dụng nó lên một chi nhánh khác.

Điều này trái ngược với các cách khác như mergerebasethường áp dụng nhiều cam kết lên một nhánh khác.

  1. Hãy chắc chắn rằng bạn đang ở chi nhánh mà bạn muốn áp dụng cam kết.

    git checkout master
    
  2. Thực hiện như sau:

    git cherry-pick <commit-hash>
    

Lưu ý:

  1. Nếu bạn chọn cherry từ một chi nhánh công cộng, bạn nên cân nhắc sử dụng

    git cherry-pick -x <commit-hash>
    

    Điều này sẽ tạo ra một thông điệp cam kết tiêu chuẩn. Bằng cách này, bạn (và đồng nghiệp của bạn) vẫn có thể theo dõi nguồn gốc của cam kết và có thể tránh xung đột hợp nhất trong tương lai.

  2. Nếu bạn có ghi chú kèm theo cam kết, họ không tuân theo lựa chọn anh đào. Để mang lại cho họ, bạn phải sử dụng:

    git notes copy <from> <to>
    

Liên kết bổ sung:


247
Nếu bạn chọn cherry từ một chi nhánh công cộng, bạn nên xem xét sử dụng git cherry-pick -x <commit-hash>. Điều này sẽ tạo ra một thông điệp cam kết tiêu chuẩn. Bằng cách này, bạn (và đồng nghiệp của bạn) vẫn có thể theo dõi nguồn gốc của cam kết và có thể tránh xung đột hợp nhất trong tương lai.
MBober

2
Là hái anh đào thực sự cần thiết? Không phải là thiết lập lại hỗn hợp hoặc thiết lập lại mềm làm một công việc tương tự?
Nav

10
Lưu ý rằng nếu bạn có ghi chú kèm theo cam kết thì chúng không tuân theo lựa chọn anh đào. Bạn phải sử dụng git notes copy <from> <to>để mang lại cho họ là tốt.
Zitrax

5
git đẩy là bước cuối cùng để thay đổi chủ
cảm thấy tốt và lập trình

58
FYI: Một cam kết ngữ nghĩa chứa tất cả các file của cây làm việc của thời điểm đó (và các cam kết hash của trước đó cam kết), do đó bạn không phải áp dụng một tổng thể cam kết một cam kết, nhưng thay đổi một cam kết đã làm trên trước cam kết "cherry-pick commit applies the changes introduced by the named commit on the current branch"Hầu hết ppl có xu hướng nghĩ về cam kết là những thay đổi (như svn là iirc), nhưng thực tế không phải vậy, mỗi cam kết đều đề cập đến cây làm việc hoàn chỉnh. Mặc dù điều này không tạo ra sự khác biệt trong trường hợp này, nhưng nó có thể giúp hiểu được lý do tại sao git hoạt động như vậy.
Emile Vrijdags

314

Trích dẫn này được lấy từ; Kiểm soát phiên bản với Git (Cuốn sách thực sự tuyệt vời, tôi khuyến khích bạn mua nó nếu bạn quan tâm đến git)

Chỉnh sửa: Vì câu trả lời này vẫn đang được hiển thị, tôi muốn thêm rất hay trong hướng dẫn bằng video hành động về nó:

Youtube: Giới thiệu về Git cherry-pick

Sử dụng git cherry-pick Lệnh git cherry-pick commit áp dụng các thay đổi được giới thiệu bởi cam kết có tên trên nhánh hiện tại. Nó sẽ giới thiệu một cam kết mới, khác biệt. Nói đúng ra, sử dụng git cherry-pick không làm thay đổi lịch sử hiện có trong kho lưu trữ; thay vào đó, nó thêm vào lịch sử. Cũng như các hoạt động Git khác giới thiệu các thay đổi thông qua quá trình áp dụng khác biệt, bạn có thể cần giải quyết xung đột để áp dụng đầy đủ các thay đổi từ cam kết đã cho . Lệnh git cherry-pick thường được sử dụng để giới thiệu các cam kết cụ thể từ một nhánh trong kho lưu trữ lên một nhánh khác. Một cách sử dụng phổ biến là chuyển tiếp hoặc cổng sau cam kết từ nhánh bảo trì sang nhánh phát triển.

$ git checkout rel_2.3
$ git cherry-pick dev~2 # commit F, above

trước: trước

sau: sau


12
khi các cam kết hái anh đào được thực hiện trên một số chi nhánh (b1) và sau đó được giao cho chủ. Và nếu nhánh b1 (từ đó xác nhận ban đầu được chọn) cũng sẽ được gửi đến chủ. Làm thế nào về các xung đột? Được chăm sóc hay làm thế nào nó hoạt động?
ký sinh

3
@parasrish Vâng, họ đã được chăm sóc với sự hợp nhất trước đó của bạn. Vì vậy, bạn đã thay đổi a, b, c, d từ nhánh (b1). Bạn cherry chỉ chọn "c". Sau đó, trong tương lai khi bạn hợp nhất từ ​​(b1) thành chủ, vì các thay đổi "c" là như nhau, nó sẽ chỉ hợp nhất các thay đổi a, b, d và vẫn là "c". Nhưng nếu bạn khôi phục sự hợp nhất của mình, thì bạn sẽ quay lại các thay đổi với "c" trong đó. Bạn sẽ cần phải cuộn chúng lại một cách riêng biệt.
Teoman shipahi

12
Cần nhấn mạnh: Trong ví dụ như đã cho, chỉ có sự khác biệt (F - E) được áp dụng cho Z. Đó là một trường hợp hẹp. Cherry-pick có thể được sử dụng để áp dụng sự khác biệt của nhiều cam kết, giả sử, tất cả sự khác biệt giữa hai cam kết không liền kề. Ví dụ: theo sau từ trên, (F - E), (E - D), (D - C) và (C - B). Điều đó tương đương với việc áp dụng sự khác biệt (F - B).
Thomas Bitonti

2
Ngoài ra, điều gì xảy ra nếu Cam kết được chọn (trong ví dụ) có nhiều hơn một tiền thân trực tiếp?
Thomas Bitonti

2
@ j2emanue nói cách khác, cherry-pick sẽ chỉ thực hiện các thay đổi của cam kết cuối cùng. Nếu bạn cam kết 3 lần khác nhau và nếu bạn chọn lần cuối, bạn sẽ không thay đổi lần cam kết thứ nhất và lần thứ hai. Lệnh Hợp nhất sẽ thực hiện tất cả các thay đổi của bạn và áp dụng cho nhánh mục tiêu (chính) của bạn.
Teoman shipahi

157

Chọn anh đào trong Git được thiết kế để áp dụng một số cam kết từ một chi nhánh vào một chi nhánh khác. Nó có thể được thực hiện nếu bạn ví dụ. đã phạm sai lầm và cam kết thay đổi thành chi nhánh sai, nhưng không muốn hợp nhất toàn bộ chi nhánh. Bạn chỉ có thể ví dụ. hoàn nguyên cam kết và chọn anh đào trên một nhánh khác.

Để sử dụng nó, bạn chỉ cần git cherry-pick hash, nơi hashlà một cam kết băm từ chi nhánh khác.

Để biết quy trình đầy đủ, hãy xem: http://technosophos.com/2009/12/04/git-cherry-picking-move-small-code-patches-across-branches.html


96

Ví dụ ngắn về tình huống, khi bạn cần hái cherry

Hãy xem xét kịch bản sau đây. Bạn có hai chi nhánh.

a) phát hành1 - Chi nhánh này sẽ đến tay khách hàng của bạn, nhưng vẫn còn một số lỗi cần khắc phục.

b) master - Nhánh master cổ điển, nơi bạn có thể thêm chức năng để phát hành2.

BÂY GIỜ : Bạn sửa một cái gì đó trong bản phát hành1 . Tất nhiên bạn cần sửa lỗi này cũng trong chủ . Và đó là một trường hợp sử dụng điển hình cho việc hái anh đào. Vì vậy, anh đào chọn trong trường hợp này có nghĩa là bạn phải mất một cam kết từ release1 chi nhánh và đưa nó vào tổng chi nhánh.


3
Bạn có thể chỉ cần cách khác. Bạn đã sửa một lỗi trong master và bạn nên chọn nó để phát hành1. Ngoài ra, chúng có thể là kho lưu trữ chứ không phải là chi nhánh
canbax

1
Tại sao không sử dụng hợp nhất cho nó?
FreeLightman

Tôi sẽ: tạo nhánh tắt phát hành, sửa nó trong nhánh, hợp nhất nhánh trong phát hành, hợp nhất phát hành trong master.
Jasper-M

57

cherry-pick là một tính năng Git. Nếu ai đó muốn Cam kết cụ thể các cam kết trong một nhánh cho một nhánh mục tiêu, thì cherry-pick được sử dụng.
bước git cherry-pick như dưới đây.

  1. kiểm tra (chuyển sang) chi nhánh mục tiêu.
  2. git cherry-pick <commit id>
    

    Ở đây id id là id hoạt động của một nhánh khác.Eg.

    git cherry-pick 9772dd546a3609b06f84b680340fb84c5463264f
    
  3. đẩy đến nhánh mục tiêu

Truy cập https://git-scm.com/docs/git-cherry-pick


43

Tôi đã chuẩn bị các hình minh họa từng bước những gì cherry-pick làm - và một hình ảnh động của những hình minh họa này (gần cuối).

  1. Trước khi cherry-hái
    (chúng ta sẽ làm một anh đào-chọn của cam kết Ltừ các chi nhánh feature): nhập mô tả hình ảnh ở đây

  1. Bắt đầu lệnh git cherry-pick feature~2
    ( feature~2là lần xác nhận thứ 2 trước đó
    feature, tức là lần xác nhận L): nhập mô tả hình ảnh ở đây

  1. Sau khi thực hiện lệnh ( git cherry-pick feature~2): nhập mô tả hình ảnh ở đây

Hoạt hình tương tự: nhập mô tả hình ảnh ở đây


Ghi chú:

Cam kết L'từ quan điểm của người dùng (commit = snapshot) bản sao chính xác của cam kết L.

Về mặt kỹ thuật (bên trong), đó là một cam kết mới, khác biệt (vì ví dụ: Lchứa một con trỏ tới K(như cha mẹ của nó), trong khi L'chứa một con trỏ tới E).


Có nghĩa là, L 'sẽ là N -> M -> L trên nhánh chính? hoặc nó sẽ độc quyền mang lại cam kết L trên nhánh chính
Priyank Thakkar

1
@PriyankThakkar, vâng, độc quyền L , không có gì khác (như bạn có thể thấy từ hình ảnh / hoạt hình).
MarianD

22

Bạn có thể nghĩ nếu một quả anh đào giống như một cuộc nổi loạn, hay đúng hơn là nó được quản lý như một cuộc nổi loạn. Bằng cách này, tôi có nghĩa là nó cần một cam kết hiện có và tái tạo nó, như là điểm khởi đầu, người đứng đầu chi nhánh mà bạn hiện đang ở.

A rebasenhận một cam kết có cha mẹ X và tạo lại cam kết như thể nó thực sự có cha mẹ Y, và đây chính xác là những gì a cherry-picklàm.

Cherry pick là nhiều hơn về cách bạn chọn các cam kết. Với pull(rebase), git hoàn toàn tái tạo các cam kết cục bộ của bạn trên đầu của những gì được kéo đến chi nhánh của bạn, nhưng với cherry-pickbạn rõ ràng chọn một số (các) cam kết và tái tạo nó (chúng) trên đầu chi nhánh hiện tại của bạn.

Vì vậy, cách bạn thực hiện nó khác nhau, nhưng dưới mui xe, chúng là các hoạt động rất giống nhau - tái tạo các cam kết.


1
Tôi thấy đây là một cái nhìn khá hữu ích về mọi thứ. Nó ngụ ý tại sao cherry-pickhành xử theo cách nó làm khi nhánh đích sau đó được sáp nhập trở lại vào nhánh nguồn. Cảm ơn ngài.
Aluan Haddad

3
tôi muốn sử dụng cherry pick thay vì git merge sau khi một tính năng được thực hiện. mọi người luôn thực hiện git merge Feature_branch khi họ hoàn thành một tính năng. Tại sao không sử dụng lệnh cherry-pick? Bạn có suy nghĩ gì không? Tại sao lại phải
vắt kiệt sức

11

Nó giống như Sao chép (từ một nơi nào đó) và Dán (đến một nơi nào đó), nhưng đối với các cam kết cụ thể.

Nếu bạn muốn thực hiện một sửa chữa nóng, ví dụ, sau đó bạn có thể sử dụng cherry-picktính năng này.

Làm việc của bạn cherry-picktrong một nhánh phát triển và mergecam kết với một nhánh phát hành. Tương tự như vậy, làm một cherry-picktừ một nhánh phát hành để làm chủ. Voila


11

Khi bạn đang làm việc với một nhóm các nhà phát triển trong một dự án, việc quản lý các thay đổi giữa một số nhánh git có thể trở thành một nhiệm vụ phức tạp. Đôi khi bạn không muốn hợp nhất cả một chi nhánh thành một chi nhánh khác và chỉ cần chọn một hoặc hai cam kết cụ thể. Quá trình này được gọi là "hái anh đào".

Tìm thấy một bài viết tuyệt vời về hái anh đào, kiểm tra nó để biết chi tiết chuyên sâu: https://www.preinglynext.com.au/blog/intro-cherry-picking-git


7

Nếu bạn muốn hợp nhất mà không có id xác nhận, bạn có thể sử dụng lệnh này

git cherry-pick master~2 master~0

Lệnh trên sẽ hợp nhất ba lần xác nhận cuối cùng của chủ từ 1 đến 3

Nếu bạn muốn làm điều này cho một lần xác nhận, chỉ cần xóa tùy chọn cuối cùng

git cherry-pick master~2

Bằng cách này, bạn sẽ hợp nhất cam kết thứ 3 từ cuối của chủ.


Điều này thật khó hiểu. Tôi nghĩ ở đây bạn đang ở một nhánh khác ngoài chủ, phải không? Và khi bạn đề cập đến hai cam kết bạn đang đề cập đến các cam kết <từ> và <đến> để xác định phạm vi bạn muốn chọn cherry. Chính xác? Nó sẽ giúp rất nhiều nếu kịch bản được mô tả. Ngoài ra tốt. Cảm ơn.
Saurabh Patil

6

Nó sẽ áp dụng một cam kết cụ thể cho chi nhánh hiện tại của bạn.

Điều này có nghĩa là :

  • tất cả các tệp được thêm bởi cam kết này sẽ được thêm vào
  • tất cả các tệp bị xóa bởi cam kết này sẽ bị xóa
  • tất cả các tệp được sửa đổi bởi cam kết này sẽ được hợp nhất. Điều này có nghĩa là toàn bộ tệp từ cam kết, không chỉ những thay đổi từ cam kết này!

Vd: Xem xét cam kết A

added newFileA
modified main:
+ import './newFileA'

cam kết B

added newFileB
modified main:
+ import './newFileB'

Nếu bạn chọn cam kết B trên một chi nhánh khác, bạn sẽ kết thúc bằng:

/newFileB
/main :
   import './newFileA'
   import './newFileB'

cam kết B chứa newFileBmain , nhưng không có newFileA , dẫn đến lỗi, vì vậy hãy thận trọng khi sử dụng.


0

Trích từ các tài liệu chính thức:

Đưa ra một hoặc nhiều cam kết hiện có, áp dụng thay đổi từng cam kết giới thiệu, ghi lại một cam kết mới cho mỗi cam kết. Điều này đòi hỏi cây làm việc của bạn phải sạch (không có sửa đổi từ cam kết CHÍNH).

Khi không rõ ràng làm thế nào để áp dụng thay đổi, điều sau đây xảy ra:

  1. Chi nhánh hiện tại và con trỏ CHÍNH ở lần xác nhận cuối cùng được thực hiện thành công.

  2. Tham chiếu CHERRY_PICK_HEAD được đặt để chỉ vào cam kết giới thiệu thay đổi khó áp dụng.

  3. Các đường dẫn trong đó thay đổi được áp dụng sạch sẽ được cập nhật cả trong tệp chỉ mục và trong cây làm việc của bạn.

  4. Đối với các đường dẫn xung đột, tệp chỉ mục ghi lại tối đa ba phiên bản, như được mô tả trong phần "TRUE MERGE" của git-merge. Các tệp cây làm việc sẽ bao gồm một mô tả về xung đột được đặt trong các dấu xung đột thông thường <<<<<<< và >>>>>>>.

Không có sửa đổi khác được thực hiện.

Đọc thêm...

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.