Jak mogę zobaczyć, które gałęzie Git śledzą, która gałąź zdalna / nadrzędna?

824

Wiem, że potrafię git branch --alli pokazuje mi to zarówno oddziały lokalne, jak i zdalne, ale nie jest to przydatne do pokazywania mi relacji między nimi.

Jak wyświetlić listę oddziałów w sposób pokazujący, który oddział lokalny śledzi, który jest zdalny?

joachim
źródło

Odpowiedzi:

1142

Bardzo porcelanowe polecenie, niezbyt dobre, jeśli chcesz tego do skryptu:

git branch -vv   # doubly verbose!

Zauważ, że w git 1.8.3 ta gałąź nadrzędna jest wyświetlana na niebiesko (patrz „ Co to jest śledzenie tej gałęzi (jeśli w ogóle) w git? ”)


Jeśli chcesz uzyskać czysty wynik, zobacz odpowiedź arcresu - używa polecenia porcelany, które, jak sądzę, nie istniało w momencie, gdy pisałem tę odpowiedź, więc jest nieco bardziej zwięzłe i działa z gałęziami skonfigurowanymi do rebase, a nie tylko scalania.

Cascabel
źródło
3
Pierwsza powyższa metoda nie zapewnia mi pożądanych informacji. Drugi ... wydaje się przesadny, zwłaszcza, że ​​odpowiedź Kubi działa. Czy coś brakuje?
garyp
3
@garyp Nie jesteś tym, który zadał pytanie. Pierwszy zapewnił to, czego potrzebował OP, a drugi dokładnie to , czego potrzebował, na wypadek, gdyby chciał to w czystej postaci do skryptu lub po prostu zapisać jako alias. („Overkill” jest w porządku, jeśli dostaniesz to, czego chcesz i nie musisz go powtarzać.) Z punktu widzenia tego pytania odpowiedź kubi zawiera pewne obce informacje, a jeśli jest więcej niż jeden pilot, to nie pokaż wszystko, ale jeśli spełnia twoje potrzeby, skorzystaj z niego.
Cascabel,
2
Jestem winien przeprosiny. Kiedy pierwotnie uruchomiłem pierwszą metodę, nie otrzymałem żadnych informacji o tym, co śledzi, co powinienem wyraźnie powiedzieć. Ale teraz widzę informacje o śledzeniu, więc musiałem mieć coś nie tak z moją konfiguracją. Więc było czegoś brakuje.
garyp
2
FWIW Byłem zdezorientowany, ponieważ -v i -vv pokazują podobne wyniki. Śledzona gałąź jest wyświetlana w nawiasach kwadratowych po skrócie i przed ostatnim zatwierdzeniem (w mojej domyślnej instalacji homebrew OSX).
jerclarke
3
Dla mnie to wszystko polega na wydrukowaniu ostatniego skrótu zatwierdzenia i komentarza dla każdej gałęzi.
capybaralet
263

git remote show origin

Zamień „origin” na dowolną nazwę pilota.

kubi
źródło
11
Mimo że to polecenie porcelany działa na człowieka (nie tyle na skrypt, co musiałoby parsować dane wyjściowe z porcelany), w tym podejściu nie podoba mi się to, że git remote showpolecenie faktycznie łączy się ze zdalnym repozytorium ... i dlatego zawiedzie, jeśli zdarzy się, że jesteś offline lub nie możesz połączyć się z repozytorium z jakiegokolwiek powodu ...
pvandenberk
17
@pvandenberk Możesz użyć, git remote show -n originaby uzyskać pewne informacje, nawet w trybie offline. Z dokumentacji zdalnej git : „Przy opcji -n zdalne głowy nie są najpierw pytane o git ls-remote <nazwa>; zamiast tego używane są informacje buforowane.”
Cerran,
5
Jedna dziwna rzecz w tym poleceniu: wyświetla zdalne gałęzie jako „śledzone”, nawet jeśli nie ma skonfigurowanej gałęzi lokalnej dla pull / push. Zawsze uważam to za mylące. Właściwie nie jestem pewien, co w tym wydaniu ma oznaczać „śledzony”. Dokumenty git na ten temat sprawiają, że brzmi to tak, jakby zdalna gałąź jest „śledzona” tylko wtedy, gdy jest połączona / powiązana z lokalną gałęzią w celu push / pull ...
Hawkeye Parker
Problem polega na tym, że muszę zadzwonić do wszystkich zdalnych nazw, dopóki nie zobaczę, czego tak naprawdę szukam.
jolvi
2
@jolvi Możesz uruchomić, git remote show | xargs git remote show -naby wyświetlić połączone informacje o śledzeniu dla wszystkich pilotów.
Synoli
107

