Git push branch จากรีโมตหนึ่งไปยังอีกอันหนึ่ง?


136

ฉันมีการตั้งค่ารีโมทต่อไปนี้:

$ git remote 
korg
rorg

และสาขาต่อไปนี้:

$ git branch -a
* (no branch)
  remotes/korg/gingerbread
  remotes/korg/gingerbread-release
  remotes/korg/honeycomb
  remotes/korg/honeycomb-mr1-release
  remotes/korg/master
  remotes/m/android-2.3.3_r1 -> refs/tags/android-2.3.3_r1a
  remotes/m/gingerbread -> korg/gingerbread

ตอนนี้ฉันต้องการที่จะผลักดันสาขาระยะไกลทั้งหมดจากkorgไปยังrorgรีโมท ฉันจะทำอย่างไร

โดยเฉพาะอย่างยิ่งโดยไม่ต้องสร้างสาขาในท้องถิ่นสำหรับแต่ละแห่งก่อนหากสามารถหลีกเลี่ยงได้


ฉันเดาว่าคำตอบนี้เทียบได้กับคำตอบนี้: stackoverflow.com/questions/6922700/… .
Legolas

คำตอบ:


52

การทดสอบอย่างรวดเร็วในการสร้างที่เก็บชั่วคราวแสดงให้เห็นว่าคุณสามารถสร้าง refspec ที่สามารถทำได้:

$ git push rorg origin/one:refs/heads/one
Counting objects: 5, done.
Writing objects: 100% (3/3), 240 bytes, done.
Total 3 (delta 0), reused 0 (delta 0)
Unpacking objects: 100% (3/3), done.
To /tmp/rorg
 * [new branch]      origin/one -> one

ดังนั้นต้นทาง / BRANCHNAME: refs / หัว / BRANCHNAME

การตรวจสอบในrorgรีโมทของฉัน:

pat@host /tmp/rorg (BARE:master)
$ git graph --all
* 5750bca (HEAD, master) c
| * 13fd55a (one) b
|/
* 822e0de a

5
ทำไมไม่git push rorg origin/one:one(ไม่มีrefs/heads/) แทน?
อาลี

2
@exalted เพราะด้วยrefs/heads/คำนำหน้าคุณกำลังผลักดันสาขาระยะไกลที่ไม่จำเป็นต้องชำระเงินเป็นone
ДМИТРИЙМАЛИКОВ

@patthoyts ฉันลองใช้คำสั่งที่กล่าวมามันบอกว่าทุกอย่างเป็นปัจจุบัน แต่ฉันมี 10 สาขาใน A ระยะไกลและ 6 สาขาใน B ระยะไกลดังนั้นคุณช่วยบอกฉันได้ไหมว่าฉันจะย้ายสาขาทางซ้ายออกได้อย่างไร
Keshav1234

221

ฉันพบสิ่งนี้:

git push rorg 'refs/remotes/korg/*:refs/heads/*'

และมันดันสาขาที่ห่างไกลทั้งหมดของฉันจาก korg ไปที่ rorg (แม้ว่าจะไม่มีสำเนาสาขาในเครื่องก็ตาม) ดูผลลัพธ์ด้านล่าง:

Counting objects: 293, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (67/67), done.
Writing objects: 100% (176/176), 48.32 KiB, done.
Total 176 (delta 105), reused 168 (delta 97)
remote: Resolving deltas:  11% (12/105)
To <<MY_REPOSITORY_URL>>
 * [new branch]      korg/gingerbread-> gingerbread
 * [new branch]      korg/gingerbread-release -> gingerbread-release
 * [new branch]      korg/honeycomb-> honeycomb
 * [new branch]      korg/HEAD -> HEAD
 * [new branch]      korg/honeycomb-mr1-release-> honeycomb-mr1-release
 * [new branch]      korg/master -> master

จากนั้นคุณสามารถทำการผลักดันเดียวกันสำหรับการtagsอ้างอิง:

