Wie füge ich meine lokalen nicht festgeschriebenen Änderungen in einem anderen Git-Zweig zusammen?

621

Wie kann ich in Git Folgendes tun?

Mein aktueller Zweig ist branch1 und ich habe einige lokale Änderungen vorgenommen. Jetzt ist mir jedoch klar, dass ich diese Änderungen eigentlich auf branch2 anwenden wollte. Gibt es eine Möglichkeit, diese Änderungen anzuwenden / zusammenzuführen, sodass sie in Zweig2 zu lokalen Änderungen werden, ohne sie in Zweig1 festzuschreiben?

Solsberg
quelle
2
Hier auf SO gibt es ein großartiges Git-Tutorial . Es ist eine Art Zentrale für alle Git-Fragen zum Stapelüberlauf.
Decio Lira

Antworten:

898

Da Ihre Dateien noch nicht festgeschrieben sind in branch1:

git stash
git checkout branch2
git stash pop

oder

git stash
git checkout branch2
git stash list       # to check the various stash made in different branch
git stash apply x    # to select the right one

Wie von Benjamin kommentiert (siehe git stashManpage ):

Fügen Sie das folgende Argument hinzu, um derzeit nicht verfolgte (neu hinzugefügte) Dateien zu speichern -u:

git stash -u
VonC
quelle
2
Bitte schön. Weitere Beispiele für die Verwendung von Stash finden Sie unter unethicalblogger.com/posts/2008/11/… .
VonC
2
Wenn Sie nach einer Lösung für dasselbe Problem suchen, jedoch mit TFS, besteht die entsprechende Lösung darin, Ihre Änderungen zurückzustellen und dann mit TFS Power Tools die Verknüpfung mit dem Schalter / migrate zum richtigen Zweig aufzuheben.
xr280xr
1
Das hat bei mir funktioniert. Ich musste jedoch auch einen lokalen Zweig erstellen, damit der 'Stash Pop' funktioniert. Kasse aus stackoverflow.com/questions/1783405/git-checkout-remote-branch wenn etwas Ähnliches geschieht mit Ihnen.
Mimoralea
21
Um auch noch untracked bunkern (neu hinzugefügte Dateien) , fügen Sie das Argument -u, so: git stash -u.
Benjohn
2
@ Benjohn Guter Punkt. Ich habe Ihren Kommentar zur besseren Sichtbarkeit in die Antwort aufgenommen.
VonC
84

Verstecken, vorübergehende Festschreibungen und erneutes Basieren können übertrieben sein. Wenn Sie die geänderten Dateien noch nicht zum Index hinzugefügt haben, können Sie möglicherweise nur den anderen Zweig auschecken.

git checkout branch2

Dies funktioniert so lange, wie sich keine Dateien, die Sie bearbeiten, zwischen Zweig1 und Zweig2 unterscheiden. Sie bleiben auf branch2, und Ihre Arbeitsänderungen bleiben erhalten. Wenn sie unterschiedlich sind, können Sie angeben, dass Sie Ihre lokalen Änderungen mit den Änderungen zusammenführen möchten, die durch Wechseln der Zweige mit der -mOption zum Auschecken eingeführt wurden.

git checkout -m branch2

Wenn Sie dem Index Änderungen hinzugefügt haben, möchten Sie diese Änderungen zuerst mit einem Reset rückgängig machen. (Dadurch bleibt Ihre Arbeitskopie erhalten, es werden nur die bereitgestellten Änderungen entfernt.)

git reset
CB Bailey
quelle
3
Ich dachte, das Versteck sei "einfacher" zu verstehen, aber Ihr Ansatz ist besser darin, das Arbeitsverzeichnis über verschiedene Branchen hinweg zu berücksichtigen. +1
VonC
6
Eine einfache traditionelle Kasse schien dem vorliegenden Problem angemessener zu sein. checkout ist leichter, es aktualisiert nur die Dateien, die geändert werden müssen. Vielleicht ist es einfacher, den Stash-Ansatz zu verstehen, oder es ist einfach nicht offensichtlich genug, dass das Auschecken in diesem Anwendungsfall "sicher" ist.
CB Bailey
Wenn checkout -mes in einer bestimmten Situation nicht "sicher" ist (möglicherweise würde dies zu einem Zusammenführungskonflikt führen), würde Stash einen Vorteil bieten (z. B. können Sie einen Stash-Pop entfernen)?
Craig McQueen
1
@craigMcQueen Sie können einen Pop-Stash nicht entfernen, aber Stash würde sich über Konflikte beschweren, wenn Sie ihn öffnen. Sie können die Konflikte beheben und dann festschreiben, aber in diesem Fall befindet sich der ursprüngliche Speicher noch auf dem Stapel! :)
Shaun F
Werden die Dateien im Falle eines Zusammenführungskonflikts nicht als gesichert .orig?
Jocull
13

