Kann "Git Pull" anstehende Änderungen automatisch speichern und löschen?

121

Ich weiß, wie man das löst:

user@host$ git pull
Updating 9386059..6e3ffde
error: Your local changes to the following files would be overwritten by merge:
    foo.bar
Please, commit your changes or stash them before you can merge.
Aborting

Aber gibt es nicht eine Möglichkeit, das zu git pulltun stashund popfür mich zu tanzen?

Wenn dieser Befehl einen anderen Namen hat, ist er in Ordnung.

Das Erstellen eines Shell-Alias ​​für git stash; git pull; git stash popist eine Lösung, aber ich suche nach einer besseren Lösung.

guettli
quelle
Was ist mit einem Git- Alias?
Am
20
git stash; git pull; git stash popProgrammgesteuertes Laufen ist gefährlich, denn wenn es nichts zu verstauen gibt, git stashwird es ein No-Op sein, aber git stash popdas letzte Versteck (falls vorhanden) wird platzen, was mit ziemlicher Sicherheit nicht das ist, was Sie wollen. User torek hat einen tollen Beitrag dazu auf Stack Overflow, aber ich kann ihn nicht finden ...
jub0bs
1
@guettli Ich habe nicht impliziert, dass Ihre Frage ein Duplikat ist, ich habe nur Jubobs 'Kommentar beantwortet.
VonC
2
In einem weiteren Schritt sollte der Vorgang nur erfolgreich sein, wenn der Stash nach dem Ziehen sauber angelegt werden kann. Wenn es Konflikte gibt, schlägt die gesamte Operation atomar fehl, sodass der Baum nicht geändert wird. Dies ist, was ich tun möchte: Entweder die Änderungen mit meinen eingefügten lokalen Änderungen herunterziehen oder mit einem Fehler fehlschlagen und mich manuell entscheiden lassen, was als nächstes zu tun ist. Ist diese Art von Git-Transaktion möglich?
Ed Avis

Antworten:

184

Für Git 2.6+ (veröffentlicht am 28. September 2015)

Das nur git config Einstellung, die von Interesse wäre, ist:

rebase.autoStash

(Mit Git 2.27, Q2 2020 haben Sie jetzt auch merge.autostash, siehe unten)

Wenn der Wert auf "true" gesetzt ist, erstellen Sie vor Beginn des Vorgangs automatisch einen temporären Stash und wenden Sie ihn nach Beendigung des Vorgangs an.
Dies bedeutet, dass Sie Rebase auf einem schmutzigen Arbeitsbaum ausführen können.

Seien Sie jedoch vorsichtig: Die endgültige Stash-Anwendung nach einer erfolgreichen Rebase kann zu nicht trivialen Konflikten führen. Der Standardwert ist false.

kombinieren Sie das mit:

pull.rebase

Wenn true, werden die Zweige über dem abgerufenen Zweig neu basiert, anstatt den Standardzweig von der Standardfernbedienung zusammenzuführen, wenn "git pull" ausgeführt wird.

git config pull.rebase true
git config rebase.autoStash true

Das würde ausreichen, damit ein einfacher git pullselbst in einem schmutzigen Baum arbeiten kann.
In diesem Fall wird kein Alias ​​benötigt.


Siehe Commit 53c76dc (04. Juli 2015) von Kevin Daudt ( Ikke) .
(Zusammengeführt von Junio ​​C Hamano - gitster- in Commit e69b408 , 17. August 2015)

pull: Dirty Tree zulassen, wenn rebase.autostashaktiviert

rebase hat gelernt, Änderungen zu speichern, wenn er auf einen schmutzigen Arbeitsbaum stößt, git pull --rebasetut dies jedoch nicht.

Überprüfen Sie nur, ob der Arbeitsbaum verschmutzt ist, wenn er rebase.autostashnicht aktiviert ist.


Hinweis: Wenn Sie ohne Autostash ziehen möchten (obwohl rebase.autoStash trueeingestellt), haben Sie seit Git 2.9 (Juni 2016):

 pull --rebase --no-autostash

Siehe Commit 450dd1d , Commit 1662297 , Commit 44a59ff , Commit 5c82bcd , Commit 6ddc97c , Commit eff960b , Commit efa195d (02. April 2016) und Commit f66398e , Commit c48d73b (21. März 2016) von Mehul Jain ( mehul2029) .
(Zusammengeführt von Junio ​​C Hamano - gitster- in Commit 7c137bb , 13. April 2016)

