Wie überprüfe ich, ob sich das Remote-Repository geändert hat und ich ziehen muss?
Jetzt benutze 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 Remote-Zweige überprüfen und die Namen der geänderten Zweige und die Anzahl der neuen Commits in jedem zurückgeben.
git fetch -v --dry-run
ist was du brauchst.Antworten:
Verwenden
git remote update
Sie diese Option zuerst , um Ihre Remote-Refs auf den neuesten Stand zu bringen. Dann können Sie eines von mehreren Dingen tun, wie zum Beispiel:git status -uno
wird Ihnen sagen, ob der Zweig, den Sie verfolgen, vor, hinter oder divergiert. Wenn nichts gesagt wird, sind lokal und remote identisch.git show-branch *master
zeigt Ihnen die Commits in allen Zweigen, deren Namen auf 'master' enden (z. B. master und origin / master ).Wenn Sie
-v
mitgit remote update
(git remote -v update
) verwenden, können Sie sehen, welche Zweige aktualisiert wurden, sodass Sie keine weiteren Befehle benötigen.Es sieht jedoch so aus, als ob Sie dies in einem Skript oder Programm tun möchten und am Ende einen True / False-Wert erhalten möchten. In diesem Fall gibt es Möglichkeiten, die Beziehung zwischen Ihrem aktuellen HEAD- Commit und dem Leiter des von Ihnen verfolgten Zweigs zu überprüfen. Da es jedoch vier mögliche Ergebnisse gibt, können Sie diese nicht auf eine Ja / Nein-Antwort reduzieren. Wenn Sie jedoch bereit sind, eine
pull --rebase
Aktion auszuführen, können Sie "lokal ist hinterher" und "lokal ist divergiert" als "ziehen müssen" und die anderen beiden als "nicht ziehen" behandeln.Sie können die Commit-ID jeder Referenz mit abrufen
git rev-parse <ref>
, also können Sie dies für Master und Origin / Master tun und diese vergleichen. Wenn sie gleich sind, sind die Zweige gleich. Wenn sie ungleich sind, möchten Sie wissen, welche vor den anderen liegt. Mitgit merge-base master origin/master
wird Ihnen der gemeinsame Vorfahr beider Zweige angezeigt. Wenn diese nicht voneinander abweichen, ist dies derselbe wie der eine oder andere. Wenn Sie drei verschiedene IDs erhalten, sind die Zweige auseinander gegangen.Um dies richtig zu tun, z. B. in einem Skript, müssen Sie in der Lage sein, auf den aktuellen Zweig und den Remote-Zweig zu verweisen, den er verfolgt. Die Funktion zum Einstellen der Bash-Eingabeaufforderung in
/etc/bash_completion.d
enthält nützlichen Code zum Abrufen von Zweigstellennamen. Allerdings müssen Sie die Namen wahrscheinlich nicht wirklich erhalten. Git hat einige nette Abkürzungen für den Verweis auf Zweige und Commits (wie in dokumentiertgit rev-parse --help
). Insbesondere können Sie@
für den aktuellen Zweig (vorausgesetzt, Sie befinden sich nicht in einem Zustand mit getrenntem Kopf) und@{u}
für den vorgelagerten Zweig (zorigin/master
. B. ) verwenden. Sogit merge-base @ @{u}
kehrt die (Hash - Wert des) begehen , an dem die Stromzweig und seine Upstream - divergieren undgit rev-parse @
undgit rev-parse @{u}
sehen Sie die Hashes der beiden Tipps geben. Dies kann im folgenden Skript zusammengefasst werden:Hinweis: Ältere Versionen von git waren für sich genommen nicht zulässig
@
, daher müssen Sie möglicherweise@{0}
stattdessen verwenden.Über die Leitung
UPSTREAM=${1:-'@{u}'}
können Sie optional einen Upstream-Zweig explizit übergeben, falls Sie einen anderen Remote-Zweig als den für den aktuellen Zweig konfigurierten vergleichen möchten. Dies hat normalerweise die Form Remotename / Branchname . Wenn kein Parameter angegeben wird, wird standardmäßig der Wert verwendet@{u}
.Das Skript setzt voraus, dass Sie eine
git fetch
oder diegit remote update
erste Option ausgeführt haben , um die Tracking-Zweige auf den neuesten Stand zu bringen. Ich habe dies nicht in das Skript integriert, da es flexibler ist, das Abrufen und Vergleichen als separate Operationen durchzuführen, z. B. wenn Sie vergleichen möchten, ohne abzurufen, da Sie bereits kürzlich abgerufen haben.quelle
git status -s -u no
, was eine kürzere Ausgabe als ergibtgit status -u no
.git remote -v update
. Schauen Sie sich die Ausgabe von an,git remote --help
um eine ausführlichere Erklärung zu erhalten.@{u}
mit Git 1.8.3.2 funktioniert,@
aber nicht. Funktioniert jedoch@
mit1.8.5.4
. Moral der Geschichte: Git verbessert sich ständig und es lohnt sich, die neueste Version zu haben, die Sie können.Wenn Sie eine vorgelagerte Niederlassung haben
Wenn Sie keine vorgelagerte Niederlassung haben
Vergleichen Sie die beiden Zweige:
Zum Beispiel:
(Ich gehe davon aus, dass
origin/master
es sich um Ihren Remote-Tracking-Zweig handelt.)Wenn in der obigen Ausgabe Commits aufgeführt sind, haben Sie eingehende Änderungen - Sie müssen zusammenführen. Wenn bis dahin keine Commits aufgeführt
git log
sind, muss nichts zusammengeführt werden.Beachten Sie, dass dies auch dann funktioniert, wenn Sie sich in einem Feature-Zweig befinden - der keine Tracking-Fernbedienung hat, da explizit auf
origin/master
den von Git gespeicherten Upstream-Zweig verwiesen wird , anstatt ihn implizit zu verwenden .quelle
git fetch; git log HEAD.. --oneline
kann verwendet werden, wenn es einen Standard-Remote-Zweig für den lokalen gibt.git rev-list HEAD...origin/master --count
gibt Ihnen die Gesamtzahl der "unterschiedlichen" Commits zwischen den beiden.Wenn dies für ein Skript ist, können Sie Folgendes verwenden:
(Hinweis: Dies hat gegenüber früheren Antworten den Vorteil, dass Sie keinen separaten Befehl benötigen, um den aktuellen Filialnamen abzurufen. "HEAD" und "@ {u}" (der Upstream des aktuellen Zweigs) kümmern sich darum. Siehe "git rev-parse --help" für weitere Details.)
quelle
git rev-parse @{u}
tatsächlich das neueste Commit ohne eingit fetch
angezeigt?==
was bedeutet "wenn es KEINE Änderungen von Upstream gibt". Ich habe!=
für meine Anwendung immer nach "ob es Änderungen gegenüber dem Upstream gibt" gesucht. Vergiss nichtgit fetch
zuerst!@
istHEAD
übrigens kurz für .@{u}
zBgit rev-parse '@{u}'
Der Befehl
listet den aktuellen Kopf auf der Fernbedienung auf - Sie können ihn mit einem vorherigen Wert vergleichen oder sehen, ob Sie den SHA in Ihrem lokalen Repo haben.
quelle
git rev-list HEAD...origin/master --count
gibt Ihnen die Gesamtzahl der "unterschiedlichen" Commits zwischen den beiden.git fetch
odergit remote update
zuerst.git status
zeigt übrigens auch eine Zählung...
ist "Commits in Origin / Master, HEAD subtrahieren" (dh Anzahl der Commits dahinter). Während...
ist der symmetrische Unterschied (dh vor und hinter)fetch
.Hier ist ein Bash-Einzeiler, der den HEAD-Commit-Hash des aktuellen Zweigs mit dem Remote-Upstream-Zweig vergleicht, ohne dass schwere
git fetch
odergit pull --dry-run
Operationen erforderlich sind:So wird diese etwas dichte Linie aufgeschlüsselt:
$(x)
Bash- Befehlssubstitutionssyntax gruppiert und verschachtelt .git rev-parse --abbrev-ref @{u}
Gibt eine abgekürzte Upstream-Referenz (z. B.origin/master
) zurück, die dann durch densed
Befehl piped in durch Leerzeichen getrennte Felder umgewandelt wird , zorigin master
.git ls-remote
die das Head-Commit des Remote-Zweigs zurückgibt. Dieser Befehl kommuniziert mit dem Remote-Repository. Dercut
Befehl piped extrahiert nur das erste Feld (den Commit-Hash) und entfernt die durch Tabulatoren getrennte Referenzzeichenfolge.git rev-parse HEAD
Gibt den lokalen Commit-Hash zurück.[ a = b ] && x || y
vervollständigt den Einzeiler: Dies ist ein Bash- String-Vergleich=
innerhalb eines Testkonstrukts[ test ]
, gefolgt von and-list- und or-list-Konstrukten&& true || false
.quelle
Ich schlage vor, Sie sehen sich das Skript https://github.com/badele/gitcheck an . Ich habe dieses Skript zum Einchecken aller Git-Repositorys in einem Durchgang codiert und es zeigt, wer nicht festgeschrieben und wer nicht gedrückt / gezogen hat.
Hier ein Beispielergebnis:
quelle
git mrepo -c
Dadurch werden alle ausstehenden Commits angezeigt.Ich habe diese Lösung auf den Kommentaren von @jberger basiert.
quelle
...
scheint dies ein gültiger Teil Ihrer Lösung zu sein.Es gibt bereits viele sehr funktionsreiche und geniale Antworten. Um einen gewissen Kontrast zu schaffen, könnte ich mit einer sehr einfachen Linie auskommen.
quelle
Ich denke, der beste Weg, dies zu tun, wäre:
Angenommen, Sie haben diese Referenz registriert. Wenn Sie das Repository geklont haben, andernfalls (dh wenn das Repo de novo lokal erstellt und auf die Fernbedienung übertragen wurde), müssen Sie die Referenzspezifikation explizit hinzufügen.
quelle
Das folgende Skript funktioniert perfekt.
quelle
Ich würde den von Brool vorgeschlagenen Weg tun. Das folgende einzeilige Skript verwendet den SHA1 Ihrer letzten festgeschriebenen Version und vergleicht ihn mit dem des Remote-Ursprungs. Änderungen werden nur abgerufen, wenn sie sich unterscheiden. Und es ist noch leichter von den Lösungen, die auf
git pull
oder basierengit fetch
.quelle
git rev-parse --verify HEAD
git log --pretty=%H ...refs/heads/master^
Sie zuerst den SHA1 Ihrer letzten festgeschriebenen Version aus und anschließendgit ls-remote origin -h refs/heads/master |cut -f1
den SHA1 des Remote-Ursprungs aus. Diese beiden sind Git-Befehle und haben nichts mit Bash zu tun. Bash in den eckigen Klammern vergleicht die Ausgabe des ersten Befehls mit der des zweiten Befehls. Wenn sie gleich sind, wird true zurückgegeben und ausgeführtgit pull
.git pull
". Ich weiß, dass ich pingelig bin, aber nur um jemandem Verwirrung zu ersparen, sollte das "und wenn sie nicht gleich sind" sein. Aus irgendeinem Grund funktioniert der erste git-Befehl bei mir nicht. (Ich bin auf Git2.4.1
.) Also benutze ichgit log --pretty=%H master | head -n1
stattdessen nur. Aber ich bin mir nicht sicher, ob das genau das gleiche ist.Wenn Sie dieses Skript ausführen, wird getestet, ob der aktuelle Zweig Folgendes benötigt
git pull
:Es ist sehr praktisch, es als Git-Hook-Pre-Commit zu verwenden, um dies zu vermeiden
wenn du
commit
vorherpulling
.Um diesen Code als Hook zu verwenden, kopieren Sie einfach das Skript und fügen Sie es ein
und
quelle
Ich möchte dies nur als tatsächlichen Beitrag veröffentlichen, da es leicht ist, dies in den Kommentaren zu übersehen.
Die richtige und beste Antwort auf diese Frage gab @Jake Berger. Vielen Dank, Alter, jeder braucht das und jeder vermisst dies in den Kommentaren. Für alle, die damit zu kämpfen haben, ist hier die richtige Antwort. Verwenden Sie einfach die Ausgabe dieses Befehls, um zu wissen, ob Sie einen Git-Pull ausführen müssen. Wenn die Ausgabe 0 ist, gibt es offensichtlich nichts zu aktualisieren.
@stackoverflow, gib diesem Kerl eine Glocke. Danke @ Jake Berger
quelle
Führen Sie es aus
git fetch (remote)
, um Ihre Remote-Refs zu aktualisieren. Es zeigt Ihnen, was neu ist. Wenn Sie dann Ihre lokale Niederlassung auschecken, wird angezeigt, ob sie sich hinter dem Upstream befindet.quelle
git status
wird dies auch angezeigt .git pull --dry-run
, aber ich denke, es ist zu schwer für ein Cron-Skript, das jede Minute ausgeführt wird.fetch
viel weiter tun, als den Status zu überprüfen. Wenn Sie eine sehr schnelle und einfache Reaktion auf Remote-Updates benötigen, sollten Sie eine Art von Benachrichtigungen an das Remote-Repository anschließen.All diese komplexen Vorschläge, während die Lösung so kurz und einfach ist:
quelle
git remote update
vor Ihrem Code ausgeführt werden, um die neuesten Informationen zum Commit des Ursprungs zu erhaltengit remote update
nicht vorgit show
Befehlen angehängt werden?Hier ist meine Version eines Bash-Skripts, das alle Repositorys in einem vordefinierten Ordner überprüft:
https://gist.github.com/henryiii/5841984
Es kann zwischen gängigen Situationen unterscheiden, z. B. Ziehen erforderlich und Drücken erforderlich, und es ist multithreaded, sodass der Abruf auf einmal erfolgt. Es hat mehrere Befehle, wie Pull und Status.
Fügen Sie einen Symlink (oder das Skript) in einen Ordner in Ihrem Pfad ein, dann funktioniert er als
git all status
(usw.). Es unterstützt nur origin / master, kann aber bearbeitet oder mit einer anderen Methode kombiniert werden.quelle
listet alles auf, auf das in einer Fernbedienung verwiesen wird, die nicht in Ihrem Repo enthalten ist. Das Abfangen von Änderungen an entfernten Refs an Dingen, die Sie bereits hatten (z. B. Zurücksetzen auf vorherige Commits), erfordert etwas mehr:
quelle
Vielleicht das, wenn Sie eine Aufgabe als crontab hinzufügen möchten:
quelle
Mit einfachem regulären Ausdruck:
quelle
Ich verwende eine Version eines Skripts, die auf Stephen Habermans Antwort basiert:
Angenommen, dieses Skript wird aufgerufen
git-fetch-and-rebase
, kann es mit einem optionalen Argument aufgerufen werdendirectory name
des lokalen Git-Repositorys , um die Operation auszuführen. Wenn das Skript ohne Argumente aufgerufen wird, wird davon ausgegangen, dass das aktuelle Verzeichnis Teil des Git-Repositorys ist.Beispiele:
Es ist auch hier erhältlich .
quelle
Nachdem ich viele Antworten und mehrere Beiträge gelesen und einen halben Tag damit verbracht habe, verschiedene Permutationen auszuprobieren, habe ich mir das ausgedacht.
Wenn Sie unter Windows arbeiten, können Sie dieses Skript unter Windows mit Git Bash ausführen, das von Git für Windows bereitgestellt wird (Installation oder portabel).
Dieses Skript erfordert Argumente
Das Skript wird
Wenn es eine vom Skript gedruckte Änderung gibt, können Sie mit dem Abrufen oder Abrufen fortfahren. Das Skript ist zwar nicht effizient, erledigt aber die Arbeit für mich.
Update - 30.10.2015: stderr to dev null, um zu verhindern, dass die URL mit dem Kennwort an die Konsole gedruckt wird.
quelle
Für die Windows-Benutzer, die auf diese Frage stoßen und danach suchen, habe ich einen Teil der Antwort in ein Powershell-Skript geändert. Passen Sie die Einstellungen nach Bedarf an, speichern Sie sie in einer
.ps1
Datei und führen Sie sie bei Bedarf aus oder planen Sie sie, wenn Sie möchten .quelle
Weil mir Neils Antwort so sehr geholfen hat, gibt es hier eine Python-Übersetzung ohne Abhängigkeiten:
hth
quelle
Sie können auch ein Phing-Skript finden , das das jetzt tut.
Ich brauchte eine Lösung, um meine Produktionsumgebungen automatisch zu aktualisieren, und wir freuen uns sehr über dieses Skript, das ich teile.
Das Skript ist in XML geschrieben und benötigt Phing .
quelle