Wie kann ich sehen, welche Git-Zweige welchen Remote- / Upstream-Zweig verfolgen?

824

Ich weiß, dass ich das kann git branch --all, und das zeigt mir sowohl lokale als auch entfernte Niederlassungen, aber es ist nicht so nützlich, um mir die Beziehungen zwischen ihnen zu zeigen.

Wie liste ich Zweige so auf, dass angezeigt wird, welcher lokale Zweig welche Fernbedienung verfolgt?

Joachim
quelle

Antworten:

1145

Sehr viel ein Porzellan-Befehl, nicht gut, wenn Sie dies für Skripte wollen:

git branch -vv   # doubly verbose!

Beachten Sie, dass mit Git 1.8.3 dieser Upstream-Zweig blau angezeigt wird (siehe " Was ist diese Zweigverfolgung (wenn überhaupt) in Git? ").


Wenn Sie eine saubere Ausgabe wünschen, lesen Sie die Antwort von arcresu - es wird ein Porzellanbefehl verwendet, von dem ich nicht glaube, dass er zu dem Zeitpunkt existiert hat, als ich diese Antwort ursprünglich geschrieben habe. Daher ist er etwas präziser und funktioniert mit Zweigen, die für die Neubasis konfiguriert sind, und nicht nur für das Zusammenführen.

Cascabel
quelle
3
Die erste Methode oben liefert nicht die gewünschten Informationen für mich. Das zweite ... scheint übertrieben, zumal Kubis Antwort funktioniert. Vermisse ich etwas
Garyp
3
@garyp Du bist nicht derjenige, der die Frage gestellt hat. Der erste lieferte das, was das OP benötigte, und der zweite lieferte genau das , was er brauchte, falls er es in einer sauberen Form für die Skripterstellung haben wollte oder es einfach als Alias ​​speichern wollte. ("Overkill" ist in Ordnung, wenn Sie das bekommen, was Sie wollen, und Sie es nicht wiederholen müssen.) Unter dem Gesichtspunkt dieser Frage liefert Kubis Antwort einige irrelevante Informationen, und wenn es mehr als eine Fernbedienung gibt, ist dies nicht der Fall Zeigen Sie nicht alles, aber wenn es Ihren Anforderungen entspricht, verwenden Sie es auf jeden Fall.
Cascabel
2
Ich schulde Entschuldigungen. Als ich ursprünglich die erste Methode ausführte, bekam ich keine Informationen darüber, welche Tracks was verfolgen, und ich hätte das explizit angeben sollen. Aber jetzt sehe ich die Tracking-Informationen, also muss etwas mit meinem Setup nicht stimmen. Also ich war etwas fehlt.
Garyp
2
FWIW Ich war verwirrt, weil -v und -vv eine so ähnliche Ausgabe zeigen. Der verfolgte Zweig wird nach dem Hash und vor dem letzten Commit in eckigen Klammern angezeigt (bei meiner Standardinstallation von OSX Homebrew).
Jerclarke
3
Für mich bedeutet dies lediglich, den letzten Commit-Hash und Kommentar für jeden Zweig auszudrucken.
Capybaralet
263

git remote show origin

Ersetzen Sie "Ursprung" durch den Namen Ihrer Fernbedienung.

kubi
quelle
11
Obwohl dieser Porzellanbefehl für einen Menschen funktioniert (nicht so sehr für ein Skript, da er die Porzellanausgabe analysieren müsste), gefällt mir an diesem Ansatz nicht, dass der git remote showBefehl tatsächlich eine Verbindung zum Remote-Repo herstellt ... und daher schlägt es fehl, wenn Sie
offline sind
17
@pvandenberk Mit können git remote show -n originSie einige Informationen auch offline abrufen . Aus der git remote-Dokumentation : "Mit der Option -n werden die Remote-Köpfe nicht zuerst mit git ls-remote <Name> abgefragt. Stattdessen werden zwischengespeicherte Informationen verwendet."
Cerran
5
Eine seltsame Sache an diesem Befehl: Er listet entfernte Zweige als "verfolgt" auf, selbst wenn kein lokaler Zweig für Pull / Push konfiguriert ist. Ich finde das immer verwirrend. Mir ist eigentlich nicht klar, was "verfolgt" in dieser Ausgabe bedeuten soll. Die Git-Dokumente zu diesem Thema lassen es so klingen, als würde ein entfernter Zweig nur dann "verfolgt", wenn er für Push / Pull mit einem lokalen Zweig verknüpft ist ...
Hawkeye Parker
Das Problem ist, dass ich dies für alle Remote-Namen aufrufen muss, bis ich sehe, wonach ich tatsächlich suche.
Jolvi
2
@jolvi Sie können die git remote show | xargs git remote show -nkombinierten Tracking-Informationen für alle Fernbedienungen anzeigen.
Synoli
107

Wenn Sie sich die Manpage ansehen git-rev-parse, sehen Sie, dass die folgende Syntax beschrieben wird:

<branchname>@{upstream}z master@{upstream}.@{u}

Das Suffix @{upstream}zu einem Zweignamen (Kurzform <branchname>@{u}) bezieht sich auf den Zweig, auf dem der durch den Zweignamen angegebene Zweig aufgebaut ist. Ein fehlender Filialname ist standardmäßig der aktuelle.

Um den Upstream der Niederlassung zu finden master, würden Sie also Folgendes tun:

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

