2015-01-28 10 views
17

Ich habe eine Reihe von Dateien in ein Versteck (stash{0}) und ich würde git applynur einige Teile/hunks dieser Dateien mögen (in der Regel bekannt als interaktiven Modus).‚git stash gelten‘ mit interaktiven Modus

Ist es möglich?

Ich habe gesehen, dass möglich ist, ein

git stash save -p 'Stash name' 

durchzuführen, aber es nicht möglich scheint

git stash apply -p 'Stash name' 

Haben Sie einen Weg, es zu erreichen, wissen zu tun?

Antwort

19

Ist es möglich?

Ja ist es!

git checkout -p [email protected]{0} 

Wo Sie die 0 in [email protected]{0} mit dem Index des Stash ersetzen können Sie anwenden möchten.

Verwenden Sie git stash list und git show -p [email protected]{n}, wenn Sie nicht sicher sind, welches n das Stash ist, das Sie anwenden möchten.

Vergessen Sie nicht zu git stash drop [email protected]{n}, wenn Sie wissen, dass Sie diesen Stash nicht mehr benötigen, da git checkout offensichtlich den Stash für Sie nicht fallen lassen wird.

Warum funktioniert es?

Der Schlüssel ist zu erkennen, dass Taschen sind im Wesentlichen references bis commits genau wie Tags und Zweige.

Tatsächlich werden sie in .git/refs/stash, eine Zeile pro Stash-Hash gespeichert.

Caveats

Wie @mgadda int den Kommentaren unten erwähnt, git checkout -p versucht, den ganzen Unterschied zwischen einem begehen und den aktuellen Arbeitsbereich zu übernehmen.

Im Falle eines git stash, wenn der Vorrat Sie gegen ein anderes getan wurde anzuwenden sind versucht zu begehen, dann wird git checkout -p [email protected]{n} versuchen, sich interaktiv die Unterschiede alle zwischen [email protected]{n}anzuwenden und alle es Eltern verpflichtet und die aktuelle Arbeitsplatz.

Zum Beispiel, wenn Sie einen Vorrat anzulegen sind versucht, die gespeichert wurde „viele Commits vor“ in den aktuellen Arbeitsbereich, git checkout -p [email protected]{n} werden versuchen, nicht nur die Änderungen in der Stash richtigen anzuwenden, sondern auch versuchen, revert Alle Änderungen zwischen dem Commit, auf dem der Stash basiert, und dem aktuellen Commit.

Wenn Sie versuchen, einen Stash "aus der Zukunft" anzuwenden, dh in einen Zweig, der eine Anzahl von Commits vor dem Commit darstellt, auf dem der Stash basiert, dann wird git checkout -p [email protected]{n} versuchen, auch alle zu übernehmen die anderen Änderungen, die zwischen dem aktuellen Commit und dem Commit aus der Zukunft stattfanden, neben den Änderungen aus dem Stash selbst.

(Falls Sie sich fragen, git checkout -p [email protected]{n} ein Versteck von einem parallelen Zweig wird versuchen, alle Änderungen zwischen der aktuellen zurückzukehren begehen und die ursprüngliche Verzweigungspunkt und auch alle Änderungen zwischen dem Verzweigungspunkt und dem anderen Zweig gelten, neben der Änderung im Versteck).

Es gibt ein paar Abhilfen, keiner von ihnen perfekt sind perfekt für jede Situation:

  1. Seien Sie sehr vorsichtig mit den Patches akzeptieren Sie, wenn Sie tun git checkout -p [email protected]{n}

  2. ein git stash pop tun, dann git stash nochmal vor git checkout -p .... Aber wenn du deinen Vorrat teilweise anwenden willst, um Konflikte zu vermeiden, wird das nicht wirklich helfen.

  3. Wenn Sie ein grafisches Diff-Tool von git (wie meld) unterstützt, können Sie git difftool verwenden und „anwenden links“, um alle Änderungen, die Sie sich interessieren.

    • git difftool -d [email protected]{n} eine ganze Stash vergleichen und alle seine Dateien

    • git difftool [email protected]{n} -- path/to/file zu vergleichen, um eine einzelne Datei

+0

Es gibt hier einen Vorbehalt, der erwähnt werden muss: Da Stashes nur Commits sind, bedeutet das, dass sie auch Eltern-Commits haben, die nicht garantiert dasselbe Eltern-Commit wie das sind, auf das Sie interaktiv Änderungen anwenden möchten. Faustregel: Wenn Sie von einem anderen Commit als dem aktuell ausgecheckten Commit verschachtelt haben, wird diese Technik nicht das leisten, was Sie erwarten. Umgehung: Wenden Sie den gesamten Satz von Änderungen aus Ihrem Stash (mit Git stash pop) an und speichern Sie ihn dann erneut (git stash). Jetzt können Sie checkout -p wie gewünscht. – mgadda

+0

@mgadda, danke. Ich habe einen Abschnitt "Vorbehalte" hinzugefügt. – LeoRochael

1

Ich glaube nicht, dass es eine Möglichkeit gibt, Änderungen durch Hunks (oder sogar durch Datei) anzuwenden. Sie müssen den Stash anwenden und dann die Änderungen, die Sie nicht interaktiv wollen (mit git stash save -p), speichern. Wenn Sie sich über Konflikte Sorgen machen, können Sie zunächst alle nicht festgeschriebenen Änderungen speichern, Ihren Versteck übernehmen, alle widersprüchlichen Kerben speichern und dann den anderen Versteck anwenden.

+0

Ja, ich frage hauptsächlich, weil ich Konflikte vermeiden will. Der Zweck ist, einige Änderungen von (sagen wir mal) * branch_A * zu erhalten und in der Lage zu sein, sie auf * branch_B * zu setzen, um die Konflikte, die diese zwei Zweige haben könnten, direkt zu vermeiden. Ihre Lösung funktioniert, aber ist genau die "komplizierte" Art, die ich vermeiden wollte ;-P – Kamafeather

+0

Der umgekehrte Ansatz, nur um "stash speichern" interaktiv die Hunks, die ich will * und dann wieder auf dem gewünschten Zweig wiederherstellen von 'git stash apply' interaktiv die hunks die ich * will *, scheint der beste ansatz zu sein. – Kamafeather