Commit f66398e umfasst insbesondere:

pull --rebase: --[no-]autostashFlag hinzufügen

Wenn die rebase.autoStashKonfigurationsvariable festgelegt ist, kann sie in git pull --rebaseder Befehlszeile nicht für " " überschrieben werden.

Lehren Sie " git pull --rebase" das --[no-]autostashBefehlszeilenflag, das den aktuellen Wert von überschreibt rebase.autoStash, falls gesetzt. Da " git rebase" die --[no-]autostashOption versteht, geht es nur darum, die Option an das zugrunde liegende " git rebase" zu übergeben, wenn " git pull --rebase" aufgerufen wird.


Warnung: Vor Git 2.14 (Q3 2017) wurde " git pull --rebase --autostash" nicht automatisch gespeichert, wenn der lokale Verlauf schnell zum Upstream weitergeleitet wird.

Siehe Commit f15e7cf (01. Juni 2017) von Tyler Brazier ( tylerbrazier) .
(Zusammengeführt von Junio ​​C Hamano - gitster- in Commit 35898ea , 05. Juni 2017)

pull: ff --rebase --autostashfunktioniert in Dirty Repo

Wenn git pull --rebase --autostashin einem verschmutzten Repository ein schneller Vorlauf durchgeführt wurde, wurde nichts automatisch gespeichert und der Pull schlug fehl.
Dies lag an einer Verknüpfung, um zu vermeiden, dass Rebase ausgeführt wird, wenn wir schnell vorspulen können, aber Autostash wird in diesem Codepfad ignoriert.


Update: Mariusz Pawelski stellt in den Kommentaren eine interessante Frage:

Also schreiben alle darüber, autostashwann Sie Rebase (oder pull --rebase) machen.

Aber niemand nimmt etwa autostashing , wenn Sie mit dem normalen Zug tun verschmilzt .
Es gibt also keinen automatischen Schalter dafür? Oder fehlt mir etwas? Ich mache git pull --rebasees lieber, aber OP fragte nach " Standard " Git Pull

Antworten:

Der ursprüngliche Thread , der diese Autostash-Funktion behandelt, wurde ursprünglich sowohl für git pull(Merge) als auch für (Merge) implementiert git pull --rebase.

Aber ... Junio ​​C Hamano (Git-Betreuer) bemerkte, dass:

Wenn dies pull-mergeetwas wäre, das den "Ärger" hervorrufen würde, der dieses Thema ausgelöst hat, überschneidet sich die lokale Änderung per Definition mit der Zusammenführung, und dieser interne "Stash Pop" berührt die Pfade, die die Zusammenführung berührt hat, und führt wahrscheinlich nicht zu "Abgelegt" "aber lassen Sie weitere Konflikte gelöst werden.

Ich vermute, dass die pull.autostashKonfiguration keine gute Ergänzung ist, da sie einen schlechten, schmerzauslösenden Workflow fördert.
In einfachen Fällen kann es nicht schaden, aber wenn lokale Änderungen komplex sind, würde es aktiv schaden, als es nicht zu haben, und die Konfiguration beraubt den Anreiz zur Auswahl.

Die Gleichung ist für "Pull-Rebase" etwas anders, da "Rebase" darauf besteht, dass Sie von einem sauberen Arbeitsbaum ausgehen, sodass sich der Ärger "Herunterladen und dann stoppen" größer anfühlt. Ich habe den Verdacht, dass eine Lockerung eine produktivere Lösung für das eigentliche Problem sein könnte.

In Bezug auf eine klassische Pull-Merge ist es also besser:

Ermutigen Sie den Benutzer, vor dem Ausführen von " git pull" über die Art der WIP nachzudenken, die er im Arbeitsbaum hat .
Ist es ein zu komplexes Tier, das das, was andere tun, stören kann, oder ist es eine triviale Veränderung, die er verstauen und zurückwerfen kann?

Wenn erstere, ist er weitaus besser dran, " checkout -b" zu arbeiten, weiter zu arbeiten, bis die lokale Veränderung in eine etwas bessere Form kommt, und "zu begehen", bevor er in den ursprünglichen Zweig zieht.

In letzterem Fall ist er besser dran:

  • " git pull",
  • Nachdem Sie Konflikte festgestellt haben, führen Sie sie aus
    • git stash,
    • git merge FETCH_HEAD und
    • git stash pop

