tirer / pousser depuis plusieurs emplacements distants

743

Le court: existe-t-il un moyen d'avoir un git repo push to et pull from a remote of remote repos (plutôt qu'une seule "origine")?

Le long: J'ai souvent une situation où je développe une application sur plusieurs ordinateurs, avec une connectivité différente - disons un ordinateur portable pendant le transport, un ordinateur "A" pendant que je suis dans un certain endroit et un autre ordinateur "B" tandis que sur un autre. En outre, l'ordinateur portable peut avoir une connectivité avec uniquement "A" ou "B", et parfois les deux.

Ce que je voudrais, c'est que git "tire" et "pousse" toujours vers tous les ordinateurs auxquels il peut actuellement se connecter, il est donc plus facile de passer d'une machine à l'autre et de continuer à travailler de manière transparente.

Zorzella
la source
39
Note pour les nouveaux visiteurs, à partir de 2016: La manière actuellement correcte de le faire, sanctionnée par des fonctionnalités de première classe git, est incluse dans la réponse de Malvineous ci-dessous . La réponse acceptée est incorrecte.
ELLIOTTCABLE
@Zorzella: Pouvez-vous mettre à jour la réponse acceptée à ce sujet, c'est un peu déroutant tel qu'il est actuellement.
ntninja

Réponses:

503

Vous pouvez configurer plusieurs référentiels distants avec la git remotecommande:

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

Pour récupérer à partir de toutes les télécommandes configurées et mettre à jour les branches de suivi, mais sans les fusionner HEAD, procédez comme suit :

git remote update

S'il n'est pas actuellement connecté à l'une des télécommandes, cela prendra du temps ou lancera une erreur, et passera à la suivante. Vous devrez fusionner manuellement à partir des référentiels récupérés ou cherry-pick, selon la façon dont vous souhaitez organiser la collecte des modifications.

Pour récupérer la branche principale d'Alt et la tirer dans votre tête actuelle, procédez comme suit:

git pull alt master

Donc, en fait, git pullc'est presque un raccourci pour git pull origin HEAD(en fait, il regarde dans le fichier de configuration pour le déterminer, mais vous avez l'idée).

Pour pousser les mises à jour, vous devez le faire manuellement pour chaque dépôt.
Une poussée a été, je pense, conçue avec le flux de travail du référentiel central à l'esprit.

araqnid
la source
donc ce que vous dites est que "git remote add foo ssh: //foo.bar/baz" crée une forme abrégée, mais j'ai encore besoin de les boucler avec un "git pull", ou de les boucler avec un "git merge "(quelle est la syntaxe ici, après une" mise à jour git remove "?) Ce nom abrégé ne fonctionnera-t-il pas également pour" git push "? C'est-à-dire que je ne peux pas "git push foo" etc (boucle)? Merci
Zorzella
8
"git pull" est fondamentalement "git fetch" suivi de "git merge". "git remote update" fait juste un tas d'appels "git fetch" pour vous. Il reste donc à faire le bit "git merge". Vous pouvez dire "git merge origin / master" et il fusionnera la version d'origine de master dans votre HEAD actuel. "git pull origin master" fait la même chose, bien qu'il fasse d'abord une récupération (et si vous avez déjà fait une mise à jour à distance de git, cela n'aura plus rien à récupérer, donc c'est redondant). Oui, vous pouvez dire "git push foo" et il poussera toutes les branches correspondantes vers la télécommande appelée "foo".
araqnid
IIUC vous ne pouvez pas pousser dans un référentiel de travail (après tout, vous pouvez pousser des modifications incompatibles / non testées / indésirables). Nous devons pousser dans des référentiels nus et ne recevoir des mises à jour que lorsque nous tirons. La solution nécessite donc un référentiel fonctionnel et nu sur chaque machine?
joeytwiddle
2
Apparemment, vous pouvez également avoir une seule poussée pour plusieurs dépôts, vérifiez cette réponse pour plus de détails stackoverflow.com/questions/14290113/…
manei_cc
797

Faire cela manuellement n'est plus nécessaire , avec les versions modernes de git! Voir la solution de Malvineous ci-dessous.

Reproduit ici:

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

Réponse originale:

C'est quelque chose que j'utilise depuis un bon moment sans conséquences graves et suggéré par Linus Torvalds sur la liste de diffusion git .