Jeśli spojrzysz na stronę podręcznika git-rev-parse, zobaczysz następującą składnię:

<branchname>@{upstream}Np master@{upstream},@{u}

Sufiks @{upstream}do nazwy gałęzi (skrócona forma <branchname>@{u}) odnosi się do gałęzi, na której odgałęzienie określone przez nazwę gałęzi jest ustawione. Brakująca nazwa gałęzi jest domyślnie ustawiona na bieżącą.

Aby znaleźć górę oddziału master, wykonaj następujące czynności:

git rev-parse --abbrev-ref master@{upstream}
# => origin/master

Aby wydrukować informacje dla każdego oddziału, możesz zrobić coś takiego:

while read branch; do
  upstream=$(git rev-parse --abbrev-ref $branch@{upstream} 2>/dev/null)
  if [[ $? == 0 ]]; then
    echo $branch tracks $upstream
  else
    echo $branch has no upstream configured
  fi
done < <(git for-each-ref --format='%(refname:short)' refs/heads/*)

# Output:
# master tracks origin/master
# ...

Jest to czystsze niż ręczne analizowanie referencji i konfiguracji.

Carl Suster
źródło
Nie mogłem zrozumieć tego fragmentu podczas analizy, mimo że go znalazłem, więc dziękuję za jasne wyjaśnienie!
Alice Purcell,
3
Dla tych z nas, którzy używają git-flow, z gałęziami o nazwie „feature / blahblah”, instrukcja zamykająca pętli while powinna brzmieć: done < <(git for-each-ref --format='%(refname:short)' refs/heads/**)Zwróć uwagę na dwie gwiazdki na końcu wzorca globu.
markeissler
2
git rev-parse --abbrev-ref HEAD@{upstream}wydaje się działać dobrze dla obecnego oddziału. To także tworzy miły alias git.
Digikata,
whileSkładnia pętli wygląda nieco dziwne dla mnie. Możesz po prostu użyć, git for-each-ref ... | while read branch; do ...który nie wymaga FIFO i działa w tej samej kolejności, co napisane polecenia.
Daniel Böhmer
Przynajmniej od wersji git 2.5.1 masz jedno-liniowy zgit for-each-ref --format='%(refname:short) tracks %(upstream:short)' refs/heads/*
Mat M
81

Alternatywą dla odpowiedzi kubi jest obejrzenie .git/configpliku, który pokazuje konfigurację lokalnego repozytorium:

cat .git/config

Abizern
źródło
6
Również git config --get-regex branch
Tamir Daniely
6
Lub dokładniej: „git config --get-regexp branch. * Merge”
yoyo
41
git for-each-ref --format='%(refname:short) <- %(upstream:short)' refs/heads

pokaże wiersz dla każdego oddziału lokalnego. Oddział śledzenia będzie wyglądał następująco:

master <- origin/master

Bez śledzenia będzie wyglądać następująco:

test <- 
Aurelien
źródło
Fajnie, aby dodać trochę uporządkowania i danych wyjściowych TAB: git for-each-ref --sort upstream --format = '% (refname: short)% 09 <-% (upstream: short)' refs / heads
dimir
Pięknie zwięzłe, a wynik jest w rzeczywistości znacznie bardziej czytelny niż zaakceptowany git branch -vv. 🙏
joki,
Jedynym problemem jest to, że nie pamiętam tego, więc użyłemgit config --global alias.track 'for-each-ref --format='\''%(refname:short) <- %(upstream:short)'\'' refs/heads'
joki,
38

Dla aktualnej gałęzi, oto dwie dobre opcje:

% git rev-parse --abbrev-ref --symbolic-full-name @{u}
origin/mainline

lub

% git for-each-ref --format='%(upstream:short)' $(git symbolic-ref -q HEAD)
origin/mainline

Ta odpowiedź znajduje się również tutaj na nieco inne pytanie, które (błędnie) zostało oznaczone jako duplikat.

cdunn2001
źródło
5
Na tej podstawie wszystkie branże mogą być wymienione w skrypcie przyjazny sposób: git for-each-ref --shell --format='%(refname:short) %(upstream:short)' refs/heads.
Daniel James
15

W przypadku bieżącego oddziału można również powiedzieć git checkout(bez żadnego oddziału). Jest to brak operacji z efektami ubocznymi, aby wyświetlić informacje o śledzeniu, jeśli istnieją, dla bieżącej gałęzi.

$ git checkout 
Your branch is up-to-date with 'origin/master'.
Eugene Yarmash
źródło
W porządku, ale możesz przypadkowo wpisać git checkout ., co nie jest żadną opcją.
Tomasz Gandor
6

Używam tego aliasu

git config --global alias.track '!f() { ([ $# -eq 2 ] && ( echo "Setting tracking for branch " $1 " -> " $2;git branch --set-upstream $1 $2; ) || ( git for-each-ref --format="local: %(refname:short) <--sync--> remote: %(upstream:short)" refs/heads && echo --Remotes && git remote -v)); }; f'

następnie

git track
Olivier Refalo
źródło
5
Myślę, że warto zauważyć, że z dwoma parametrami twoje polecenie konfiguruje gałąź ścieżki.
albfan,
3

Na podstawie odpowiedzi Oliviera Refalo

if [ $# -eq 2 ] 
then
    echo "Setting tracking for branch " $1 " -> " $2
    git branch --set-upstream $1 $2
else
    echo "-- Local --" 
    git for-each-ref --shell --format="[ %(upstream:short) != '' ] && echo -e '\t%(refname:short) <--> %(upstream:short)'" refs/heads | sh
    echo "-- Remote --" 
    REMOTES=$(git remote -v) 
    if [ "$REMOTES" != '' ]
    then
        echo $REMOTES
    fi  
fi

Pokazuje tylko lokalnie ze skonfigurowaną ścieżką.

Napisz go na skrypcie o nazwie git-track na swojej ścieżce, a otrzymasz polecenie git track

Bardziej rozbudowana wersja na https://github.com/albfan/git-showupstream

albfan
źródło
1

git config --get-regexp "branch\.$current_branch\.remote"

poda nazwę śledzonego pilota

git config --get-regexp "branch\.$current_branch\.merge"

poda nazwę oddziału, który jest śledzony.

Musisz zastąpić $ current_branch nazwą swojej aktualnej gałęzi. Możesz uzyskać to dynamicznie za pomocągit rev-parse --abbrev-ref HEAD

Poniższy mini-skrypt łączy te rzeczy. Umieść go w pliku o nazwie git-tracking, spraw , by był wykonywalny i upewnij się, że znajduje się na twojej ścieżce.

wtedy możesz powiedzieć

$ git  tracking
<current_branch_name>-><remote_repo_name>/<remote_branch_name>

zwróć uwagę, że nazwa oddziału zdalnego może różnić się od nazwy oddziału lokalnego (choć zazwyczaj nie jest). Na przykład:

$git tracking 
xxx_xls_xslx_thing -> origin/totally_bogus

jak widać w kodzie, kluczem do tego jest wyodrębnienie danych z konfiguracji git. Po prostu używam sed, aby usunąć zbędne dane.

#!/bin/sh

current_branch=$(git rev-parse --abbrev-ref HEAD)
remote=$(git config --get-regexp "branch\.$current_branch\.remote" | sed -e "s/^.* //")
remote_branch=$(git config --get-regexp "branch\.$current_branch\.merge" | \
  sed -e "s/^.* //" -e "s/refs\/.*\///")

echo "$current_branch -> $remote/$remote_branch"
masukomi
źródło
1

Oto schludny i prosty. Może sprawdzić git remote -v, który pokazuje wszystkie pochodzenie i upstream bieżącego oddziału.

MJeremy
źródło