tarik / dorong dari beberapa lokasi jarak jauh

743

Singkatnya: apakah ada cara untuk mendorong git repo ke dan menarik dari daftar repo jarak jauh (daripada satu "asal" tunggal)?

Lama: Saya sering mengalami situasi ketika saya sedang mengembangkan aplikasi di banyak komputer, dengan konektivitas yang berbeda - misalnya laptop saat transit, komputer "A" saat saya berada di lokasi tertentu, dan komputer lain "B" sementara di yang lain. Selain itu, laptop mungkin memiliki konektivitas hanya dengan "A" atau "B", dan terkadang keduanya.

Yang ingin saya lakukan adalah agar git selalu "menarik" dari dan "mendorong" ke semua komputer yang saat ini dapat terhubung, sehingga lebih mudah untuk beralih dari satu mesin ke yang lain dan terus bekerja dengan lancar.

Zorzella
sumber
39
Catatan untuk pengunjung baru, per 2016: Cara yang saat ini benar untuk melakukan ini, disetujui oleh gitfitur kelas satu , termasuk dalam jawaban malvine di bawah ini . Jawaban yang diterima salah.
DAPAT DITERIMA
@Zorzella: Dapatkah Anda memperbarui jawaban yang diterima tentang ini, agak membingungkan seperti saat ini.
ntninja

Jawaban:

503

Anda dapat mengonfigurasi beberapa repositori jarak jauh dengan git remoteperintah:

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

Untuk mengambil dari semua remote yang dikonfigurasi dan memperbarui cabang pelacakan, tetapi tidak bergabung HEAD, lakukan:

git remote update

Jika saat ini tidak terhubung ke salah satu remote, itu akan mengambil waktu atau melemparkan kesalahan, dan pergi ke yang berikutnya. Anda harus menggabungkan secara manual dari repositori yang diambil, atau cherry-pick, tergantung pada bagaimana Anda ingin mengatur pengumpulan perubahan.

Untuk mengambil cabang master dari alt dan menariknya ke kepala Anda saat ini, lakukan:

git pull alt master

Jadi sebenarnya git pullhampir singkatan untuk git pull origin HEAD(sebenarnya terlihat di file konfigurasi untuk menentukan ini, tetapi Anda mendapatkan ide).

Untuk mendorong pembaruan, Anda harus melakukannya untuk setiap repo secara manual.
Suatu dorongan, saya pikir, dirancang dengan alur kerja sentral-repositori dalam pikiran.

araqnid
sumber
jadi apa yang Anda katakan adalah "git remote add foo ssh: //foo.bar/baz" membuat bentuk steno, tapi saya masih perlu mengulanginya dengan "git pull", atau melingkari mereka dengan "git gabungkan "(apa sintaksinya di sini, setelah" git remove update "?) Tidakkah nama singkatan ini juga berfungsi untuk" git push "? Yaitu saya tidak bisa "git push foo" dll (loop)? Terima kasih
Zorzella
8
"git pull" pada dasarnya adalah "git fetch" diikuti oleh "git merge". "git remote update" hanya melakukan banyak panggilan "git fetch" untuk Anda. Jadi yang tersisa adalah melakukan sedikit "git merge". Anda dapat mengatakan "git merge origin / master" dan itu akan menggabungkan versi master asli ke HEAD Anda saat ini. "git pull origin master" melakukan hal yang sama, meskipun itu akan melakukan pengambilan pertama (dan jika Anda sudah melakukan pembaruan jarak jauh git, itu tidak akan memiliki apa-apa lagi untuk diambil, jadi itu berlebihan). Ya, Anda bisa mengatakan "git push foo" dan itu akan mendorong semua cabang yang cocok ke remote yang disebut "foo".
araqnid
IIUC Anda tidak dapat mendorong ke repositori yang berfungsi (setelah semua Anda mungkin mendorong perubahan yang tidak kompatibel / tidak teruji / tidak diinginkan). Kita harus mendorong ke repositori telanjang, dan hanya menerima pembaruan ketika kita menarik. Jadi solusinya memerlukan repositori yang berfungsi dan kosong pada setiap mesin?
joeytwiddle
2
Rupanya Anda juga dapat memiliki satu dorongan tunggal untuk beberapa repo, periksa jawaban ini untuk lebih jelasnya stackoverflow.com/questions/14290113/...
manei_cc
797

Melakukan ini secara manual tidak lagi diperlukan , dengan versi modern git! Lihat solusi Malvineous , di bawah ini.

Diproduksi ulang di sini:

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

Jawaban asli:

Ini sesuatu yang telah saya gunakan cukup lama tanpa konsekuensi buruk dan disarankan oleh Linus Torvalds di milis git .

