Wie behebt man das Festschreiben an den falschen Git-Zweig?

621

Ich habe mich gerade perfekt für den falschen Zweig entschieden. Wie mache ich das letzte Commit in meinem Hauptzweig rückgängig und nehme dann dieselben Änderungen und bringe sie in meinen Upgrade-Zweig?

Mikewilliamson
quelle

Antworten:

975

Wenn Sie Ihre Änderungen noch nicht übernommen haben, können Sie auch einen Soft-Reset durchführen:

git reset --soft HEAD^

Dadurch wird das Festschreiben zurückgesetzt, die festgeschriebenen Änderungen werden jedoch wieder in Ihren Index aufgenommen. Angenommen, die Filialen sind in Bezug aufeinander relativ aktuell, können Sie mit git in die andere Filiale auschecken, woraufhin Sie einfach Folgendes festlegen können:

git checkout branch
git commit

Der Nachteil ist, dass Sie Ihre Festschreibungsnachricht erneut eingeben müssen.

Blair Holloway
quelle
10
Beachten Sie, dass durch den Soft-Reset Ihre Änderungen inszeniert und bereit zum Festschreiben sind. Ich war ein wenig verwirrt, als meine IDE nicht zeigte, dass die Dateien nach dem Soft-Reset in den geänderten Zustand zurückkehren.
Mtjhax
9
perfekte Lösung, hatte tatsächlich ein paar Commits, so wie HEAD ^^ und bam alles ist Soße
Pablo
8
Vielen Dank. Das hat mich zweimal gerettet. Wenn sich die Zweige etwas unterscheiden, müssen Sie nach dem Zurücksetzen und vor dem Auschecken möglicherweise Ihre Änderungen aufbewahren, bevor Sie einen anderen Zweig auschecken können. Wenden Sie den Vorrat nach dem Auschecken erneut an
Kirby
17
zsh Benutzer: Sie könnten feststellen, dass Sie dem ^ wie git reset --soft HEAD\^
folgt
54
Wenn Sie mehr bekommen? Verwenden Sie in Ihrer Windows-Befehlszeile Anführungszeichen, um HEAD ^ wie folgt zu umgeben: git reset --soft "HEAD ^"
Nate Cook
140

4 Jahre zu spät zum Thema, aber dies könnte für jemanden hilfreich sein.

Wenn Sie vergessen haben, vor dem Festschreiben einen neuen Zweig zu erstellen, und alle auf dem Master festgeschrieben haben, ist der folgende Ansatz einfacher, unabhängig davon, wie viele Festschreibungen Sie durchgeführt haben:

git stash                       # skip if all changes are committed
git branch my_feature
git reset --hard origin/master
git checkout my_feature
git stash pop                   # skip if all changes were committed

Jetzt haben Sie Ihren Hauptzweig gleich origin/masterund alle neuen Commits sind aktiviert my_feature. Beachten Sie, dass my_featurees sich um einen lokalen Zweig handelt, nicht um einen Remote-Zweig.

fotanus
quelle
Danke für die Antwort. Jetzt verwende ich egit und frage mich, ob ich dasselbe erreichen kann, indem ich Folgendes tue: 1) Benenne den aktuellen 'Master' in 'my_feature' um. 2) Erstellen Sie den lokalen 'Master' aus 'Ursprung / Master' neu. Ich bin nicht sicher, was egit unter der Haube für diese Operationen tut, aber dies scheint eine praktikable Lösung zu sein
mjj1409
Warum die Fusion? Sie könnten die Niederlassung direkt auf erstellen master, setzen Sie dann masterauf origin/master.
Caesarsol
1
Das ist der interessanteste Teil: Sie benötigen keine Anzahl von Commits, da origin/mastersich diese bereits auf dem Commit befinden, auf das Sie zurücksetzen möchten! Die Gutschrift für den Tipp ist jedoch diese Seite: github.com/blog/…
caesarsol
4
Dies sollte die akzeptierte Antwort sein. Einfach, offensichtlich, unkompliziert, funktioniert unabhängig von der Anzahl der Commits und verwendet nur grundlegende Git-Funktionen. Ich habe diese Schritte mit TortoiseGit gemacht. Vielen Dank! :)
Ian Grainger
1
Ich dachte, dies sei die beste Antwort, aber es gibt eine Einschränkung. Es hilft nur, wenn Sie kürzlich von der Fernbedienung gezogen haben. Und es wird davon ausgegangen, dass Sie zunächst eine Fernbedienung haben. Wenn Sie nur lokale Zweige "Master" haben und Ihr neues Feature behoben ist, ist die einzig richtige Antwort ein Zurücksetzen des Masters, das eine bestimmte Anzahl von Commits zurückzählt.
Pauljohn32
111

