การเก็บเชอร์รี่กับ Git หมายถึงอะไร


2338

เมื่อเร็ว ๆ นี้ฉันถูกขอให้cherry-pickกระทำ

ดังนั้นการเก็บเชอร์รี่ในคอมไพล์หมายความว่าอย่างไร คุณจะทำอย่างไรมันได้หรือไม่?


13
แทนที่จะรวมกันด้วยการหยิบเชอร์รี่ที่รับจากสาขาไปยังสาขาเป้าหมาย (เช่น: หลัก) นั้นง่ายกว่า
Levent Divilioglu

คำตอบ:


2857

การเลือกเชอร์รี่ใน Git หมายถึงการเลือกคำสั่งจากสาขาหนึ่งและนำไปใช้กับสาขาอื่น

สิ่งนี้ตรงกันข้ามกับวิธีอื่น ๆ เช่นmergeและrebaseโดยปกติแล้วจะใช้ความมุ่งมั่นมากมายในสาขาอื่น

  1. ตรวจสอบให้แน่ใจว่าคุณอยู่ในสาขาที่คุณต้องการใช้คำสั่ง

    git checkout master
    
  2. ดำเนินการต่อไปนี้:

    git cherry-pick <commit-hash>
    

หมายเหตุ:

  1. ถ้าคุณเลือกเชอร์รี่จากสาขาสาธารณะคุณควรพิจารณาใช้

    git cherry-pick -x <commit-hash>
    

    สิ่งนี้จะสร้างข้อความยืนยันมาตรฐาน วิธีนี้คุณ (และเพื่อนร่วมงานของคุณ) ยังสามารถติดตามที่มาของการกระทำและอาจหลีกเลี่ยงการรวมความขัดแย้งในอนาคต

  2. หากคุณมีบันทึกย่อที่แนบมากับความมุ่งมั่นพวกเขาจะไม่ทำตามเชอร์รี่เลือก หากต้องการนำมาไว้ด้วยคุณต้องใช้:

    git notes copy <from> <to>
    

ลิงก์เพิ่มเติม:


247
git cherry-pick -x <commit-hash>หากคุณเชอร์รี่เลือกจากสาขาสาธารณะคุณควรพิจารณาการใช้ สิ่งนี้จะสร้างข้อความยืนยันมาตรฐาน วิธีนี้คุณ (และเพื่อนร่วมงานของคุณ) ยังสามารถติดตามที่มาของการกระทำและอาจหลีกเลี่ยงการรวมความขัดแย้งในอนาคต
MBober

2
การเก็บเชอร์รี่จำเป็นจริงๆหรือ? การรีเซ็ตแบบผสมหรือการรีเซ็ตแบบอ่อนจะไม่ทำงานที่คล้ายกันหรือไม่
Nav

10
โปรดทราบว่าถ้าคุณมีบันทึกย่อที่แนบมากับการส่งคำสั่งพวกเขาจะไม่ติดตามเชอร์รี่ คุณต้องใช้git notes copy <from> <to>เพื่อนำพวกเขาไปด้วยเช่นกัน
Zitrax

5
git push เป็นขั้นตอนสุดท้ายในการเปลี่ยนแปลงต้นแบบ
รู้สึกดีและเขียนโปรแกรม

58
FYI: การกระทำความหมายมีไฟล์ทั้งหมดของต้นไม้ในการทำงานของช่วงเวลานั้น (และกระทำกัญชาของก่อนหน้านี้กระทำ) ดังนั้นคุณจะไม่ได้ใช้ทั้งกระทำการอื่นกระทำ แต่การเปลี่ยนแปลงกระทำได้ในก่อนหน้านี้กระทำ"cherry-pick commit applies the changes introduced by the named commit on the current branch"ส่วนใหญ่ ppl มีแนวโน้มที่จะคิดว่าการกระทำเป็นการเปลี่ยนแปลง (เช่น svn คือ iirc) แต่ไม่ใช่การกระทำแต่ละหมายถึงต้นไม้การทำงานที่สมบูรณ์ แม้ว่านี่จะไม่ได้สร้างความแตกต่างในกรณีนี้ แต่ก็สามารถช่วยในการทำความเข้าใจว่าทำไมคอมไพล์ทำงานเหมือน
Emile Vrijdags

314

