746 Stimmen

Prüfen, ob ein Pull in Git erforderlich ist

Wie prüfe ich, ob sich das entfernte Repository geändert hat und ich einen Pull durchführen muss?

Jetzt verwende ich dieses einfache Skript:

git pull --dry-run | grep -q -v 'Already up-to-date.' && changed=1

Aber es ist ziemlich schwer.

Gibt es einen besseren Weg? Die ideale Lösung würde alle entfernten Zweige überprüfen und die Namen der geänderten Zweige sowie die Anzahl der neuen Übertragungen in jedem Zweig zurückgeben.

16 Stimmen

Bitte beachten Sie: "git pull --dry-run" funktioniert nicht so, wie vermutlich erwartet. Es scheint, dass git pull unbekannte Optionen direkt an git fetch weitergibt. Das Ergebnis ist das eines normalen git pull.

34 Stimmen

"pull" ist nur ein kurzer Weg, um "fetch" und "merge" auf einmal zu machen, wenn Sie den Status der entfernten Repo überprüfen müssen, simulieren Sie wirklich ein "fetch". Also git fetch -v --dry-run ist das, was Sie brauchen.

0 Stimmen

Ich habe die von OP vorgeschlagene Lösung ausprobiert, und es hat nichts gebracht. Wahrscheinlich nicht der beste Ansatz?

1009voto

Neil Mayhew Punkte 13319

Erste Verwendung git remote update , um Ihre Fernreferenten auf den neuesten Stand zu bringen. Dann können Sie eines von mehreren Dingen tun, z. B:

  1. git status -uno zeigt Ihnen an, ob der verfolgte Zweig vor oder hinter Ihnen liegt oder abgewichen ist. Wenn nichts angezeigt wird, sind der lokale und der entfernte Zweig identisch.

  2. git show-branch *master zeigt Ihnen die Übertragungen in allen Zweigen, deren Namen auf 'master' enden (z.B. Meister y Ursprung/Master ).

を使用する場合 -v con git remote update ( git remote -v update ) können Sie sehen, welche Zweige aktualisiert wurden, so dass Sie eigentlich keine weiteren Befehle benötigen.

Es sieht jedoch so aus, als ob Sie dies in einem Skript oder Programm tun wollen und am Ende einen true/false-Wert erhalten. Wenn dem so ist, gibt es Möglichkeiten, die Beziehung zwischen Ihrem aktuellen KOPF commit und dem Leiter des Zweigs, den Sie verfolgen, obwohl man das nicht auf eine Ja/Nein-Antwort reduzieren kann, da es vier mögliche Ergebnisse gibt. Wenn Sie jedoch bereit sind, eine pull --rebase dann können Sie "local is behind" und "local has diverged" als "need to pull" behandeln, und die anderen beiden ("local is ahead" und "same") als "don't need to pull".

Sie können die Commit-ID einer beliebigen Referenz mit git rev-parse <ref> so können Sie dies tun für Meister y Ursprung/Master und vergleichen sie. Wenn sie gleich sind, sind die Zweige identisch. Wenn sie ungleich sind, wollen Sie wissen, welcher vor dem anderen liegt. verwenden git merge-base master origin/master gibt den gemeinsamen Vorfahren der beiden Zweige an, und wenn sie sich nicht auseinanderentwickelt haben, ist dies derselbe wie bei dem einen oder dem anderen Zweig. Wenn Sie drei verschiedene IDs erhalten, haben sich die Zweige auseinanderentwickelt.

Um dies richtig zu tun, z.B. in einem Skript, müssen Sie in der Lage sein, sich auf den aktuellen Zweig und den entfernten Zweig zu beziehen, den er verfolgt. Die Funktion bash prompt-setting in /etc/bash_completion.d enthält nützlichen Code, um Zweignamen zu ermitteln. Wahrscheinlich brauchen Sie die Namen aber gar nicht zu ermitteln. Git hat ein paar nette Abkürzungen, um auf Zweige und Übertragungen zu verweisen (wie dokumentiert in git rev-parse --help ). Sie können insbesondere Folgendes verwenden @ für den aktuellen Zweig (vorausgesetzt, Sie befinden sich nicht in einem abgetrennten Kopfzustand) und @{u} für seinen vorgelagerten Zweig (z. B. origin/master ). Also git merge-base @ @{u} gibt den (Hash des) Commits zurück, an dem der aktuelle Zweig und sein Upstream auseinanderlaufen und git rev-parse @ y git rev-parse @{u} erhalten Sie die Hashes der beiden Tipps. Dies lässt sich in dem folgenden Skript zusammenfassen:

