วิธีคัดลอกคอมมิทจากสาขาหนึ่งไปอีกสาขาหนึ่ง


728

ฉันมีสองสาขาจากเจ้านายของฉัน:

  • v2.1 : (รุ่น 2) ฉันทำงานมาหลายเดือนแล้ว
  • wss : ที่ฉันสร้างเมื่อวานนี้เพื่อเพิ่มหนึ่งคุณลักษณะเฉพาะให้กับเจ้านายของฉัน (กำลังการผลิต)

มีวิธีการคัดลอกเมื่อวานนี้มุ่งมั่นจาก wss เพื่อ v2.1?


หากต้องการคัดลอกคอมมิชชัน (หรือช่วงของการกระทำ) จากสาขาหนึ่งไปยังอีกสาขาคำตอบนี้ช่วยฉันได้ดีที่สุด: stackoverflow.com/questions/1994463/…
caramba

คำตอบ:


565

คุณควรมีเวิร์กโฟลว์ที่ให้คุณทำสิ่งนี้ได้ทั้งหมดโดยการรวม:

- x - x - x (v2) - x - x - x (v2.1)
           \
            x - x - x (wss)

ดังนั้นสิ่งที่คุณต้องทำคือการและgit checkout v2.1 git merge wssหากมีเหตุผลบางอย่างที่คุณไม่สามารถทำเช่นนี้และคุณไม่สามารถใช้rebase คอมไพล์ที่จะย้ายสาขา WSS ของคุณไปยังสถานที่ที่เหมาะสมคำสั่งที่จะคว้าเดียวกระทำจากที่ไหนสักแห่งและใช้มันที่อื่น ๆ เป็นคอมไพล์เชอร์รี่เลือก git cherry-pick <SHA of commit to cherry-pick>เพียงตรวจสอบสาขาที่คุณต้องการใช้มันในและวิ่ง

วิธีการรีบูตอาจช่วยคุณได้:

หากประวัติของคุณมีลักษณะเช่นนี้:

- x - x - x (v2) - x - x - x (v2.1)
           \
            x - x - x (v2-only) - x - x - x (wss)

คุณสามารถใช้git rebase --onto v2 v2-only wssเพื่อย้าย wss โดยตรงไปยัง v2:

- x - x - x (v2) - x - x - x (v2.1)
          |\
          |  x - x - x (v2-only)
           \
             x - x - x (wss)

จากนั้นคุณสามารถผสาน! หากคุณจริงๆจริงๆจริงๆไม่สามารถรับไปยังจุดที่คุณสามารถผสานคุณยังสามารถใช้ rebase อย่างมีประสิทธิภาพจะหลายเชอร์รี่หยิบในครั้งเดียว:

# wss-starting-point is the SHA1/branch immediately before the first commit to rebase
git branch wss-to-rebase wss
git rebase --onto v2.1 wss-starting-point wss-to-rebase
git checkout v2.1
git merge wss-to-rebase

หมายเหตุ: เหตุผลที่ใช้งานพิเศษบางอย่างเพื่อทำสิ่งนี้คือมันกำลังสร้างการคอมมิตซ้ำในที่เก็บของคุณ นี่ไม่ใช่สิ่งที่ดีจริงๆ - จุดรวมของการแยกและการรวมที่ง่ายคือการสามารถทำทุกอย่างได้โดยการคอมมิชชันที่เดียวและรวมเข้ากับทุกที่ที่ต้องการ การทำซ้ำหมายถึงเจตนาที่จะไม่รวมสาขาทั้งสอง (ถ้าคุณตัดสินใจว่าคุณต้องการภายหลังคุณจะได้รับความขัดแย้ง)


1
ไม่สามารถเห็นด้วยเพิ่มเติมกับคำตอบนี้ +1 ดูคำตอบเก่า ๆ ของฉันเพื่อแสดงผลของการเก็บเชอร์รี่: stackoverflow.com/questions/881092/…
VonC

18
คำตอบที่ยอดเยี่ยมเกี่ยวกับวิธีการทำเช่นนี้ในวิธีที่เหมาะสม ! ฉันหวังว่าฉันจะสามารถโหวตสองครั้งสำหรับความพยายามในการสร้างไดอะแกรม ASCII ได้เช่นกัน
gotgenes

