Nur eine Datei aus mehreren Dateien verstecken, die sich mit Git geändert haben?

3069

Wie kann ich nur eine von mehreren geänderten Dateien in meinem Zweig speichern?

Rachel
quelle
109
Ich denke nicht, dass die akzeptierte Antwort von @ bukzor eine korrekte Antwort auf die Frage ist, wie sie gestellt wurde. git stash --keep-indexbehält zwar den Index bei, versteckt aber alles - sowohl im Index als auch außerhalb.
Raman
@Antonio Es scheint mir, dass Ihr Kopfgeld eigentlich eine separate Frage sein sollte, da die ursprüngliche Frage nichts speziell mit TortoiseGit zu tun hat.
JesusFreke
1
@JesusFreke Ja, angesichts des Ergebnisses hätte ich 50 Wiederholungen sparen können :) Es ist nur so, dass dies die Frage ist, auf die Sie umgeleitet werden, wenn Sie versuchen, nach "partiellem Stash Tortoisegit" zu suchen. Tortoisegit scheint hier kein beliebtes Thema zu sein stackoverflow.com/questions/tagged/tortoisegit
Antonio
7
>>>>>>>>> git diff -- *filename* > ~/patchdann git checkout -- *filename*und später können Sie den Patch mitgit apply ~/patch
neaumusic
36
Die meisten der unten aufgeführten Antworten sind veraltet. Seit Git 2.13 (Q2 2017) wird es mit unterstützt git stash push [--] [<pathspec>...].
Ohad Schneider

Antworten:

1372

Haftungsausschluss : Die folgende Antwort gilt für Git vor Git 2.13. Schauen Sie sich für Git 2.13 und höher eine weitere Antwort weiter unten an .


Warnung

Wie in den Kommentaren erwähnt, wird dadurch alles inszeniert, sowohl inszeniert als auch nicht inszeniert. Der --keep-Index lässt den Index nach Abschluss des Stashs einfach in Ruhe. Dies kann zu Zusammenführungskonflikten führen, wenn Sie den Stash später öffnen.


Dadurch wird alles gespeichert, was Sie zuvor noch nicht hinzugefügt haben. Nur git adddie Dinge, die Sie behalten möchten, und dann ausführen.

git stash --keep-index

Wenn Sie beispielsweise ein altes Commit in mehrere Änderungssätze aufteilen möchten, können Sie folgende Prozedur verwenden:

  1. git rebase -i <last good commit>
  2. Markieren Sie einige Änderungen als edit.
  3. git reset HEAD^
  4. git add <files you want to keep in this change>
  5. git stash --keep-index
  6. Repariere die Dinge nach Bedarf. Vergessen Sie git addkeine Änderungen.
  7. git commit
  8. git stash pop
  9. Wiederholen Sie dies nach Bedarf ab Nr. 5.
  10. git rebase --continue
Bukzor
quelle
47
Ich finde diesen Ansatz viel einfacher: stackoverflow.com/a/5506483/457268
k0pernikus
561
Ich bin mir nicht sicher, warum dies positiv bewertet wird. Jeder muss eine andere Erwartung haben als ich. Der ursprüngliche Beitrag fragt: "Wie kann ich nur einen Teil der nicht festgeschriebenen Änderungen aufbewahren?" Wenn ich benutze git stash save -k, git statbleibt der Index (grün in ) ja erhalten, aber der gesamte Änderungssatz (sowohl grün als auch rot) geht in den Vorrat. Dies verstößt gegen die Anforderung des OP, "nur einige Änderungen zu speichern". Ich möchte nur einen Teil der roten (für die zukünftige Verwendung) verstauen.
Pistos
70
Wenn Sie mehr an der Antwort auf die Frage von @Pistos interessiert sind (wie ich), dann schauen Sie hier: stackoverflow.com/questions/5506339/…
Raman
27
@ Raman: Ausgezeichnet! git stash -pist genau das, wonach ich gesucht habe. Ich frage mich, ob dieser Schalter erst kürzlich hinzugefügt wurde.
Pistos
14
WARNUNG: git stash --keep-indexist defekt. Wenn Sie weitere Änderungen vornehmen, versuchen git stash popSie später, Zusammenführungskonflikte zu erhalten, da der Stash die geänderten Dateien enthält, die Sie gespeichert haben, und nicht nur die, die Sie nicht gespeichert haben. Zum Beispiel: Ich ändere die Dateien A und B und verstecke dann B, weil ich die Änderungen in A testen möchte. Ich finde ein Problem mit A, das ich dann behebe. Ich begebe A; Jetzt kann ich nicht mehr speichern, da sich eine alte Version von A ohne guten Grund im Speicher befindet und einen Zusammenführungskonflikt verursacht. In der Praxis können A und B viele Dateien sein, vielleicht sogar Binärbilder oder so, also muss ich im Grunde aufgeben und verlieren B.
rjmunro
3015