git push rorg 'refs/tags/*:refs/tags/*'

2
ในคอมไพล์ใหม่เพียงพอ (เวอร์ชันอะไร) นี่ควรเป็นคำตอบที่ยอมรับได้ @ bjarke-freund-hansen คุณต้องการเปลี่ยนคำตอบที่ยอมรับหรือไม่หากคุณเห็นด้วยเพื่อประโยชน์ของผู้ค้นหาในอนาคต
Jonah Graham

1
"ในคอมไพล์ใหม่เพียงพอ (เวอร์ชันใด) นี่ควรเป็นคำตอบที่ยอมรับ" อย่างที่ฉันรู้สิ่งนี้ควรใช้ได้กับเวอร์ชันคอมไพล์สาธารณะทุกเวอร์ชันเนื่องจากลายเซ็นแบบพุชและสัญลักษณ์แทนการอ้างอิงนั้นเป็นเรื่องธรรมดา
radistao

3
ให้Everything up-to-dateคอมไพล์ 2.10.0 โดยไม่มีอะไรเกิดขึ้นในขณะที่ทำแบบเดียวกันกับแต่ละสาขา
user239558

6
แค่คิดว่าฉันควรจะเรียกนี้ออก: HEADวิธีการนี้น่าจะสร้างสาขาที่เกิดขึ้นจริงในระยะไกลที่เรียกว่า แต่สามารถลบได้ git push rorg :HEAD
Mark Stickley