#!/bin/sh

UPSTREAM=${1:-'@{u}'}
LOCAL=$(git rev-parse @)
REMOTE=$(git rev-parse "$UPSTREAM")
BASE=$(git merge-base @ "$UPSTREAM")

if [ $LOCAL = $REMOTE ]; then
    echo "Up-to-date"
elif [ $LOCAL = $BASE ]; then
    echo "Need to pull"
elif [ $REMOTE = $BASE ]; then
    echo "Need to push"
else
    echo "Diverged"
fi

Anmerkung: ältere Versionen von Git erlaubten nicht @ selbständig, daher müssen Sie möglicherweise @{0} stattdessen.

Die Linie UPSTREAM=${1:-'@{u}'} ermöglicht es Ihnen, einen Upstream-Zweig explizit zu übergeben, falls Sie gegen einen anderen entfernten Zweig als den für den aktuellen Zweig konfigurierten prüfen wollen. Dies würde typischerweise in der folgenden Form geschehen entfernter Name/Branchenname . Wenn kein Parameter angegeben wird, ist der Wert standardmäßig @{u} .

Das Skript geht davon aus, dass Sie eine git fetch o git remote update Zunächst müssen die Verfolgungszweige auf den neuesten Stand gebracht werden. Ich habe dies nicht in das Skript eingebaut, weil es flexibler ist, den Abruf und den Vergleich als getrennte Operationen durchzuführen, z. B. wenn Sie ohne Abruf vergleichen wollen, weil Sie bereits vor kurzem abgerufen haben.

4 Stimmen

@takeshin Ich denke, Sie könnten git ls-remote origin -h refs/heads/master, wie von @brool vorgeschlagen, mit git rev-list --max-count=1 origin/master kombinieren. Wenn sie den gleichen Hash zurückgeben, hat sich der entfernte Zweig nicht geändert, seit Sie Ihre entfernten Refs zuletzt aktualisiert haben (mit pull, fetch, remote update, etc.) Das hätte den Vorteil, dass Sie den Inhalt aller Commits nicht sofort abrufen müssten, sondern dies auf einen günstigeren Zeitpunkt verschieben könnten. Da die Fernaktualisierung jedoch nicht zerstörerisch ist, können Sie sie auch so durchführen.

3 Stimmen

Sie könnten auch versuchen git status -s -u no was eine kürzere Ausgabe ergibt als git status -u no .

0 Stimmen

Dies funktioniert nicht, wenn Sie sich nicht in der lokalen Verfolgungsstelle befinden. Siehe meine Antwort für eine allgemeinere Lösung.

149voto

Debajit Punkte 44620

Wenn Sie einen Upstream-Zweig haben

git fetch <remote>
git status

Wenn Sie keinen Upstream-Zweig haben

Vergleichen Sie die beiden Zweige:

git fetch <remote>
git log <local_branch_name>..<remote_branch_name> --oneline

Zum Beispiel:

git fetch origin

# See if there are any incoming changes
git log HEAD..origin/master --oneline

(Ich nehme an origin/master ist Ihr entfernter Verfolgungszweig)

Wenn in der obigen Ausgabe irgendwelche Commits aufgelistet sind, dann haben Sie eingehende Änderungen, die Sie zusammenführen müssen. Wenn keine Commits aufgelistet sind von git log dann gibt es nichts zu fusionieren.

Beachten Sie, dass dies auch dann funktioniert, wenn Sie sich auf einem Feature-Branch befinden, der keinen Tracking-Remote hat, da er sich explizit auf origin/master anstelle der impliziten Verwendung der vorgelagerter Zweig von Git erinnert.

2 Stimmen

Auch eine kürzere Schreibweise git fetch; git log HEAD.. --oneline kann verwendet werden, wenn es einen Standardfernzweig für den lokalen Zweig gibt.

0 Stimmen

@philpirozhkov Wenn Sie eine Standard-Fernverzweigung haben, sollte ein einfaches "git status" ausreichen, denke ich. Meine Antwort war eine allgemeine Antwort für zwei beliebige Zweige, von denen einer den anderen verfolgen kann oder auch nicht.