Abgesehen davon hat Git 2.27 (Q2 2020) git pullgelernt, zu warnen, wenn keine pull.rebaseKonfiguration vorhanden ist und weder --[no-]rebasenoch --ff-onlyangegeben ist (was zu einer Zusammenführung führen würde).

Siehe Commit d18c950 (10. März 2020) von Alex Henrie ( alexhenrie) .
(Zusammengeführt von Junio ​​C Hamano - gitster- in Commit 1c56d6f , 27. März 2020)

pull: warnen, wenn der Benutzer nicht gesagt hat, ob er neu aufbauen oder zusammenführen soll

Unterzeichnet von: Alex Henrie

Oft vergessen unerfahrene Git-Benutzer, " pull --rebase" zu sagen, und erhalten eine unnötige Zusammenführung vom Upstream.

Normalerweise möchten sie entweder pull --rebasein den einfacheren Fällen " pull --ff-only" oder " " die Kopie der Hauptintegrationszweige aktualisieren und ihre Arbeit separat neu starten.
Die pull.rebaseKonfigurationsvariable hilft ihnen in den einfacheren Fällen, aber es gibt keinen Mechanismus, um diese Benutzer darauf aufmerksam zu machen.

Geben Sie eine Warnmeldung aus, wenn keine --[no-]rebaseOption über die Befehlszeile und keine pull.rebaseKonfigurationsvariable angegeben wird.
Dies wird diejenigen stören, die niemals " pull --rebase" wollen ", die nichts Besonderes tun mussten, aber die Kosten für die Unannehmlichkeiten werden nur einmal pro Benutzer bezahlt, was ein angemessener Preis sein sollte, um einer Reihe neuer Benutzer zu helfen.


Mit Git 2.27 (Q2 2020) git mergelernt " --autostash" die Option " " und die neue merge.autostashEinstellung.

Sehen Sie verpflichten d9f15d3 , begehen f8a1785 , begehen a03b555 , begehen 804fe31 , begehen 12b6e13 , begehen 0dd562e , begehen 0816f1d , begehen 9bb3dea , begehen 4d4bc15 , begehen b309a97 , begehen f213f06 , begehen 86ed00a , begehen facca7f , begehen be1bb60 , begehen efcf6cf , begehen c20de8b , verpflichten bfa50c2 , Commit 3442c3d , Commit 5b2f6d9 (07. April 2020), Commit 65c425a(04. April 2020) und Commit fd6852c , Commit 805d9ea (21. März 2020) von Denton Liu ( Denton-L) .
(Zusammengeführt von Junio ​​C Hamano - gitster- in Commit Bf10200 , 29. April 2020)

pull: pass --autostash zum Zusammenführen

Unterzeichnet von: Denton Liu

Vorher --autostashnur mit gearbeitet git pull --rebase.

Im letzten Patch wurde jedoch auch das Zusammenführen gelernt, --autostashsodass es keinen Grund mehr gibt, warum wir diese Einschränkung nicht mehr haben sollten.
Lehren Sie Pull to Pass --autostashzum Zusammenführen, genau wie beim Rebase.

Und:

rebase: Verwendung apply_autostash()von sequencer.c

Unterzeichnet von: Denton Liu

Die apply_autostash()Funktion in builtin/rebase.cist der apply_autostash()Funktion sequencer.cinsofern ähnlich genug , als sie fast austauschbar sind, mit Ausnahme der Art von Argument, die sie akzeptieren. Machen Sie die sequencer.cVersion extern und verwenden Sie sie in Rebase.

Die Rebase-Version wurde in 6defce2b02 ("eingebaute Rebase: Support- --autostashOption", 2018-09-04, Git v2.20.0-rc0 - Zusammenführung in Stapel 8 aufgeführt ) als Teil der Shell-zu-C-Konvertierung eingeführt.
Die Funktion wurde dupliziert, da zu diesem Zeitpunkt ein weiteres Projekt in Bearbeitung war, das die interaktive Rebase ebenfalls von Shell auf C konvertierte, und sie nicht durch Refactoring der sequencer.cVersion von mit ihnen in Konflikt geraten wollten apply_autostash().
Da beide Bemühungen längst abgeschlossen sind, können wir sie jetzt frei miteinander kombinieren.