คำพูดนี้นำมาจาก; การควบคุมเวอร์ชันด้วย Git (หนังสือยอดเยี่ยมจริง ๆ ฉันแนะนำให้คุณซื้อถ้าคุณสนใจ git)

แก้ไข: เนื่องจากคำตอบนี้ยังคงได้รับความประทับใจฉันต้องการเพิ่มดีมากในวิดีโอสอนเกี่ยวกับมัน:

Youtube: รู้เบื้องต้นเกี่ยวกับ Git cherry-pick

การใช้ git cherry-pick คำสั่ง git cherry-pick กระทำการเปลี่ยนแปลงที่แนะนำโดย commit ที่มีชื่อในสาขาปัจจุบัน มันจะแนะนำการกระทำใหม่ที่แตกต่าง การพูดอย่างเคร่งครัดโดยใช้ git cherry-pick จะไม่เปลี่ยนประวัติที่มีอยู่ในที่เก็บ มันจะเพิ่มเข้าไปในประวัติศาสตร์แทน เช่นเดียวกับการดำเนินการอื่น ๆ ของ Git ที่แนะนำการเปลี่ยนแปลงผ่านกระบวนการของการใช้ diff คุณอาจต้องแก้ไขข้อขัดแย้งเพื่อใช้การเปลี่ยนแปลงที่เกิดขึ้นจากการกระทำที่ให้ไว้ คำสั่ง git cherry-pick มักใช้เพื่อแนะนำการคอมมิตเฉพาะจากหนึ่งสาขาภายในที่เก็บไปยังสาขาอื่น การใช้งานทั่วไปคือการส่งต่อหรือพอร์ตย้อนกลับมุ่งหน้าจากสาขาการบำรุงรักษาไปยังสาขาการพัฒนา

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

ก่อน: ก่อน

หลังจาก: หลังจาก


12
เมื่อกระทำการเชอร์รี่ที่หยิบมาถูกนำไปใช้ในบางสาขา (b1) และส่งต่อไปยังต้นแบบ และถ้าสาขา b1 (จากการเลือกกระทำที่ได้รับมา แต่เดิม) ก็พยายามที่จะส่งไปยังต้นแบบ แล้วความขัดแย้งล่ะ? นั่นเป็นสิ่งที่ได้รับการดูแลหรือมันทำงานอย่างไร?
ปรสิต

3
@parasrish ใช่พวกเขาได้รับการดูแลจากการรวมก่อนหน้านี้ของคุณแล้ว ดังนั้นคุณจึงเปลี่ยนสาขา a, b, c, d จาก (b1) คุณเชอร์รี่เลือกเฉพาะ "c" จากนั้นในอนาคตเมื่อคุณรวมจาก (b1) เป็นหลักเนื่องจากการเปลี่ยนแปลง "c" เหมือนกันจะเป็นการรวม a, b, d และการเปลี่ยนแปลง "c" เท่านั้น แต่ถ้าคุณย้อนกลับการผสานคุณจะกลับไปเปลี่ยนแปลงด้วย "c" ในนั้น คุณจะต้องย้อนกลับแยกกัน
Teoman shipahi

12
ควรเน้น: ในตัวอย่างตามที่กำหนดจะใช้เฉพาะความแตกต่าง (F - E) กับ Z ซึ่งเป็นกรณีที่แคบ Cherry-pick อาจถูกนำมาใช้เพื่อใช้ความแตกต่างของคอมมิทหลายคอมเม้นท์ทั้งหมดของความแตกต่างระหว่างคอมมิทที่ไม่ติดกันสองคอมมิท ตัวอย่างเช่นจากข้างบน, (F - E), (E - D), (D - C) และ (C - B) นั่นเท่ากับการใช้ความแตกต่าง (F - B)
โทมัส Bitonti

2
นอกจากนี้จะเกิดอะไรขึ้นถ้า Commit ที่เลือก (ในตัวอย่าง) มีมากกว่ารุ่นก่อนหน้ามากกว่าหนึ่งคน
โทมัส Bitonti

2
@ j2emanue ในคำอื่น ๆ เชอร์รี่เลือกจะใช้การเปลี่ยนแปลงล่าสุดกระทำ หากคุณส่งมอบ 3 ครั้งและหากคุณเลือกซื้อครั้งสุดท้ายจะไม่ทำการเปลี่ยนแปลงในครั้งแรกและครั้งที่สอง คำสั่งผสานจะทำการเปลี่ยนแปลงทั้งหมดของคุณและนำไปใช้กับสาขาเป้าหมาย (ต้นแบบ) ของคุณ
Teoman shipahi

