git: ใช้การเปลี่ยนแปลงที่นำมาใช้โดยกระทำใน repo หนึ่งกับ repo อื่น


115

ฉันมีrepo1และrepo2เครื่องในท้องถิ่น มีความคล้ายคลึงกันมาก แต่สาขาหลังเป็นสาขาอื่น ๆ ( repo1ไม่ได้รับการดูแลอีกต่อไป)

/path/to/repo1 $ git log HEAD~5..HEAD~4
<some_sha> Add: Introduce feature X

วิธีการใช้การเปลี่ยนแปลงที่ทำโดยกระทำ<some_sha>ในrepo1การrepo2?

ฉันจำเป็นต้องเตรียมแพทช์บางส่วนหรือไม่หรือเป็นไปได้ที่จะทำcherry-pickระหว่าง repos?

วิธีการทำเช่นเดียวกัน แต่สำหรับช่วงของการกระทำ?


2
คุณไม่สามารถดึงจาก repo1 เป็น repo2 ได้หรือไม่?
zwol

สำหรับกรณีที่เฉพาะเจาะจงมากขึ้นเล็กน้อยที่คุณต้องการใช้การเปลี่ยนแปลงกับไฟล์หรือไฟล์ที่ถูกย้ายในที่เก็บใดที่หนึ่งโปรดดูที่นี่: stackoverflow.com/questions/3491270/…
Braham Snyder

คำตอบ:


31

ในฐานะแฮ็คคุณสามารถลองแก้ไขสูตรเพื่อเปรียบเทียบการคอมมิทในที่เก็บสองที่แตกต่างกันในหน้า GitTipsเช่น

GIT_ALTERNATE_OBJECT_DIRECTORIES=../repo/.git/objects \
git cherry-pick $(git --git-dir=../repo/.git rev-parse --verify <commit>)

ที่../repoเป็นเส้นทางไปยังพื้นที่เก็บข้อมูลอื่น ๆ

ด้วยความทันสมัย Git คุณสามารถใช้การแก้ไขหลายครั้งและช่วงการแก้ไขด้วยเชอร์รี่เลือก

$(git --git-dir=../repo/.git rev-parse --verify <commit>) อยู่ที่นี่เพื่อแปล<commit>(ตัวอย่างHEADหรือv0.2หรือmaster~2ซึ่งเป็นค่าที่อยู่ในพื้นที่เก็บข้อมูลที่สองคุณคัดลอกจาก) ลง SHA-1 ตัวบ่งชี้ของการกระทำ หากคุณทราบ SHA-1 ของการเปลี่ยนแปลงที่คุณต้องการเลือกก็ไม่จำเป็น

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

GIT_ALTERNATE_OBJECT_DIRECTORIES=../repo/.git/objects git repack -a -d -f

สิ่งนี้ทำให้อ็อบเจ็กต์เหล่านั้นยืมมาจากที่เก็บที่สองในที่เก็บต้นฉบับ

ไม่ผ่านการทดสอบ


วิธีแก้ปัญหาที่ไม่แฮ็กคือทำตามคำตอบของ knittl :

  • ไปที่ที่เก็บที่สองที่คุณต้องการคัดลอกคอมมิตและสร้างแพตช์จากคอมมิตที่คุณต้องการ git format-patch
  • เลือกคัดลอกแพตช์ (0001- * ฯลฯ ) ไปยังที่เก็บของคุณ
  • ใช้git am --3wayทาแพทช์

1
ใช้งานได้ดี หากคุณมีปัญหากับการกระทำให้ทำ 'git reset HEAD; คอมไพล์เพิ่ม '.
gumik

5
มันยอดเยี่ยมมาก - คุณจะทำอะไรได้บ้าง? แค่ sha1 ... sha2?
hvgotcodes

ฉันก็ได้รับเช่นกันfatal: unable to read tree ...แต่หลังจากที่git reset HEAD^ทุกอย่างทำงานได้ดี
jmarceli