Eine kürzere Alternative zum zuvor erwähnten Stash-Ansatz wäre:

Verschieben Sie die Änderungen vorübergehend in einen Stash.

  1. git stash

Erstellen Sie einen neuen Zweig, wechseln Sie zu ihm und fügen Sie ihn in nur einem Schritt hinzu.

  1. git stash branch new_branch_name

Dann einfach addund commitdie Änderungen an diesem neuen Zweig.

rbento
quelle
10

WARNUNG: Nicht für Git-Neulinge.

Dies kommt in meinem Workflow so oft vor, dass ich fast versucht habe, einen neuen Git-Befehl dafür zu schreiben. Der übliche git stashAblauf ist der richtige Weg, aber etwas umständlich. Normalerweise mache ich zuerst ein neues Commit, da, wenn ich mir die Änderungen angesehen habe, alle Informationen in meinem Kopf frisch sind und es besser ist, einfach mit dem zu beginnen, git commitwas ich gefunden habe (normalerweise ein Bugfix des Masters, den ich bei der Arbeit an einem entdeckt habe Feature-Zweig) sofort.

Es ist auch hilfreich, wenn Sie häufig auf solche Situationen stoßen, neben Ihrem aktuellen Arbeitsverzeichnis ein anderes Arbeitsverzeichnis zu haben, in dem der masterZweig immer ausgecheckt ist.

Wie ich das erreiche, sieht so aus:

  1. git commit die Änderungen sofort mit einer guten Commit-Nachricht.
  2. git reset HEAD~1 um das Commit von der aktuellen Verzweigung rückgängig zu machen.
  3. (optional) Arbeiten Sie weiter an der Funktion.

Manchmal später (asynchron) oder sofort in einem anderen Terminalfenster:

  1. cd my-project-master Das ist ein weiterer WD, der das gleiche teilt .git
  2. git reflog um den Bugfix zu finden, den ich gerade gemacht habe.
  3. git cherry-pick SHA1 des Commits.

Optional (immer noch asynchron) können Sie dann Ihren Feature-Zweig neu gründen (oder zusammenführen), um den Bugfix zu erhalten, normalerweise, wenn Sie eine PR einreichen möchten und Ihren Feature-Zweig und WD bereits bereinigt haben:

  1. cd my-project Das ist der Haupt-WD, an dem ich arbeite.
  2. git rebase master um die Bugfixes zu bekommen.

Auf diese Weise kann ich ununterbrochen an der Funktion weiterarbeiten und muss mich nicht darum kümmern, git stashirgendetwas zu git checkouttun oder meinen WD vor einem zu bereinigen (und dann den Backout des Feature-Zweigs erneut überprüfen zu lassen.) Und trotzdem alle meine Bugfixes auf masteranstatt gehen lassen versteckt in meinem Feature-Zweig.

IMO git stashund git checkoutist eine echte PIA, wenn Sie gerade an einem großen Feature arbeiten.

Chakrit
quelle
Interessante und gültige Alternative zu meiner Antwort. +1
VonC
Kommst du aus mercurial? Das my-project-masterTeilen des gleichen .gitlässt es so klingen. Warum nicht git checkout -b bugfixABC; git commit -a; git reset HEAD^ --hard, dann später (asynchron) , während auf master, git cherry-pick <SHA1 of the commit(s) in bugfixABC? (oder sogar, um zu vermeiden, dass Sie die SHA1 herausfinden müssen git rebase --onto master feature bugfixABC, von wo auch immer Sie sich gerade befinden. Das bedeutet, dass Sie dies direkt nach dem git resetoben genannten tun können , während Sie eingeschaltet sind feature.)
Gauthier
OP klingt jedoch so, als wären sie nicht bereit, die Änderungen zu übernehmen. In diesem Fall checkout -mist es einfach besser.
Gauthier
2

Wenn es um festgeschriebene Änderungen geht, sollten Sie sich git-rebase ansehen, aber wie in einem Kommentar von VonC erwähnt, wäre git-stash sicherlich der gute Weg, dies zu tun, wenn Sie über lokale Änderungen sprechen.

claf
quelle
Ich verstehe diese Lösung nicht: Sie würde den Festschreibungsverlauf von Zweig2 von Zweig1 neu schreiben ... warum alle festgeschriebenen Änderungen von Zweig1 in Zweig2 abrufen, wenn wir nur lokale nicht festgeschriebene Änderungen von Zweig1 in Zweig2 erhalten möchten? ...
VonC
@VonC: vereinbart, in diesem Fall erhält die Rebase alle festgeschriebenen Änderungen seit der letzten Zusammenführung zwischen Zweigen in Zweig1. Ich habe den "nicht festgeschriebenen" Parameter dieser Frage zuerst nicht erhalten. Rebase ist nicht die gute Antwort.
Claf
@claferri: pfew ... Ich bekam allmählich Kopfschmerzen;) Ich hätte Ihre Antwort abgelehnt, aber da ich selbst eine veröffentlicht hatte, gab es einen "klaren Interessenkonflikt". Mit Ihrem aktualisierten Beitrag muss ich jetzt überhaupt nicht mehr abstimmen. Danke :)
VonC
@VonC: Das nächste Mal können Sie gerne abstimmen, solange meine Antwort so falsch ist wie diese;)
Claf
1

