Śledź wszystkie zdalne oddziały git jako oddziały lokalne


175

Śledzenie pojedynczego oddziału zdalnego jako oddziału lokalnego jest dość proste.

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

Przeniesienie wszystkich lokalnych oddziałów do zdalnego, w razie potrzeby tworzenie nowych oddziałów zdalnych jest również łatwe.

$ git push --all origin

Chcę zrobić odwrotnie. Jeśli mam X zdalnych oddziałów w jednym źródle:

$ git branch -r 
branch1
branch2
branch3
.
.
.

Czy mogę utworzyć lokalne gałęzie śledzenia dla wszystkich tych zdalnych oddziałów bez konieczności ręcznego tworzenia każdego z nich? Powiedz na przykład:

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

Szukałem w Google i RTM, ale do tej pory wpadłem na pryczę.


3
Istnieje jeszcze prostszy sposób śledzenia pojedynczego oddziału zdalnego jako oddziału lokalnego:git checkout --track origin/branchname
Cerran

Nie jest to dokładnie to, o co prosiłeś, ale działa dla mnie: pobierz uzupełnienia git: github.com/git/git/blob/master/contrib/completion/… . Następnie wpisz git pull origin i naciśnij tab, aby uzyskać listę zdalnych gałęzi. Następnie kontynuuj pisanie i naciśnij return.
Max Heiber

Odpowiedzi:


111

Korzystanie z basha:

po 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

kredyty: Val Blant, elias i Hugo

przed git 1.9.1

Uwaga: poniższy kod, jeśli jest używany w nowszych wersjach git (> v1.9.1), powoduje

  1. (błąd) Wszystkie utworzone gałęzie do śledzenia mastera
  2. (irytacja) Wszystkie utworzone nazwy oddziałów lokalnych, które mają być poprzedzone origin/
for remote in `git branch -r `; do git branch --track $remote; done

Zaktualizuj oddziały, zakładając, że nie ma zmian w lokalnych oddziałach śledzenia:

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

Zignoruj ​​niejednoznaczne ostrzeżenia dotyczące refname, git wydaje się preferować lokalny oddział tak, jak powinien.


2
Dzięki za ostrzeżenie o ostrzeżeniach dotyczących nazwy referencyjnej. To było pomocne.
Paul

1
Dzięki Otto, podejrzewałem, że skrypty będą jedynym rozwiązaniem. Podałeś dość prosty.
Janson,

1
@Jason czy nadal jedynym rozwiązaniem jest tworzenie skryptów?
cregox

1
@Cawas: aż będziesz musiał ręcznie tworzyć gałęzie śledzące, ale git pullma --allprzełącznik, który pobierze + scali wszystkie śledzone gałęzie.
naught101

13
To nie zadziałało dla mnie w Git 1.9.1. „git branch --track <banch_name>” tworzy nową gałąź <branch_name>, która śledzi lokalny oddział główny, zamiast zdalnej gałęzi, o którą nam chodziło. Więc ten skrypt stworzył kilka lokalnych gałęzi, wszystkie wskazujące na lokalny wzorzec. Poniżej zamieszczę rozwiązanie.
Val Blant

183

Odpowiedź udzielona przez Otto jest dobra, ale wszystkie utworzone gałęzie będą miały „origin /” na początku nazwy. Jeśli chcesz, aby ostatnia część (po ostatnim /) była twoimi wynikowymi nazwami gałęzi, użyj tego:

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

Ma również tę zaletę, że nie daje żadnych ostrzeżeń o niejednoznacznych referencjach.


Git nie doda „pochodzenia” do nazwy lokalnego oddziału śledzenia.
Adam Dymitruk

14
@adymitruk: Właściwie zachowuje się dokładnie tak, jak powiedziałem dla mnie na OSX 10.6.4, używając git 1.7.2.2 (najnowsza stabilna na ten komentarz). Otto wspomina nawet o niejednoznacznych ostrzeżeniach dotyczących nazw referencyjnych - ostrzeżenia nie musiałyby istnieć, gdyby „pochodzenie /” nie było częścią każdej nazwy lokalnego oddziału. Oto wyjście „git branch” po uruchomieniu polecenia Otto: [master, origin / HEAD, origin / charts, origin / master, origin / production, origin / staging]. I moje polecenie: [wykresy, master, produkcja, inscenizacja].
tjmcewan

