Ziehen / Drücken von mehreren entfernten Standorten


743

Das kurze: Gibt es eine Möglichkeit, ein Git-Repo auf eine Liste von Remote-Repos zu schieben und von dieser zu ziehen (anstatt auf einen einzelnen "Ursprung")?

Das lange: Ich habe oft eine Situation, in der ich eine App auf mehreren Computern mit unterschiedlicher Konnektivität entwickle - beispielsweise einen Laptop während der Übertragung, einen Computer "A" an einem bestimmten Ort und einen anderen Computer "B". während auf einem anderen. Außerdem kann der Laptop nur mit "A" oder "B" und manchmal mit beiden verbunden sein.

Was ich möchte, ist, dass git immer von allen Computern "zieht" und "pusht", auf die es derzeit eine Verbindung herstellen kann, damit es einfacher ist, von einem Computer zum anderen zu springen und nahtlos weiterzuarbeiten.


39
Hinweis für neue Besucher, ab 2016: Der aktuell richtige Weg , dies zu tun, sanktionierte durch erstklassige gitFunktionen, ist in enthalten malvineous ‚s Antwort unten . Die akzeptierte Antwort ist falsch.
ELLIOTTCABLE

@Zorzella: Kannst du die akzeptierte Antwort dazu aktualisieren? Es ist ein bisschen verwirrend, wie es derzeit ist.
Ntninja

Antworten:


503

Sie können mehrere Remote-Repositorys mit dem folgenden git remoteBefehl konfigurieren :

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

Gehen Sie folgendermaßen vor, um von allen konfigurierten Fernbedienungen abzurufen und Tracking-Zweige zu aktualisieren, aber nicht zusammenzuführen HEAD:

git remote update

Wenn es derzeit nicht mit einer der Fernbedienungen verbunden ist, dauert es eine Weile oder es wird ein Fehler ausgegeben und mit der nächsten fortgefahren. Sie müssen manuell aus den abgerufenen Repositorys zusammenführen oder cherry-pick, je nachdem, wie Sie das Sammeln von Änderungen organisieren möchten.

Gehen Sie wie folgt vor, um den Hauptzweig von alt abzurufen und in Ihren aktuellen Kopf zu ziehen:

git pull alt master

Also in der Tat git pullist fast Abkürzung für git pull origin HEAD(eigentlich sieht es in der Konfigurationsdatei, um dies zu bestimmen, aber Sie bekommen die Idee).

Um Updates zu pushen, müssen Sie dies für jedes Repo manuell tun.
Ich denke, ein Push wurde unter Berücksichtigung des Workflows des zentralen Repositorys entwickelt.


Sie sagen also, dass "git remote add foo ssh: //foo.bar/baz" eine Kurzform erstellt, aber ich muss sie immer noch mit einem "git pull" oder mit einem "git" durchlaufen merge "(wie lautet die Syntax hier nach einem" git remove update "?) Funktioniert dieser Kurzname nicht auch für" git push "? Dh kann ich nicht "git push foo" etc (Schleife)? Danke
Zorzella

8
"git pull" ist im Grunde "git fetch", gefolgt von "git merge". "git remote update" erledigt nur eine Reihe von "git fetch" -Aufrufen für Sie. Was also bleibt, ist das "Git Merge" -Bit. Sie können "git merge origin / master" sagen und die Origin-Version von master wird in Ihrem aktuellen HEAD zusammengeführt. "git pull origin master" macht dasselbe, obwohl es zuerst einen Abruf ausführt (und wenn Sie bereits ein git remote update durchgeführt haben, muss das nicht mehr abgerufen werden, daher ist es redundant). Ja, Sie können "git push foo" sagen und alle passenden Zweige werden auf die Fernbedienung "foo" übertragen.
Araqnid

IIUC können Sie nicht in ein funktionierendes Repository verschieben (schließlich können Sie inkompatible / nicht getestete / unerwünschte Änderungen übertragen). Wir müssen in nackte Repositorys pushen und nur dann Updates erhalten, wenn wir ziehen. Die Lösung erfordert also ein funktionierendes und ein nacktes Repository auf jedem Computer?
Joeytwiddle

2
Anscheinend können Sie auch einen einzigen Push für mehrere Repos ausführen.
manei_cc

797

Dies manuell zu tun ist bei modernen Versionen von nicht mehr erforderlichgit ! Siehe Malvineous 'Lösung unten.

Hier wiedergegeben:

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

Ursprüngliche Antwort:

Dies ist etwas, das ich seit einiger Zeit ohne schlimme Konsequenzen benutze und das Linus Torvalds auf der Git-Mailingliste vorgeschlagen hat .

Die Lösung von araqnid ist die richtige, um Code in Ihr Repository zu bringen. Wenn Sie jedoch wie ich mehrere gleichwertige autorisierende Upstreams haben (ich behalte einige meiner kritischeren Projekte, die sowohl für einen privaten Upstream als auch für GitHub und Codaset geklont wurden), ist dies der Fall Es kann schmerzhaft sein, jeden Tag Änderungen an jedem einzelnen vorzunehmen.

