Traccia tutti i rami git remoti come rami locali


175

Tracciare un singolo ramo remoto come ramo locale è abbastanza semplice.

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

Anche inviare tutti i rami locali al telecomando, creare nuovi rami remoti secondo necessità è anche facile.

$ git push --all origin

Voglio fare il contrario. Se ho un numero X di filiali remote su una singola fonte:

$ git branch -r 
branch1
branch2
branch3
.
.
.

Posso creare filiali di localizzazione locali per tutte quelle filiali remote senza la necessità di crearle manualmente? Dì qualcosa come:

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

Ho cercato su Google e RTM, ma finora ho scoperto la cuccetta.


3
Esiste un modo ancora più semplice per tracciare un singolo ramo remoto come ramo locale:git checkout --track origin/branchname
Cerran

Questo non è esattamente quello che mi hai chiesto, ma funziona per me: ottieni i completamenti git: github.com/git/git/blob/master/contrib/completion/… . Quindi digitare git pull origin e premere tab, per ottenere un elenco di filiali remote. Quindi continua a digitare e premi return.
Max Heiber,

Risposte:


111

Usando bash:

dopo 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

crediti: Val Blant, elias e Hugo

prima di git 1.9.1

Nota: il seguente codice se usato nelle versioni successive di git (> v1.9.1) causa

  1. (bug) Tutti i rami creati per tenere traccia del master
  2. (seccatura) Tutti i nomi delle filiali locali creati a cui aggiungere il prefisso origin/
for remote in `git branch -r `; do git branch --track $remote; done

Aggiorna i rami, supponendo che non vi siano modifiche sui rami di tracciamento locali:

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

Ignora gli ambigui avvertimenti di refname, git sembra preferire il ramo locale come dovrebbe.


2
Grazie per l'heads-up sugli avvisi refname. Questo è stato utile.
Paul,

1
Grazie Otto, sospettavo che gli script fossero l'unica soluzione. Ne hai fornito uno piuttosto semplice.
Janson,

1
@Jason è ancora oggi lo scripting l'unica soluzione?
Cregox,

1
@Cawas: devi creare manualmente i rami di tracciamento, ma hai git pullun --allinterruttore che recupererà + unirà tutti i rami tracciati.
naught101

13
Questo non ha funzionato per me su Git 1.9.1. "git branch --track <banch_name>" crea un nuovo ramo <branch_name> che tiene traccia del master del ramo locale, anziché del ramo remoto desiderato. Quindi questo script ha creato un gruppo di rami locali che puntavano tutti al master locale. Pubblicherò la soluzione qui sotto.
Val Blant,

183

La risposta data da Otto è buona, ma tutti i rami creati avranno "origine /" come inizio del nome. Se vuoi solo che l'ultima parte (dopo l'ultima /) sia il nome del tuo ramo risultante, usa questo:

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

Ha anche il vantaggio di non darti avvertimenti su riferimenti ambigui.


Git non aggiungerà "origine" al nome della filiale di tracciamento locale.
Adam Dymitruk,

14
@adymitruk: In realtà si comporta esattamente come ho detto per me su OSX 10.6.4, usando git 1.7.2.2 (l'ultima versione stabile di questo commento). Otto menziona persino avvisi ambigui di nomignoli: gli avvertimenti non dovrebbero esistere se "origine /" non facesse parte del nome di ciascun ramo locale. Ecco l'output di 'git branch' dopo aver eseguito il comando di Otto: [master, origin / HEAD, origin / chart, origin / master, origin / production, origin / staging]. E il mio comando: [grafici, master, produzione, messa in scena].
tjmcewan,

1
+ Modifica: trovato article.gmane.org/gmane.comp.version-control.git/112575 spiegando il perché.
Philip Oakley,

8
Sono d'accordo - questa è una soluzione migliore di quella che è attualmente la risposta "accettata".
tobias.mcnulty

2
Invece di grep -v master, che ne dici grep -v /HEAD? Questo sembra filtrare il ramo predefinito, senza bisogno di personalizzazione
dashrb

22

La maggior parte delle risposte qui sono state complicate dall'analisi dell'output di git branch -r. È possibile utilizzare il forciclo seguente per creare i rami di tracciamento contro tutti i rami sul telecomando in questo modo.

Esempio

Di 'che ho questi rami remoti.

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

Conferma che non stiamo monitorando altro che master, a livello locale:

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

Puoi utilizzare questo solo rivestimento per creare i rami di tracciamento:

$ 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.

Ora conferma:

$ git branch
  development
  integration
* master
  production
  staging

Per eliminarli:

$ 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).

