เป็นไปได้ไหมที่เชอร์รี่จะเลือกคอมมิทจากคอมไพล์ git อื่น?


726

ฉันกำลังทำงานกับที่เก็บ git ที่ต้องการคอมมิทจากที่เก็บ git อื่นที่ไม่รู้อะไรเลยก่อน

โดยทั่วไปแล้วฉันจะเลือกใช้เชอร์รี่โดยใช้HEAD@{x}ในการอ้างอิง แต่เนื่องจาก.gitไม่มีความรู้ใด ๆ ในรายการ reflog นี้ (ไดเรกทอรีทางกายภาพที่แตกต่างกัน) ฉันจะเลือกเชอร์รี่นี้ได้อย่างไรหรือฉันจะทำอย่างไร

git-svnฉันใช้ สาขาแรกของฉันคือการใช้git-svnของtrunkของธุรกรรมซื้อคืนภาคการโค่นล้มและสาขาต่อไปคือการใช้git-svnในสาขาการโค่นล้ม


2
นี่คือเหตุผลที่Ben Leeให้การเปิดรับคำถามนี้: "ฉันจะให้รางวัลแก่คำตอบที่ถูกต้องแทนที่จะเป็นคำตอบที่ยอมรับฉันแค่รอ 24 ชั่วโมงเพื่อทำเช่นนั้น" อย่างไรก็ตามฉันไม่เข้าใจว่าคำตอบใดควรเป็น "คำตอบที่ถูกต้อง" และทำไมคำตอบที่ยอมรับไม่ได้ "ถูกต้อง"

1
ยังไม่ชัดเจนว่าลักษณะของปัญหาคืออะไร repos ที่แตกต่างกันเหล่านี้มีความเกี่ยวข้องอย่างไรถ้าทั้งหมด? เป็นอีกคนหนึ่งที่แยกจากกันหรือไม่? หรือว่าพวกเขาทั้งสองโครงการแยกจากกันและไม่เกี่ยวข้องอย่างสมบูรณ์?

@Cupcake คำตอบที่ได้รับการยอมรับเป็นสิ่งที่ดีและช่วย OP อย่างชัดเจนดังนั้นจึงควรได้รับการยอมรับ โดย "ถูกต้อง" ฉันแค่หมายถึง "เหมาะสมกับฉัน" (และตัดสินความคิดเห็นที่เหมาะสมสำหรับคนอื่น ๆ ด้วย) ฉันแค่คิดว่าคนที่ฉันให้รางวัลเพื่อรับตัวแทนมากที่สุดเท่าที่คำตอบที่ยอมรับ
Ben Lee

คำตอบ:


556

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

เช่นนั้น:

git remote add other https://example.link/repository.git
git fetch other

git cherry-pickตอนนี้คุณมีข้อมูลทั้งหมดที่จะเพียงแค่ทำ

ข้อมูลเพิ่มเติมเกี่ยวกับการทำงานกับรีโมทที่นี่: https://git-scm.com/book/en/v2/Git-Basics-Working-with-Remotes


1
ถ้าฉันใช้ git-svn สาขาแรกของฉันใช้ Git-SVN ของลำต้นและต่อไปคือการใช้ Git-SVN ในสาขา (ขอบคุณสำหรับการตอบกลับอย่างรวดเร็ว)
gitcoder182

1
เมื่อคุณโคลนพื้นที่เก็บข้อมูล Subversion ครั้งแรกตรวจสอบให้แน่ใจว่าคุณได้โคลนพื้นที่เก็บข้อมูลทั้งหมดไม่เพียง แต่ลำต้น ตรวจสอบให้แน่ใจว่าคุณใช้--stdlayoutตัวเลือกของ git-svn หากคุณใช้โครงร่าง trunk / branch / tags มาตรฐานในการโค่นล้ม จากนั้นสาขาการโค่นล้มจะเป็นเพียงสาขา git ระยะไกล
wilhelmtell

33
หากคุณกำลังใช้ Github คุณสามารถดึงแพทช์โดยท้าย .patch การกระทำของ URL git am < d821j8djd2dj812.patchแล้วใช้มันด้วย นอกเหนือจาก GH แล้วแนวคิดที่คล้ายกันสามารถทำได้ตามที่อ้างถึงในคำตอบทางเลือกด้านล่าง
radicand

2
@radicand คำตอบใดต่อไปนี้เป็น "ทางเลือก" อย่างใดอย่างหนึ่ง กรุณาลิงค์ไป

7
รายละเอียดขั้นตอนในการเลือกเชอร์รี่จาก repo อื่น: coderwall.com/p/sgpksw/git-cherry-pick-from-another-repository
T. Kim Kim Nguyen

854

คำตอบตามที่ได้รับคือการใช้ format-patch แต่เนื่องจากคำถามคือวิธีการรับเชอร์รี่จากโฟลเดอร์อื่นนี่คือส่วนหนึ่งของรหัสที่ต้องทำ:

