ดึง / ดันจากสถานที่ห่างไกลหลายแห่ง


743

สั้น:มีวิธีที่จะมี repo git ผลักดันและดึงจากรายการ repos ระยะไกล (แทนที่จะเป็น "แหล่งกำเนิด" เดียว)?

ความยาว:ฉันมักจะมีสถานการณ์เมื่อฉันพัฒนาแอพในคอมพิวเตอร์หลายเครื่องที่มีการเชื่อมต่อที่แตกต่างกัน - พูดว่าแล็ปท็อประหว่างทางคอมพิวเตอร์ "A" ในขณะที่ฉันอยู่ในสถานที่หนึ่งและคอมพิวเตอร์อีกเครื่อง "B" ในขณะที่อีก นอกจากนี้แล็ปท็อปอาจมีการเชื่อมต่อด้วย "A" หรือ "B" เท่านั้นและบางครั้งทั้งสองอย่าง

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


39
หมายเหตุสำหรับผู้เข้าชมใหม่เป็น 2016: วิธีที่ถูกต้องในปัจจุบันการทำเช่นนี้ทำนองคลองธรรมโดยชั้นแรกgitคุณสมบัติจะรวมอยู่ในmalvineous 's คำตอบด้านล่าง คำตอบที่ยอมรับไม่ถูกต้อง
ELLIOTTCABLE

@Zorzella: คุณสามารถอัปเดตคำตอบที่ยอมรับได้ในเรื่องนี้มันค่อนข้างสับสนในขณะนี้
ntninja

คำตอบ:


503

คุณสามารถกำหนดค่าที่เก็บระยะไกลหลายแห่งได้ด้วยgit remoteคำสั่ง:

git remote add alt alt-machine:/path/to/repo

ในการดึงข้อมูลจากรีโมทที่ตั้งค่าไว้ทั้งหมดและอัปเดตสาขาการติดตาม แต่ไม่รวมให้HEADทำ:

git remote update

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

ในการดึงสาขาหลักจาก alt และดึงเข้าไปในหัวปัจจุบันของคุณให้ทำ:

git pull alt master

ดังนั้นในความgit pullเป็นจริงเกือบจะจดจ่อgit pull origin HEAD(จริง ๆ แล้วมันดูในไฟล์กำหนดค่าเพื่อกำหนดสิ่งนี้ แต่คุณได้รับแนวคิด)

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


ดังนั้นสิ่งที่คุณพูดคือ "git remote เพิ่ม foo ssh: //foo.bar/baz" สร้างรูปแบบย่อ แต่ฉันยังคงต้องวนรอบพวกเขาด้วย "git pull" หรือวนรอบพวกเขาด้วย "git" ผสาน "(นี่คือรูปแบบไวยากรณ์หลังจาก" git remove update "?) ชื่อชวเลขนี้จะใช้งานไม่ได้สำหรับ" git push "หรือไม่ เช่นฉันไม่ "git push foo" เป็นต้น (วนซ้ำ)? ขอบคุณ
Zorzella

8
"git pull" นั้นเป็น "git fetch" แล้วตามด้วย "git merge" "git remote update" ใช้เครืองเรียก git fetch มาให้คุณ ดังนั้นสิ่งที่เหลือคือทำบิต "คอมไพล์ผสาน" คุณสามารถพูดว่า "ต้นกำเนิดคอมไพล์ผสาน / ต้นแบบ" และมันจะรวมรุ่นต้นแบบของแหล่งกำเนิดลงใน HEAD ปัจจุบันของคุณ "git pull origin origin" ทำสิ่งเดียวกันแม้ว่ามันจะทำการดึงข้อมูลมาก่อน (และถ้าคุณได้ทำการอัพเดตแบบรีโมต git แล้วนั่นจะไม่สามารถดึงข้อมูลเพิ่มเติมได้อีกดังนั้นจึงเป็นการทำซ้ำซ้อน) ใช่คุณสามารถพูดว่า "git push foo" และมันจะผลักกิ่งก้านสาขาที่ตรงกันทั้งหมดไปยังรีโมทที่เรียกว่า "foo"
araqnid

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