Um die Informationen für jeden Zweig auszudrucken, können Sie Folgendes tun:

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

Dies ist sauberer als das manuelle Parsen von Refs und Konfigurationen.

Carl Suster
quelle
Ich konnte dieses Bit in rev-parse nicht verstehen, obwohl ich es gefunden habe, also danke für die klare Erklärung!
Alice Purcell
3
Für diejenigen von uns, die git-flow mit Zweigen mit dem Namen "feature / blahblah" verwenden, sollte die abschließende Anweisung der while-Schleife lauten: done < <(git for-each-ref --format='%(refname:short)' refs/heads/**)Beachten Sie die beiden Sternchen am Ende des Glob-Musters.
markeissler
2
git rev-parse --abbrev-ref HEAD@{upstream}scheint für die aktuelle Branche gut zu funktionieren. Es macht auch für einen schönen Git-Alias.
Digikata
Die whileLoop-Syntax sieht für mich etwas komisch aus. Sie können nur das verwenden, git for-each-ref ... | while read branch; do ...das kein FIFO benötigt und in derselben Reihenfolge wie die geschriebenen Befehle ausgeführt wird.
Daniel Böhmer
Zumindest seit Git 2.5.1 haben Sie einen Einzeiler mitgit for-each-ref --format='%(refname:short) tracks %(upstream:short)' refs/heads/*
Mat M
81

Eine Alternative zu Kubis Antwort besteht darin, sich die .git/configDatei anzusehen, in der die Konfiguration des lokalen Repositorys angezeigt wird :

cat .git/config

Abizern
quelle
6
Auch git config --get-regex branch
Tamir Daniely
6
Oder genauer gesagt 'git config --get-regexp branch. * Merge'
yoyo
41
git for-each-ref --format='%(refname:short) <- %(upstream:short)' refs/heads

zeigt eine Zeile für jeden lokalen Zweig. Ein Tracking-Zweig sieht folgendermaßen aus:

master <- origin/master

Ein Nicht-Tracking sieht folgendermaßen aus:

test <- 
Aurelien
quelle
Schön, um etwas Ordnung und TAB-Bett-Ausgabe hinzuzufügen: git for-each-ref --sort upstream --format = '% (refname: short)% 09 <-% (upstream: short)' refs / Heads
dimir
Schön prägnant und die Ausgabe ist tatsächlich viel besser lesbar als die akzeptierte git branch -vv. 🙏
joki
Das einzige Problem ist, dass ich mich nicht daran erinnern kann, also habe ichgit config --global alias.track 'for-each-ref --format='\''%(refname:short) <- %(upstream:short)'\'' refs/heads'
joki
38

Für die aktuelle Branche gibt es zwei gute Möglichkeiten:

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

oder

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

Diese Antwort ist auch hier auf eine etwas andere Frage, die (fälschlicherweise) als Duplikat markiert wurde.

cdunn2001
quelle
5
Auf dieser Grundlage können alle Zweige skriptfreundlich aufgelistet werden : git for-each-ref --shell --format='%(refname:short) %(upstream:short)' refs/heads.
Daniel James
15

Für den aktuellen Zweig könnte man auch sagen git checkout(ohne irgendeinen Zweig). Dies ist ein No-Op mit Nebenwirkungen, um die Tracking-Informationen für den aktuellen Zweig anzuzeigen, falls vorhanden.

$ git checkout 
Your branch is up-to-date with 'origin/master'.
Eugene Yarmash
quelle
Fair genug, aber Sie können versehentlich tippen git checkout ., was kein No-Op ist.
Tomasz Gandor
6

Ich benutze diesen Alias

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'

dann

git track
Olivier Refalo
quelle
5
Ich denke, es ist erwähnenswert, dass Ihr Befehl mit zwei Parametern einen Track-Zweig konfiguriert.
Albfan
3

Basierend auf der Antwort von Olivier 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

Es wird nur lokal mit konfigurierter Spur angezeigt.

Schreiben Sie es in ein Skript namens git-track auf Ihrem Pfad und Sie erhalten einen git track- Befehl

Eine ausführlichere Version unter https://github.com/albfan/git-showupstream

Albfan
quelle
1

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

gibt Ihnen den Namen der Fernbedienung, die verfolgt wird

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

gibt Ihnen den Namen des Remote-Zweigs, der verfolgt wird.

Sie müssen $ current_branch durch den Namen Ihres aktuellen Zweigs ersetzen. Sie können das dynamisch mit bekommengit rev-parse --abbrev-ref HEAD

Das folgende Mini-Skript kombiniert diese Dinge. Stecken Sie es in eine Datei mit dem Namen git-tracking, machen Sie es ausführbar und stellen Sie sicher, dass es sich in Ihrem Pfad befindet.

dann kannst du sagen

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

Beachten Sie, dass sich der Name des Remote-Zweigs von Ihrem lokalen Zweig unterscheiden kann (obwohl dies normalerweise nicht der Fall ist). Zum Beispiel:

$git tracking 
xxx_xls_xslx_thing -> origin/totally_bogus

Wie Sie im Code sehen können, ist der Schlüssel dazu das Extrahieren der Daten aus der Git-Konfiguration. Ich benutze nur sed, um die fremden Daten zu löschen.

#!/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
quelle
1

Hier ist eine ordentliche und einfache. Kann überprüfen git remote -v, was Ihnen den gesamten Ursprung und vor dem aktuellen Zweig zeigt.

MJeremy
quelle