Sie können auch verwenden git stash save -p "my commit message" . Auf diese Weise können Sie auswählen, welche Hunks zum Stash hinzugefügt werden sollen. Es können auch ganze Dateien ausgewählt werden.

Sie werden mit ein paar Aktionen für jedes Stück aufgefordert:

   y - stash this hunk
   n - do not stash this hunk
   q - quit; do not stash this hunk or any of the remaining ones
   a - stash this hunk and all later hunks in the file
   d - do not stash this hunk or any of the later hunks in the file
   g - select a hunk to go to
   / - search for a hunk matching the given regex
   j - leave this hunk undecided, see next undecided hunk
   J - leave this hunk undecided, see next hunk
   k - leave this hunk undecided, see previous undecided hunk
   K - leave this hunk undecided, see previous hunk
   s - split the current hunk into smaller hunks
   e - manually edit the current hunk
   ? - print help
konrad.kruczynski
quelle
5
Es war nicht. Es wurde etwa 7 Jahre später von Darcs ausgeliehen.
Nomen
6
Ich bin ein TortoiseGit-Süchtiger. TortoiseGit unterstützt dies jedoch nicht stash -p. Ich vergebe diese Antwort, weil sie am interaktivsten / benutzerfreundlichsten bleibt.
Antonio
27
Vielleicht möchten Sie hinzufügen : git stash save -p my stash message; da die Reihenfolge der Argumente nicht sehr intuitiv ist ...
Chris Maes
15
Zwischen diesem und git log -p, denke ich, -pmuss die Flagge bedeuten "Mach das Coole, was ich will, aber ich weiß nicht, wie ich es ausdrücken soll."
Kyle Strand
2
Warum um alles in der Welt ist diese großartige Antwort auf Platz 12? nach all diesen 0, +1, +2 Antworten ??????
DenisFLASH
548

Da es bei git im Wesentlichen um die Verwaltung des gesamten Repository- Inhalts und -Index (und nicht einer oder mehrerer Dateien) geht, git stashhandelt es sich nicht überraschend ummit dem gesamten Arbeitsverzeichnis.

Seit Git 2.13 (Q2 2017) können Sie einzelne Dateien mit git stash pushfolgenden Elementen speichern :

git stash push [--] [<pathspec>...]

Wenn pathspec' git stash push' angegeben wird, zeichnet der neue Stash die geänderten Zustände nur für die Dateien auf, die der Pfadspezifikation entsprechen. Weitere Informationen finden Sie unter " Stash-Änderungen an bestimmten Dateien ".

Vereinfachtes Beispiel:

 git stash push path/to/file

Der Testfall für diese Funktion zeigt einige weitere Optionen:

test_expect_success 'stash with multiple pathspec arguments' '
    >foo &&
    >bar &&
    >extra &&
    git add foo bar extra &&

    git stash push -- foo bar &&   

    test_path_is_missing bar &&
    test_path_is_missing foo &&
    test_path_is_file extra &&

    git stash pop &&
    test_path_is_file foo &&
    test_path_is_file bar &&
    test_path_is_file extra

Bei der ursprünglichen Antwort (unten, Juni 2010) ging es darum, manuell auszuwählen, was Sie verstauen möchten.

Casebash- Kommentare:

Dies (die stash --patchursprüngliche Lösung) ist nett, aber oft habe ich viele Dateien geändert, so dass die Verwendung von Patches ärgerlich ist

bukzor ‚s Antwort (upvoted November 2011) schlägt vor , eine praktischere Lösung, basierend auf
git add+git stash --keep-index .
Gehen Sie und sehen Sie seine Antwort, die die offizielle sein sollte (anstelle meiner).

Zu dieser Option weist chhh in den Kommentaren auf einen alternativen Workflow hin:

Sie sollten git reset --softnach einem solchen Vorrat " " " " tun, um Ihre klare Inszenierung wiederherzustellen:
Um zum ursprünglichen Zustand zurückzukehren - der ein klarer Staging-Bereich ist und nur einige ausgewählte nicht inszenierte Modifikationen enthält, können Sie den Index sanft zurücksetzen, um ihn zu erhalten (ohne) etwas wie Sie zu begehen - bukzor - tat).


(Ursprüngliche Antwort Juni 2010: manuelle Aufbewahrung)

Dennoch git stash save --patchkonnte ermöglicht es Ihnen , die teilweise stashing erreichen Sie nach:

Mit --patchkönnen Sie interaktiv Hunks aus dem Diff zwischen HEAD und dem zu verstauenden Arbeitsbaum auswählen.
Der Stash-Eintrag ist so aufgebaut, dass sein Indexstatus mit dem Indexstatus Ihres Repositorys übereinstimmt und sein Arbeitsbaum nur die Änderungen enthält, die Sie interaktiv ausgewählt haben. Die ausgewählten Änderungen werden dann von Ihrem Arbeitsbaum zurückgesetzt.

