Suivre toutes les branches git distantes en tant que branches locales

175

Le suivi d'une seule branche distante en tant que branche locale est assez simple.

$ git checkout --track -b ${branch_name} origin/${branch_name}

Pousser toutes les branches locales vers la télécommande, créer de nouvelles branches distantes selon les besoins est également facile.

$ git push --all origin

Je veux faire l'inverse. Si j'ai un nombre X de succursales distantes à une seule source:

$ git branch -r 
branch1
branch2
branch3
.
.
.

Puis-je créer des branches de suivi locales pour toutes ces branches distantes sans avoir à les créer manuellement? Dites quelque chose comme:

$ git checkout --track -b --all origin

J'ai googlé et des RTM, mais je suis venu jusqu'à présent.

Janson
la source
3
Il existe un moyen encore plus simple de suivre une seule branche distante en tant que branche locale:git checkout --track origin/branchname
Cerran
Ce n'est pas exactement ce que vous avez demandé, mais cela fonctionne pour moi: obtenez les complétions git: github.com/git/git/blob/master/contrib/completion/… . Puis tapez git pull origin et appuyez sur tab, pour obtenir une liste des branches distantes. Puis continuez à taper et appuyez sur return.
Max Heiber

Réponses:

111

Utilisation de bash:

après git 1.9.1
for i in `git branch -a | grep remote | grep -v HEAD | grep -v master`; do git branch --track ${i#remotes/origin/} $i; done

crédits: Val Blant, elias et Hugo

avant git 1.9.1

Remarque: le code suivant s'il est utilisé dans les versions ultérieures de git (> v1.9.1) provoque

  1. (bug) Toutes les branches créées pour suivre le master
  2. (ennui) Tous les noms de succursales locales créés doivent être préfixés avec origin/
for remote in `git branch -r `; do git branch --track $remote; done

Mettez à jour les succursales, en supposant qu'il n'y a pas de changements sur vos succursales de suivi locales:

for remote in `git branch -r `; do git checkout $remote ; git pull; done

Ignorez les avertissements ambigus de refname, git semble préférer la branche locale comme il se doit.

Otto
la source
2
Merci pour les avertissements concernant les refname. Cela a été utile.
Paul
1
Merci Otto, je soupçonnais que le script serait la seule solution. Vous en avez fourni un assez simple.
Janson
1
@Jason est-il encore aujourd'hui la seule solution?
cregox
1
@Cawas: vous devez créer manuellement des branches de suivi, mais git pulldispose d'un --allcommutateur, qui récupérera + fusionnera toutes les branches suivies.
naught101
13
Cela n'a pas fonctionné pour moi sur Git 1.9.1. "git branch --track <banch_name>" crée une nouvelle branche <branch_name> qui suit le maître de la branche locale, au lieu de la branche distante que nous voulions. Donc, ce script a créé un tas de branches locales pointant toutes vers le maître local. Je posterai la solution ci-dessous.
Val Blant
183

La réponse d'Otto est bonne, mais toutes les branches créées auront "origine /" comme début du nom. Si vous voulez juste que la dernière partie (après le dernier /) soit vos noms de branche résultants, utilisez ceci:

for remote in `git branch -r | grep -v /HEAD`; do git checkout --track $remote ; done

Il a également l'avantage de ne vous donner aucun avertissement sur les références ambiguës.

tjmcewan
la source
Git n'ajoutera pas "origine" au nom de la branche de suivi locale.
Adam Dymitruk
14
@adymitruk: En fait, il se comporte exactement comme je l'ai dit pour moi sur OSX 10.6.4, en utilisant git 1.7.2.2 (la dernière version stable de ce commentaire). Otto mentionne même des avertissements de nom de référence ambigus - les avertissements n'auraient pas besoin d'exister si "origin /" ne faisait pas partie de chaque nom de branche locale. Voici la sortie 'git branch' après avoir exécuté la commande d'Otto: [master, origin / HEAD, origin / charts, origin / master, origin / production, origin / staging]. Et ma commande: [graphiques, master, production, mise en scène].
tjmcewan
1
+ Edit: trouvé l' article.gmane.org/gmane.comp.version-control.git/112575 expliquant pourquoi.
Philip Oakley
8
Je suis d'accord - c'est une meilleure solution que ce qui est actuellement la réponse «acceptée».
tobias.mcnulty
2
Au lieu de grep -v master, qu'en est-il grep -v /HEAD? Cela semble filtrer la branche par défaut, sans nécessiter de personnalisation
dashrb
22

La plupart des réponses ici compliquent trop l'analyse de la sortie de git branch -r. Vous pouvez utiliser la forboucle suivante pour créer les branches de suivi contre toutes les branches de la télécommande comme ceci.

Exemple

Disons que j'ai ces succursales éloignées.

$ git branch -r
  origin/HEAD -> origin/master
  origin/development
  origin/integration
  origin/master
  origin/production
  origin/staging

Confirmez que nous ne suivons déjà rien d'autre que le maître, localement:

$ git branch -l    # or using just git branch
* master

Vous pouvez utiliser cette seule ligne pour créer les branches de suivi:

$ for i in $(git branch -r | grep -vE "HEAD|master"); do 
    git branch --track ${i#*/} $i; done
Branch development set up to track remote branch development from origin.
Branch integration set up to track remote branch integration from origin.
Branch production set up to track remote branch production from origin.
Branch staging set up to track remote branch staging from origin.

Maintenant confirmez:

$ git branch
  development
  integration
* master
  production
  staging

Pour les supprimer:

$ git br -D production development integration staging 
Deleted branch production (was xxxxx).
Deleted branch development (was xxxxx).
Deleted branch integration (was xxxxx).
Deleted branch staging (was xxxxx).

Si vous utilisez le -vvcommutateur pour, git branchvous pouvez confirmer:

$ git br -vv
  development xxxxx [origin/development] commit log msg ....
  integration xxxxx [origin/integration] commit log msg ....
* master      xxxxx [origin/master] commit log msg ....
  production  xxxxx [origin/production] commit log msg ....
  staging     xxxxx [origin/staging] commit log msg ....

Répartition de la boucle for

La boucle appelle essentiellement la commande git branch -r, filtrant toutes les branches HEAD ou master dans la sortie en utilisant grep -vE "HEAD|master". Pour obtenir les noms des seules branches moins la origin/sous - chaîne, nous utilisons la manipulation de chaîne de Bash ${var#stringtoremove}. Cela supprimera la chaîne "stringtoremove" de la variable $var. Dans notre cas, nous supprimons la chaîne origin/de la variable $i.

REMARQUE: vous pouvez également utiliser git checkout --track ...pour faire ceci:

$ for i in $(git branch -r | grep -vE "HEAD|master" | sed 's/^[ ]\+//'); do 
    git checkout --track $i; done

Mais je ne me soucie pas particulièrement de cette méthode, car elle vous permet de basculer entre les branches lors de la vérification. Une fois terminé, il vous laissera sur la dernière branche créée.

Références

slm
la source
1
Fonctionne parfaitement avec git version 2.3.2 (Apple Git-55)
AndrewD
22

Mise à jour Q1 2020: Mohsen Abasi propose dans les commentaires , sur la base des 2014 slm de réponse , l'alternative plus simple:

for i in $(git branch -r | grep -vE "HEAD|master" | sed 's/^[ ]\+//'); 

Et il utilise à la $()place des backticks obsolètes .

Comme je l'ai mentionné dans une autre vieille réponse , l'utilisation git for-each-refest probablement plus rapide .
Et j'utiliser la nouvelle (Git 2.23+) git switchcommande , qui remplace la confusiongit checkout .

for i in $(git for-each-ref --format=%(refname:short) \
  --no-merged=origin/HEAD refs/remotes/origin); do \
    git switch --track $i; \
done

De cette façon, pas grepnécessaire.


Ancienne réponse originale (2011):

Voici mon one-liner que j'utilise (dans un shell bash, testé avec msysgit1.7.4):

Pour copier-coller:

remote=origin ; for brname in `git branch -r | grep $remote | grep -v master | grep -v HEAD | awk '{gsub(/^[^\/]+\//,"",$1); print $1}'`; do git branch --set-upstream-to $remote/$brname $brname; done

Pour plus de lisibilité:

remote=origin ; // put here the name of the remote you want
for brname in `
    git branch -r | grep $remote | grep -v master | grep -v HEAD 
    | awk '{gsub(/^[^\/]+\//,"",$1); print $1}'
`; do 
    git branch --set-upstream-to $remote/$brname $brname; 
done
  • il ne sélectionnera que les branches en amont de la télécommande que vous spécifiez dans la remotevariable (cela peut être ' origin' ou le nom que vous avez défini pour l'une des télécommandes de votre dépôt Git actuel).
  • il va extraire le nom de la branche: origin/a/Branch/Name => a/Branch/Namevia l' awkexpression.
  • il définira la branche amont via --set-upstream-to(ou -u) , non --track:
    l'avantage est que, si la branche existe déjà, elle n'échouera pas et ne changera pas l'origine de la branche, elle ne configurera que le branch.xxx.(remote|merge)paramètre.

    branch.aBranchName.remote=origin
    branch.aBranchName.merge=refs/heads/a/Branch/Name
    

Cette commande créera des branches locales pour toutes les branches en amont distantes et définira leur paramètre distant et de fusion sur cette branche distante.

VonC
la source
5
Cela me donne "fatal: branch 'n'importe quoi' n'existe pas" pour chaque branche qui n'existe que sur la télécommande et qui n'a pas de branche locale correspondante.
Chris Dodd
je pense que si un nom de branche contient / par exemple: feature / rc-41-bckend, cette solution ne fonctionne pas !!!!
Mohsen Abasi
@VonC Basé sur la réponse de "slm": $ for i in $ (git branch -r | grep -vE "HEAD | master" | sed 's / ^ [] \ + //'); faire git checkout --track $ i; done
Mohsen Abasi
@MohsenAbasi Ça a l'air bien. Dans ma réponse, j'ai mentionné utiliser --set-upstream-toplutôt --trackque si.
VonC
@MohsenAbasi J'ai inclus votre alternative dans la réponse pour plus de visibilité. J'ai ajouté une autre façon possible de répertorier les branches distantes et d'utiliser à la git switchplace de git checkout. Mais votre (très bonne) idée demeure.
VonC
14

Vous pourriez écrire cela assez facilement, mais je ne sais pas quand cela serait utile. Ces succursales prendraient assez rapidement du retard et vous deviez les mettre à jour tout le temps.

Les branches distantes seront automatiquement mises à jour, il est donc plus simple de créer simplement la branche locale à l'endroit où vous voulez réellement travailler dessus.

Dustin
la source
2
C'est un bon point. Le cas d'utilisation principal auquel je pense est la configuration d'un environnement de développement local basé sur un référentiel git distant. Ainsi, lorsque je fais mon clonage initial, je souhaite également suivre toutes les branches distantes telles qu'elles sont à ce moment-là.
Janson
1
Le pratique git upmet à jour toutes les succursales locales.
Hugo le
pour fusionner deux dépôts et supprimer la télécommande
endolith
9
for i in `git branch -a | grep remote`; do git branch --track ${i#remotes/origin/} $i; done
Val Blant
la source
4
J'ai dû ajouter un | grep -v HEADau pipeline pour qu'il fonctionne correctement.
Elias Dorneles le
9

sans aucun script (dans un répertoire vide):

$ git clone --bare repo_url .git
$ git config core.bare false
$ git checkout

après cela, toutes les succursales distantes seront considérées comme locales.


original (en russe) .

Aleksandr Barakin
la source
C'est de loin la solution la plus simple et a fonctionné pour moi sur 2.21.0.windows.1
Rotsiser Mho
7

Si vous souhaitez utiliser PowerShell et que votre télécommande s'appelle origin. Ensuite, cela fonctionne.

git fetch    
git branch -r  | %{$_ -replace "  origin/"} | %{git branch --track $_ "origin/$_"}
BigMiner
la source
Cela a été très utile, j'ai fini par utiliser une légère variation pour le faire fonctionner avec mon git svn clone'drepo:git branch -r | %{$_ -replace " origin/"} | %{git checkout -b $_ "origin/$_"}
Nate
J'ai aussi fait une légère variation car mes succursales locales existent déjà:git branch -r | %{$_ -replace " origin/"} | %{git branch -u "origin/$_" $_}
ch271828n
3
for branch in `git branch -a | grep remotes | grep -v HEAD | grep -v master`; do  git branch --track ${branch##*/} $branch; done

Utilisez ceci et vous n'aurez pas d'avertissement tel que: refname 'origin / dev' est ambigu

Bruziuz
la source
3

Voici ma solution de la commande BASH faisant référence par @tjmcewan:

for remote in `git branch -r | grep -v /HEAD `; do git branch --track ${remote/"origin/"/""}; done

Mon objectif est de résoudre le problème que toutes les branches créées auront "origin /" comme début du nom, car j'ai testé que $ variables distantes incluent toujours "origin /":

for remote in `git branch -r | grep -v /HEAD`; do echo $remote ; done
Nick Tsai
la source
Après avoir testé le BASH de @tjmcewan, j'ai trouvé que le nom de toutes les branches suivies sans 'origine /' sur local, je ne sais pas pourquoi.
Nick Tsai
1
La première commande crée des brances qui suivent "master". Ce n'est pas ce que la plupart des gens veulent.
Alexei Osipov
@AlexeiOsipov Merci!
Nick Tsai
2

Pour faire la même chose que la réponse de tjmcewan mais sous Windows, appelez ceci à partir d'un fichier batch :

for /f "delims=" %%r in ('git branch -r ^| grep -v master') do git checkout --track %%r

Ou ceci depuis la ligne de commande :

for /f "delims=" %r in ('git branch -r ^| grep -v master') do git checkout --track %r
Hugo
la source
1

À partir de git 2.23:

for branch in `git branch -r | grep origin/`; do git switch -t -C ${branch#origin/} $branch; git pull; done

L' -Cindicateur de git switchcréation ou de réinitialisation s'il existe déjà.

documentation du commutateur git

AeroX
la source
0

Dans le cas où vous avez déjà vérifié certaines branches et que vous souhaitez

  • vérifiez toutes les branches restantes de la télécommande
  • assurez-vous que toutes les succursales locales suivent les succursales distantes

vous pouvez utiliser le script compatible bash et zsh suivant:

git branch -r | while read b; do if git branch | grep -q " ${b##*/}$"; then git branch --set-upstream ${b##*/} $b; else git branch --track ${b##*/} $b; fi; done
Simonair
la source
0
for rembranch in `git remote update 2>&1 > /dev/null ; git branch -r|egrep -wv "HEAD|master"`
do 
    git checkout --track -b `echo $rembranch|awk -F\/ '{print $2}'` $rembranch; 
done

Explication:

ligne 1: 'git branch -r' (suivi de 'git remote update' pour mettre à jour les informations sur les modifications apportées à remote) répertorie toutes les branches distantes; «egrep -vw» est utilisé pour frapper les entrées ayant HEAD et master dans le résultat.

ligne 3: suivez la branche distante nommée tout en la récupérant localement. Un simple awk est utilisé pour éviter que «origin /» ne soit le suffixe des branches locales.

ksvrgh
la source
0

En utilisant bash, si vous souhaitez vérifier toutes les branches:

for remote in `git branch -r`; do git checkout $(echo $remote | cut -d'/' -f 2); done

Il est important de noter que lorsque vous effectuez une extraction qui fait tomber de nouvelles branches de suivi à distance, vous n'en avez pas automatiquement de copies locales modifiables.

Jason Chen
la source