1
ทุกคนที่ไม่คุ้นเคยกับโครงสร้าง refs git push rorg refs/tags/*:refs/tags/*และสงสัยว่าจะผลักดันแท็กที่คุณต้องการคำสั่งนี้: ซึ่งก็เหมือนกับgit push rorg --tagsแต่ก็เป็นการดีที่จะเข้าใจว่าสิ่งเหล่านี้กำลังทำอะไร :)
Mark Stickley

13

เพื่อเสริมคำตอบของ patthoytนี่คือเชลล์สคริปต์สั้น ๆ ที่ผลักกิ่งก้านทั้งหมดจากรีโมตหนึ่งไปยังอีกอันหนึ่ง:

SRC_REMOTE=korg
DST_REMOTE=rorg
for a in $(git branch --list --remote "$SRC_REMOTE/*" | grep -v --regexp='->')
  do git push "$DST_REMOTE" "$a:refs/heads/${a//$SRC_REMOTE\/}"
done

เพื่อสรุปสำหรับแต่ละสาขาระยะไกลบนรีโมตต้นทาง (ไม่รวมสาขา "ตัวชี้" เช่น HEAD) ให้กดอ้างอิงนั้นไปยังรีโมตปลายทาง ( ${a//$SRC_REMOTE\/}บิตตัดชื่อรีโมตต้นทางออกจากชื่อสาขากล่าวคือorigin/masterกลายเป็นmaster)


3
สำหรับพวกเราที่ต้องทำในครั้งเดียว:git push -u $DST_REMOTE $(for a in $(git branch --list --remote "$SRC_REMOTE/*" | grep -v --regexp='->'); do echo "$a:refs/heads/${a//$SRC_REMOTE\/}"; done)
Jayen

6

ใช้งานได้ใน Zsh

โปรดสังเกตว่าอัญประกาศเดี่ยวเป็นสิ่งจำเป็นเพื่อป้องกันการขยายพารามิเตอร์ที่ไม่คาดคิดในบางกรณี

git push rorg 'refs/remotes/korg/*:refs/heads/*'

ขออภัยฉันลงคะแนนให้ แต่คำตอบของคุณเหมือนกับ radistao ด้านบน ( stackoverflow.com/a/21133502/235878 ) ซึ่งโพสต์ใน '14
Patrick

@Patrick คุณขาดบริบท - และสิ่งที่สำคัญมาก IMO - คำตอบที่คุณพูดถึงนั้นเขียนขึ้นในปี 2014 แต่ไม่มีเครื่องหมายคำพูดเดี่ยวจนกว่าจะมีการแก้ไขประมาณ 1 ปีก่อนที่ความคิดเห็นของคุณ ดังนั้นในขณะที่เขียนคำตอบนี้มันจึงแตกต่างไปในทางที่ค่อนข้างตรงประเด็น
0xC0000022L

1
@ 0xC0000022L ขอบคุณที่แจ้งเรื่องนี้ให้ฉันทราบ ฉันสามารถดูได้ว่าการขยายพารามิเตอร์อาจส่งผลต่อผลลัพธ์โดยไม่ได้ตั้งใจอย่างไร ในความคิดของฉันถ้าคำตอบนี้คือการเน้นคำพูดเดียวที่ขาดหายไปมันจะเป็นการดีกว่าที่จะเรียกมันออกมาอย่างชัดเจนแทนที่จะปล่อยให้ผู้อ่านทำงานนักสืบ ... ไม่ว่าในกรณีใดฉันคิดว่ามันยุติธรรมที่จะกู้คืน การโหวตลงเนื่องจากเป็นคำตอบที่ดีกว่าในปี '17
Patrick

@ แพทริกจริงมากอาจถูกชี้ให้เห็น ... หรือควรจะเป็น
0xC0000022L

-1

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

ฉันต้องการผลักดันหลายสาขาจากรีโมทหนึ่งไปยังอีกที่หนึ่ง คำตอบเหล่านี้จำเป็นต้องมีสาขาในท้องถิ่นก่อนหน้านี้

SRC_R=origin1
DEST_R=origin2
for cbranch in $(git branch -r | grep $SRC_R | cut -d '/' -f2,3,4,5 | cut -d ' ' -f1)
do
    git checkout $cbranch
    git push $DEST_R $cbranch
done

เพียงแค่เปลี่ยน origin1 เป็นรีโมตต้นทางและ origin2 เป็นรีโมตปลายทาง คัดลอกสิ่งนี้ลงใน "remoteBranchCloner.sh" และเรียกโดยใช้ "sh callBranchCloner.sh"

อาจมีวิธีที่ดีกว่าที่ไม่ต้องกดหลาย ๆ ครั้ง

หากคุณใช้รหัสของฉันคุณอาจต้องการใช้การแคชข้อมูลรับรองมิฉะนั้นคุณจะต้องพิมพ์เวลาให้บริการข้อมูลรับรองของคุณ

สำหรับ Windows :

หมายเหตุ: สคริปต์นี้สำหรับลินุกซ์ หากคุณเรียกใช้ใน "git bash"สคริปต์จะใช้งานได้ แต่คุณไม่สามารถเรียกใช้จากคอนโซลดั้งเดิมได้โดยไม่ต้องติดตั้งสิ่งพิเศษ

git config [--global] credential.helper wincred

สำหรับ linux

git config [--global] credential.helper cache

โดยที่ [--global] หมายถึงเพิ่มทางเลือก --global

หากคุณต้องการตั้งค่าการติดตามระยะไกลสำหรับทุกสาขาเป็นรีโมตใหม่:

DEST_R=remotename
for cbranch in `git branch`
do
    git checkout $cbranch
    git branch -u guru/$cbranch
done

จัดเก็บเป็นไฟล์. sh และรันด้วย "sh filename.sh" จะตั้งค่าให้อัปสตรีมทั้งหมดติดตาม 'remotename' แบบรีโมต


-1

เนื่องจากมีHEADการสร้างสาขาพิเศษในคำตอบก่อนหน้านี้วิธีที่สะอาดที่สุดที่ฉันพบคือการโคลนลงในที่เก็บเปล่าจากนั้นผลักกิ่งก้านทั้งหมดไปที่รีโมตดังนี้:

git clone --bare <from-repository>
cd <from-repo-dir>
git push --set-upstream <to-repository> --all
git push --set-upstream <to-repository> --tags
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.