Dadurch werden jedoch der vollständige Index (der möglicherweise nicht Ihren Wünschen entspricht, da er möglicherweise andere bereits indizierte Dateien enthält) und ein Teilarbeitsbaum (der möglicherweise so aussieht wie der, den Sie speichern möchten) gespeichert.

git stash --patch --no-keep-index

könnte besser passen.


Wenn --patchdies nicht funktioniert, kann ein manueller Vorgang Folgendes bewirken:

Für eine oder mehrere Dateien wäre eine Zwischenlösung:

  • kopiere sie außerhalb des Git-Repos
    (Eigentlich schlägt eleotlecram eine interessante Alternative vor )
  • git stash
  • kopiere sie zurück
  • git stash # Dieses Mal werden nur die gewünschten Dateien gespeichert
  • git stash pop stash@{1} # Wenden Sie alle Änderungen an Ihren Dateien erneut an
  • git checkout -- afile # Setzen Sie die Datei vor lokalen Änderungen auf den HEAD-Inhalt zurück

Am Ende dieses ziemlich umständlichen Prozesses werden nur eine oder mehrere Dateien gespeichert.

VonC
quelle
3
Das ist schön, aber oft habe ich viele Dateien geändert, so dass die Verwendung von Patch ärgerlich ist
Casebash
6
@VonC: Es ist ein guter Stil, nur eine Antwort pro Antwort zu haben. Das Kopieren und Einfügen der Antworten anderer in Ihre eigenen ist ebenfalls schlecht.
Bukzor
3
@bukzor: Es tut mir leid, wenn meine bearbeitete Antwort unangemessen schien. Meine einzige Absicht war es, Ihre Antwort sichtbarer zu machen. Ich habe meinen Beitrag erneut bearbeitet, um diese Absicht klarer zu machen.
VonC
1
@ Kal: true, stackoverflow.com/a/13941132/6309 schlägt eine git reset(gemischte)
VonC
3
git is fundamentally about managing a all repository content and index and not one or several files- Diese Implementierung überschattet das zu lösende Problem. Es ist eine Erklärung, aber keine Rechtfertigung. Bei jedem Versionsverwaltungssystem geht es darum, "mehrere Dateien zu verwalten". Schauen Sie sich nur an, welche Kommentare am meisten positiv bewertet werden.
Victor Sergienko
90

Wenn git stash -p(oder git add -pmit stash --keep-index) zu umständlich wäre, fand ich es einfacher zu bedienen diff, checkoutund apply:

So "verstauen" Sie nur eine bestimmte Datei / ein bestimmtes Verzeichnis:

git diff path/to/dir > stashed.diff
git checkout path/to/dir

Dann danach

git apply stashed.diff
blau gefärbt
quelle
1
Interessante Alternative zu der, die git add -pich oben in meiner eigenen Antwort erwähnt habe. +1.
VonC
11
Beachten Sie, dass Binärdateien (wie PNGs) nicht in die Diff-Datei ausgegeben werden. Das ist also keine 100% ige Lösung.
void.pointer
1
@ RobertDailey: Das ist ein interessanter Punkt für mich, ebenso git diff > file.diffwie git applymeine üblichen Teilversteck-Tools. Ich muss möglicherweise in Betracht ziehen, git stash -pfür größere Änderungssätze zu wechseln.
thekingoftruth
1
@thekingoftruth Hier ist der Alias, den ich zum Erstellen von Patch-Dateien verwende und der Binärdateien unterstützt : patch = log --pretty=email --patch-with-stat --reverse --full-index --binary. Beachten Sie jedoch, dass Ihre Änderungen erforderlich sind, damit der Patch festgeschrieben wird.
void.pointer
2
Dies funktionierte für mich nicht sauber, wenn die zu verstauende Datei so etwas wie war ../../foo/bar.txt. Der Patch generiert OK, aber ich muss dann zum Repository-Stammverzeichnis wechseln, damit der Patch angewendet wird. Wenn Sie also Probleme damit haben, stellen Sie einfach sicher, dass Sie dies aus dem Repository-Stammverzeichnis tun.
Michael Anderson
86

Verwenden Sie git stash pushwie folgt:

git stash push [--] [<pathspec>...]

Zum Beispiel:

git stash push -- my/file.sh

Dies ist seit Git 2.13 verfügbar, das im Frühjahr 2017 veröffentlicht wurde.

