pull / push z wielu zdalnych lokalizacji

743

Krótko mówiąc: czy istnieje sposób na wypchnięcie repozytorium git i pobranie z listy zdalnych repozytoriów (zamiast pojedynczego „pochodzenia”)?

Długie: często mam sytuację, gdy tworzę aplikację na wielu komputerach, z różnymi łączami - powiedz laptop podczas transportu, komputer „A”, gdy jestem w określonej lokalizacji, i inny komputer „B” podczas gdy na innym. Ponadto laptop może mieć łączność tylko z „A” lub „B”, a czasami jednocześnie.

Chciałbym, aby git zawsze „ściągał” i „przepychał” do wszystkich komputerów, z którymi może się obecnie łączyć, więc łatwiej jest przeskakiwać z jednej maszyny na drugą i kontynuować płynną pracę.

Zorzella
źródło
39
Informacja dla nowych użytkowników, jak od 2016: Aktualnie-poprawny sposób to, usankcjonowane przez pierwszorzędnych zrobić gitcech, jest zawarty w malvineous „s odpowiedź poniżej . Przyjęta odpowiedź jest niepoprawna.
ELLIOTTCABLE
@Zorzella: Czy możesz zaktualizować zaakceptowaną odpowiedź na ten temat, jest to trochę mylące z obecnym.
ntninja

Odpowiedzi:

503

Możesz skonfigurować wiele zdalnych repozytoriów za pomocą git remotepolecenia:

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

Aby pobrać ze wszystkich skonfigurowanych pilotów i zaktualizować gałęzie śledzenia, ale nie scalić się z nimi HEAD, wykonaj:

git remote update

Jeśli nie jest on aktualnie podłączony do jednego z pilotów, upłynie limit czasu lub zgłosi błąd i przejdzie do następnego. Będziesz musiał ręcznie scalić z pobranych repozytoriów lub cherry-pick, w zależności od tego, jak chcesz zorganizować zbieranie zmian.

Aby pobrać gałąź master z alt i przeciągnąć ją do bieżącej głowy, wykonaj:

git pull alt master

W rzeczywistości git pulljest to prawie skrót git pull origin HEAD(właściwie wygląda to w pliku konfiguracyjnym, aby to ustalić, ale masz pomysł).

W przypadku wypychania aktualizacji musisz to zrobić ręcznie dla każdego repozytorium.
Myślę, że push został zaprojektowany z myślą o przepływie pracy centralnego repozytorium.

araqnid
źródło
więc mówisz, że „git remote add foo ssh: //foo.bar/baz” tworzy krótszą formę, ale nadal muszę zapętlać je za pomocą „git pull” lub zapętlać je za pomocą „git” merge ”(jaka jest tutaj składnia po aktualizacji„ git remove ”?) Czy ta krótka nazwa nie będzie również działać w przypadku„ git push ”? Czy nie mogę „git push foo” itp. (Pętla)? Dzięki
Zorzella,
8
„git pull” to w zasadzie „git fetch”, po którym następuje „git merge”. Funkcja „zdalna aktualizacja git” wykonuje po prostu kilka wywołań funkcji „git fetch”. Pozostaje więc wykonać bit „git merge”. Możesz powiedzieć „git merge origin / master”, a to połączy wersję master źródła w bieżącym HEAD. „Git pull origin master” robi to samo, chociaż najpierw pobierze pobieranie (a jeśli już wykonałeś zdalną aktualizację git, nie będzie nic więcej do pobrania, więc jest zbędny). Tak, możesz powiedzieć „git push foo”, co spowoduje wypchnięcie wszystkich pasujących gałęzi do pilota o nazwie „foo”.
araqnid
IIUC nie możesz pchać do działającego repozytorium (w końcu możesz pchać niekompatybilne / nieprzetestowane / niechciane zmiany). Musimy przepychać się do czystych repozytoriów i otrzymywać aktualizacje tylko wtedy, gdy ściągniemy. Czy to rozwiązanie wymaga działającego i czystego repozytorium na każdym komputerze?
joeytwiddle
2
Wygląda na to, że możesz mieć jedno naciśnięcie na kilka repozytoriów, sprawdź tę odpowiedź, aby uzyskać więcej informacji stackoverflow.com/questions/14290113/…
manei_cc
797

Robienie tego ręcznie nie jest już konieczne , dzięki nowoczesnym wersjom git! Zobacz rozwiązanie Malvineousa poniżej.

Reprodukcja tutaj:

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

Oryginalna odpowiedź:

Tego używam od dłuższego czasu bez złych konsekwencji i zasugerował Linus Torvalds na liście mailowej git .