Solusi araqnid adalah solusi yang tepat untuk membawa kode ke dalam repositori Anda ... tetapi ketika Anda, seperti saya, memiliki beberapa upstream stream yang setara (saya menyimpan beberapa proyek kritis saya yang dikloning ke upstream pribadi, GitHub, dan Codaset), itu bisa menjadi sakit untuk mendorong perubahan untuk masing-masing, setiap hari.

Singkat cerita, git remote addsemua remote Anda secara terpisah ... dan kemudian git config -edan tambahkan remote-gabungan. Dengan asumsi Anda memiliki repositori ini config:

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

... untuk membuat remote-gabungan untuk "Paws"dan "Codaset", saya bisa menambahkan yang berikut setelah semuanya:

[remote "Origin"]
    url = [email protected]:Paws/Paws.o.git
    url = [email protected]:elliottcable/paws-o.git

Setelah saya melakukan ini, ketika saya git push Origin Master, itu akan mendorong keduanya Paws/Masterdan Codaset/Mastersecara berurutan, membuat hidup sedikit lebih mudah.

DAPAT DILAKUKAN
sumber
104
git config -emembuka .git/configfile di editor pilihan Anda.
Richard
3
Untuk berjaga-jaga. Mengkonfirmasikan bahwa memiliki remote dengan 2 url masih melakukan pekerjaan pada 1.7.12.4. Terima kasih.
foobar
26
Saya menamai "origin" remote "all" untuk memberikan semantik yang sedikit lebih bersih
ErichBSchulz
1
@ JamesWomack lihat jawaban @ Malvineous, di bawah ini. Ini "lebih benar" sekarang, karena gitbaris perintah mendukung ini secara asli, dengan git remote set-url ... --add.
DAPAT DITERIMA
1
Di bawah [branch "Master"]set remote = Origindan git pullakan menggunakan kedua remote.
Bengt
264

Sejak git 1.8 (Oktober 2012) Anda dapat melakukan ini dari baris perintah:

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

Kemudian git pushakan mendorong ke user1 @ repo1, lalu mendorong ke user2 @ repo2.

Malvine
sumber
19
Saya sangat menyarankan terhadap solusi ini. Kami telah menggunakannya di perusahaan kami dan mengalami masalah serius dengan pengait yang gagal di satu repositori, tetapi tidak di yang lain. Kemudian, perubahan hanya ada dalam satu repositori.
Michael Schmeißer
4
@ MichaelSchmeißer: Mungkin Anda bisa melihat pesan kesalahan saat mendorong, perbaiki masalah, lalu dorong lagi untuk mengembalikan semuanya ke kondisi bersih?
Malvineous
7
Masalahnya adalah bahwa memperbaiki push yang ditolak melibatkan mengubah komit yang telah didorong ke repo lain. Jadi, jika seseorang sudah melakukan pekerjaan berdasarkan komitmen tersebut pada saat mereka diperbaiki, semuanya menjadi sangat buruk, yang terjadi di kantor kami.
Michael Schmeißer
9
Ah ya, itu bisa rumit. Namun bagi saya itu sepertinya kait perlu didesain ulang. Dorongan yang gagal tidak memecah git secara normal, jadi memperkenalkan titik kegagalan baru (yang juga mencegah Anda menggunakan fitur gift yang bagus) mungkin bukan solusi terbaik. Tentu saja saya mengatakan ini tanpa mengetahui apa kebutuhan Anda ...
Malvineous
3
Tidak. Sejak menulis pertanyaan saya, saya sudah membaca posting web lain dan kemudian menguji hal ini. Dari membaca posting lain, saya mendapat kecurigaan bahwa hanya baris pertama yang digunakan. Saya baru saja menguji ini: memang, hanya URL dari baris pertama yang diperiksa oleh git fetch. (Mengingat ini, saya tidak mengerti apa tujuan dari git remote set-url --addtanpa itu --push.)
imz - Ivan Zakharyaschev
34

Saya menambahkan alias ini ke my ~ / .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;'
Nona Urbiz
sumber
6
Ini luar biasa! Saya akhirnya memiliki alias Git: git config alias.pushall '!for i in remote git; do git push $i; done;'
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功 法轮功
Saya pikir saya lebih suka solusi alias daripada membuat remote baru. Lihat juga stackoverflow.com/questions/41372919/…
donquixote
1
Tweak kecil yang disarankan:alias pushall='for i in `git remote`; do echo "Pushing to " $i; git push $i; done;'
Scott C Wilson
25

Anda dapat menambahkan remote dengan:

git remote add a urla
git remote add b urlb

Kemudian untuk memperbarui semua repo lakukan:

git remote update
FelipeC
sumber
15

Inilah contoh saya dengan skrip bash di dalam .gitconfigbagian alias

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