Sandstrom
quelle
1
Aber ich erwähne es git stash pushbereits in meiner obigen Antwort vom letzten März vor 5 Monaten. Und ich habe diesen neuen Git 2.13-Befehl hier detailliert beschrieben: stackoverflow.com/a/42963606/6309 .
VonC
Ich bin froh, dass Git so schnell voranschreitet, dass dies lange Zeit nicht möglich war und dann 2.13 veröffentlicht wird und plötzlich eine einfache Lösung verfügbar ist!
Sandstrom
1
@VonC Sie haben Recht, Sie erwähnen auch die richtige Antwort. Zwischen den beiden Antworten ist diese jedoch leichter zu lesen (kein verwirrender Text und es gibt auch ein Beispiel). Vielleicht hätten sie stattdessen Ihre Antwort bearbeiten sollen
Utopik
@Utopik Du hattest mich bei "du hast recht" ... aber ja, ich habe meine Antwort so bearbeitet, dass sie ein Beispiel enthält.
VonC
Verwendet man dann git stash apply, um die versteckten Änderungen wiederherzustellen?
Tschad
49

Angenommen, Sie haben 3 Dateien

a.rb
b.rb
c.rb

und du willst nur b.rb und c.rb verstauen, aber nicht a.rb.

Sie können so etwas tun

# commit the files temporarily you don't want to stash
git add a.rb
git commit -m "temp" 

# then stash the other files
git stash save "stash message"

# then undo the previous temp commit
git reset --soft HEAD^
git reset

Und du bist fertig! HTH.

venkatareddy
quelle
29

Ein anderer Weg, dies zu tun:

# Save everything
git stash 

# Re-apply everything, but keep the stash
git stash apply

git checkout <"files you don't want in your stash">

# Save only the things you wanted saved
git stash

# Re-apply the original state and drop it from your stash
git stash apply stash@{1}
git stash drop stash@{1}

git checkout <"files you put in your stash">

Ich habe mir das ausgedacht, nachdem ich (noch einmal) auf diese Seite gekommen bin und die ersten beiden Antworten nicht gemocht habe (die erste Antwort beantwortet die Frage einfach nicht und ich habe es nicht ganz gemocht, mit dem -pinteraktiven Modus zu arbeiten).

Die Idee entspricht der von @VonC vorgeschlagenen Verwendung von Dateien außerhalb des Repositorys. Sie speichern die gewünschten Änderungen irgendwo, entfernen die nicht gewünschten Änderungen in Ihrem Vorrat und wenden die Änderungen, die Sie aus dem Weg geräumt haben, erneut an. Ich habe jedoch den Git-Stash als "irgendwo" verwendet (und als Ergebnis gibt es am Ende einen zusätzlichen Schritt: Entfernen der Cahnges, die Sie in den Stash gelegt haben, weil Sie diese ebenfalls aus dem Weg geräumt haben).

Jaspis
quelle
1
Ich bevorzuge diesen Ansatz am meisten. Es bietet einen einfachen Workflow in Tortoisegit, bei dem nur Stash- und Revert-Befehle verwendet werden.
Mark Ch
Es ist nicht ratsam, auf Antworten zu SO unter Verwendung von Positionen zu verweisen. Die Positionen ändern sich, wenn sich die Bewertungen ändern.
Bryan Ash
2
@BryanAsh Nun, es ist nicht so, dass es hier wichtig ist. Ich gebe eine Anekdote, anstatt mich wirklich auf die anderen Antworten zu beziehen. Die Nachricht ist, dass mir die Antworten, die der Community gefallen haben, nicht gefallen haben und nicht, was diese Antworten tatsächlich enthalten. Außerdem macht es die 900-Stimmen-Lücke zwischen der zweiten und dritten Antwort unwahrscheinlich, dass sich dies in naher Zukunft ändert, und sollte sich dies jemals ändern, kann ich es jederzeit so bearbeiten, dass es "die Spitze der Antworten zu der Zeit" sagt. Wirklich, ich sehe nicht, wie das in dieser Situation irgendein Problem ist.
Jasper
23

Update (14.02.2015) - Ich habe das Skript ein wenig umgeschrieben, um den Fall von Konflikten besser zu behandeln, die jetzt als nicht zusammengeführte Konflikte und nicht als .rej-Dateien dargestellt werden sollten.


Ich finde es oft intuitiver, das Gegenteil von @ bukzors Ansatz zu tun. Das heißt, einige Änderungen zu inszenieren und dann nur diese inszenierten Änderungen zu speichern.

Leider bietet git keinen Git-Stash - nur Index oder ähnliches, deshalb habe ich ein Skript erstellt, um dies zu tun.

#!/bin/sh

# first, go to the root of the git repo
cd `git rev-parse --show-toplevel`

# create a commit with only the stuff in staging
INDEXTREE=`git write-tree`
INDEXCOMMIT=`echo "" | git commit-tree $INDEXTREE -p HEAD`

