Ich habe einen Kollegen, der behauptet, das git pull
sei schädlich, und der sich immer dann aufregt, wenn jemand es benutzt.
Der git pull
Befehl scheint der kanonische Weg zu sein, um Ihr lokales Repository zu aktualisieren. Schafft die Verwendung git pull
Probleme? Welche Probleme entstehen dadurch? Gibt es eine bessere Möglichkeit, ein Git-Repository zu aktualisieren?
git pull --rebase
diese Strategie einfach als Standard für neue Zweigegit config branch.autosetuprebase
--rebase
Flag hinzufügt ,git pull
um lokal mit remote zu synchronisieren , und dann Ihre lokalen Änderungen zusätzlich zu den aktualisierten lokalen wiedergibt . Wenn Sie dann drücken, müssen Sie nur Ihre neuen Commits an das Ende der Remote-Datei anhängen. Ziemlich einfach.Antworten:
Zusammenfassung
Erstellt standardmäßig
git pull
Zusammenführungs-Commits, die dem Codeverlauf Rauschen und Komplexität hinzufügen. Darüber hinauspull
ist es einfach, nicht darüber nachzudenken, wie Ihre Änderungen durch eingehende Änderungen beeinflusst werden könnten.Der
git pull
Befehl ist sicher, solange er nur Schnellvorlaufzusammenführungen ausführt. Wenngit pull
konfiguriert ist, dass nur Schnellvorlaufzusammenführungen durchgeführt werden und eine Schnellvorlaufzusammenführung nicht möglich ist, wird Git mit einem Fehler beendet. Dies gibt Ihnen die Möglichkeit, die eingehenden Commits zu untersuchen, darüber nachzudenken, wie sie sich auf Ihre lokalen Commits auswirken könnten, und die beste Vorgehensweise (Zusammenführen, Wiederherstellen, Zurücksetzen usw.) festzulegen.Mit Git 2.0 und neuer können Sie Folgendes ausführen:
um das Standardverhalten auf nur schnellen Vorlauf zu ändern. Bei Git-Versionen zwischen 1.6.6 und 1.9.x müssen Sie sich angewöhnen, Folgendes zu tippen:
Bei allen Git-Versionen empfehle ich jedoch, einen
git up
Alias wie folgt zu konfigurieren :und mit
git up
anstelle vongit pull
. Ich bevorzuge diesen Alias,git pull --ff-only
weil:origin/*
Äste, die stromaufwärts nicht mehr existieren.Probleme mit
git pull
git pull
ist nicht schlecht, wenn es richtig verwendet wird. Einige kürzlich vorgenommene Änderungen an Git haben diegit pull
ordnungsgemäße Verwendung vereinfacht , aber leidergit pull
weist das Standardverhalten einer Ebene mehrere Probleme auf:git pull
Diese Probleme werden nachstehend ausführlicher beschrieben.
Nichtlineare Geschichte
Standardmäßig entspricht der
git pull
Befehl der Ausführunggit fetch
gefolgt vongit merge @{u}
. Wenn sich im lokalen Repository nicht gepuschte Commits befinden, erstellt der Zusammenführungsteil vongit pull
ein Zusammenführungs-Commit.Merge Commits sind an sich nichts Schlechtes, aber sie können gefährlich sein und sollten mit Respekt behandelt werden:
Natürlich gibt es eine Zeit und einen Ort für Zusammenführungen, aber das Verständnis, wann Zusammenführungen verwendet werden sollten und wann nicht, kann die Nützlichkeit Ihres Repositorys verbessern.
Beachten Sie, dass der Zweck von Git darin besteht, das Teilen und Konsumieren der Entwicklung einer Codebasis zu vereinfachen und den Verlauf nicht genau so aufzuzeichnen, wie er sich entfaltet hat. (Wenn Sie nicht einverstanden sind, berücksichtigen Sie den
rebase
Befehl und warum er erstellt wurde.) Die von erstellten Zusammenführungs-Commitsgit pull
vermitteln anderen keine nützliche Semantik. Sie sagen lediglich, dass jemand anderes zufällig in das Repository verschoben wurde, bevor Sie mit Ihren Änderungen fertig waren. Warum haben diese Zusammenführungsverpflichtungen, wenn sie für andere nicht von Bedeutung sind und gefährlich sein könnten?Es ist möglich,
git pull
eine Neubasis anstelle einer Zusammenführung zu konfigurieren , dies hat jedoch auch Probleme (wird später erläutert). Sollte stattdessengit pull
so konfiguriert werden, dass nur Schnellvorlaufzusammenführungen durchgeführt werden.Wiedereinführung von Rebased-Out-Commits
Angenommen, jemand stößt einen Zweig zurück und drückt ihn mit Gewalt. Dies sollte im Allgemeinen nicht passieren, ist jedoch manchmal erforderlich (z. B. um eine versehentlich festgeschriebene und gepusste 50-GB-Protokolldatei zu entfernen). Durch die Zusammenführung von
git pull
wird die neue Version des Upstream-Zweigs mit der alten Version zusammengeführt, die noch in Ihrem lokalen Repository vorhanden ist. Wenn Sie das Ergebnis drücken, kommen Pitchgabeln und Taschenlampen auf Sie zu.Einige mögen argumentieren, dass das eigentliche Problem darin besteht, Aktualisierungen zu erzwingen. Ja, es ist im Allgemeinen ratsam, Kraftstöße nach Möglichkeit zu vermeiden, aber manchmal sind sie unvermeidlich. Entwickler müssen bereit sein, mit Force-Updates umzugehen, da dies manchmal vorkommt. Dies bedeutet, dass die alten Commits nicht blind über ein gewöhnliches System zusammengeführt werden
git pull
.Überraschen Sie die Änderungen im Arbeitsverzeichnis
Es gibt keine Möglichkeit vorherzusagen, wie das Arbeitsverzeichnis oder der Index aussehen wird, bis
git pull
dies abgeschlossen ist. Möglicherweise gibt es Zusammenführungskonflikte, die Sie lösen müssen, bevor Sie etwas anderes tun können. Möglicherweise wird eine 50-GB-Protokolldatei in Ihr Arbeitsverzeichnis eingefügt, weil jemand sie versehentlich verschoben hat. Möglicherweise wird ein Verzeichnis, in dem Sie arbeiten, umbenannt.git remote update -p
(odergit fetch --all -p
) ermöglicht es Ihnen, die Commits anderer Personen zu überprüfen, bevor Sie sich für eine Zusammenführung oder Neugründung entscheiden. So können Sie einen Plan erstellen, bevor Sie Maßnahmen ergreifen.Schwierigkeiten beim Überprüfen der Commits anderer Personen
Angenommen, Sie sind gerade dabei, einige Änderungen vorzunehmen, und jemand anderes möchte, dass Sie einige Commits überprüfen, die er gerade gepusht hat.
git pull
Durch die Zusammenführungs- (oder Rebase-) Operation werden das Arbeitsverzeichnis und der Index geändert. Dies bedeutet, dass Ihr Arbeitsverzeichnis und Ihr Index sauber sein müssen.Sie könnten
git stash
und dann verwendengit pull
, aber was tun Sie, wenn Sie mit der Überprüfung fertig sind? Um dorthin zurückzukehren, wo Sie waren, müssen Sie die von erstellte Zusammenführung rückgängig machengit pull
und den Stash anwenden.git remote update -p
(odergit fetch --all -p
) ändert das Arbeitsverzeichnis oder den Index nicht, sodass die Ausführung jederzeit sicher ist - selbst wenn Sie Änderungen vorgenommen und / oder nicht bereitgestellt haben. Sie können pausieren, was Sie tun, und das Commit eines anderen überprüfen, ohne sich Gedanken über das Verstecken oder Beenden des Commits machen zu müssen, an dem Sie arbeiten.git pull
gibt Ihnen diese Flexibilität nicht.Wiederherstellen auf einem Remote-Zweig
Ein gängiges Git-Verwendungsmuster besteht darin
git pull
, die neuesten Änderungen vorzunehmen, gefolgt von agit rebase @{u}
, um das eingeführte Zusammenführungs-Commit zu beseitigengit pull
. Es ist üblich genug , dass Git einige Konfigurationsoptionen hat diese beiden Schritte zu einem einzigen Schritt zu verringern , indem sie sagen ,git pull
ein Fütterungsmaterial anstelle einer Serie auszuführen (siehebranch.<branch>.rebase
,branch.autosetuprebase
undpull.rebase
Optionen).Wenn Sie ein nicht gepushtes Zusammenführungs-Commit haben, das Sie beibehalten möchten (z. B. ein Commit
master
, in das ein Push- Feature-Zweig zusammengeführt wird ), gibt es leider weder ein Rebase-Pull (git pull
mitbranch.<branch>.rebase
set totrue
) noch ein Merge-Pull (das Standardverhaltengit pull
), gefolgt von a Rebase wird funktionieren. Dies liegt daran,git rebase
dass Zusammenführungen ohne die--preserve-merges
Option eliminiert werden (die DAG wird linearisiert) . Der Rebase-Pull-Vorgang kann nicht so konfiguriert werden, dass Zusammenführungen beibehalten werden, und ein Merge-Pull gefolgt von agit rebase -p @{u}
beseitigt die durch das Merge-Pull verursachte Zusammenführung nicht. Update: Git v1.8.5 hinzugefügtgit pull --rebase=preserve
undgit config pull.rebase preserve
. Diese Ursachegit pull
zu tun ,git rebase --preserve-merges
nachdem die Upstream - Commits holen. (Danke an Funkaster für das Heads-up!)Bereinigte Zweige bereinigen
git pull
Bereinigt keine Remote-Tracking-Zweige, die Zweigen entsprechen, die aus dem Remote-Repository gelöscht wurden. Wenn beispielsweise jemand einen Zweigfoo
aus dem Remote-Repo löscht , wird dies weiterhin angezeigtorigin/foo
.Dies führt dazu, dass Benutzer versehentlich getötete Zweige wiederbeleben, weil sie glauben, noch aktiv zu sein.
Eine bessere Alternative: Verwenden Sie
git up
anstelle vongit pull
Stattdessen
git pull
empfehle ich, den folgendengit up
Alias zu erstellen und zu verwenden :Dieser Alias lädt die neuesten Commits von allen Upstream-Zweigen herunter (Bereinigen der toten Zweige) und versucht, den lokalen Zweig schnell auf den neuesten Commit im Upstream-Zweig vorzuspulen. Wenn dies erfolgreich war, gab es keine lokalen Commits, sodass kein Risiko für Zusammenführungskonflikte bestand. Der schnelle Vorlauf schlägt fehl, wenn lokale (nicht gepusste) Commits vorhanden sind, sodass Sie die Möglichkeit haben, die Upstream-Commits zu überprüfen, bevor Sie Maßnahmen ergreifen.
Dadurch wird Ihr Arbeitsverzeichnis immer noch auf unvorhersehbare Weise geändert, jedoch nur, wenn Sie keine lokalen Änderungen vorgenommen haben. Im Gegensatz zu
git pull
,git up
werden Sie nie auf eine Aufforderung fallen Sie einen Merge - Konflikt zu beheben erwarten.Andere Option:
git pull --ff-only --all -p
Das Folgende ist eine Alternative zum obigen
git up
Alias:Diese Version von
git up
hat das gleiche Verhalten wie der vorherigegit up
Alias, außer:-p
Argument, an das übergeben wirdfetch
), die sich in zukünftigen Versionen von Git ändern kannWenn Sie Git 2.0 oder neuer ausführen
Mit Git 2.0 und neuer können Sie konfigurieren
git pull
, dass standardmäßig nur Schnellvorlaufzusammenführungen durchgeführt werden:Dies führt
git pull
dazugit pull --ff-only
, dass es sich so verhält, aber es werden immer noch nicht alle Upstream-Commits abgerufen oder alteorigin/*
Zweige bereinigt, daher bevorzuge ich es immer nochgit up
.quelle
git remote update -p
entspricht äquivalent zugit fetch --all -p
. Ich habe die Angewohnheit zu tippen,git remote update -p
weil es einmalfetch
keine-p
Option gab. Bezüglich der Führung!
siehe die Beschreibung vonalias.*
ingit help config
. Es heißt: "Wenn der Alias-Erweiterung ein Ausrufezeichen vorangestellt ist, wird sie als Shell-Befehl behandelt."pull.ff
Konfiguration hinzu, die anscheinend dasselbe ohne Aliase erreicht.git up
nach einer interessanten Alternative.git pull
.Meine Antwort, aus der Diskussion gezogen , die entstand auf Hacker News:
Ich bin versucht, die Frage nur mit dem Betteridge-Gesetz der Schlagzeilen zu beantworten: Warum wird dies
git pull
als schädlich angesehen? Ist es nicht.quelle
git pull
. Es kann jedoch zu Konflikten mit einigen schädlichen Praktiken kommen, z. B. dem Wunsch, die Geschichte mehr als unbedingt notwendig umzuschreiben. Aber git ist flexibel. Wenn Sie es also anders verwenden möchten, tun Sie dies auf jeden Fall. Aber das liegt daran, dass Sie (naja, @Richard Hansen) etwas Ungewöhnliches in Git machen wollen und nicht daran, dassgit pull
es schädlich ist.git rebase
und betrachtengit pull
schädlich? "Ja wirklich?"git pull
ohne die--rebase
Option ist die Richtung der Zusammenführung, die es erstellt. Wenn Sie sich den Unterschied ansehen, gehören jetzt alle Änderungen in dieser Zusammenführung eher der Person, die gezogen hat, als der Person, die die Änderungen vorgenommen hat. Ich mag einen Workflow, bei dem das Zusammenführen für zwei separate Zweige (A -> B) reserviert ist, sodass das Zusammenführungs-Commit klar ist, was eingeführt wurde, und das erneute Basieren für das Aktualisieren auf demselben Zweig (Remote A -> lokales A) reserviert ist )Es wird nicht als schädlich angesehen, wenn Sie Git richtig verwenden. Ich sehe, wie sich dies angesichts Ihres Anwendungsfalls negativ auf Sie auswirkt, aber Sie können Probleme vermeiden, indem Sie den freigegebenen Verlauf nicht ändern.
quelle
git pull
ist dies kein Problem. Verzweigen in Git ist billig.Die akzeptierte Antwort behauptet
Aber ab Git 1.8.5 , das diese Antwort nachdatiert, können Sie dies tun
oder
oder
Die Dokumente sagen
Diese vorherige Diskussion enthält detailliertere Informationen und Diagramme: git pull --rebase --preserve-merges . Es erklärt auch, warum
git pull --rebase=preserve
nicht dasselbe ist wiegit pull --rebase --preserve-merges
, was nicht das Richtige tut.Diese andere vorherige Diskussion erklärt, was die Preserve-Merges-Variante von Rebase tatsächlich bewirkt und wie sie viel komplexer ist als eine reguläre Rebase: Was genau macht Git's "Rebase - Preserve-Merges" (und warum?)
quelle
Wenn Sie zum alten Git-Repository gehen, ist der Alias, den sie vorschlagen, anders. https://github.com/aanand/git-up
git config --global alias.up 'pull --rebase --autostash'
Das funktioniert perfekt für mich.
quelle