Die bisher gegebenen Antworten sind nicht ideal, da sie viel unnötige Arbeit zur Lösung von Zusammenführungskonflikten erfordern oder zu viele Annahmen treffen, die häufig falsch sind. So macht man es perfekt. Der Link führt zu meiner eigenen Seite.

So verpflichten Sie sich zu einem anderen Zweig in git

Sie haben nicht festgeschriebene Änderungen an my_branch, für die Sie eine Festschreibung vornehmen möchten master, ohne alle Änderungen von zu übernehmen my_branch.

Beispiel

git merge master
git stash -u
git checkout master
git stash apply
git reset
git add example.js
git commit
git checkout .
git clean -f -d
git checkout my_branch
git merge master
git stash pop

Erläuterung

Beginnen Sie mit der Zusammenführung masterin Ihrem Zweig, da Sie dies ohnehin irgendwann tun müssen. Jetzt ist der beste Zeitpunkt, um Konflikte zu lösen.

Die -uOption (aka --include-untracked) in git stash -uhindert Sie daran , untracked Dateien zu verlieren , wenn Sie später tun git clean -f -dinnerhalb master.

Nachdem git checkout masteres wichtig ist, dass Sie NICHT tun git stash pop, weil Sie diesen Vorrat später benötigen. Wenn Sie das Versteck Pop erstellt in my_branchund führen Sie dann git stashin master, werden Sie unnötige merge Konflikte verursachen , wenn Sie später , dass Stash gelten my_branch.

git resetstuft alles auf, was daraus resultiert git stash apply. Beispielsweise werden Dateien, die im Stash geändert wurden, aber nicht vorhanden sind master, als Konflikte "von uns gelöscht" bereitgestellt.

git checkout .und git clean -f -dverwerfen Sie alles, was nicht festgeschrieben ist: alle Änderungen an nachverfolgten Dateien sowie alle nicht nachverfolgten Dateien und Verzeichnisse. Sie sind bereits im Stash gespeichert und masterwürden beim Zurückschalten unnötige Zusammenführungskonflikte verursachen, wenn Sie zurück zu wechseln my_branch.

Der letzte git stash popbasiert auf dem Original my_branchund verursacht daher keine Zusammenführungskonflikte. Wenn Ihr Stash jedoch nicht verfolgte Dateien enthält, die Sie als Master festgelegt haben, beschwert sich git, dass "nicht verfolgte Dateien nicht aus dem Stash wiederhergestellt werden konnten". Um diesen Konflikt zu beheben, löschen Sie die Dateien von Ihrem Arbeits Baum, dann git stash pop, git add .und git reset.

Vladimir Kornea
quelle
2
Ihre Antwort wurde nicht gelöscht, weil sie mit Ihrer Website verknüpft war. Sie wurde gelöscht, weil sie mit dieser anderen Antwort aus einem anderen Konto identisch war . Ich sehe, dass das andere Konto das gleiche Profil wie Sie hat. Verwenden Sie zwei Konten? Sie können beide Konten zusammenführen lassen. Markiere auch einen Mod, um die Situation zu erklären, und du kannst deine ursprüngliche Antwort (mit der Gegenstimme) nicht löschen.
1
Sie können sie nicht getrennt zu halten , wenn sie zusammengefügt, aber Sie sind erlaubt , mehrere Konten zu haben, solange Sie sie nicht verwenden , um Betrug zu begehen Abstimmung (oder sie miteinander im Allgemeinen interact haben). Erkläre deine Situation einem Mod. Außerdem war das Löschen ein ehrlicher Fehler. Wie können Sie erwarten, dass jemand sagt, dass Sie zwei verschiedene Konten verwendet haben?
3
Sie müssen Flagge Ihren Beitrag und verwenden Sie die andere Option eine Mod aufmerksam zu machen, werden sie nicht achten Sie auf , wenn Sie Ihre gelöschten Antwort bearbeiten. Ich habe deine Posts bereits für Mod-Aufmerksamkeit markiert, aber sie sind ziemlich beschäftigt, also sei geduldig, sie werden sich irgendwann bei dir melden.
1
Veröffentlichen Sie keine doppelten Inhalte, insbesondere nicht von verschiedenen Konten. Stimmen Sie ab oder markieren Sie, um als Duplikat zu schließen, wenn zwei Fragen gleich sind.
Bill the Lizard