# create a child commit with the changes in the working tree
git add -A
WORKINGTREE=`git write-tree`
WORKINGCOMMIT=`echo "" | git commit-tree $WORKINGTREE -p $INDEXCOMMIT`

# get back to a clean state with no changes, staged or otherwise
git reset -q --hard

# Cherry-pick the index changes back to the index, and stash.
# This cherry-pick is guaranteed to succeed
git cherry-pick -n $INDEXCOMMIT
git stash

# Now cherry-pick the working tree changes. This cherry-pick may fail
# due to conflicts
git cherry-pick -n $WORKINGCOMMIT

CONFLICTS=`git ls-files -u`
if test -z "$CONFLICTS"; then
    # If there are no conflicts, it's safe to reset, so that
    # any previously unstaged changes remain unstaged
    #
    # However, if there are conflicts, then we don't want to reset the files
    # and lose the merge/conflict info.
    git reset -q
fi

Sie können das obige Skript als git-stash-indexirgendwo auf Ihrem Pfad speichern und es dann als Git-Stash-Index aufrufen

# <hack hack hack>
git add <files that you want to stash>
git stash-index

Jetzt enthält der Stash einen neuen Eintrag, der nur die Änderungen enthält, die Sie bereitgestellt haben, und Ihr Arbeitsbaum enthält weiterhin alle nicht bereitgestellten Änderungen.

In einigen Fällen können die Änderungen des Arbeitsbaums von den Indexänderungen abhängen. Wenn Sie also die Indexänderungen speichern, treten bei den Änderungen des Arbeitsbaums Konflikte auf. In diesem Fall erhalten Sie die üblichen nicht zusammengeführten Konflikte, die Sie mit git merge / git mergetool / etc. Lösen können.

JesusFreke
quelle
Empfehlen Sie pushdanstelle cdund popdam Ende des Skripts. Wenn das Skript erfolgreich ist, befindet sich der Benutzer im selben Verzeichnis wie vor dem Ausführen.
Nate
1
@Nate: Soweit ich weiß, sollte das Verzeichnis für den Benutzer nur geändert werden, wenn er das Skript bezogen hat. Wenn Sie das Skript normal (~ / bin / git-stash-index) oder über git (git stash-index) ausführen, wird es in einer separaten Terminalsitzung ausgeführt, und Änderungen des Arbeitsverzeichnisses in dieser Sitzung wirken sich nicht auf das aus Arbeitsverzeichnis in der Terminalsitzung des Benutzers. Kennen Sie einen häufigen Anwendungsfall, wenn dies nicht der Fall ist? (außer das Skript zu beschaffen, das ich nicht als "gewöhnlich" betrachten würde)
JesusFreke
20

Wenn Sie keine Nachricht mit Ihren versteckten Änderungen angeben möchten, übergeben Sie den Dateinamen nach einem Doppelstrich.

$ git stash -- filename.ext

Wenn es sich um eine nicht verfolgte / neue Datei handelt, müssen Sie sie zuerst bereitstellen.

Diese Methode funktioniert in Git-Versionen 2.13+

Sealocal
quelle
Diese Antwort ist ausführlich, dies ist prägnant. Wenn es jemandem hilft, werde ich es verlassen. Niemand auf dieser Seite erwähnt diese Syntax und das Ergebnis - sie erwähnen stattdessen "git stash push".
Sealocal
Dies ist die Antwort, nach der ich gesucht habe. Vielen Dank! +1
nicodp
19

Da das Erstellen von Zweigen in Git trivial ist, können Sie einfach einen temporären Zweig erstellen und die einzelnen Dateien darin einchecken.

shangxiao
quelle
2
Sie können keinen Zweig mit nicht bereitgestellten Änderungen erstellen. Sie können alle Änderungen problemlos in einen neuen Zweig verschieben (Stash / Stash Pop), aber dann kehren Sie zum ersten Punkt zurück: Wie testen Sie Ihren Zweig mit nur einigen dieser Änderungen, ohne die anderen zu verlieren?
Bukzor
7
Sie können keine Zweige wechseln, wenn Sie lokale Änderungen haben. Sie können jedoch einen neuen Zweig erstellen und Dateien selektiv hinzufügen / festschreiben, dann einen weiteren Zweig erstellen und das Gleiche rekursiv tun ... dann den ursprünglichen Zweig auschecken und selektiv wieder zusammenführen. Ich habe es gerade getan. Es scheint tatsächlich die natürliche Art zu sein, Dinge zu tun, da Sie im Wesentlichen Feature-Zweige erstellen.
iain
3
@iain können Sie Zweige wechseln, wenn Sie lokale Änderungen haben, solange diese keine Zusammenführung erfordern. Siehe Beispiel Gist . Dies gilt mindestens ab Git v2.7.0.
Colin D Bennett
18

Sie können dies einfach tun:

git stash push "filename"

oder mit einer optionalen Nachricht