@hvgotcodes มันใช้งานได้สำหรับฉันเพียงแค่ส่งช่วงเป็น<commit>แต่rev-parse --verifyคำสั่งไม่ชอบเพราะยอมรับเฉพาะค่าคอมมิตเดียว แต่เนื่องจากcherry-pickยอมรับทั้งค่าคอมมิตเดี่ยวและช่วงฉันถามว่าทำไมถึงrev-parseจำเป็น?
Chuim

1
@Chuim: git rev-parseเป็นสิ่งจำเป็นหากคุณต้องการที่จะหมายถึงการกระทำโดยใช้ชื่อโทษตามในพื้นที่เก็บข้อมูลอื่น ๆ เช่นmaster, HEAD^^หรือสิ่งที่ต้องการที่มิ rev-parse เปลี่ยนเป็นตัวระบุ SHA-1 สากล
Jakub Narębski

207

คุณอาจต้องการใช้git format-patchแล้วจึงgit amนำโปรแกรมแก้ไขนั้นไปใช้กับที่เก็บของคุณ

/path/to/1 $ git format-patch sha1^..sha1
/path/to/1 $ cd /path/to/2
/path/to/2 $ git am -3 /path/to/1/0001-…-….patch

หรือในบรรทัดเดียว:

/path/to/2 $ git --git-dir=/path/to/1/.git format-patch --stdout sha1^..sha1 | git am -3

9
วิธีนี้พิสูจน์แล้วว่าง่ายและปลอดภัยกว่าคำตอบของการเลือกเชอร์รี่โดยตรงโดยใช้GIT_ALTERNATE_OBJECT_DIRECTORIES(อันนั้นอาจทำให้ที่เก็บของฉันเสียหาย)
Chuim

2
เมื่อมีข้อขัดแย้งจะใช้ไม่ได้เนื่องจากไม่พบข้อตกลงในสาขาอื่น
Roger Far

2
เพิ่ม--ignore-whitespaceไปยังgit amคำสั่งอาจจะแก้ปัญหาความขัดแย้งใด ๆ และหลีกเลี่ยงการต้องดำเนินการ 3 วิธีผสาน
Hugheth

98

คุณสามารถทำได้cherry-pickถ้าคุณเพิ่ม repo ที่สองเป็นรีโมตในครั้งแรก (และจากนั้นfetch)


11
นั่นเป็นวิธีที่เหมาะสมที่จะทำ
Wilbert

5
นี่เป็นวิธีที่ถูกต้องสำหรับฉันเช่นกัน และฉันเพิ่งใช้มันและได้ผลดีสำหรับฉัน
Ricky Nelson

11
ผมค่อนข้างจะพูดว่า: ทำgit fetch [remote-name]ใน repo git cherry-pick [sha1]ที่สองแล้ว

5
วิธีนี้ใช้ได้ผลดีสำหรับฉันขอบคุณ เนื่องจาก repo ที่สองเป็นแบบโลคัลเช่นกันจึงต้องใช้ URI ของไฟล์เมื่อเพิ่มเป็นรีโมต
palimpsestor

2
ในกรณีของฉันฉันมีสองโคลนของที่เก็บ git ระยะไกลขนาดมหึมา (เพื่อให้ทำงานคู่ขนานได้) ซึ่งหมายความว่าประวัติทั้งหมดจะถูกดาวน์โหลดและเก็บไว้แล้วสองครั้งใน HD ของฉัน ถ้าฉันยังควรจะต้องเพิ่มแต่ละเป็นระยะไกลของอื่น ๆ cherry-pickที่จะสร้างยังสองฉบับพิเศษของประวัติศาสตร์เดียวกันและอาจจะต้องมีการซิงค์ในหมู่พวกเขาก่อนที่ผมจะสามารถ ดังนั้นถึงแม้ว่ามันอาจจะเป็นวิธีที่ "ถูกต้อง" แต่ก็ไม่ได้เป็นวิธีที่ใช้ได้จริงเสมอไป
Chuim

6

ฉันเขียนสคริปต์เล็ก ๆ สำหรับใช้เอาต์พุตที่แตกต่างของ repo diff https://github.com/raghakh/android-dev-scripts/commit/a57dcba727d271bf2116f981392b0dcbb22734d0


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