$ git --git-dir=../<some_other_repo>/.git \
format-patch -k -1 --stdout <commit SHA> | \
git am -3 -k

(คำอธิบายจาก@cong ma )

git format-patchคำสั่งสร้างแพทช์จากsome_other_repo's กระทำที่ระบุโดย SHA มัน ( -1หนึ่งเดียวกระทำเพียงอย่างเดียว) แพ็ตช์นี้ถูกไพพ์ไปgit amซึ่งใช้แพ็ตช์แบบโลคัล ( -3หมายถึงการลองผสานสามทางหากแพตช์ไม่สามารถใช้งานได้หมดจด) หวังว่าจะอธิบาย


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

45
@NickF git format-patchคำสั่งสร้างแพตช์จากsome_other_repoการคอมมิชชันที่ระบุโดย SHA ( -1สำหรับการคอมมิทเพียงครั้งเดียว) แพ็ตช์นี้ถูกไพพ์ไปgit amซึ่งใช้แพ็ตช์แบบโลคัล ( -3หมายถึงการลองผสานสามทางหากแพตช์ไม่สามารถใช้งานได้หมดจด) หวังว่าจะอธิบาย
Cong Ma

3
ข้อผิดพลาด: แพตช์ล้มเหลว: somefile.cs: 85 ข้อผิดพลาด: somefile.cs: แพทช์ไม่ได้ใช้คุณแก้ไขแพตช์ของคุณหรือไม่? มันใช้ไม่ได้กับ blobs ที่บันทึกไว้ในดัชนี ไม่สามารถถอยกลับไปรวมสามทางได้ โปรแกรมปะแก้ล้มเหลวที่ 0001 ชิ้นส่วน GUI ที่เพิ่ม พบสำเนาของแพตช์ที่ล้มเหลวใน: <some_other_repo> /.git/rebase-apply/patch เมื่อคุณแก้ไขปัญหานี้แล้วให้เรียกใช้ "git am - ต่อเนื่อง" หากคุณต้องการข้ามแพทช์นี้ให้เรียกใช้ "git am --skip" แทน หากต้องการคืนค่าสาขาเดิมและหยุดการแก้ไขให้เรียกใช้ "git am --abort"
ทอม

8
@ Tom --ignore-whitespaceลองใช้ คำสั่งแบบเต็ม: git --git-dir=../<some_other_repo>/.git format-patch -k -1 --stdout <commit SHA> | git am -3 -k --ignore-whitespace
Jake Graham Arnold

7
@BoomShadow เพราะมันง่ายกว่า การเพิ่มรีโมตและการดึงข้อมูลทำให้เกิดการเปลี่ยนแปลงของ repo อื่นทั้งหมด บรรทัดคำสั่งนี้เป็นการกระทำครั้งเดียว
Jonathon Reinhart

151

นี่คือตัวอย่างของ remote-fetch-merge

cd /home/you/projectA
git remote add projectB /home/you/projectB
git fetch projectB

จากนั้นคุณสามารถ:

git cherry-pick <first_commit>..<last_commit>

หรือคุณอาจรวมสาขาทั้งหมด

git merge projectB/master

54
git merge projectB/master เป็นอย่างมากผิดมากเพราะคุณไม่ได้ใช้การเปลี่ยนแปลงจากการกระทำเพียงครั้งเดียว (เช่นเชอร์รี่เลือกที่จะ), คุณจริงผสานในการเปลี่ยนแปลงทั้งหมดในprojectB/masterที่ไม่ได้มีอยู่ในตัวคุณเองmasterสาขา

4
ฉันสันนิษฐานว่านี่เป็นความตั้งใจของผู้โพสต์ดั้งเดิม มิฉะนั้นใช่นี่ไม่ใช่ตัวเลือกที่เหมาะสมสำหรับพวกเขา
Brian

5
สิ่งนี้จะทำงานได้อย่างยอดเยี่ยมเมื่อมีที่เก็บสองรายการที่เกี่ยวข้อง
Ronny Ager-Wick

1
ฉันสร้างสำเนาจากที่เก็บคอมไพล์ (เพียงเพื่อ "เล่น" โดยไม่ทำลาย repo ดั้งเดิม) และเพื่อให้ทันสมัยกับแหล่งที่มาคำตอบจาก Brian คือสิ่งที่ฉันต้องการดังนั้น Cupcake Cupcake ฉัน ต้องบอกว่ามันไม่ใช่ "ผิด" แต่เป็นกรณีการใช้งานอื่น แต่มันก็ดีจากคุณที่จะชี้ให้เห็นถึงหายนะที่อาจเกิดขึ้น: D
ferrari2k

6
IMO สิ่งนี้จำเป็นต้องได้รับการยอมรับ git remote rm projectBนอกจากนี้หากคุณต้องการที่จะลบระยะไกลหลังจากที่คุณกำลังทำเชอร์รี่ยกจากมันใช้ ใช้git tag -d tag-nameเพื่อลบแท็กใด ๆ ที่ดึงมาจาก repo ระยะไกล การกระทำระยะไกลจะไม่ปรากฏในประวัติของคุณอีกต่อไปและการตัดแต่งจะลบออกจากการจัดเก็บในที่สุด
ADTC