Lange Rede, kurzer git remote addSinn , alle Ihre Fernbedienungen einzeln… und dann git config -eund fügen Sie eine zusammengeführte Fernbedienung hinzu. Angenommen, Sie haben dieses Repository 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/*

… Um eine zusammengeführte Fernbedienung für "Paws"und zu erstellen "Codaset", kann ich nach all diesen Folgendes hinzufügen:

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

Sobald ich dies getan habe git push Origin Master, wird es nacheinander Paws/Masterund Codaset/Masternacheinander gedrückt, was das Leben ein wenig einfacher macht.


104
git config -eöffnet die .git/configDatei in Ihrem bevorzugten Editor.
Richard

3
Nur für den Fall. Bestätigen, dass eine Fernbedienung mit 2 URLs am 1.7.12.4 noch funktioniert. Vielen Dank.
Foobar

26
Ich habe den "Ursprung" remote "all" genannt, um ihm eine etwas sauberere Semantik zu verleihen
ErichBSchulz

1
@ JamesWomack siehe @ Malvineous 'Antwort unten. Es ist jetzt "korrekter", da gitdie Befehlszeile dies nativ unterstützt, mit git remote set-url ... --add.
ELLIOTTCABLE

1
Unter [branch "Master"]Set remote = Originund git pullwerden beide Fernbedienungen verwendet.
Bengt

264

Seit Git 1.8 (Oktober 2012) können Sie dies über die Befehlszeile tun:

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

Dann git pushwird auf user1 @ repo1 und dann auf user2 @ repo2 gedrückt.


19
Ich rate dringend von dieser Lösung ab. Wir haben es in unserer Firma verwendet und sind in ernsthafte Schwierigkeiten geraten, weil Hooks an einem Repository fehlgeschlagen sind, am anderen jedoch nicht. Änderungssätze waren dann nur in einem Repository vorhanden.
Michael Schmeißer

4
@ MichaelSchmeißer: Vermutlich konnten Sie die Fehlermeldungen beim Drücken sehen, das Problem beheben und dann erneut drücken, um alles wieder in einen sauberen Zustand zu bringen?
Malvineous

7
Das Problem ist, dass das Korrigieren des abgelehnten Pushs das Ändern der Commits beinhaltet, die bereits auf das andere Repo übertragen wurden. Wenn also jemand zu dem Zeitpunkt, an dem er repariert wurde, bereits auf diesen Verpflichtungen basiert, werden die Dinge wirklich böse, was in unserem Büro der Fall war.
Michael Schmeißer

9
Ah ja, das könnte schwierig werden. Mir scheint jedoch, dass die Haken neu gestaltet werden müssen. Ein fehlgeschlagener Push bricht Git nicht normal, daher ist die Einführung eines neuen Fehlerpunkts (der Sie auch daran hindert, eine raffinierte Git-Funktion zu verwenden) wahrscheinlich nicht die beste Lösung. Natürlich sage ich das, ohne zu wissen, was Ihre Anforderungen sind ...
Malvineous

3
Nein. Seit ich meine Frage geschrieben habe, habe ich andere Webpostings gelesen und diese Sache dann getestet. Durch das Lesen anderer Beiträge habe ich den Verdacht, dass nur die erste Zeile verwendet wird. Ich habe dies gerade getestet: In der Tat wird nur die URL aus der ersten Zeile von überprüft git fetch. (Angesichts dessen verstehe ich nicht, worauf der Zweck verzichten git remote set-url --addkann --push.)
imz - Ivan Zakharyaschev

34

Ich habe diese Aliase zu meinem ~ / .bashrc hinzugefügt:

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
Das ist fantastisch! git config alias.pushall '!for i in ; do git push $i; done;'
Am

Ich glaube, ich bevorzuge die Alias-Lösung gegenüber der Erstellung einer neuen Fernbedienung. Siehe auch stackoverflow.com/questions/41372919/…
donquixote

1
Kleine vorgeschlagene Optimierung:alias pushall='for i in `git remote`; do echo "Pushing to " $i; git push $i; done;'
Scott C Wilson

25

Sie können Fernbedienungen hinzufügen mit:

git remote add a urla
git remote add b urlb

Um dann alle Repos zu aktualisieren, gehen Sie wie folgt vor:

git remote update

15

Hier ist mein Beispiel mit Bash-Skript im .gitconfigAlias-Bereich

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

7

Ich habe dem Remote- "Ursprung" in der .git congfig-Datei zwei separate Pushurl hinzugefügt. Wenn ich laufe git push origin "branchName", läuft es durch und drückt auf jede URL. Ich bin mir nicht sicher, ob es einen einfacheren Weg gibt, dies zu erreichen, aber dies funktioniert für mich, wenn ich gleichzeitig zum Github-Quellcode und zum My.visualStudio-Quellcode pushe.

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

4

Ich nahm mir die Freiheit, die Antwort von nona-urbiz zu erweitern; füge dies einfach zu deinem ~ / .bashrc hinzu:

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

Verwendungszweck:

git-pullall master

git-pushall master ## or
git-pushall

Wenn Sie kein Verzweigungsargument für git-pullall angeben, schlägt das Abrufen von nicht standardmäßigen Fernbedienungen fehl. habe dieses Verhalten so belassen, wie es ist, da es analog zu git ist.


3

Sie benötigen ein Skript, um sie zu durchlaufen. Git bietet kein "Push all". Sie könnten theoretisch einen Push in mehreren Threads ausführen, eine native Methode ist jedoch nicht verfügbar.

Das Abrufen ist noch komplizierter, und ich würde empfehlen, dies linear zu tun.

Ich denke, Ihre beste Antwort ist, eine Maschine zu haben, an der jeder drückt / zieht, wenn das überhaupt möglich ist.


2
Das Problem ist, wie ich beschrieben habe, dass es keine zentrale, immer verfügbare Box gibt. Wenn ich ein Looping-Bash-Skript schreiben muss, soll es so sein, aber es fühlt sich komisch an, dass eine verteilte VC mir hier nicht mehr helfen würde ...
Zorzella

2
Bei der Verteilung wird davon ausgegangen, dass nicht jeder verfügbar ist oder dazu gedrängt werden möchte. Es bezieht sich auch auf verschiedene Repositorys in unterschiedlichen Zuständen und auf die Annahme, dass andere gleichzeitig daran arbeiten. Die Reihenfolge, in der Sie Push- und Pull-Vorgänge aus einer Reihe von Repositorys ausführen, wirkt sich auf den Status verschiedener Repositorys aus. Sie müssen mehrere Durchgänge ausführen, um alle wirklich zu synchronisieren. Aus diesem Grund gibt es kein "Pull / Push All". Dann gibt es Konflikte ...;)
Jeff Ferland

3

Für die Aktualisierung der Fernbedienungen (dh des pullFalls) sind die Dinge einfacher geworden.

Die Aussage von Linus

Leider gibt es nicht einmal eine Möglichkeit, dies mit einem Git-Alias ​​vorzutäuschen.

in dem referenzierten Eintrag auf der Git-Mailingliste in elliottcables Antwort ist nicht mehr wahr.

git fetchIch habe den --allParameter irgendwo in der Vergangenheit gelernt , um alle Fernbedienungen auf einmal abrufen zu können.

Wenn nicht alle angefordert werden, kann der --multipleSchalter verwendet werden, um mehrere Fernbedienungen oder eine Gruppe anzugeben.


3

Ich wollte in VSO / TFS arbeiten und dann öffentlich auf GitHub pushen, wenn ich fertig bin. Erstes Repo in privatem VSO erstellt. Als es an der Zeit war, GitHub hinzuzufügen, tat ich Folgendes:

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

Arbeitete wie ein Champion ...

Geben Sie für eine Überprüfung der Integrität "git remote -v" aus, um die einem Projekt zugeordneten Repositorys aufzulisten.

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)

Einfacher Weg, für mich gearbeitet ... Hoffe das hilft jemandem.


4
Laufen git push -fohne Grund, z. B. git pushwenn man nicht weiß oder genau weiß, was man tut, ist eine schlechte Idee und möglicherweise schädlich. Dies beantwortet auch nicht die Frage, sondern wie man eine zweite Fernbedienung hinzufügt.
Karl Richter

2

Fügen Sie der globalen gitconfig (/home/user/.gitconfig) mit dem folgenden Befehl einen Alias ​​hinzu.

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

Sobald Sie Code festschreiben, sagen wir

Git Push

standardmäßig zum Ursprung pushen. Nach dem obigen Alias ​​können wir sagen

Git Pushall

Der Code wird auf alle Fernbedienungen einschließlich der Ursprungsfernbedienung aktualisiert.


1

Hinzufügen der all Fernbedienung wird etwas mühsam, da Sie sie auf jedem von Ihnen verwendeten Computer einrichten müssen.

Auch die bashund git Aliase , sofern alle an , dass Sie drückt haben alle Fernbedienungen. (Beispiel: Ich habe eine Gabelung sshag, die ich auf GitHub und GitLab pflege. Ich habe den Upstream Fernbedienung hinzugefügt, aber ich habe keine Berechtigung, darauf zu pushen.)

Hier ist ein git Alias , der nur auf Remotes mit einer Push-URL pusht, die enthält @.

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

-3

Neue Fernbedienung hinzufügen

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

git remote -vv

Abrufen von mehreren Speicherorten

git fetch --all

An Orte drücken

git push -u upstream/dev
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.