Se si utilizza l' -vvinterruttore per git branchè possibile confermare:

$ 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 ....

Ripartizione di for loop

Fondamentalmente il loop chiama il comando git branch -r, filtrando qualsiasi HEAD o rami master nell'output usando grep -vE "HEAD|master". Per ottenere i nomi dei soli rami meno la origin/sottostringa usiamo la manipolazione delle stringhe di Bash ${var#stringtoremove}. Ciò rimuoverà la stringa "stringtoremove" dalla variabile $var. Nel nostro caso stiamo rimuovendo la stringa origin/dalla variabile $i.

NOTA: in alternativa puoi usare anche git checkout --track ...per fare questo:

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

Ma non mi interessa particolarmente questo metodo, dal momento che ti sta cambiando tra i rami mentre esegue un checkout. Al termine, ti lascerà sull'ultimo ramo creato.

Riferimenti


1
Funziona perfettamente con la versione 2.3.2 di Git (Apple Git-55)
AndrewD,

22

Aggiornamento Q1 2020: Mohsen Abasi propone nei commenti , sulla base del 2014 SLM 's risposta , la più semplice alternativa:

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

E utilizza $()invece backtick obsoleti .

Come ho già detto in un'altra vecchia risposta , l'utilizzo git for-each-refè probabilmente più veloce .
E vorrei usare il nuovo git switchcomando (Git 2.23+) , che sostituisce la confusionegit checkout .

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

In questo modo, non è grepnecessario.


Vecchia risposta originale (2011):

Ecco il mio one-liner che uso (in una shell bash, testato con msysgit1.7.4):

Per copia-incolla:

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