130

คุณสามารถทำได้ แต่ต้องใช้สองขั้นตอน นี่คือวิธี:

git fetch <remote-git-url> <branch> && git cherry-pick FETCH_HEAD

แทนที่<remote-git-url>ด้วย url หรือพา ธ ไปยังที่เก็บที่คุณต้องการให้เชอร์รี่เลือก

แทนที่<branch>ด้วยชื่อสาขาหรือแท็กที่คุณต้องการเลือกรับจากพื้นที่เก็บข้อมูลระยะไกล

คุณสามารถแทนที่FETCH_HEADด้วย git SHA จากสาขาได้

อัปเดต: แก้ไขตามความคิดเห็นของ @ pkalinow


8
มันใช้งานได้กับชื่อสาขา แต่ไม่ใช่กับ SHA หากคุณต้องการเชอร์รี่เลือกคอมมิชชันที่แสดงโดยแฮชของมันให้ใช้สิ่งนี้แทน: git fetch <repo-url> <branch> && git cherry-pick <sha>.
pkalinow

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

นี่คือสิ่งที่ฉันต้องการด้วยการติดตั้งโค้ดของเราสำหรับลูกค้าที่แตกต่างกัน (ซึ่งแต่ละคนมีที่เก็บ / ส้อมของตัวเอง) เราต้องการวิธีในการรับคอมมิชชันเฉพาะลงในฐาน / ลำตัวของเรา ขอขอบคุณ!
RedSands

นี่ควรเป็นคำตอบที่ได้รับการยอมรับสำหรับการเก็บเชอร์รี่ one-shot ฉันใช้มันตลอดเวลาเมื่อเลือกระหว่าง repos ที่มีอยู่แล้ว URL ระยะไกลนั้นเป็นเพียงเส้นทางของระบบไฟล์ในท้องถิ่น
Amedee Van Gasse

61

นี่คือขั้นตอนในการเพิ่มรีโมตดึงข้อมูลสาขาและเลือกการกระทำของเชอร์รี่

# Cloning our fork
$ git clone git@github.com:ifad/rest-client.git

# Adding (as "endel") the repo from we want to cherry-pick
$ git remote add endel git://github.com/endel/rest-client.git

# Fetch their branches
$ git fetch endel

# List their commits
$ git log endel/master

# Cherry-pick the commit we need
$ git cherry-pick 97fedac

ที่มา: https://coderwall.com/p/sgpksw


17

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


11

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

git fetch ssh://git@stash.mycompany.com:7999/repo_to_get_it_from.git branchToPickFrom && git cherry-pick 02a197e9533
# 

เรียก git [URL สาขา] [Branch to cherry-pick จาก] && git cherry-pick [กระทำ ID]


1
ไชโยไม่ต้องการssh://ส่วนสำหรับhttps://
Leo


1

สมมติว่าAมีการซื้อคืนที่คุณต้องการเชอร์รี่เลือกจากและBเป็นหนึ่งที่คุณต้องการเชอร์รี่เลือกที่จะคุณสามารถทำเช่นนี้โดยการเพิ่มการ</path/to/repo/A/>/.git/objects </path/to/repo/B>/.git/objects/info/alternatesสร้างalternatesไฟล์นี้หากไม่มีอยู่

สิ่งนี้จะทำให้ repo B เข้าถึงวัตถุ git ทั้งหมดจาก repo A และจะทำให้เชอร์รี่เลือกใช้งานได้สำหรับคุณ


0

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

git reset --hard
git remote update --prune
git pull --rebase --all
git cherry-pick -n remotes/origin/$(BRANCH)

โดยทำให้เจ้านายของ repo เปลือยอยู่เสมอเราสามารถเชอร์รี่เลือกการเปลี่ยนแปลงที่เสนอที่เผยแพร่ไปยัง repo เปลือย นอกจากนี้เรายังมีวิธีการที่ซับซ้อนกว่านี้ในการเลือกหลายสาขาสำหรับการตรวจสอบและทดสอบแบบรวม

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


-n หมายถึงไม่มีการกระทำตาม git docsและฉันมีความสำคัญมากที่จะเห็นการเปลี่ยนแปลงก่อนที่จะทำการกระทำ
canbax

0

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

# Directory from which to cherry-pick
GIT_DIR=...
# Pick changes only for this file
FILE_PATH=...
# Apply changes from this commit
FIST_COMMIT=master
# Apply changes until you reach this commit
LAST_COMMIT=...

for sha in $(git --git-dir=$GIT_DIR log --reverse --topo-order --format=%H $LAST_COMMIT_SHA..master -- $FILE_PATH ) ; do 
  git --git-dir=$GIT_DIR  format-patch -k -1 --stdout $sha -- $FILE_PATH | 
    git am -3 -k
done
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.