Wenn Sie eine saubere (unveränderte) Arbeitskopie haben

So setzen Sie ein Commit zurück (stellen Sie sicher, dass Sie den Hash des Commits für den nächsten Schritt notieren):

git reset --hard HEAD^

So ziehen Sie dieses Commit in einen anderen Zweig:

git checkout other-branch
git cherry-pick COMMIT-HASH

Wenn Sie Änderungen geändert oder nicht verfolgt haben

Beachten Sie auch , dass git reset --hardwird keine untracked und modifizierte Änderungen töten Sie haben könnten, wenn Sie also diejenigen , haben Sie vielleicht lieber:

git reset HEAD^
git checkout .
Michael Mrozek
quelle
git rev-parse BRANCH_NAMEum die sha zu bekommen.
Wilhelmtell
12
Wenn Sie vergessen haben, den Hash zuerst zu notieren, verwenden Sie einfach git reflog show <branch>!
Cascabel
2
@Jefromi Ich hatte dort für eine Minute Angst.
Ian Hunter
13
Für ein besonders sicheres Gefühl führen Sie den Kirschpickel zuerst am richtigen Zweig durch und setzen Sie dann den falschen Zweig zurück.
Alter Mooij
1
Auch im Falle von nicht verfolgten Änderungen kann man sie git stashvor dem Zurücksetzen verwenden und git stash popanschließend verwenden, um sie wiederherzustellen, so dass man sich nicht vor dem --hardTeil fürchten muss
Clemens Klein-Robbenhaar
20

Wenn Sie Ihre Änderungen bereits gepusht haben, müssen Sie nach dem Zurücksetzen des KOPFES Ihren nächsten Push erzwingen.

git reset --hard HEAD^
git merge COMMIT_SHA1
git push --force

Warnung: Durch einen Hard-Reset werden nicht festgeschriebene Änderungen in Ihrer Arbeitskopie rückgängig gemacht, während durch einen Force-Push der Status des Remote-Zweigs vollständig mit dem aktuellen Status des lokalen Zweigs überschrieben wird.

Nur für den Fall, unter Windows (über die Windows-Befehlszeile, nicht über Bash) sind es tatsächlich vier ^^^^statt eins

git reset --hard HEAD^^^^
Igor Zevaka
quelle
6
Beachten Sie, dass Sie nicht zwangsweise auf einen Zweig pushen sollten , den andere Personen verwenden, es sei denn, dies ist unbedingt erforderlich. Andernfalls können sie nicht pushen, bis sie die Basis wiederherstellen. Wenn Sie der einzige Entwickler sind, der git verwendet, ist dies jedoch in Ordnung.
Blair Holloway
2
Oder es sei denn, Sie erkennen schnell genug, bevor jemand anderes die fehlerhaften Commits gezogen hat.
Michael Mior
Wenn Sie mehr als ein Commit git reset --hard COMMIT_HASH git push --force
deaktiviert haben
17

Ich habe kürzlich das Gleiche getan, bei dem ich versehentlich einen Wechsel zum Master vorgenommen habe, als ich mich zu einem anderen Zweig hätte verpflichten sollen. Aber ich habe nichts geschoben.

Wenn Sie sich nur für den falschen Zweig entschieden haben und seitdem nichts geändert haben und nicht zum Repo gewechselt sind, können Sie Folgendes tun:

// rewind master to point to the commit just before your most recent commit.
// this takes all changes in your most recent commit, and turns them into unstaged changes. 
git reset HEAD~1 

// temporarily save your unstaged changes as a commit that's not attached to any branch using git stash
// all temporary commits created with git stash are put into a stack of temporary commits.
git stash

// create other-branch (if the other branch doesn't already exist)
git branch other-branch

// checkout the other branch you should have committed to.
git checkout other-branch

// take the temporary commit you created, and apply all of those changes to the new branch. 
//This also deletes the temporary commit from the stack of temp commits.
git stash pop

// add the changes you want with git add...

// re-commit your changes onto other-branch
git commit -m "some message..."