Saya menambahkan dua pushurl terpisah ke "asal" jauh di file congfig .git. Ketika saya menjalankan git push origin "branchName"Kemudian itu akan berjalan melalui dan mendorong ke setiap url. Tidak yakin apakah ada cara yang lebih mudah untuk mencapai hal ini tetapi ini bekerja untuk saya sendiri untuk mendorong ke kode sumber Github dan untuk mendorong ke kode sumber My.visualStudio pada saat yang sama.

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

Saya mengambil kebebasan untuk memperluas jawaban dari nona-urbiz; tambahkan saja ini ke ~ / .bashrc Anda:

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

Pemakaian:

git-pullall master

git-pushall master ## or
git-pushall

Jika Anda tidak memberikan argumen cabang untuk git-pullall maka tarikan dari remote non-default akan gagal; membiarkan perilaku ini apa adanya, karena analog dengan git.

hsk81
sumber
3

Anda membutuhkan skrip untuk mengulanginya. Git tidak menyediakan "push all." Secara teoritis Anda bisa melakukan push di banyak utas, tetapi metode asli tidak tersedia.

Pengambilan bahkan lebih rumit, dan saya sarankan melakukannya secara linear.

Saya pikir jawaban terbaik Anda adalah memiliki satu mesin yang setiap orang melakukan push / pull, jika memungkinkan.

Jeff Ferland
sumber
2
Masalahnya adalah, seperti yang saya jelaskan, tidak ada kotak pusat selalu tersedia. Jika saya harus menulis script bash perulangan, jadi itu, tapi rasanya lucu bahwa VC didistribusikan tidak akan membantu saya lebih lanjut di sini ...
Zorzella
2
Disebarkan, diasumsikan bahwa tidak semua orang tersedia, atau ingin didorong. Ini juga berhubungan dengan repositori yang berbeda berada di negara yang berbeda, dan asumsi bahwa orang lain mengerjakannya secara bersamaan. Urutan yang Anda tekan & tarik dari kumpulan repositori memengaruhi kondisi repositori yang berbeda, dan Anda harus membuat beberapa lintasan agar semuanya benar-benar disinkronkan. Inilah sebabnya mengapa tidak ada "tarik / dorong semua". Lalu ada konflik ...;)
Jeff Ferland
3

Untuk memperbarui remote (yaitu pullkasing), segalanya menjadi lebih mudah.

Pernyataan Linus

Sayangnya, bahkan tidak ada cara untuk memalsukan ini dengan alias git.

dalam entri yang direferensikan di milis Git dalam jawaban elliottcable tidak lagi benar.

git fetchmempelajari --allparameter di suatu tempat di masa lalu yang memungkinkan untuk mengambil semua remote sekaligus.

Jika tidak semua diminta, orang dapat menggunakan --multiplesakelar untuk menentukan beberapa remote atau grup.

eek
sumber
3

Saya ingin bekerja di VSO / TFS, lalu dorong publik ke GitHub saat siap. Repo awal dibuat dalam VSO pribadi. Ketika tiba saatnya untuk menambahkan ke GitHub saya lakukan:

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

Bekerja seperti ...

Untuk pemeriksaan kewarasan, keluarkan "git remote -v" untuk mendaftar repositori yang terkait dengan proyek.

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)

Cara sederhana, berhasil untuk saya ... Semoga ini bisa membantu seseorang.

Joe Healy
sumber
4
Berlari git push -ftanpa alasan, misalnya kegagalan git pushatau tahu persis apa yang dilakukan seseorang, adalah ide yang buruk dan berpotensi berbahaya. Ini juga tidak menjawab pertanyaan, tetapi bagaimana menambahkan remote kedua.
Karl Richter
2

tambahkan alias ke global gitconfig (/home/user/.gitconfig) dengan perintah di bawah ini.

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

Setelah Anda melakukan kode, kami katakan

git push

untuk mendorong ke asal secara default. Setelah alias di atas, bisa kita katakan

git pushall

dan kode akan diperbarui ke semua remote termasuk remote asal.

dhirajforyou
sumber
1

Menambahkan allremote menjadi agak membosankan karena Anda harus melakukan setup pada setiap mesin yang Anda gunakan.

Juga, bashdan git alias asalkan semua menganggap bahwa Anda telah mendorong semua remote. (Mis: Saya memiliki garpu sshagyang saya pertahankan di GitHub dan GitLab. Saya memiliki remote hulu yang ditambahkan, tetapi saya tidak memiliki izin untuk mendorongnya.)

Berikut ini adalah git alias yang hanya mendorong ke jarak jauh dengan URL push yang menyertakan @.

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

Menambahkan remote baru

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

git remote -vv

Ambil beberapa lokasi

git fetch --all

Dorong ke lokasi

git push -u upstream/dev
Dadaso Zanzane
sumber