Rozwiązanie araqnid jest odpowiednie do wprowadzenia kodu do repozytorium… ale kiedy, tak jak ja, masz wiele równoważnych autorytatywnych upstreamów (trzymam niektóre z moich bardziej krytycznych projektów sklonowane zarówno na prywatnym serwerze, GitHub, jak i Codaset), codzienne zmiany mogą być trudne.

Krótko mówiąc, git remote add wszystkie Twoje piloty indywidualnie… a następnie git config -edodaj scalonego pilota. Zakładając, że masz to repozytorium 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/*

… Aby utworzyć scalony-zdalny dla "Paws"i "Codaset", mogę dodać następujące po tych wszystkich:

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

Kiedy to zrobię, kiedy git push Origin Masterto zrobię, popchnie to jedno Paws/Masteri drugie Codaset/Master, co ułatwi życie.

ELLIOTTCABLE
źródło
104
git config -eotwiera .git/configplik w preferowanym edytorze.
Richard
3
W razie czego. Potwierdzenie, że posiadanie pilota z 2 adresami URL nadal wykonuje zadanie w dniu 1.7.12.4. Dzięki.
foobar
26
Nazwałem
1
@JamesWomack patrz odpowiedź @ Malvineousa poniżej. Jest teraz „bardziej poprawny”, ponieważ gitwiersz poleceń obsługuje to natywnie, z git remote set-url ... --add.
ELLIOTTCABLE,
1
W [branch "Master"]zestawie remote = Origini git pullbędą używać oba piloty.
Bengt
264

Od wersji 1.8 Gitta (październik 2012 r.) Możesz to zrobić z wiersza poleceń:

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

Następnie git pushprześle do użytkownika user1 @ repo1, a następnie do user2 @ repo2.

Malvineous
źródło
19
Zdecydowanie odradzam to rozwiązanie. Wykorzystaliśmy go w naszej firmie i popadliśmy w poważne kłopoty z hakami zawiedzionymi w jednym repozytorium, ale nie w drugim. Zestawy zmian były wtedy obecne tylko w jednym repozytorium.
Michael Schmeißer
4
@ MichaelSchmeißer: Prawdopodobnie widziałeś komunikaty o błędach podczas wypychania, napraw problem, a następnie pchnij ponownie, aby wszystko powróciło do stanu czystego?
Malvineous
7
Problem polega na tym, że naprawienie odrzuconego wypychania polega na zmianie zatwierdzeń, które zostały już wypchnięte na inne repozytorium. Tak więc, jeśli ktoś już oparł się na tych zobowiązaniach do czasu ich naprawienia, sytuacja staje się naprawdę paskudna, jak miało to miejsce w naszym biurze.
Michael Schmeißer
9
Ach tak, to może być trudne. Wydaje mi się jednak, że haczyki wymagają przeprojektowania. Nieudane wypychanie nie łamie gita normalnie, więc wprowadzenie nowego punktu awarii (który również uniemożliwia użycie sprytnej funkcji git) prawdopodobnie nie jest najlepszym rozwiązaniem. Oczywiście mówię to, nie wiedząc, jakie są twoje wymagania ...
Malvineous
3
Nie. Od czasu napisania mojego pytania przeczytałem inne posty w Internecie, a następnie przetestowałem to. Po przeczytaniu innych postów mam podejrzenie, że używana jest tylko pierwsza linia. Właśnie to przetestowałem: w rzeczywistości sprawdzany jest tylko adres URL z pierwszego wiersza git fetch. (Biorąc to pod uwagę, nie rozumiem, bez czego git remote set-url --addmoże być cel --push.)
imz - Iwan Zachararyszew
34

Dodałem te aliasy do mojego ~ / .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
źródło
6
To jest niesamowite! Skończyło się na tym, że mam alias Git: git config alias.pushall '!for i in git remote; do git push $i; done;'
Ciro Santilli 冠状 病毒 审查 六四 事件 法轮功
Myślę, że wolę rozwiązanie aliasowe niż tworzenie nowego pilota. Zobacz także stackoverflow.com/questions/41372919/…
donquixote
1
Mała sugerowana poprawka:alias pushall='for i in `git remote`; do echo "Pushing to " $i; git push $i; done;'
Scott C Wilson
25

Możesz dodawać piloty za pomocą:

git remote add a urla
git remote add b urlb

Następnie, aby zaktualizować wszystkie repozytoria:

git remote update
FelipeC
źródło
15

Oto mój przykład ze skryptem bash w .gitconfigsekcji aliasów

[alias]
        pushall = "!f(){ for i in `git remote`; do git push $i; done; };f"
troex
źródło
7

Dodałem dwa oddzielne pushurl do zdalnego „origin” w pliku .git congfig. Kiedy biegnę, git push origin "branchName"to przejdzie i przepchnie do każdego adresu URL. Nie jestem pewien, czy istnieje łatwiejszy sposób na osiągnięcie tego, ale to działa na mnie, aby jednocześnie przesłać do kodu źródłowego Github i do kodu źródłowego My.visualStudio.

[remote "origin"]
  url = "Main Repo URL"
  fetch = +refs/heads/*:refs/remotes/origin/*
  pushurl = "repo1 URL"
  pushurl = "reop2 URl"
dstineback
źródło
4

Pozwoliłem sobie rozszerzyć odpowiedź od non-urbiz; po prostu dodaj to do swojego ~ / .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

Stosowanie:

git-pullall master

git-pushall master ## or
git-pushall

Jeśli nie podasz żadnego argumentu gałęzi dla git-pullall, ściąganie z innych niż domyślne pilotów zakończy się niepowodzeniem; pozostawił takie zachowanie, ponieważ jest analogiczne do git.

hsk81
źródło
3

Będziesz potrzebował skryptu, aby przejść przez nie. Git nie zapewnia „push all”. Można teoretycznie wykonać wypychanie w wielu wątkach, ale natywna metoda nie jest dostępna.

Pobieranie jest jeszcze bardziej skomplikowane i polecam to zrobić liniowo.

Myślę, że twoją najlepszą odpowiedzią jest posiadanie maszyny, na którą wszyscy robią push / pull, jeśli to w ogóle możliwe.

Jeff Ferland
źródło
2
Problem polega na tym, jak opisałem, że nie ma centralnego zawsze dostępnego pudełka. Jeśli muszę napisać skrypt bash z pętlą, niech tak będzie, ale wydaje się zabawne, że rozproszone VC nie pomogłoby mi tutaj bardziej ...
Zorzella
2
Dystrybucja zakłada, że ​​nie wszyscy są dostępni lub chcieli zostać zepchnięci. Dotyczy to również różnych repozytoriów znajdujących się w różnych stanach oraz założenia, że ​​inni pracują nad nimi jednocześnie. Kolejność wypychania i wyciągania z zestawu repozytoriów wpływa na stan różnych repozytoriów i musiałbyś wykonać wiele przejść, aby wszystkie były naprawdę zsynchronizowane. Dlatego nie ma „pull / push all”. Potem są konflikty ...;)
Jeff Ferland
3

W przypadku aktualizacji pilotów (tj. pullObudowy) sprawy stały się łatwiejsze.

Oświadczenie Linusa

Niestety, nie ma nawet żadnego sposobu, aby to sfałszować za pomocą aliasu git.

w wymienionej wpisu na listę mailingową Git w odpowiedzi elliottcable użytkownika nie jest już prawdą.

git fetch nauczyłem się --all gdzieś w przeszłości parametru pozwalającego pobrać wszystkie piloty za jednym razem.

Jeśli nie wszystkie są wymagane, można użyć --multipleprzełącznika, aby określić wiele pilotów lub grupę.

eckes
źródło
3

Chciałem pracować w VSO / TFS, a następnie pchnąć publicznie do GitHub, gdy będzie gotowy. Pierwsze repo utworzone w prywatnym VSO. Kiedy przyszedł czas na dodanie do GitHub, zrobiłem:

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

Pracował jak mistrz ...

W celu sprawdzenia poprawności należy wydać polecenie „git remote -v”, aby wyświetlić listę repozytoriów powiązanych z projektem.

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)

Prosty sposób, pracował dla mnie ... Mam nadzieję, że to komuś pomaga.

Joe Healy
źródło
4
Bieganie git push -fbez powodu, np. Niepowodzenie git pushlub wiedza o tym, co się robi, jest złym pomysłem, potencjalnie szkodliwym. To również nie odpowiada na pytanie, ale jak dodać drugiego pilota.
Karl Richter
2

dodaj alias do globalnego gitconfig (/home/user/.gitconfig) za pomocą poniższego polecenia.

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

Po zatwierdzeniu kodu mówimy

git push

domyślnie wypychać do źródła. Po powyższym aliasie możemy powiedzieć

git pushall

a kod zostanie zaktualizowany do wszystkich pilotów, w tym zdalnego pochodzenia.

dhirajforyou
źródło
1

Dodawanie all pilota staje się trochę żmudne, ponieważ musisz skonfigurować na każdym używanym komputerze.

Ponadto wszystkie podane aliasybash i zakładają, że będziesz naciskać na wszystkie piloty. (Np .: Mam rozwidlenie, które utrzymuję w GitHub i GitLab. Mam upstreamgit sshag dodany pilot , ale nie mam uprawnień, aby do niego pchać.)

Oto git alias, który naciska tylko na piloty z włączonym wypychanym adresem URL @.

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

Dodanie nowego pilota

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

git remote -vv

Pobierz z wielu lokalizacji

git fetch --all

Przekaż do lokalizacji

git push -u upstream/dev
Dadaso Zanzane
źródło