157

การเก็บเชอร์รี่ใน Git ได้รับการออกแบบมาเพื่อใช้ความมุ่งมั่นจากสาขาหนึ่งไปยังสาขาอื่น สามารถทำได้หากคุณเช่น ทำผิดพลาดและมุ่งมั่นที่จะเปลี่ยนเป็นสาขาที่ไม่ถูกต้อง แต่ไม่ต้องการรวมทั้งสาขา คุณสามารถทำได้เช่น ย้อนกลับการกระทำและเชอร์รี่เลือกในสาขาอื่น

ที่จะใช้มันคุณเพียงแค่ต้องgit cherry-pick hashที่hashจะกระทำกัญชาจากสาขาอื่น ๆ

สำหรับขั้นตอนทั้งหมดโปรดดูที่: http://technosophos.com/2009/12/04/git-cherry-picking-move-small-code-patches-across-branches.html


96

ตัวอย่างสั้น ๆ ของสถานการณ์เมื่อคุณต้องการรับเชอร์รี่

พิจารณาสถานการณ์สมมติต่อไปนี้ คุณมีสองสาขา

a) release1 - สาขานี้จะให้ลูกค้าของคุณ แต่ยังคงมีข้อบกพร่องบางอย่างที่จะได้รับการแก้ไข

b) master - สาขามาสเตอร์คลาสสิกที่คุณสามารถเพิ่มฟังก์ชันการทำงานสำหรับ release2

ตอนนี้ : คุณแก้ไขปัญหาบางอย่างในrelease1 แน่นอนว่าคุณต้องมีการแก้ไขนี้เป็นหลักเช่นกัน และนั่นเป็นกรณีใช้งานทั่วไปสำหรับเก็บเชอร์รี่ ดังนั้นการเลือกเชอร์รี่ในสถานการณ์นี้หมายความว่าคุณรับการส่งมอบจากสาขาrelease1และรวมเข้าไปในสาขาหลัก


3
คุณอาจต้องการวิธีอื่น คุณแก้ไขข้อผิดพลาดในต้นแบบและคุณควรเลือกมันเพื่อปล่อย 1 นอกจากนี้พวกเขาอาจจะเป็นที่เก็บมากกว่าสาขา
canbax

1
ทำไมไม่ใช้การผสานมัน
ฟรีไลท์แมน

ฉันต้องการ: สร้าง branch off release, แก้ไขใน branch, รวม branch ใน release, ผสาน release ใน master
Jasper-M

57

cherry-pick เป็นคุณสมบัติของ Git หากมีคนต้องการที่จะกระทำการกระทำที่เฉพาะเจาะจงในสาขาเดียวไปยังสาขาเป้าหมายจะใช้เชอร์รี่เลือก
คอมไพล์ขั้นตอนเชอร์รี่รับมีดังนี้

  1. ชำระเงิน (เปลี่ยนเป็น) สาขาเป้าหมาย
  2. git cherry-pick <commit id>
    

    คอมมิทกระทำนี่คือรหัสกิจกรรมของสาขาอื่น.

    git cherry-pick 9772dd546a3609b06f84b680340fb84c5463264f
    
  3. ผลักดันไปยังสาขาเป้าหมาย

เยี่ยมชมhttps://git-scm.com/docs/git-cherry-pick


43

ฉันเตรียมภาพประกอบทีละขั้นตอนที่เชอร์รี่เลือกทำ - และภาพเคลื่อนไหวของภาพประกอบเหล่านี้ (ใกล้ถึงจุดสิ้นสุด)

  1. ก่อนที่เชอร์รี่แคะ
    (เราจะไปทำเชอร์รี่เลือกของการกระทำLจากสาขาfeature): ป้อนคำอธิบายรูปภาพที่นี่

  1. เริ่มต้นคำสั่งgit cherry-pick feature~2
    ( feature~2เป็น 2 ครั้งที่กระทำก่อน
    featureคือกระทำL): ป้อนคำอธิบายรูปภาพที่นี่

  1. หลังจากดำเนินการคำสั่ง ( git cherry-pick feature~2): ป้อนคำอธิบายรูปภาพที่นี่

