Versteckt nur nicht bereitgestellte Änderungen in Git

228

Ich möchte den folgenden Arbeitsablauf ausführen:

  1. Fügen Sie der Bühne Änderungen hinzu.
  2. Bewahren Sie alle anderen Änderungen auf, die nicht bereitgestellt wurden.
  3. Mach ein paar Sachen mit den Dingen in der Phase (zB bauen, Tests ausführen usw.)
  4. Wenden Sie den Vorrat an.

Gibt es eine Möglichkeit, Schritt 2 auszuführen?

Beispiel

 echo "123" > foo
 git add foo # Assumes this is a git directory
 echo "456" >> foo
 git stash
 cat foo # Should yield 123
Unapiedra
quelle
Warum übernehmen Sie Ihre Änderungen nicht, nachdem Sie sie bereitgestellt haben?
Shizzmo
3
IIRC --keepindex macht genau das
sehe
4
Denn wenn beispielsweise der Build fehlschlägt, möchte ich kein Commit dafür haben. Ich weiß, dass ich das Commit löschen kann, aber ich möchte dies nach Möglichkeit ohne Commit tun.
Unapiedra
Sehe, danke. Ich kann bestätigen, dass dies funktioniert. Ich habe mir das Handbuch unter linux.die.net/man/1/git-stash angesehen, das veraltet ist. man git stashist viel besser.
Unapiedra
es ist --keep-index, fwiw.
Jaf0

Antworten:

285

git stash savehat eine Option --keep-index, die genau das tut, was Sie brauchen.

Also renn git stash save --keep-index.

vhallac
quelle
9
Wahr. Ich benutze weiter savemit git stash. Vielleicht ist es der Programmierer in mir, der darauf besteht, die Symmetrie mit apply / pop zu respektieren. :)
Vhallac
104
Hinweis: Dadurch werden alle Ihre Änderungen weiterhin gespeichert . Der einzige Unterschied zu regulären git stash saveist, dass die bereits bereitgestellten Änderungen auch in Ihrer Arbeitskopie verbleiben. Im obigen Workflow würde dies gut funktionieren, da Sie den Stash nur auf eine lokale Kopie anwenden, die bereits die Hälfte der Änderungen des Stash enthält (welcher Git klug genug ist, um ihn zu ignorieren). Wenn Sie den Code jedoch bearbeiten, bevor Sie den Stash erneut anwenden, können beim Zusammenführen möglicherweise Zusammenführungskonflikte auftreten. Fyi.
Peterflynn
2
@ytpete Das hat mich so oft gebissen. Ich wünschte wirklich, es gäbe eine Möglichkeit für Git, nur die Dinge zu verstauen, die Sie nicht aufbewahren ... Ich lege oft Dinge fest und mache dann einen vollständigen GIT-Stash, wissend, dass ich es kann, git commit --ammendwenn es Probleme mit dem gibt, was ich begangen habe.
rjmunro
1
--amend(anstatt --ammend)
Rhubbarb
19
Diese Lösung funktioniert bei mir aufgrund der von Peterflynn beschriebenen Probleme nicht. Es ist keine gute Antwort auf die Frage, da es die inszenierten Änderungen immer noch versteckt. Hat jemand eine bessere Lösung?
user643011
43

Dies kann in drei Schritten erfolgen: Speichern von bereitgestellten Änderungen, Speichern aller anderen Elemente, Wiederherstellen des Index mit bereitgestellten Änderungen. Welches ist im Grunde:

git commit -m 'Save index'
git stash push -u -m 'Unstaged changes and untracked files'
git reset --soft HEAD^

Dies wird genau das tun, was Sie wollen.

alesguzik
quelle
3
Hinweis: -uVersteckt auch nicht verfolgte Dateien.
ma11hew28
Dieser Ansatz dupliziert im Wesentlichen das, was git stash save --keep-indexmit viel mehr Arbeit verbunden ist. Ich sehe keine Vorteile.
Inigo
1
@vas Nein, der Ansatz dupliziert das nicht. Siehe Peterflynns Kommentar zur akzeptierten Antwort.
Alexander Klauer
28
git stash save --keep-index

Auch Re:

Warum übernehmen Sie Ihre Änderungen nicht, nachdem Sie sie bereitgestellt haben? - Shin