HINWEIS: Im obigen Beispiel habe ich 1 Commit mit git reset HEAD ~ 1 zurückgespult. Wenn Sie jedoch n Commits zurückspulen möchten, können Sie HEIT ~ n zurücksetzen.

Wenn Sie sich am Ende für den falschen Zweig entschieden und mehr Code geschrieben haben, bevor Sie festgestellt haben, dass Sie sich für den falschen Zweig entschieden haben, können Sie git stash verwenden, um Ihre laufende Arbeit zu speichern:

// save the not-ready-to-commit work you're in the middle of
git stash 

// rewind n commits
git reset HEAD~n 

// stash the committed changes as a single temp commit onto the stack. 
git stash 

// create other-branch (if it doesn't already exist)
git branch other-branch

// checkout the other branch you should have committed to.
git checkout other-branch

// apply all the committed changes to the new branch
git stash pop

// add the changes you want with git add...

// re-commit your changes onto the new branch as a single commit.
git commit -m "some message..."

// pop the changes you were in the middle of and continue coding
git stash pop

HINWEIS: Ich habe diese Website als Referenz verwendet. Https://www.clearvision-cm.com/blog/what-to-do-when-you-commit-to-the-wrong-git-branch/

Ali Mizan
quelle
Ähnliches passierte mir, ich habe ein paar Änderungen im Master vorgenommen, aber ich hätte es in einer neuen Niederlassung tun und PR senden sollen. Am Ende habe ich nur ein git checkout -b new_branchRecht von dort aus ausgeführt. Ich muss mich nicht erneut festlegen.
Nishchal Gautam
11

Wenn es sich bei Ihrem Szenario also um ein Szenario handelt, für das Sie sich verpflichtet haben, das Sie masterjedoch festlegen möchten another-branch(das möglicherweise noch nicht vorhanden ist), das Sie jedoch noch nicht gepusht haben, ist dies recht einfach zu beheben.

// if your branch doesn't exist, then add the -b argument 
git checkout -b another-branch
git branch --force master origin/master

Jetzt sind alle Ihre Verpflichtungen mastererfüllt another-branch.

Mit Liebe bezogen von: http://haacked.com/archive/2015/06/29/git-migrate/

Lorcan O'Neill
quelle
scheint der einfachste Ansatz zu sein! Nicht sicher, warum so wenig Liebe und Upwotes
keligijus
4
Das schien bei mir nicht zu funktionieren. another-branchexistierte bereits. In diesem Fall hat es nur die Commits zunichte gemacht, die ich gemacht hatte, um sie zu meistern, und sie nicht übernommen another-branch.
Giselle Serate
6

Um näher auf diese Antwort, falls Sie mehrere Commits haben, sich von, zum Beispiel developzu new_branch:

git checkout develop # You're probably there already
git reflog # Find LAST_GOOD, FIRST_NEW, LAST_NEW hashes
git checkout new_branch
git cherry-pick FIRST_NEW^..LAST_NEW # ^.. includes FIRST_NEW
git reflog # Confirm that your commits are safely home in their new branch!
git checkout develop
git reset --hard LAST_GOOD # develop is now back where it started
Arsenius
quelle
1
Ich musste drei Commits rückgängig machen, und diese Frage scheint meinen Arsch aus dem Feuer gezogen zu haben. Vielen Dank!
Holdenweb
3

Wenn Sie auf dieses Problem stoßen und Visual Studio haben, können Sie Folgendes tun:

Klicken Sie mit der rechten Maustaste auf Ihre Filiale und wählen Sie View History:

Geben Sie hier die Bildbeschreibung ein

Klicken Sie mit der rechten Maustaste auf Commit, zu dem Sie zurückkehren möchten. Und nach Bedarf zurücksetzen oder zurücksetzen.

Geben Sie hier die Bildbeschreibung ein

Trevor
quelle
3

Für mehrere Commits im falschen Zweig

Wenn es für Sie nur 1 Commit ist, stehen Ihnen viele andere einfachere Reset-Lösungen zur Verfügung. Für mich wurden ungefähr 10 Commits versehentlich durchgeführt, masteranstatt, nennen wir es branch_xyz, und ich wollte den Commit-Verlauf nicht verlieren.