@VonC: ขอบคุณสำหรับการสนับสนุนและข้อมูลเพิ่มเติมเกี่ยวกับเหตุผลที่จะไม่เลือกเชอร์รี่ - ฉันรู้ว่าฉัน skimped เล็กน้อยที่นั่น @gotgenes: ขอบคุณ! ฉันคิดว่ามันคุ้มค่ากับความพยายามทั้งหมด - เพียงแค่ดู manpage git-rebase ไม่มีวิธีที่ดีกว่าที่จะอธิบาย
Cascabel

สำหรับสาเหตุที่คุณไม่สามารถผสานได้ - การรวม Git ไม่ได้สนุกกับ git-svn ในการคัดลอกชุดของการคอมมิชชันจากสาขา SVN หนึ่งไปยังอีกสาขาฉันลงเอยด้วยการหยิบเชอร์รี่จากนั้นทำการรีบูต / ตอบแบบโต้ตอบเพื่อลบการgit-svn-idอ้างอิงที่ไม่ถูกต้องก่อนนำdcommitกลับมาอีกครั้ง แม้ว่าฉันอาจจะได้ออกจากขั้นตอนเชอร์รี่เลือกและเพียงใช้ rebase ด้วยตัวเอง
บ๊อบ

1
นี่คือกรณีการใช้งานของฉัน: การแก้ไขข้อบกพร่องที่สำคัญมุ่งมั่นที่จะสาขาคุณสมบัติ ฉันต้องการมันเป็นหลักในการผลิต นี่จะช่วยชนของฉัน
Captain Hypertext

910

ใช้

git cherry-pick <commit>

เพื่อนำไปใช้<commit>ที่คุณสาขาในปัจจุบัน

ฉันเองอาจจะตรวจสอบความมุ่งมั่นที่ฉันเลือกgitkและเชอร์รี่เลือกพวกเขาด้วยการคลิกขวาที่รายการส่งมอบตรงนั้นแทน


หากคุณต้องการอัตโนมัติมากขึ้น (ด้วยอันตรายทั้งหมด) และสมมติว่ากระทำทั้งหมดตั้งแต่เมื่อวานเกิดขึ้นกับ wss คุณสามารถสร้างรายการการกระทำโดยใช้git log( --prettyโดย Jefromi แนะนำ)

git log --reverse --since=yesterday --pretty=%H

ดังนั้นทุกอย่างเข้าด้วยกันสมมติว่าคุณใช้ bash

for commit in $(git log --reverse --since=yesterday --pretty=%H);
do
    git cherry-pick $commit
done

หากมีบางอย่างผิดพลาดที่นี่ (มีศักยภาพมากมาย) คุณกำลังมีปัญหาเนื่องจากการดำเนินการกับการชำระเงินสดดังนั้นควรเลือกใช้เชอร์รี่หรือหยิบใช้การรีบูทตามที่ Jefromi แนะนำ


ตัวยึดทั้งหมดสำหรับตัวเลือก --prety อยู่ใน git-log manpage คุณสามารถรับรูปแบบใดก็ได้ที่คุณต้องการ - มีประโยชน์อย่างยิ่งสำหรับการรับเขตข้อมูลที่คุณต้องการสำหรับสคริปต์ในรูปแบบแยกวิเคราะห์ได้ง่าย
Cascabel

ฉันอยากจะชี้ให้เห็นว่าถ้าคุณต้องการสร้างพันธะที่ซ้ำกันจริงๆวิธีที่ใช้git rebaseในคำตอบของฉันนั้นแข็งแกร่งกว่า โดยเฉพาะอย่างยิ่งการใช้ลูป for เช่นนี้หากหนึ่งใน cherry-picks ล้มเหลวมันจะยังคงพยายามทำส่วนที่เหลือทั้งหมด นี่คือ ... ไม่ดีมากสมมุติว่า
Cascabel

2
ตกลง นั่นเป็นเหตุผลที่ฉันไม่เคยใช้มัน แต่ทำด้วยตนเอง แต่เชอร์รี่เลือกยังคงเป็นคำตอบอย่างน้อยชื่อคำถาม ฉันแก้ไขคำตอบ
Benjamin Bannier