git stash push -m "Some message" "filename"
vinodsaluja
quelle
1
Dies fügt nichts Neues hinzu. Git Stash Push wird bereits in mehreren Antworten erwähnt
JesusFreke
12

Speichern Sie den folgenden Code in einer Datei mit dem Namen stash. Verwendung ist stash <filename_regex>. Das Argument ist der reguläre Ausdruck für den vollständigen Pfad der Datei. Zum Beispiel, um a / b / c.txt stash a/b/c.txtoder stash .*/c.txtusw. zu verstauen .

$ chmod +x stash
$ stash .*.xml
$ stash xyz.xml

Code zum Kopieren in die Datei:

#! /usr/bin/expect --
log_user 0
set filename_regexp [lindex $argv 0]

spawn git stash -p

for {} 1 {} {
  expect {
    -re "diff --git a/($filename_regexp) " {
      set filename $expect_out(1,string)
    }
    "diff --git a/" {
      set filename ""
    }
    "Stash this hunk " {
      if {$filename == ""} {
        send "n\n"
      } else {
        send "a\n"
        send_user "$filename\n"
      }
    }
    "Stash deletion " {
      send "n\n"
    }
    eof {
      exit
    }
  }
}
Aprikose
quelle
2
Tolle Methode. Ich hätte dies als Antwort gewählt. Tipp für zukünftige Leser: Sie müssen auf dem vollen Weg übereinstimmen. zB stash subdir / foo.c
er0
12

Nur für den Fall, dass Sie tatsächlich Änderungen verwerfen möchten, wann immer Sie sie verwenden git stash(und Git Stash nicht wirklich verwenden, um sie vorübergehend zu speichern), können Sie sie in diesem Fall verwenden

git checkout -- <file>

[ HINWEIS ]

Das git stashist nur eine schnellere und einfachere Alternative zum Verzweigen und Ausführen.

Devesh
quelle
8

Das Problem bei VonCs "Zwischen" -Lösung zum Kopieren von Dateien außerhalb des Git-Repos besteht darin, dass Sie Pfadinformationen verlieren, was das spätere Zurückkopieren einer Reihe von Dateien etwas mühsam macht.

Es ist einfacher, tar zu verwenden (ähnliche Tools werden es wahrscheinlich tun) als zu kopieren:

  • tar cvf /tmp/stash.tar Pfad / zu / einigen / Dateipfad / zu / einigen / anderen / Dateien (... usw.)
  • Git Checkout-Pfad / zu / einigen / Dateipfad / zu / einigen / anderen / Dateien
  • git stash
  • tar xvf /tmp/stash.tar
  • usw. (siehe VonCs "Zwischen" -Vorschlag)
eleotlecram
quelle
checkout -fwird nicht benötigt, checkout(ohne -f) ist genug, ich habe die Antwort aktualisiert.
Eleotlecram
8

Manchmal habe ich eine nicht verwandte Änderung an meinem Zweig vorgenommen, bevor ich sie festgeschrieben habe, und ich möchte sie in einen anderen Zweig verschieben und separat festschreiben (wie Master). Ich mache das:

git stash
git checkout master
git stash pop
git add <files that you want to commit>
git commit -m 'Minor feature'
git stash
git checkout topic1
git stash pop
...<resume work>...

Beachten Sie, dass das erste stash& stash popbeseitigt werden kann. Sie können alle Ihre Änderungen auf das übertragenmaster beim Auschecken Filiale übertragen, jedoch nur, wenn keine Konflikte vorliegen. Auch wenn Sie einen neuen Zweig für die Teiländerungen erstellen, benötigen Sie den Stash.

Sie können es vereinfachen, indem Sie keine Konflikte und keinen neuen Zweig annehmen:

git checkout master
git add <files that you want to commit>
git commit -m 'Minor feature'
git checkout topic1
...<resume work>...

Versteck nicht einmal benötigt ...

void.pointer
quelle
8

Dies kann mit SourceTree in 3 Schritten einfach durchgeführt werden.

  1. Legen Sie vorübergehend alles fest, was Sie nicht verstauen möchten.
  2. Git alles andere hinzufügen, dann verstauen.
  3. Pop Ihr ​​temporäres Commit, indem Sie git reset ausführen und das Commit vor Ihrem temporären festsetzen.

Dies alles kann in SourceTree in Sekundenschnelle erledigt werden, wo Sie einfach auf die Dateien (oder sogar einzelne Zeilen) klicken können, die Sie hinzufügen möchten. Einmal hinzugefügt, verpflichten Sie sie einfach zu einem temporären Commit. Klicken Sie anschließend auf das Kontrollkästchen, um alle Änderungen hinzuzufügen, und klicken Sie dann auf Stash, um alles zu speichern. Wenn die versteckten Änderungen nicht im Weg sind, werfen Sie einen Blick auf Ihre Festschreibungsliste und notieren Sie sich den Hash für das Festschreiben vor Ihrem temporären Festschreiben. Führen Sie dann "git reset hash_b4_temp_commit" aus direkt davor begehen. Jetzt haben Sie nur noch das Zeug, das Sie nicht verstauen wollten.