Per una maggiore leggibilità:

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
  • selezionerà solo i rami upstream dal telecomando specificato nella remotevariabile (può essere "origin ' o qualunque sia il nome impostato per uno dei telecomandi dell'attuale repository Git).
  • estrarrà il nome del ramo: origin/a/Branch/Name => a/Branch/Nameattraverso l' awkespressione.
  • imposterà il ramo upstream attraverso --set-upstream-to(o -u) , non --track:
    il vantaggio è che, se il ramo esiste già, non fallirà e non cambierà l'origine di quel ramo, configurerà solo l' branch.xxx.(remote|merge)impostazione.

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

Tale comando creerà diramazioni locali per tutti i rami remoti a monte e imposterà le impostazioni remote e di unione su quel ramo remoto.


5
Questo mi dà "fatale: ramo 'qualunque' non esiste" per ogni ramo che esiste solo sul telecomando e non ha un ramo locale corrispondente.
Chris Dodd,

penso che se un nome di ramo contiene / ad esempio: feature / rc-41-bckend, questa soluzione non funziona !!!!
Mohsen Abasi,

@VonC Basato sulla risposta di "slm": $ per i in $ (git branch -r | grep -vE "HEAD | master" | sed 's / ^ [] \ + //'); esegui il checkout di git --track $ i; fatto
Mohsen Abasi il

@MohsenAbasi Sembra buono. Nella mia risposta, ho citato l'uso --set-upstream-toinvece di --trackperò.
VonC

@MohsenAbasi Ho incluso la tua alternativa nella risposta per una maggiore visibilità. Ho aggiunto un altro modo possibile per elencare i rami remoti e utilizzare al git switchposto di git checkout. Ma la tua (ottima) idea rimane.
VonC

14

Potresti scriverlo abbastanza facilmente, ma non so quando sarebbe prezioso. Quei rami rimarrebbero abbastanza rapidamente indietro e dovresti aggiornarli continuamente.

I rami remoti verranno automaticamente aggiornati, quindi è più semplice creare il ramo locale nel punto in cui si desidera effettivamente lavorarci.


2
È un buon punto. Il caso d'uso principale a cui sto pensando è la creazione di un ambiente di sviluppo locale basato su un repository git remoto. Quindi, quando eseguo il mio clone iniziale, voglio anche tenere traccia di tutti i rami remoti come sono in quel momento.
Janson,

1
I pratici git upaggiornamenti aggiornano tutte le filiali locali.
Hugo,

per unire due repos ed eliminando il telecomando
endolith

9
for i in `git branch -a | grep remote`; do git branch --track ${i#remotes/origin/} $i; done

4
Ho dovuto aggiungere un | grep -v HEADalla pipeline per farlo funzionare correttamente.
Elias Dorneles,

9

senza alcun script (in una directory vuota):

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

successivamente, tutti i rami remoti saranno visti come locali.


originale (in russo) .


Questa è di gran lunga la soluzione più semplice e ha funzionato per me su 2.21.0.windows.1
Rotsiser Mho

7

Se si desidera utilizzare PowerShell e il telecomando si chiama origine. Quindi funziona.

git fetch    
git branch -r  | %{$_ -replace "  origin/"} | %{git branch --track $_ "origin/$_"}

Questo è stato molto utile, ho finito per usare una leggera variazione per farlo funzionare con il mio git svn clone'drepository:git branch -r | %{$_ -replace " origin/"} | %{git checkout -b $_ "origin/$_"}
Nate

Ho anche fatto una leggera variazione perché le mie filiali locali esistono già: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

Usa questo e non avrai questo avviso come: refname 'origin / dev' è ambiguo


3

Ecco la mia soluzione del comando BASH che fa riferimento a @tjmcewan:

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

Il mio obiettivo è risolvere il problema che tutti i rami creati avranno "origine /" come inizio del nome, perché ho testato che le variabili $ remote includono ancora "origine /":

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

Dopo aver testato il BASH di @tjmcewan ho scoperto che tutti i nomi dei rami tracciati senza "origine /" su locale, non so perché.
Nick Tsai,

1
Il primo comando crea dei brances che tracciano "master". Non è roba che la maggior parte delle persone potrebbe desiderare.
Alexei Osipov,

@AlexeiOsipov Grazie!
Nick Tsai,

2

Per fare lo stesso della risposta di tjmcewan ma su Windows, chiamalo da un file batch :

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

O questo dalla riga di comando :

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

1

Da git 2.23 in poi:

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

Il -Cflag per git switchcrea o ripristina se esiste già.

documentazione dell'interruttore git


0

Nel caso in cui tu abbia già estratto alcune filiali e desideri farlo

  • controlla tutti i rami rimanenti dal telecomando
  • assicurarsi che tutte le filiali locali seguano le filiali remote

puoi usare i seguenti script compatibili con bash e zsh:

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

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

Spiegazione:

riga 1: 'git branch -r' (seguito da 'git remote update' per aggiornare le informazioni sulle modifiche a remote) elenca tutti i rami remoti; 'egrep -vw' è usato per battere le voci con HEAD e master nel risultato.

riga 3: traccia il ramo remoto denominato durante il check-out a livello locale. Un semplice awk viene utilizzato per evitare che 'origine /' sia il suffisso per le filiali locali.


0

Usando bash, se vuoi controllare tutti i rami:

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

È importante notare che quando esegui un recupero che fa cadere nuovi rami di tracciamento remoto, non hai automaticamente copie locali modificabili di essi.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.