A: Weil Sie immer getesteten Code einchecken sollten :) Das bedeutet, dass Sie die Tests nur mit den Änderungen ausführen müssen, die Sie festschreiben möchten

Abgesehen von der Tatsache, dass Sie als erfahrener Programmierer natürlich den angeborenen Drang haben, nur diese Änderungen zu testen und zu überprüfen - nur teilweise ein Scherz

sehe sehen
quelle
14

Mit git version 2.7.4dir darfst du:

git stash save --patch

Das gitfragen Sie Ihre Änderungen in Stash hinzuzufügen , oder nicht.
Und du antwortest dann einfach yodern

Sie können das Arbeitsverzeichnis wie immer wiederherstellen:

git stash pop

oder, wenn Sie gespeicherte Änderungen im Vorrat behalten möchten:

git stash apply
Eugen Konkov
quelle
Das ist fantastisch. Es ist etwas arbeitsintensiv, aber zumindest können Sie ganze Dateien überspringen und hinzufügen.
Dustin Oprea
5

Wenn ich frühere Antworten erweitere, habe ich manchmal eine komplexe Reihe von Änderungen, möchte aber zuerst eine separate Änderung vornehmen. Beispielsweise habe ich möglicherweise einen Fehler oder einen anderen falschen Code entdeckt, den ich vor meinen bereitgestellten Änderungen beheben möchte. Ein möglicher Weg ist folgender:

Verstecke zuerst alles, aber lass die inszenierten Änderungen intakt

$ git stash save --keep-index [--include-untracked]

Verstecken Sie jetzt die inszenierten Änderungen auch separat

$ git stash save

Änderungen zur Behebung vornehmen; und testen; verpflichten sie:

$ git add [--interactive] [--patch]

$ git commit -m "fix ..."

Stellen Sie nun die zuvor bereitgestellten Änderungen wieder her:

$ git stash pop

Lösen Sie alle Konflikte und beachten Sie, dass git bei Konflikten diesen Top-Stash-Eintrag angewendet, aber nicht gelöscht hat.

(... Übernehmen Sie dann die bereitgestellten Änderungen, stellen Sie den Vorrat aller anderen Änderungen wieder her und fahren Sie fort ...)

Rhubbarb
quelle
4

Führen Sie den folgenden Befehl aus, um die nicht getaggten (nicht zum Festschreiben hinzugefügten) Dateien zum Stash hinzuzufügen:

git stash -k

Dann können Sie die bereitgestellten Dateien festschreiben. Danach können Sie die zuletzt gespeicherten Dateien mit dem folgenden Befehl zurückholen:

git stash pop
srth12
quelle
3

Es ist schwieriger, nur den Arbeitsbaum (nicht bereitgestellte Änderungen) in Git zu verstecken, als es sein sollte. Die akzeptierte Antwort stashes die unstaged Veränderungen, aber auch die stashes inszeniert Veränderungen (und Blätter sie als gut inszeniert), was selten ist , was Sie wollen.

Dieser Alias ​​funktioniert gut:

stash-working = "!f() { \
  git commit --quiet -m \"temp for stash-working\" && \
  git stash push \"$@\" && \
  git reset --quiet --soft HEAD~1; }; f"

Es schreibt die bereitgestellten Änderungen vorübergehend fest, erstellt einen Stash aus den verbleibenden Änderungen (und ermöglicht die Übergabe zusätzlicher Argumente wie --include-untrackedund --messageals Alias-Argumente) und setzt dann das temporäre Festschreiben zurück, um die bereitgestellten Änderungen zurückzugewinnen.

Es ähnelt der Antwort von @Simon Knapp, weist jedoch einige geringfügige Unterschiede auf: Es verwendet --quietdie temporären Aktionen, akzeptiert eine beliebige Anzahl von Parametern für den Stash push, anstatt den Code fest zu codieren -m, und fügt hinzu--soft zum Finale bei Zurücksetzen, damit der Index beim Start erhalten bleibt.

Für das entgegengesetzte Problem, nur die inszenierten Änderungen (Alias stash-index) zu verstecken, siehe diese Antwort .

Raman
quelle
2

Ein weiterer Tipp im Zusammenhang mit der Frage:

Wenn Sie Ihre nicht bereitgestellten Änderungen effektiv mit speichern

$ git stash save --keep-index