Was Sie tun konnten und was mich rettete, war die Verwendung dieser Antwort als Referenz in einem 4-stufigen Prozess.

  1. Erstellen Sie einen neuen temporären Zweig aus master
  2. In den Zweig einbinden, der ursprünglich für Commits vorgesehen war, d. H. branch_xyz
  3. Commits rückgängig machen auf master
  4. Löschen Sie den temporären Zweig.

Hier sind die obigen Schritte im Detail -

  1. Erstellen Sie einen neuen Zweig aus dem master(wo ich versehentlich viele Änderungen vorgenommen hatte)

    git checkout -b temp_branch_xyz
    

    Hinweis: Das -bFlag wird verwendet, um einen neuen Zweig zu erstellen. Um
    zu überprüfen, ob wir das richtig verstanden haben, würde ich schnell git branchsicherstellen, dass wir uns im temp_branch_xyzZweig befinden, und git logprüfen, ob wir die Commits richtig ausgeführt haben.

  2. Führen Sie den temporären Zweig in den Zweig ein, der ursprünglich für die Commits vorgesehen war, d branch_xyz. H.
    Wechseln Sie zunächst zum ursprünglichen Zweig, z. B. branch_xyz(Möglicherweise müssen Sie dies tun, git fetchwenn Sie dies nicht getan haben).

    git checkout branch_xyz
    

    Hinweis: -bFlag nicht verwenden
    Lassen Sie uns jetzt den temporären Zweig mit dem Zweig zusammenführen, den wir gerade auscheckenbranch_xyz

    git merge temp_branch_xyz
    

    Möglicherweise müssen Sie sich hier um einige Konflikte kümmern, wenn es solche gibt. Sie können nach erfolgreicher Zusammenführung drücken (ich würde) oder mit den nächsten Schritten fortfahren.

  3. Lösen Sie die versehentlichen Commits auf mastermit dieser Antwort als Referenz, ersten Schalter auf demmaster

    git checkout master
    

    Machen Sie es dann vollständig rückgängig, um es an die Fernbedienung anzupassen (oder an ein bestimmtes Commit, wenn Sie möchten).

    git reset --hard origin/master
    

    Ich würde wieder ein git logVorher und Nachher machen, um sicherzustellen, dass die beabsichtigten Änderungen wirksam werden.

  4. Löschen der Beweise, dh Löschen des temporären Zweigs. Dazu müssen Sie zuerst den Zweig auschecken, in den die Temperatur zusammengeführt wurde, dh branch_xyz(Wenn Sie eingeschaltet bleiben masterund den folgenden Befehl ausführen, erhalten Sie möglicherweise eine error: The branch 'temp_branch_xyz' is not fully merged)

    git checkout branch_xyz
    

    und löschen Sie dann den Beweis für dieses Missgeschick

    git branch -d temp_branch_xyz
    

Los geht's.

Mitali Cyrus
quelle
1

Wenn die Verzweigung wollten Sie Ihre Änderungen gelten bereits vorhanden ist (Zweig entwickeln , zum Beispiel), folgen Sie den Anweisungen, die von bereitgestellt wurden fotanus unten, dann gilt :

git checkout develop
git rebase develop my_feature # applies changes to correct branch
git checkout develop # 'cuz rebasing will leave you on my_feature
git merge develop my_feature # will be a fast-forward
git branch -d my_feature

Und natürlich können Sie Tempbranch oder einen anderen Filialnamen anstelle von my_feature verwenden, wenn Sie möchten .

Falls zutreffend, verzögern Sie den Stash-Pop (Anwenden) auch, bis Sie ihn in Ihrem Zielzweig zusammengeführt haben.

fbicknel
quelle
Ich denke, der erste Befehl (Checkout-Entwicklung) ist unnötig ... die Rebase wird als erstes "my_feature" auschecken.
JoelFan
Sie können auch den Parameter "my_feature" des Befehls "rebase" weglassen (da Sie "my_feature" bereits ausgecheckt haben). Sie können auch den "Develop" -Parameter der "Merge"
weglassen
1

Für mich wurde dies gelöst, indem das Commit, das ich gepusht hatte, zurückgesetzt und dann das Commit für den anderen Zweig ausgewählt wurde.

git checkout branch_that_had_the_commit_originally
git revert COMMIT-HASH
git checkout branch_that_was_supposed_to_have_the_commit
git cherry pick COMMIT-HASH

Sie können verwenden git log, um den richtigen Hash zu finden, und Sie können diese Änderungen jederzeit übertragen!

arr0nax
quelle