2
เห็นได้ชัดว่าคุณยังสามารถกดหนึ่งครั้งสำหรับ repos หลายรายการตรวจสอบคำตอบนี้สำหรับรายละเอียดเพิ่มเติมstackoverflow.com/questions/14290113/ …
manei_cc

797

ทำด้วยตนเองนี้ไม่จำเป็นอีกต่อไปกับรุ่นที่ทันสมัยของgit! ดูวิธีแก้ปัญหาของMalvineousด้านล่าง

ทำซ้ำที่นี่:

git remote set-url origin --push --add <a remote>
git remote set-url origin --push --add <another remote>

คำตอบเดิม:

บางสิ่งบางอย่างที่ฉันได้รับการใช้สำหรับค่อนข้างขณะที่โดยไม่มีผลกระทบที่ไม่ดีและแนะนำโดย Linus Torvalds ในรายชื่อผู้รับจดหมายคอมไพล์

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

เรื่องสั้นสั้น ๆgit remote addรีโมททั้งหมดของคุณแยกต่างหาก…จากนั้นgit config -eเพิ่มรีโมต merg ที่รวมกัน สมมติว่าคุณมีที่เก็บนี้config:

[remote "GitHub"]
    url = git@github.com:elliottcable/Paws.o.git
    fetch = +refs/heads/*:refs/remotes/GitHub/*
[branch "Master"]
    remote = GitHub
    merge = refs/heads/Master
[remote "Codaset"]
    url = git@codaset.com:elliottcable/paws-o.git
    fetch = +refs/heads/*:refs/remotes/Codaset/*
[remote "Paws"]
    url = git@github.com:Paws/Paws.o.git
    fetch = +refs/heads/*:refs/remotes/Paws/*

... เพื่อสร้าง ‐ รีโมทสำหรับ"Paws"และ"Codaset"ฉันสามารถเพิ่มรายการต่อไปนี้ได้ทั้งหมด:

[remote "Origin"]
    url = git@github.com:Paws/Paws.o.git
    url = git@codaset.com:elliottcable/paws-o.git

เมื่อฉันทำสิ่งนี้เมื่อฉันgit push Origin Masterมันจะผลักดันให้ทั้งสองPaws/MasterและCodaset/Masterตามลำดับทำให้ชีวิตง่ายขึ้นเล็กน้อย


104
git config -eเปิด.git/configไฟล์ในโปรแกรมแก้ไขที่คุณต้องการ
ริชาร์ด

3
ในกรณีที่ การยืนยันว่าการมีรีโมตที่มี 2 URL ยังคงทำงานบน 1.7.12.4 ขอบคุณ
foobar

26
ฉันชื่อ "แหล่งกำเนิด" ระยะไกล "ทั้งหมด" เพื่อให้ความหมายที่สะอาดกว่าเล็กน้อย
ErichBSchulz

1
@JamesWomack ดูคำตอบของ @ Malvineous ด้านล่าง มัน“ถูกต้องมากขึ้น” ตอนนี้เป็นของบรรทัดคำสั่งนี้สนับสนุนโดยกำเนิดด้วยgit git remote set-url ... --add
ELLIOTTCABLE

1
ภายใต้การ[branch "Master"]ตั้งค่าremote = Originและgit pullจะใช้รีโมททั้งสอง
Bengt

264

ตั้งแต่ git 1.8 (ตุลาคม 2012) คุณสามารถทำได้จากบรรทัดคำสั่ง:

git remote set-url origin --push --add user1@repo1
git remote set-url origin --push --add user2@repo2
git remote -v

จากนั้นgit pushจะพุชไปที่ user1 @ repo1 จากนั้นกดไปที่ user2 @ repo2


19
ฉันขอแนะนำอย่างยิ่งกับการแก้ปัญหานี้ เราได้ใช้มันใน บริษัท ของเราและมีปัญหาร้ายแรงกับ hooks ที่ล้มเหลวในที่เก็บหนึ่ง แต่ไม่ได้อยู่ที่อื่น การแก้ไขมีอยู่แล้วในที่เก็บเดียวเท่านั้น
Michael Schmeißer

4
@ MichaelSchmeißer: น่าจะเป็นไปได้ว่าคุณเห็นข้อความแสดงข้อผิดพลาดขณะผลักดันแก้ไขปัญหาจากนั้นผลักดันอีกครั้งเพื่อให้ทุกอย่างกลับสู่สภาพที่สะอาดหรือไม่
Malvineous

7
ปัญหาคือการแก้ไขการผลักดันที่ถูกปฏิเสธเกี่ยวข้องกับการเปลี่ยนการกระทำที่ได้รับการผลักไปยัง repo อื่นแล้ว ดังนั้นถ้ามีใครบางคนทำงานตามที่ได้ทำไปตามเวลาที่ได้รับการแก้ไขสิ่งต่าง ๆ น่ารังเกียจจริง ๆ ซึ่งเป็นกรณีในสำนักงานของเรา
Michael Schmeißer

9
อ่าใช่นั่นอาจเป็นเรื่องยุ่งยาก อย่างไรก็ตามสำหรับฉันที่ดูเหมือนว่าตะขอจะต้องได้รับการออกแบบใหม่ การกดที่ล้มเหลวจะไม่ทำลาย git ตามปกติดังนั้นการแนะนำจุดใหม่ของความล้มเหลว (ซึ่งป้องกันไม่ให้คุณใช้คุณสมบัติ git ที่ดี) อาจไม่ใช่ทางออกที่ดีที่สุด แน่นอนผมพูดแบบนี้ไม่ทราบว่าสิ่งที่ต้องการของคุณ ...
Malvineous

3
ไม่ได้ตั้งแต่เขียนคำถามของฉันฉันได้อ่านโพสต์บนเว็บอื่นแล้วทดสอบสิ่งนี้ จากการอ่านการโพสต์อื่น ๆ ฉันสงสัยว่ามีเพียงบรรทัดแรกเท่านั้นที่ใช้ ผมได้ทดสอบเพียงแค่นี้: แน่นอนเพียง URL git fetchจากบรรทัดแรกจะถูกตรวจสอบโดย (รับสิ่งนี้ฉันไม่เข้าใจว่าจุดประสงค์ของการgit remote set-url --addอยู่ไม่สามารถทำได้--push)
imz - Ivan Zakharyaschev

34

ฉันเพิ่มชื่อแทนเหล่านี้ใน ~ / .bashrc ของฉัน:

alias pushall='for i in `git remote`; do git push $i; done;'
alias pullall='for i in `git remote`; do git pull $i; done;'

6
นี่มันเจ๋งมาก! ฉันลงเอยด้วยการมีนามแฝง Git: git config alias.pushall '!for i in git remote; do git push $i; done;'
Ciro Santilli 法轮功病毒审查六四事件法轮功

ฉันคิดว่าฉันชอบโซลูชันนามแฝงในการสร้างรีโมตใหม่ ดูstackoverflow.com/questions/41372919/
donquixote

1
ปรับแต่งเล็กน้อยที่แนะนำ:alias pushall='for i in `git remote`; do echo "Pushing to " $i; git push $i; done;'
Scott C Wilson

25

คุณสามารถเพิ่มรีโมทด้วย:

git remote add a urla
git remote add b urlb

จากนั้นให้อัพเดต repos ทั้งหมด:

git remote update

15

นี่คือตัวอย่างของฉันกับสคริปต์ทุบตีใน.gitconfigส่วนนามแฝง

[alias]
        pushall = "!f(){ for i in `git remote`; do git push $i; done; };f"

7

ฉันเพิ่ม pushurl สองอันแยกกันใน "แหล่งกำเนิด" รีโมตในไฟล์. git congfig เมื่อฉันวิ่งgit push origin "branchName"แล้วมันจะวิ่งผ่านและผลักไปยังแต่ละ URL ไม่แน่ใจว่ามีวิธีที่ง่ายกว่าในการทำสิ่งนี้ให้สำเร็จหรือไม่ แต่นี่ใช้สำหรับฉันที่จะผลักดันไปยังซอร์สโค้ด Github และผลักดันไปยังซอร์สโค้ด My.visualStudio ในเวลาเดียวกัน

[remote "origin"]
  url = "Main Repo URL"
  fetch = +refs/heads/*:refs/remotes/origin/*
  pushurl = "repo1 URL"
  pushurl = "reop2 URl"

4

ฉันใช้เสรีภาพในการขยายคำตอบจาก nona-urbiz; เพียงเพิ่มส่วนนี้ใน ~ / .bashrc ของคุณ:

git-pullall () { for RMT in $(git remote); do git pull -v $RMT $1; done; }    
alias git-pullall=git-pullall

git-pushall () { for RMT in $(git remote); do git push -v $RMT $1; done; }
alias git-pushall=git-pushall

การใช้งาน:

git-pullall master

git-pushall master ## or
git-pushall

หากคุณไม่ได้ระบุอาร์กิวเมนต์สาขาใด ๆ สำหรับ git-pullall การดึงจากรีโมทที่ไม่ใช่ค่าเริ่มต้นจะล้มเหลว ออกพฤติกรรมนี้ตามที่มันเป็นเพราะมันคล้ายกับคอมไพล์


3

คุณจะต้องสคริปต์เพื่อวนรอบพวกเขา Git ไม่ได้ให้ "กดทั้งหมด" ในทางทฤษฎีคุณสามารถทำการพุชหลายเธรดได้ แต่ไม่มีวิธีการเนทีฟ

การดึงข้อมูลนั้นซับซ้อนมากขึ้นและฉันขอแนะนำให้ทำแบบเชิงเส้น

ฉันคิดว่าคำตอบที่ดีที่สุดของคุณคือการมีเครื่องหนึ่งครั้งที่ทุกคนผลัก / ดึงหากเป็นไปได้


2
ปัญหาคือตามที่ฉันอธิบายไม่มีกล่องกลางเสมอ ถ้าผมต้องเขียนสคริปต์ทุบตีวนลูปเพื่อให้มัน แต่มันให้ความรู้สึกตลกที่กระจาย VC จะไม่ช่วยให้ผมเพิ่มเติมได้ที่นี่ ...
Zorzella

2
การเผยแพร่นั้นจะถือว่าไม่ใช่ทุกคนที่มีอยู่หรือต้องการถูกผลักดัน นอกจากนี้ยังเกี่ยวข้องกับแหล่งเก็บข้อมูลที่แตกต่างกันซึ่งอยู่ในสถานะที่แตกต่างกันและข้อสันนิษฐานที่ว่าคนอื่น ๆ กำลังทำงานกับพวกเขาพร้อมกัน คำสั่งซื้อที่คุณกด & ดึงจากชุดที่เก็บมีผลกับสถานะของที่เก็บที่ต่างกันและคุณต้องทำการผ่านหลายครั้งเพื่อให้ซิงค์ทั้งหมด นี่คือเหตุผลที่ไม่มี "ดึง / ดันทั้งหมด" จากนั้นก็มีความขัดแย้ง ... ;)
Jeff Ferland

3

สำหรับการอัปเดตรีโมท (เช่นpullกรณี) สิ่งต่าง ๆ ได้ง่ายขึ้น

คำสั่งของ Linus

น่าเศร้าที่ไม่มีวิธีใดที่จะปลอมแปลงสิ่งนี้ด้วยนามแฝงคอมไพล์

ในรายการอ้างอิงที่รายการส่งจดหมายของ Gitในคำตอบของ elliottcableนั้นไม่เป็นความจริงอีกต่อไป

git fetchเรียนรู้--allพารามิเตอร์ในอดีตทำให้สามารถดึงรีโมททั้งหมดได้ในครั้งเดียว

หากไม่ได้รับการร้องขอทั้งหมดสามารถใช้--multipleสวิตช์เพื่อระบุรีโมตหลายตัวหรือกลุ่ม


3

ฉันต้องการทำงานใน VSO / TFS จากนั้นผลักดันสู่ GitHub เมื่อพร้อมแล้ว repo เริ่มต้นสร้างขึ้นใน VSO ส่วนตัว เมื่อถึงเวลาต้องเพิ่มใน GitHub ฉันได้:

git remote add mygithubrepo https://github.com/jhealy/kinect2.git
git push -f mygithubrepo master

ทำงานเหมือนแชมป์ ...

สำหรับการตรวจสอบสติให้ออก "git remote -v" เพื่อแสดงรายการที่เก็บที่เชื่อมโยงกับโครงการ

C:\dev\kinect\vso-repo-k2work\FaceNSkinWPF>git remote -v
githubrepo      https://github.com/jhealy/kinect2.git (fetch)
githubrepo      https://github.com/jhealy/kinect2.git (push)
origin  https://devfish.visualstudio.com/DefaultCollection/_git/Kinect2Work (fetch)
origin  https://devfish.visualstudio.com/DefaultCollection/_git/Kinect2Work (push)

วิธีง่ายๆใช้งานได้สำหรับฉัน ... หวังว่านี่จะช่วยให้ใครบางคน


4
การทำงานgit push -fโดยไม่มีเหตุผลเช่นความล้มเหลวgit pushหรือการรู้ว่ากำลังทำอะไรอยู่นั้นเป็นความคิดที่ไม่ดีซึ่งอาจเป็นอันตรายได้ นี่ยังไม่ตอบคำถาม แต่จะเพิ่มรีโมตตัวที่สองได้อย่างไร
Karl Richter

2

เพิ่มนามแฝงให้กับ gitconfig ทั่วโลก (/home/user/.gitconfig) ด้วยคำสั่งด้านล่าง

git config --global alias.pushall '!f(){ for var in $(git remote show); do echo "pushing to $var"; git push $var; done; }; f'

เมื่อคุณส่งรหัสเราจะพูด

git push

เพื่อผลักดันให้กำเนิดโดยค่าเริ่มต้น หลังจากนามแฝงข้างต้นเราสามารถพูดได้

คอมไพล์ pushall

และรหัสจะถูกอัปเดตเป็นรีโมททั้งหมดรวมถึงรีโมตต้นทาง


1

การเพิ่มallรีโมตทำให้เกิดความเบื่อหน่ายตามที่คุณต้องตั้งค่าในแต่ละเครื่องที่คุณใช้

นอกจากนี้นามแฝงbashและgit นามแฝงที่ให้ไว้ทั้งหมดจะถือว่าคุณได้กดไปที่รีโมททั้งหมด (Ex: ฉันมีส้อมของsshag. ที่ฉันรักษาบน GitHub และ GitLab ฉันมีต้นน้ำเพิ่มระยะไกล แต่ฉันไม่ได้รับอนุญาตที่จะผลักดันไป.)

นี่คือgit นามแฝงว่ามีเพียงที่จะผลักดันให้รีโมทพร้อม URL @ที่มีการผลักดัน

psall    = "!f() { \
    for R in $(git remote -v | awk '/@.*push/ { print $1 }'); do \
    git push $R $1; \
    done \
    }; f"

-3

การเพิ่มรีโมตใหม่

git remote add upstream https://github.com/example-org/example-repo.git

git remote -vv

ดึงฟอร์มจากหลายตำแหน่ง

git fetch --all

กดไปยังสถานที่ต่างๆ

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