1
มีคนมุ่งมั่นที่จะสาขาเก่า / ไม่ถูกต้องและเชอร์รี่เลือกให้ฉันใส่ลงไปในสาขาที่ถูกต้อง สมบูรณ์
Patrick

8
สายตาที่หายากgitคำตอบที่ง่ายและตรงไปตรงมาแก้ปัญหาแทนที่จะเดินผ่านความซับซ้อนของคอมไพล์เพื่อพิสูจน์ว่าผู้ตอบรู้ได้ดีเพียงใด
Przemek D

74

git cherry-pick : ใช้การเปลี่ยนแปลงที่นำเสนอโดยบางคอมมิทที่มีอยู่

สมมติว่าเรามีสาขาAพร้อม (X, Y, Z) เราจำเป็นต้องเพิ่มกระทำเหล่านี้ไปยังสาขาB เราจะใช้การcherry-pickดำเนินการ

เมื่อเราใช้cherry-pickเราควรเพิ่มกระทำในสาขาBในลำดับเดียวกับที่กระทำจะปรากฏในสาขา

cherry-pick สนับสนุนช่วงของการคอมมิต แต่ถ้าคุณรวมการคอมมิทในช่วงนั้นมันจะซับซ้อนมากขึ้น

git checkout B
git cherry-pick SHA-COMMIT-X
git cherry-pick SHA-COMMIT-Y
git cherry-pick SHA-COMMIT-Z

ตัวอย่างของเวิร์กโฟลว์:

ป้อนคำอธิบายรูปภาพที่นี่

เราสามารถใช้cherry-pickกับตัวเลือก

-e or - edit : ด้วยตัวเลือกนี้ git cherry-pick จะช่วยให้คุณแก้ไขข้อความยืนยันก่อนที่จะส่งข้อมูล

-n หรือ - no-commit : โดยปกติคำสั่งจะสร้างลำดับของการคอมมิท แฟล็กนี้ใช้การเปลี่ยนแปลงที่จำเป็นในการเลือกเชอร์รี่แต่ละรายการที่กำหนดไว้กับแผนผังการทำงานของคุณและดัชนีโดยไม่ทำการคอมมิตใด ๆ นอกจากนี้เมื่อใช้ตัวเลือกนี้ดัชนีของคุณไม่จำเป็นต้องตรงกับ HEAD Cherry-pick ทำกับสถานะเริ่มต้นของดัชนีของคุณ

ที่นี่น่าสนใจบทความcherry-pickเกี่ยวกับ


19

คุณสามารถสร้างโปรแกรมแก้ไขจากข้อผูกพันที่คุณต้องการคัดลอกและใช้โปรแกรมแก้ไขกับสาขาปลายทาง


16
แม้ว่าคุณจะด้วยเหตุผลบางอย่างอยากจะใช้แพทช์ (e) แทนเชอร์รี่เลือก (s) / rebase วิธีที่ตรงไปตรงมาจะทำมันอยู่กับและgit format-patch <revision range> git am *.patch
Cascabel

มันต้องการcheckoutสาขาอื่น
CoolMind

12

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

git branch deploy deploy_template
git checkout deploy
git rebase master

สิ่งนี้จะสร้างการปรับใช้สาขาใหม่ (ฉันใช้ -f เพื่อเขียนทับการปรับใช้สาขาที่มีอยู่) บน deploy_template จากนั้นรีบูตสาขาใหม่นี้ไปยังมาสเตอร์


1

สำหรับกรณีที่เรียบง่ายเพียงแค่คัดลอกการกระทำล่าสุดจากสาขา wss ไปยัง v2.1 คุณสามารถคว้ารหัสการกระทำ ( git log --oneline | head -n 1) และทำ:

git checkout v2.1
git merge <commit>

สิ่งนี้จำเป็นต้องเช็คเอาท์ที่สาขาอื่น
CoolMind

1

คำสั่ง cherry-pick สามารถอ่านรายการการคอมมิทจากอินพุตมาตรฐาน

คำสั่ง cherry-picks กระทำโดยผู้ใช้ John ที่มีอยู่ในสาขา "พัฒนา" แต่ไม่ได้อยู่ในสาขา "ปล่อย" และดำเนินการตามลำดับเวลา

git log develop --not release --format=%H --reverse --author John | git cherry-pick --stdin
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.