1
+ Edycja: znaleziono artykuł.gmane.org/ gmane.comp.version- control.git/112575 wyjaśniający dlaczego.
Philip Oakley,

8
Zgadzam się - to lepsze rozwiązanie niż obecnie „akceptowana” odpowiedź.
tobias.mcnulty

2
A może zamiast grep -v mastertego grep -v /HEAD? Wydaje się, że odfiltrowuje domyślną gałąź, bez konieczności dostosowywania
dashrb

22

Większość odpowiedzi tutaj zbytnio komplikuje analizowanie danych wyjściowych git branch -r. Możesz użyć następującej forpętli, aby utworzyć gałęzie śledzenia dla wszystkich gałęzi na pilocie, w ten sposób.

Przykład

Powiedzmy, że mam te zdalne oddziały.

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

Potwierdź, że nie śledzimy już lokalnie niczego poza głównym:

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

Możesz użyć tego jednego linera do tworzenia gałęzi śledzenia:

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

Teraz potwierdź:

$ git branch
  development
  integration
* master
  production
  staging

Aby je usunąć:

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

Jeśli użyjesz -vvprzełącznika do git branch, możesz potwierdzić:

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

Podział pętli for

Pętla w zasadzie wywołuje polecenie git branch -r, odfiltrowując z wyjścia wszelkie gałęzie HEAD lub master, używając grep -vE "HEAD|master". Aby uzyskać nazwy tylko gałęzi bez origin/podłańcucha, używamy operacji na łańcuchach Basha ${var#stringtoremove}. Spowoduje to usunięcie ze zmiennej napisu „stringtoremove” $var. W naszym przypadku usuwamy ciąg origin/ze zmiennej $i.

UWAGA: Alternatywnie możesz również git checkout --track ...to zrobić:

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

Ale nie obchodzi mnie ta metoda, ponieważ przełącza cię między gałęziami, gdy wykonuje kasę. Po zakończeniu pozostawi cię na ostatniej utworzonej gałęzi.

Bibliografia


1
Doskonale współpracuje z wersją git 2.3.2 (Apple Git-55)
AndrewD

22

Aktualizacja Q1 2020: Mohsen Abasi proponuje w komentarzach , na podstawie 2014 SLM „s odpowiedzi , prostszą alternatywę:

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

I używa $()zamiast przestarzałych grawitacji .

Jak wspomniałem w innej starej odpowiedzi , używanie git for-each-refjest prawdopodobnie szybsze .
I chciałbym użyć nowego (GIT 2.23+) git switchpolecenia , który zastępuje mylącegit checkout .

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

W ten sposób nie jest greppotrzebne.


Stara (2011) oryginalna odpowiedź:

Oto moja jedna linijka, której używam (w powłoce bash, przetestowana za pomocą msysgit1.7.4):

W przypadku kopiowania i wklejania:

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

Aby uzyskać większą czytelność:

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
  • wybierze tylko górne gałęzie ze zdalnego, które określisz w remotezmiennej (może to być „ origin” lub jakakolwiek inna nazwa, którą nadałeś jednemu z pilotów bieżącego repozytorium Git).
  • wyodrębni nazwę gałęzi: origin/a/Branch/Name => a/Branch/Namepoprzez awkwyrażenie.
  • ustawi gałąź upstream przez --set-upstream-to(lub -u) , nie --track:
    Zaletą jest to, że jeśli gałąź już istnieje, nie zawiedzie i nie zmieni pochodzenia gałęzi, tylko skonfiguruje branch.xxx.(remote|merge)ustawienie.

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

To polecenie utworzy lokalne gałęzie dla wszystkich zdalnych gałęzi nadrzędnych i ustawi ich zdalne i scalające ustawienia na tę zdalną gałąź.


5
To daje mi „fatal: branch 'cokolwiek' nie istnieje” dla każdej gałęzi, która istnieje tylko na zdalnym i nie ma odpowiadającej gałęzi lokalnej.
Chris Dodd,

Myślę, że jeśli nazwa oddziału zawiera / na przykład: feature / rc-41-bckend, to rozwiązanie nie działa !!!!
Mohsen Abasi

@VonC Na podstawie odpowiedzi "slm": $ for i in $ (git branch -r | grep -vE "HEAD | master" | sed 's / ^ [] \ + //'); do git checkout --track $ i; gotowe
Mohsen Abasi

@MohsenAbasi Wygląda dobrze. W mojej odpowiedzi wspomniałem o używaniu --set-upstream-tozamiast --trackchociaż.
VonC

@MohsenAbasi W odpowiedzi zawarłem Twoją alternatywę, aby uzyskać lepszą widoczność. Dodałem inny możliwy sposób wyświetlania zdalnych gałęzi i używania git switchzamiast git checkout. Ale twój (bardzo dobry) pomysł pozostaje.
VonC

14

Można by to łatwo napisać, ale nie wiem, kiedy będzie to cenne. Te gałęzie dość szybko pozostawałyby w tyle i musiałbyś je cały czas aktualizować.

Zdalne gałęzie będą automatycznie aktualizowane, więc najłatwiej jest po prostu utworzyć oddział lokalny w miejscu, w którym faktycznie chcesz nad nim pracować.


2
Trafne spostrzeżenie. Głównym przypadkiem użycia, o którym myślę, jest skonfigurowanie lokalnego środowiska deweloperskiego opartego na zdalnym repozytorium git. Więc kiedy robię mój pierwszy klon, chcę również śledzić wszystkie zdalne gałęzie, jakie są w tym czasie.
Janson,

1
Poręczny git upaktualizuje wszystkie lokalne oddziały.
Hugo

za połączenie dwóch repozytoriów i usunięcie zdalnego
endolitu

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

4
Musiałem dodać | grep -v HEADdo potoku, aby działał poprawnie.
Elias Dorneles


7

Jeśli chcesz używać PowerShell, a Twój pilot nazywa się origin. Wtedy to działa.

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

To było bardzo pomocne, ostatecznie użyłem niewielkiej zmiany, aby działało z moim git svn clone'drepozytorium:git branch -r | %{$_ -replace " origin/"} | %{git checkout -b $_ "origin/$_"}
Nate

Zrobiłem również niewielką różnicę, ponieważ moje lokalne oddziały już istnieją: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

Użyj tego, a nie będziesz mieć takiego ostrzeżenia, jak: nazwa referencyjna „pochodzenie / dev” jest niejednoznaczna


3

Oto moje rozwiązanie polecenia BASH odwołujące się do @tjmcewan:

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

Moim celem jest rozwiązanie problemu polegającego na tym, że wszystkie utworzone gałęzie będą miały „origin /” na początku nazwy, ponieważ sprawdziłem, że zmienne zdalne $ nadal zawierają „origin /”:

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

Po przetestowaniu BASH @tjmcewan stwierdziłem, że nazwy wszystkich śledzonych gałęzi bez 'origin /' na lokalnym, nie wiem dlaczego.
Nick Tsai

1
Pierwsze polecenie tworzy branże, które śledzą „master”. To nie jest coś, czego większość ludzi może chcieć.
Alexei Osipov

@AlexeiOsipov Dzięki!
Nick Tsai,

2

Aby zrobić to samo, co odpowiedź tjmcewan, ale w systemie Windows, wywołaj to z pliku wsadowego :

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

Lub to z linii poleceń :

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

1

Od git 2.23 wzwyż:

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

-CFlaga dla git switchtworzy lub resetuje, jeśli już istnieje.

dokumentacja przełącznika git


0

Na wypadek, gdybyś już wyewidencjonował niektóre gałęzie i chcesz

  • sprawdź wszystkie pozostałe gałęzie z pilota
  • upewnij się, że wszystkie lokalne oddziały śledzą zdalne oddziały

możesz użyć następującego skryptu kompatybilnego z bash i 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

Wyjaśnienie:

linia 1: „git branch -r” (po którym następuje „git remote update”, aby zaktualizować informacje o zmianach w zdalnym) wyświetla wszystkie zdalne gałęzie; 'egrep -vw' jest używane do wybicia wpisów mających w wyniku HEAD i master.

linia 3: Śledź nazwaną zdalną gałąź podczas sprawdzania jej lokalnie. Prosty awk jest używany, aby uniknąć 'origin /' będącego sufiksem dla lokalnych gałęzi.


0

Używając basha, jeśli chcesz sprawdzić wszystkie gałęzie:

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

Ważne jest, aby pamiętać, że kiedy wykonujesz pobieranie, które obniża nowe gałęzie zdalnego śledzenia, nie masz automatycznie lokalnych, edytowalnych kopii ich.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.