66 Stimmen

git rev-list HEAD...origin/master --count gibt Ihnen die Gesamtzahl der "unterschiedlichen" Übertragungen zwischen den beiden.

104voto

Stephen Haberman Punkte 1324

Wenn dies für ein Skript ist, können Sie verwenden:

git fetch
$(git rev-parse HEAD) == $(git rev-parse @{u})

(Hinweis: Der Vorteil dieser gegenüber den vorherigen Antworten ist, dass Sie keinen separaten Befehl benötigen, um den Namen des aktuellen Zweigs zu erhalten. "HEAD" und "@{u}" (der Upstream des aktuellen Zweigs) kümmern sich darum. Siehe "git rev-parse --help" für weitere Details).

0 Stimmen

Ich entdeckte @{u} unabhängig und hatte meine Antwort aktualisiert, bevor ich Ihre sah.

1 Stimmen

Will git rev-parse @{u} tatsächlich die letzte Übertragung ohne git fetch ?

4 Stimmen

Das war die Eintrittskarte! Obwohl, Ihre Logik ist mit == was bedeutet, "wenn es KEINE Änderungen von Upstream gibt". Ich benutzte != um zu prüfen, ob es für meine Anwendung Änderungen von Upstream gibt. Vergessen Sie nicht git fetch zuerst!

45voto

wjordan Punkte 18512

Hier ist ein Bash-Einzeiler, der den HEAD-Commit-Hash des aktuellen Zweigs mit dem des entfernten Upstream-Zweigs vergleicht, nicht schwer git fetch o git pull --dry-run Operationen erforderlich:

[ $(git rev-parse HEAD) = $(git ls-remote $(git rev-parse --abbrev-ref @{u} | \
sed 's/\// /g') | cut -f1) ] && echo up to date || echo not up to date

Diese etwas dichte Linie ist folgendermaßen aufgeteilt:

  • Befehle werden gruppiert und verschachtelt mit $(x) Bash Befehls-Ersatz Syntax.
  • git rev-parse --abbrev-ref @{u} gibt eine abgekürzte Upstream-Referenz zurück (z. B. origin/master ), die dann in durch Leerzeichen getrennte Felder umgewandelt werden, und zwar durch das über die Pipeline geführte sed Befehl, z.B. origin master .
  • Diese Zeichenkette wird in git ls-remote die den Head-Commit des entfernten Zweigs zurückgibt. Dieser Befehl kommuniziert mit dem entfernten Repository. Der gepipte cut extrahiert nur das erste Feld (den Commit-Hash) und entfernt die tabulatorgetrennte Referenzzeichenfolge.
  • git rev-parse HEAD gibt den lokalen Commit-Hash zurück.
  • Die Bash-Syntax [ a = b ] && x || y vervollständigt den Einzeiler: Dies ist ein Bash String-Vergleich = innerhalb eines Testkonstrukts [ test ] gefolgt von den Konstrukten and-list und or-list && true || false .

2 Stimmen

Ich würde no verwenden Sie /g in sed, wenn Sie Schrägstriche in den Zweignamen verwenden. Das heißt, nur "sed 's/\// /".

0 Stimmen

@wjordan Ihre Lösung schlägt fehl, wenn das entfernte Repository nicht erreichbar ist (oder gewartet wird) und löst "up to date" aus.

44voto

brool Punkte 2093

Der Befehl

git ls-remote origin -h refs/heads/master

listet den aktuellen Head auf der Gegenstelle auf - Sie können ihn mit einem früheren Wert vergleichen oder nachsehen, ob Sie den SHA in Ihrem lokalen Repo haben.

1 Stimmen

Gibt es ein Beispielskript zum Vergleich dieser Werte?

33 Stimmen

git rev-list HEAD...origin/master --count gibt Ihnen die Gesamtzahl der "unterschiedlichen" Übertragungen zwischen den beiden.

3 Stimmen

@jberger, um das klarzustellen, wird nur die Anzahl der Commits angezeigt, hinter denen Sie zurückliegen (nicht vor und zurück), und es funktioniert nur, wenn Sie git fetch o git remote update Erstens. git status zeigt übrigens auch eine Zählung an.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X