Triynko
quelle
8

Ich würde verwenden git stash save --patch. Ich finde die Interaktivität nicht ärgerlich, da es währenddessen Optionen gibt, um den gewünschten Vorgang auf ganze Dateien anzuwenden.

Raffi Khatchadourian
quelle
3
Erstaunt, dass diese Antwort so wenig Unterstützung bietet, dass sie die beste Lösung ist, ohne dass ein Aufsatz erforderlich ist.
Robstarbuck
Auf jeden Fall die gute Antwort, git stash -permöglicht es Ihnen, eine ganze Datei schnell zu verstauen und danach zu beenden.
Richard Dally
7

Jede Antwort hier ist so kompliziert ...

Was ist damit zu "verstauen":

git diff /dir/to/file/file_to_stash > /tmp/stash.patch
git checkout -- /dir/to/file/file_to_stash

Dies, um die Dateiänderung zurückzusetzen:

git apply /tmp/stash.patch

Genau das gleiche Verhalten wie beim Verstauen einer Datei und beim erneuten Einlegen.

Christophe Fondacci
quelle
Ich habe es versucht, aber nichts passiert. Wenn ich git applykeinen Fehler habe, aber Änderungen auch nicht zurückgebracht werden
ClementWalter
Die in / tmp generierte Patch-Datei wurde wahrscheinlich gelöscht. Möglicherweise haben Sie zwischen dem Diff und dem Apply neu gestartet. Versuchen Sie es mit einem anderen dauerhafteren Ort. Es funktioniert. Überprüfen Sie auch den Inhalt der Patch-Datei.
Christophe Fondacci
4

Ich habe Antworten und Kommentare zu diesem und einer Reihe ähnlicher Themen überprüft. Beachten Sie, dass keiner der folgenden Befehle korrekt ist, um bestimmte verfolgte / nicht verfolgte Dateien speichern zu können :

  • git stash -p (--patch): Wählen Sie Hunks manuell aus, ausgenommen nicht verfolgte Dateien
  • git stash -k (--keep-index): Verstecke alle verfolgten / nicht verfolgten Dateien und behalte sie im Arbeitsverzeichnis
  • git stash -u (--include-untracked): Versteckt alle verfolgten / nicht verfolgten Dateien
  • git stash -p (--patch) -u (--include-untracked): ungültiger Befehl

Derzeit ist die vernünftigste Methode, um bestimmte verfolgte / nicht verfolgte Dateien zu speichern, folgende:

  • Übernehmen Sie vorübergehend die Dateien, die Sie nicht speichern möchten
  • Hinzufügen und verstauen
  • Pop das temporäre Commit

Ich habe ein einfaches Skript für diese Prozedur in einer Antwort auf eine andere Frage geschrieben , und hier finden Sie Schritte zum Ausführen der Prozedur in SourceTree .

ZimbiX
quelle
4

Lösung

Lokale Änderungen:

  • file_A (geändert) nicht bereitgestellt
  • file_B (geändert) nicht bereitgestellt
  • file_C (geändert) nicht bereitgestellt

So erstellen Sie einen Stash "my_stash" mit nur den Änderungen in file_C :

1. git add file_C
2. git stash save --keep-index temp_stash
3. git stash save my_stash
4. git stash pop stash@#{1}

Erledigt.


Erläuterung

  1. hinzufügen file_C in den Staging - Bereich
  2. Erstellen Sie einen temporären Stash mit dem Namen "temp_stash" und behalten Sie die Änderungen in file_C bei
  3. Erstellen Sie den gewünschten Stash ("my_stash") nur mit den Änderungen in file_C
  4. Wenden Sie die Änderungen in "temp_stash" (file_A und file_B) auf Ihren lokalen Code an und löschen Sie den Stash

Sie können den Git-Status zwischen den Schritten verwenden, um zu sehen, was los ist.

Alex 75
quelle
3

Wenn Sie versuchen, zwischen zwei Zweigen zu wechseln, tritt diese Situation auf.

Versuchen Sie, die Dateien mit " git add filepath" hinzuzufügen .

Führen Sie diese Zeile später aus

git stash --keep-index

Sireesh Yarlagadda
quelle
3

Um eine einzelne Datei zu verstauen, verwenden Sie git stash --patch [file].

Dies wird dazu auffordern : Stash this hunk [y,n,q,a,d,j,J,g,/,e,?]? ?. aGeben Sie einfach ein (verstauen Sie dieses Stück und alle späteren Stücke in der Datei) und schon geht es Ihnen gut.