VonC
quelle
Ab 2.4.2 ist dies noch nicht implementiert. Vielleicht eines Tages. rebase.autoStashgilt nur bei Verwendung von rebase. pull.rebasegilt nur bei Verwendung von Pull.
Randal Schwartz
"Das würde ausreichen, damit ein einfacher Trottel auch in einem schmutzigen Baum funktioniert." Wie Randal kommentierte, ist dies noch nicht wahr. Die Pull.c des aktuellen Masters wählt weiterhin die_on_unclean_work_tree.
Pradhan
1
@ Pradhan Ich stimme zu. Die Implementierung ist erst heute Morgen im Master angekommen und sollte für Git 2.6 bereit sein. Ich habe die Antwort bearbeitet, um dies zu verdeutlichen.
VonC
Ich habe bestätigt, dass Autostash mit Git funktioniert 2.5.5.
Joshua Hoblitt
1
Also schreiben alle über Autostash, wenn Sie dies tun rebase(oder pull --rebase). Aber niemand kümmert sich um Autostashing, wenn Sie mit Zusammenführungen normal arbeiten pull. Es gibt also keinen automatischen Schalter dafür? Oder fehlt mir etwas? Ich mache git pull --rebasees lieber, aber OP fragte nach "Standard"git pull
Mariusz Pawelski
41

Um ein paar Sekunden für entgegenkommende Entdecker zu sparen, hier eine Zusammenfassung (dank @VonC):

git pull --rebase --autostash
Vitaliy Ulantikov
quelle
6
Der Punkt ist: Nach einem git config pull.rebase trueund git config rebase.autoStash truealles, was Sie jemals brauchen werden, ist git pull. Einfach git pull. Keine weiteren Optionen erforderlich.
VonC
3
Anscheinend benötigen Sie mindestens Git 2.9 für die --autostashOption. Das -c rebase.autoStash=truefunktioniert ab Git 2.6.
ntc2
15

Wie im obigen Kommentar angegeben, funktioniert das Festlegen der beiden Konfigurationswerte derzeit nicht git pull, da die Autostash-Konfiguration nur für tatsächliche Rebases gilt. Diese Git-Befehle machen, was Sie wollen:

git fetch
git rebase --autostash FETCH_HEAD

Oder setzen Sie es als Alias:

git config alias.pullr '!git fetch; git rebase --autostash FETCH_HEAD'

Dann mach:

git pullr

Natürlich kann dieser Alias ​​nach Wunsch umbenannt werden.

user397114
quelle
7

Mit Git 2.6+ können Sie Folgendes verwenden:

alias gup='git -c rebase.autoStash=true pull --rebase'

Dies --rebasemacht Git-Pull rebaseanstelle von merge, so dass Einstellungen / Optionen wie --ff-onlynicht zutreffen.

Ich verwende --ff-onlystandardmäßig einen Alias ​​zum Ziehen ( git pull --ff-only) und kann ihn dann gup(von oben) verwenden, falls eine Schnellvorlaufzusammenführung nicht möglich ist oder Änderungen gespeichert sind.

blau gefärbt
quelle
Was ist der Hauptunterschied zwischen git pull --ff-onlyundgit pull pull --rebase --autostash
am
0

Wie Sie bereits erwähnt haben, ist dies der richtige Weg. Sie können es in einem Alias ​​verwenden, um Ihre Eingabe zu speichern und eine Verknüpfung zu verwenden, oder Sie können es in einer einzelnen Zeile verwenden (kann auch ein Alias ​​sein).

git stash && git pull --rebase && git stash pop

Es wird dasselbe tun wie Sie, aber in einer einzigen Zeile (&&) und wenn Sie als Alias ​​festgelegt sind, wird es sogar kürzer sein.

In den folgenden Zeilen werden die eingehenden / ausgehenden Änderungen angezeigt, bevor Sie ziehen / drücken

git log ^master origin/master
git log master ^origin/master
CodeWizard
quelle
8
Dieser Ansatz ist unsicher: Wenn nichts zu verstauen ist, führt der erste Befehl nichts aus und entfernt dann stash popeinige zufällige Dinge von zuvor.
John Zwinck
Nur um ganz klar zu sein: Selbst wenn git stashnichts verstaut wird, "gibt" es immer noch keinen Fehlercode zurück, so dass das && weiterhin mit git pullund fortfährt git stash popund ein vorheriges Versteck einfügt . Verwenden Sie dies also besser nicht, es sei denn, Sie sind sich sehr sicher, dass es etwas verstaut!
MoonLite