La solution de araqnid est la bonne pour introduire du code dans votre référentiel ... mais lorsque vous, comme moi, avez plusieurs équivalents faisant autorité en amont (je garde certains de mes projets les plus critiques clonés à la fois vers un amont privé, GitHub et Codaset), il peut être une douleur de pousser des changements à chacun, chaque jour.

Longue histoire courte, git remote add toutes vos télécommandes individuellement ... puis git config -eajoutez une télécommande fusionnée. En supposant que vous ayez ce référentiel 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/*

... pour créer une télécommande fusionnée pour "Paws"et "Codaset", je peux ajouter ce qui suit après tout cela:

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

Une fois que j'ai fait cela, quand je le ferai git push Origin Master, cela ira aux deux Paws/Masteret Codaset/Masterséquentiellement, ce qui facilitera un peu la vie.

ELLIOTTCABLE
la source
104
git config -eouvre le .git/configfichier dans votre éditeur préféré.
Richard
3
Au cas où. Confirmer que le fait d'avoir une télécommande avec 2 URL fait toujours le travail sur 1.7.12.4. Merci.
foobar
26
J'ai nommé la télécommande "origin" "all" pour lui donner une sémantique légèrement plus propre
ErichBSchulz
1
@JamesWomack voir la réponse de @ Malvineous, ci-dessous. C'est "plus correct" maintenant, car gitla ligne de commande de 'supporte cela nativement, avec git remote set-url ... --add.
ELLIOTTCABLE
1
Sous [branch "Master"]défini remote = Originet git pullutilisera les deux télécommandes.
Bengt
264

Depuis git 1.8 (octobre 2012), vous pouvez le faire depuis la ligne de commande:

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

Ensuite git push, poussera vers user1 @ repo1, puis poussera vers user2 @ repo2.

Malvineous
la source
19
Je déconseille fortement cette solution. Nous l'avons utilisé dans notre entreprise et avons rencontré de sérieux problèmes avec des crochets qui échouent dans un référentiel, mais pas dans l'autre. Les ensembles de modifications n'étaient alors présents que dans un seul référentiel.
Michael Schmeißer
4
@ MichaelSchmeißer: Vraisemblablement, vous pouvez voir les messages d'erreur lorsque vous poussez, résolvez le problème, puis appuyez à nouveau pour que tout revienne à un état propre?
Malvineous
7
Le problème est que la correction du push rejeté implique de changer les commits qui ont déjà été poussés vers l'autre dépôt. Donc, si quelqu'un a déjà basé le travail sur ces engagements au moment où ils sont corrigés, les choses deviennent vraiment désagréables, ce qui était le cas dans notre bureau.
Michael Schmeißer
9
Ah oui, cela pourrait devenir délicat. Cependant, il me semble que les crochets doivent être repensés. Un push échoué ne casse pas git normalement, donc l'introduction d'un nouveau point d'échec (qui vous empêche également d'utiliser une fonctionnalité git astucieuse) n'est probablement pas la meilleure solution. Bien sûr, je dis cela sans savoir quelles sont vos exigences ...
Malvineous
3
Non. Depuis que j'ai écrit ma question, j'ai lu d'autres articles sur le Web et j'ai testé cette chose. En lisant d'autres articles, j'ai le soupçon que seule la première ligne est utilisée. Je viens de tester ceci: en effet, seule l'URL de la première ligne est inspectée par git fetch. (Compte tenu de cela, je ne comprends pas ce que le but de git remote set-url --addpeut être sans --push.)
imz - Ivan Zakharyaschev
34

J'ai ajouté ces alias à mon ~ / .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
la source
6
C'est génial! J'ai fini par avoir un alias Git: git config alias.pushall '!for i in git remote; do git push $i; done;'
Ciro Santilli 22 冠状 病 六四 事件 法轮功
Je pense que je préfère la solution d'alias à la création d'une nouvelle télécommande. Voir aussi stackoverflow.com/questions/41372919/…
donquixote
1
Petit ajustement suggéré:alias pushall='for i in `git remote`; do echo "Pushing to " $i; git push $i; done;'
Scott C Wilson
25

Vous pouvez ajouter des télécommandes avec:

git remote add a urla
git remote add b urlb

Ensuite, pour mettre à jour tous les dépôts:

git remote update
FelipeC
la source
15

Voici mon exemple avec le script bash dans la .gitconfigsection alias

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

J'ai ajouté deux pushurl séparés à l '"origine" distante dans le fichier congfig .git. Quand je cours git push origin "branchName", il passe par et passe à chaque URL. Je ne sais pas s'il existe un moyen plus facile d'accomplir cela, mais cela fonctionne pour moi-même pour pousser vers le code source Github et pour pousser vers le code source My.visualStudio en même temps.

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

J'ai pris la liberté d'élargir la réponse de nona-urbiz; ajoutez simplement ceci à votre ~ / .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

Usage:

git-pullall master

git-pushall master ## or
git-pushall

Si vous ne fournissez aucun argument de branche pour git-pullall, alors l'extraction à partir de télécommandes autres que par défaut échouera; laissé ce comportement tel quel, car il est analogue à git.

hsk81
la source
3

Vous aurez besoin d'un script pour les parcourir. Git ne propose pas de «pousser tout». Vous pourriez théoriquement faire un push dans plusieurs threads, mais une méthode native n'est pas disponible.

La récupération est encore plus compliquée, et je recommanderais de le faire de manière linéaire.

Je pense que votre meilleure réponse est d'avoir une seule machine à laquelle tout le monde fait un push / pull, si c'est possible.

Jeff Ferland
la source
2
Le problème est, comme je l'ai décrit, qu'il n'y a pas de boîte centrale toujours disponible. Si je dois écrire un script bash en boucle, tant
pis
2
Étant distribué, cela suppose que tout le monde n'est pas disponible ou n'a pas voulu être poussé. Cela concerne également le fait que différents référentiels se trouvent dans des états différents et l'hypothèse que d'autres y travaillent simultanément. L'ordre dans lequel vous poussez et tirez d'un ensemble de référentiels affecte l'état des différents référentiels, et vous devez effectuer plusieurs passes pour les synchroniser. C'est pourquoi il n'y a pas de "pull / push all". Puis il y a des conflits ...;)
Jeff Ferland
3

Pour la mise à jour des télécommandes (c'est-à-dire le pullcas), les choses sont devenues plus faciles.

La déclaration de Linus

Malheureusement, il n'y a même aucun moyen de simuler cela avec un alias git.

dans l'entrée référencée de la liste de diffusion Git dans la réponse d'elliottcable n'est plus vraie.

git fetchappris le --allparamètre quelque part dans le passé permettant de récupérer toutes les télécommandes en une seule fois.

Si tous ne sont pas demandés, on pourrait utiliser le --multiplecommutateur afin de spécifier plusieurs télécommandes ou un groupe.

eckes
la source
3

Je voulais travailler dans VSO / TFS, puis pousser publiquement vers GitHub lorsque je suis prêt. Repo initial créé dans VSO privé. Quand est venu le temps d'ajouter à GitHub, j'ai fait:

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

A travaillé comme un champion ...

Pour un contrôle d'intégrité, lancez "git remote -v" pour répertorier les référentiels associés à un projet.

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)

Manière simple, a fonctionné pour moi ... J'espère que cela aide quelqu'un.

Joe Healy
la source
4
Courir git push -fsans raison, par exemple l'échec de git pushou savoir exactement ce que l'on fait, est une mauvaise idée et potentiellement nuisible. Cela ne répond pas non plus à la question, mais comment ajouter une deuxième télécommande.
Karl Richter
2

ajoutez un alias à gitconfig global (/home/user/.gitconfig) avec la commande ci-dessous.

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

Une fois que vous avez validé le code, nous disons

git push

pour pousser à l'origine par défaut. Après l'alias ci-dessus, on peut dire

git pushall

et le code sera mis à jour pour toutes les télécommandes, y compris la télécommande d'origine.

dhirajforyou
la source
1

Ajout du all télécommande devient un peu fastidieux car vous devez configurer sur chaque machine que vous utilisez.

Également bashgit alias et fournis supposent tous que vous disposerez de toutes les télécommandes. (Ex: j'en ai une fourchette sshagque je conserve sur GitHub et GitLab. J'ai l' amont télécommande en ajoutée, mais je n'ai pas la permission d'y pousser.)

Voici un git alias qui ne pousse que vers les télécommandes avec une URL push qui inclut @.

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

Ajout d'une nouvelle télécommande

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

git remote -vv

Récupérer plusieurs emplacements

git fetch --all

Poussez vers des emplacements

git push -u upstream/dev
Dadaso Zanzane
la source