Möglicherweise möchten Sie dem Stash eine Nachricht geben, damit bei der Ausführung eines git stash listVorgangs klarer wird, was Sie zuvor gespeichert haben, insbesondere, wenn Sie diesem Stash-Vorgang weitere Speicherungen folgen. Beispielsweise

$ git stash save --keep-index "Änderungen noch nicht inszeniert"

(obwohl es tatsächlich alle Änderungen enthält, wie in anderen Antworten angegeben).

Zum Beispiel könnte auf das oben Gesagte sofort folgen:

$ git stash save "inszenierte Änderungen für Feature X"

Beachten Sie jedoch, dass Sie dann nicht verwenden können

$ git stash apply "stash @ {1}" ### ✘ macht nicht ganz das, was Sie vielleicht wollen

um nur die nicht bereitgestellten Änderungen wiederherzustellen.

Rhubbarb
quelle
2

Git hat keinen Befehl, der nur Ihre nicht bereitgestellten Änderungen versteckt.

Mit Git können Sie jedoch angeben, welche Dateien Sie speichern möchten.

git stash push --message 'Unstaged changes' -- app/controllers/products_controller.rb test/controllers/products_controller_test.rb

Wenn Sie nur bestimmte Änderungen in diesen Dateien speichern möchten, fügen Sie die --patchOption hinzu.

git stash push --patch --message 'Unstaged changes' -- app/controllers/products_controller.rb test/controllers/products_controller_test.rb

Mit dieser --include-untrackedOption können Sie nicht verfolgte Dateien speichern.

git stash push --include-untracked --message 'Untracked files' -- app/controllers/widgets_controller.rb test/controllers/widgets_controller_test.rb

Führen Sie git help stash(oder man git-stash) aus, um weitere Informationen zu erhalten.

Hinweis: Wenn Ihre nicht bereitgestellten Änderungen eher disoganisiert sind, ist die Antwort von @ alesguzik wahrscheinlich einfacher.

ma11hew28
quelle
0

Die moderne Form dieses Befehls ist git stash push [--] [<pathspec>...], da Git 2.16+ ( git stash saveveraltet )

Sie können dies mit einem Platzhalterformular kombinieren, zum Beispiel:

git stash push --all --keep-index ':(glob)**/*.testextension' 

Aber das funktioniert nicht gut mit Git für Windows, bis Git 2.22 (Q2 2019), siehe Ausgabe 2037 , wenn man bedenkt, dass git stashes in C neu implementiert wurde (anstelle eines Shell-Skripts).

Siehe Commit 7db9302 (11. März 2019) von Thomas Gummerer ( tgummerer) .
Siehe Commit 1366c78 , Commit 7b556aa (07. März 2019) von Johannes Schindelin ( dscho) .
(Zusammengeführt von Junio ​​C Hamano - gitster- in Commit 0ba1ba4 , 22. April 2019)

eingebaut stash: Griff:(glob) Pfadspezifikationen erneut verarbeiten

Wenn Sie beispielsweise eine Liste von Pfadspezifikationen an übergeben, git addmüssen Sie darauf achten, das ursprüngliche Formular zu verwenden, nicht die analysierte Form der Pfadspezifikationen.

Dies macht einen Unterschied, zB beim Anrufen

git stash -- ':(glob)**/*.txt'

Dabei enthält das ursprüngliche Formular das :(glob)Präfix, das analysierte Formular jedoch nicht.

In der integrierten git stashVersion haben wir jedoch das analysierte (dh falsche) Formular übergeben und git addwürden mit der Fehlermeldung fehlschlagen:

fatal: pathspec '**/*.txt' did not match any files

In der Phase, in der git stashdie Änderungen aus dem Arbeitsbaum entfernt werden, auch wenn refs/stashsie tatsächlich erfolgreich aktualisiert wurden.

VonC
quelle
0

Ich verwende einen Alias, der eine Zeichenfolge akzeptiert, die als Nachricht an den Stash-Eintrag verwendet werden soll.

mystash = "!f() { git commit -m hold && git stash push -m \"$1\" && git reset HEAD^; }; f"

Welche:

  • legt alles im Index fest,
  • versteckt, was im Arbeitsbaum geändert wird (könnte natürlich hinzufügen -uoder-a ),
  • Setzt das letzte Commit auf den Arbeitsversuch zurück (möglicherweise möchten Sie es verwenden --soft, um es im Index zu behalten).
Simon Knapp
quelle