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

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.


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.


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


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

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 ...)


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

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 .


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.


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.


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.


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).
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.