ภาพเคลื่อนไหวเดียวกัน: ป้อนคำอธิบายรูปภาพที่นี่


บันทึก:

กระทำL'คือจากจุดที่ผู้ใช้ในมุมมองของ (= กระทำ snapshot)Lสำเนาถูกต้องของการกระทำ

ในทางเทคนิค (ภายใน) มันเป็นคอมมิชชันใหม่ที่แตกต่างกัน (เพราะเช่นLมีตัวชี้ไปที่K(เป็นพาเรนต์) ในขณะที่L'มีตัวชี้ไปยังE)


มันหมายความว่า L 'จะเป็น N -> M -> L ในสาขาหลัก? มิฉะนั้นจะนำมาซึ่งการกระทำ L ในสาขาหลักโดยเฉพาะ
Priyank Thakkar

1
@PriyankThakkar ใช่เฉพาะ Lไม่มีอะไร (ตามที่คุณเห็นจากรูปภาพ / อนิเมชั่น)
MarianD

22

คุณสามารถคิดว่าถ้าเชอร์รี่เลือกเป็นเหมือนการลดราคาหรือค่อนข้างจะจัดการเช่นการลดราคา โดยสิ่งนี้ฉันหมายความว่ามันใช้ความมุ่งมั่นที่มีอยู่และสร้างมันใหม่รับเป็นจุดเริ่มต้นหัวของสาขาที่คุณกำลัง

A rebaseรับค่าคอมมิชชันที่มีพาเรนต์ X และสร้างการคอมมิทใหม่ราวกับว่ามันมีพาเรนต์ Y และนี่คือสิ่งที่cherry-pickทำ

เชอร์รี่เลือกเป็นมากกว่าเกี่ยวกับวิธีที่คุณเลือกกระทำ ด้วยpull(rebase) คอมไพล์จะสร้างค่าคอมมิชชันท้องถิ่นของคุณขึ้นมาใหม่บนสิ่งที่ถูกดึงไปยังสาขาของคุณ แต่ด้วยการที่cherry-pickคุณเลือกกระทำอย่างชัดเจนและสร้างมันขึ้นมาใหม่โดยปริยายบนสาขาปัจจุบันของคุณ

ดังนั้นวิธีที่คุณทำแตกต่างกัน แต่ภายใต้ประทุนพวกเขามีการดำเนินงานที่คล้ายกันมาก - การงอกใหม่ของความมุ่งมั่น


1
ฉันคิดว่านี่เป็นมุมมองที่เป็นประโยชน์สำหรับสิ่งต่าง ๆ มันบอกเป็นนัยว่าทำไมมันcherry-pickทำงานอย่างไรเมื่อสาขาเป้าหมายถูกรวมกลับเข้าไปในสาขาต้นทางในภายหลัง ขอบคุณครับ
Aluan Haddad

3
ฉันต้องการใช้ Cherry Pick แทนที่จะเป็นคอมไพล์ผสานหลังจากคุณสมบัติเสร็จสิ้น ทุกคนมักจะคอมไพล์ผสาน feature_branch เมื่อพวกเขาเสร็จสิ้นคุณสมบัติ ทำไมไม่ใช้คำสั่ง cherry-pick? คุณมีความคิดใด ๆ หรือไม่เหตุใดจึงไม่ต้องมายุ่งกับการบีบถ้าฉันสามารถเก็บเชอร์รี่ได้
j2emanue

11

มันเป็นเหมือน Copy (จากที่อื่น) และ Paste (ไปยังที่อื่น) แต่สำหรับคอมมิทเฉพาะ

หากคุณต้องการแก้ไขcherry-pickด่วนเช่นคุณสามารถใช้คุณสมบัติได้

ทำของคุณcherry-pickในสาขาการพัฒนาและmergeที่มุ่งมั่นที่จะปล่อยสาขา ในทำนองเดียวกันทำcherry-pickจากสาขาที่วางจำหน่ายถึงต้นแบบ voila


11

เมื่อคุณทำงานกับทีมนักพัฒนาในโครงการการจัดการการเปลี่ยนแปลงระหว่างสาขา git จำนวนมากอาจกลายเป็นงานที่ซับซ้อน บางครั้งคุณไม่ต้องการรวมสาขาทั้งหมดเข้ากับสาขาอื่นและจำเป็นต้องเลือกการกระทำที่เฉพาะเจาะจงหนึ่งหรือสองครั้ง กระบวนการนี้เรียกว่า 'การเก็บเชอร์รี่'

พบบทความยอดเยี่ยมเกี่ยวกับการเก็บเชอร์รี่ตรวจสอบรายละเอียดเชิงลึกได้ที่: https://www.previousnext.com.au/blog/intro-cherry-picking-git


7

หากคุณต้องการผสานโดยไม่ต้องผูกรหัสคุณสามารถใช้คำสั่งนี้

git cherry-pick master~2 master~0

คำสั่งดังกล่าวจะรวมการผูกพันหลักสามครั้งสุดท้ายจาก 1 ถึง 3

หากคุณต้องการทำสิ่งนี้เพียงครั้งเดียวให้ลบตัวเลือกสุดท้าย

git cherry-pick master~2

วิธีนี้คุณจะรวมการคอมมิชชันที่ 3 จากจุดสิ้นสุดของมาสเตอร์


นี่คือความสับสน ฉันคิดว่าที่นี่คุณอยู่ในสาขาอื่นที่ไม่ใช่เจ้านายใช่มั้ย และเมื่อคุณพูดถึงการกระทำสองอย่างคุณจะหมายถึง <from> และ <to> มุ่งมั่นที่จะกำหนดช่วงที่คุณต้องการให้เชอร์รี่เลือก แก้ไข? มันจะช่วยได้อย่างมากหากมีการอธิบายสถานการณ์ นอกจากนี้ที่ดีแม้ว่า ขอบคุณ
Saurabh Patil

6

มันจะใช้ความมุ่งมั่นเฉพาะกับสาขาปัจจุบันของคุณ

หมายความว่า:

  • ไฟล์ทั้งหมดที่เพิ่มโดยการกระทำนี้จะถูกเพิ่ม
  • ไฟล์ทั้งหมดที่ถูกลบโดยคอมมิชชันนี้จะถูกลบ
  • ไฟล์ทั้งหมดที่แก้ไขโดยคอมมิชชันนี้จะถูกรวมเข้าด้วยกัน ซึ่งหมายความว่าไฟล์ทั้งหมดจากการกระทำไม่เพียง แต่การเปลี่ยนแปลงจากการกระทำนี้!

Ex: พิจารณากระทำ

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

กระทำ B

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

หากคุณเลือกรับเชอร์รี่ Bในสาขาอื่นคุณจะพบกับ:

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

ตั้งแต่คอมมิทBมีnewFileBและmainแต่ไม่มีnewFileAทำให้เกิดบั๊กดังนั้นควรใช้ด้วยความระมัดระวัง


0

ตัดตอนมาจากเอกสารอย่างเป็นทางการ:

รับคอมมิชชันที่มีอยู่ตั้งแต่หนึ่งรายการขึ้นไปใช้การเปลี่ยนแปลงที่แนะนำแต่ละรายการบันทึกการกระทำใหม่ สิ่งนี้ต้องการให้ต้นไม้ทำงานของคุณต้องสะอาด (ไม่มีการดัดแปลงจาก HEAD commit)

เมื่อไม่ชัดเจนว่าจะใช้การเปลี่ยนแปลงอย่างไรสิ่งต่อไปนี้จะเกิดขึ้น:

  1. สาขาปัจจุบันและตัวชี้ HEAD ยังคงอยู่ที่การกระทำครั้งสุดท้ายที่ทำสำเร็จ

  2. การอ้างอิง CHERRY_PICK_HEAD ถูกกำหนดให้ชี้ไปที่การคอมมิชชันที่แนะนำการเปลี่ยนแปลงที่ใช้ยาก

  3. พา ธ ที่การเปลี่ยนแปลงที่นำไปใช้อย่างสะอาดถูกอัพเดตทั้งในไฟล์ดัชนีและในแผนผังการทำงานของคุณ

  4. สำหรับเส้นทางที่ขัดแย้งกันไฟล์ดัชนีจะบันทึกได้ถึงสามเวอร์ชันตามที่อธิบายไว้ในส่วน "TRUE MERGE" ของ git-merge ไฟล์แผนผังการทำงานจะมีคำอธิบายของความขัดแย้งที่อยู่ในเครื่องหมายความขัดแย้งตามปกติ <<<<<<< และ >>>>>>>

ไม่มีการแก้ไขอื่น ๆ

อ่านเพิ่มเติม...

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.