Vinicius Brasilien
quelle
Vermisst pushwie ingit stash push --patch [file]
Filipe Esperandio
@FilipeEsperandio pushfunktioniert nur in neueren Versionen von Git save. In beiden Fällen pushoder saveimpliziert durch den Aufruf stash: "Das Aufrufen von git stash ohne Argumente entspricht git stash push", docs
patrick
2

Ähnliche Situation. Hat sich verpflichtet und festgestellt, dass es nicht in Ordnung ist.

git commit -a -m "message"
git log -p

Aufgrund der Antworten hat mir das geholfen.

# revert to previous state, keeping the files changed
git reset HEAD~
#make sure it's ok
git diff
git status
#revert the file we don't want to be within the commit
git checkout specs/nagios/nagios.spec
#make sure it's ok
git status
git diff
#now go ahead with commit
git commit -a -m "same|new message"
#eventually push tu remote
git push
David Hrbáč
quelle
2

In dieser Situation habe ich git add -p(interaktiv) git commit -m blahund dann bei Bedarf verstaut, was noch übrig ist.

J0hnG4lt
quelle
2

Ich weiß nicht, wie ich es in der Kommandozeile machen soll, nur mit SourceTree. Nehmen wir an, Sie haben Datei A geändert und haben zwei Änderungsblöcke in Datei B. Wenn Sie nur den zweiten Teil in Datei B speichern und alles andere unberührt lassen möchten, gehen Sie folgendermaßen vor:

  1. Alles inszenieren
  2. Nehmen Sie Änderungen an Ihrer Arbeitskopie vor, die alle Änderungen in Datei A rückgängig machen (z. B. das externe Diff-Tool starten und die Dateien übereinstimmen lassen.)
  3. Lassen Sie Datei B so aussehen, als würde nur eine zweite Änderung darauf angewendet. (z. B. externes Diff-Tool starten und erste Änderung rückgängig machen.)
  4. Erstellen Sie einen Stash mit "Bereitgestellte Änderungen beibehalten".
  5. Alles hinter die Bühne bringen
  6. Erledigt!
Juozas Kontvainis
quelle
2
git add .                           //stage all the files
git reset <pathToFileWillBeStashed> //unstage file which will be stashed
git stash                           //stash the file(s)
git reset .                         // unstage all staged files
git stash pop                       // unstash file(s)
Celikz
quelle
1
Nun, das solltest du nicht tun. Die Antwort sollte eine Lösung für die Frage bieten. Sie könnten einfach Ihre eigene Frage stellen.
L_J
Diese Lösung ist eine der einfachsten Antworten auf diese Frage. Lesen Sie die Frage, vergleichen Sie alle Antworten und meine. Wenn Sie Zweifel haben, dass diese Antwort weder eine zutreffende Lösung noch unzureichende Informationen zu der Frage enthält, können wir erneut sprechen.
Celikz
Dies funktioniert nicht, da der dritte Befehl "git stash" keine bereitgestellten Dateien berücksichtigt. Sowohl bereitgestellte als auch nicht bereitgestellte Dateien werden in den Stash verschoben. Die Fragen fragen speziell, wie man nur eine Datei
versteckt
0

Ein komplizierter Weg wäre, zuerst alles zu begehen:

git add -u
git commit // creates commit with sha-1 A

Zurück zum ursprünglichen Commit zurücksetzen, aber die_one_file aus dem neuen Commit auschecken:

git reset --hard HEAD^
git checkout A path/to/the_one_file

Jetzt können Sie die_one_file verstauen:

git stash

Bereinigen Sie, indem Sie den festgeschriebenen Inhalt in Ihrem Dateisystem speichern und auf das ursprüngliche Festschreiben zurücksetzen:

git reset --hard A
git reset --soft HEAD^

Ja, etwas umständlich ...

Martin G.
quelle
0

Ich fand keine Antwort als das, was ich brauchte und das ist so einfach wie:

git add -A
git reset HEAD fileThatYouWantToStash
git commit -m "committing all but one file"
git stash

Dadurch wird genau eine Datei gespeichert.

SCBuergel.eth
quelle
0

Schnelle Antwort


Um eine bestimmte geänderte Datei in git zurückzusetzen, können Sie die folgende Zeile ausführen:

git checkout <branch-name> -- <file-path>

Hier ist ein aktuelles Beispiel:

git checkout master -- battery_monitoring/msg_passing.py

Benyamin Jafari
quelle
0

Wenn Sie einige geänderte Dateien speichern möchten, einfach nur

Fügen Sie die Dateien, die Sie nicht speichern möchten, in Stage hinzu und führen Sie sie dann ausgit stash save --keep-index

Es werden alle nicht bereitgestellten geänderten Dateien gespeichert

Amin Shojaei
quelle