Rollback des lokalen und Remote-Git-Repositorys um 1 Commit


187

Ich habe ähnliche Beiträge zu diesem Thema gelesen und kann für mein ganzes Leben nicht herausfinden, wie ich das richtig machen soll.

Ich habe ungefähr 1000 Dateien eingecheckt, die ich nicht möchte, und ich möchte lieber nicht 1by1 durchgehen und sie alle aus dem Repo entfernen.

  • Ich habe eine entfernte masterNiederlassung.
  • Ich habe die örtliche masterNiederlassung.

Sie sind beide in der gleichen Revision.

Ich möchte meine Fernbedienung um 1 Commit zurücksetzen.

Sagen Sie, meine Geschichte masterist auf A--B--C--D--E.
Ich möchte mein lokales auf zurücksetzen D.
Schieben Sie es dann auf Remote, damit mein aktueller Hash sowohl Remote als auch lokal ist.

Ich habe Probleme damit.
Ich benutze Git Tower, bin aber mit der Kommandozeile vertraut. Irgendeine Hilfe?

UPDATE: Großartige Kommentare unten. Die Verwendung eines Resets scheint teilweise nicht zu empfehlen, insbesondere wenn das Repository für andere Benutzer freigegeben ist. Was ist der beste Weg, um die Änderungen des vorherigen Commits ohne Hard-Reset rückgängig zu machen ? Gibt es einen Weg?


Ich habe meine Antwort aktualisiert, um "die Änderungen des vorherigen Commits rückgängig zu machen, ohne einen Hard-Reset zu verwenden".
VonC

3
Verwenden Sie git revertdiese Option, um auf Hard-Resets zu verzichten und Benutzer nicht zu stören.
user562374


Es wird davon abgeraten, die Fernbedienung zurückzusetzen, aber wenn Sie dies möchten, tun Sie es. Es gibt Hunderte von Möglichkeiten, dies zu tun, aber das Ergebnis wäre auf der Serverseite dasselbe.
FelipeC

Antworten:


306

Wenn noch niemand Ihr Remote-Repo gezogen hat, können Sie Ihren Zweig-HEAD ändern und ihn zwangsweise auf das Remote-Repo drücken:

git reset --hard HEAD^ 
git push -f 

(oder wenn Sie direkten Zugriff auf das Remote-Repo haben, können Sie dessen HEAD-Referenz ändern , obwohl es sich um ein reines Repo handelt. )

Beachten Sie, wie von Alien-Technologie in den Kommentaren unten unter Windows (CMD-Sitzung) kommentiert, Folgendes^^ :

git reset --hard HEAD^^
git push -f 

Update seit 2011: Die
Verwendung git push --force-with-lease( die ich hier vorstelle und die 2013 mit Git 1.8.5 eingeführt wurde) ist sicherer.

Siehe Schwern ‚s Antwort zur Illustration.


Was ist, wenn jemand das Repo bereits gezogen hat? Was würde ich dann tun?

Dann würde ich etwas vorschlagen, das die Geschichte nicht umschreibt:

  • git revert lokal Ihr letztes Commit (Erstellen eines neuen Commits, das das vorherige Commit umkehrt)
  • Drücken Sie die von git revert.

1
Was ist, wenn jemand das Repo bereits gezogen hat? Was würde ich dann tun?
Jamis Charles

1
@gwho erstellt einen Zweig? Nein, es bewegt den KOPF eines Zweigs, aber Sie befinden sich immer noch im selben Zweig. Da es sich bei dem Push jedoch nicht mehr um einen Schnellvorlauf handelt, müssen Sie diesen Push erzwingen.
VonC

1
Gibt es eine Möglichkeit zu wissen, ob jemand das Repo gezogen hat?
Pinkerton

4
In Windows wird das Zeichen ^ zur Zeilenfortsetzung und zum Entkommen eines Zeichens verwendet, wobei der Befehl ausgeführt wird: git reset --hard HEAD ^^
Alien Technology

1
@AlienTechnology Mit Powershell musste ich unter Windows 10 nur das letzte Commit eingeben reset --hard HEAD^und nicht reset --hard HEAD^^zurücksetzen.
Gaspacchio

56

Setzen Sie den lokalen Zweig um eine Revision zurück ( HEAD^bedeutet eine Revision zurück):

git reset --hard HEAD^

Schieben Sie die Änderungen zum Ursprung:

git push --force

Sie müssen das Drücken erzwingen, da Git sonst erkennen würde, dass Sie origindurch ein Commit im Rückstand sind und sich nichts ändern wird.

Wenn Sie dies mit tun, --forcewird git angewiesen, HEADdas Remote-Repo zu überschreiben, ohne die dortigen Fortschritte zu berücksichtigen.


1
Ich würde vorschlagen, dies nicht als Zurücksetzen zu bezeichnen, da dies ein spezifischer Begriff mit einer ganz anderen Bedeutung in git ist.
Cascabel

@ Jefromi: Danke für den Hinweis. Bearbeitet.
eckes

Gute Antwort. Ich habe gelesen, dass die Verwendung eines Resets teilweise nicht empfohlen wird, insbesondere wenn das Repository für andere Benutzer freigegeben wird. Gibt es eine sauberere Möglichkeit, die alle Änderungen Ihres vorherigen Commits rückgängig macht?
Jamis Charles

Achtung! Verstauen Sie Ihre nicht
festgeschriebenen

Das ist cool. Bedeutet dies also, dass git push origin masterGit in diesem Fall in der Lage ist, ein neues Commit auf der Fernbedienung zu erstellen, da der lokale Zweig mindestens einmal vor dem Commit liegt? Darüber hinaus muss sich letzteres wesentlich von dem unterscheiden, worauf der Kopf im Remote-Repo hinweist.
MadPhysicist

18

Wenn Sie das letzte Commit zurücksetzen möchten, hören Sie:

Schritt 1:

Überprüfen Sie Ihre lokalen Commits mit Nachrichten

$ git log

Schritt 2:

Entfernen Sie das letzte Commit, ohne die Änderungen vom lokalen Zweig (oder Master) zurückzusetzen.

$ git reset HEAD^

ODER wenn Sie nicht möchten, dass zuletzt festgeschriebene Dateien und Aktualisierungen abgehört werden

$ git reset HEAD^ --hard

Schritt 3:

Wir können die Dateien und Codes aktualisieren und müssen erneut mit Gewalt pushen, um das vorherige Commit zu löschen. Es wird neues Commit behalten.

$ git push origin branch -f

Das ist es!


Das ist nicht zurückkehrt ein begehen, es zu ersetzen. Bitte verwirren Sie uns Anfänger nicht, indem Sie herkömmliche Begriffe missbrauchen.
Suncat2000

7

Durch Eingabe des folgenden Befehls können Sie Ihren Git-Commit-Verlauf anzeigen -

$ git log

Angenommen, Ihr Verlauf in diesem bestimmten Zweig ist wie folgt: commit_A, commit_B, commit_C, commit_D. Wobei commit_D das letzte Commit ist und hier bleibt HEAD. Um Ihr letztes Commit von lokal und remote zu entfernen, müssen Sie Folgendes tun:

Schritt 1: Entfernen Sie das letzte Commit lokal durch -

$ git reset --hard HEAD ~

Dadurch wird Ihr Commit-HEAD in commit_C geändert

Schritt 2: Übertragen Sie Ihre Änderung für ein neues HEAD-Commit auf Remote

$ git push origin + HEAD

Dieser Befehl löscht das letzte Commit von Remote.

PS: Dieser Befehl wurde unter Mac OS X getestet und sollte auch unter anderen Betriebssystemen funktionieren (ohne Anspruch auf andere Betriebssysteme).



2

Hier ist eine aktualisierte Version des Verfahrens, die sicherer ist.

git reset --hard HEAD^ 
git push --force-with-lease

git push -fwird das Remote-Repository wahllos durch Ihre eigenen Änderungen ersetzen. Wenn jemand anderes Änderungen vorgenommen hat, gehen diese verloren. git push --force-with-leasewird Ihre Rebase nur pushen, wenn das Repository wie erwartet ist. Wenn jemand anderes bereits gedrückt hat, schlägt Ihr Push fehl.

Siehe –force als schädlich angesehen; Verstehen von Git's Force-with-Lease .

Ich empfehle Aliasing als repush = push --force-with-lease.

Was ist, wenn jemand das Repo bereits gezogen hat? Was würde ich dann tun?

Sag es ihnen git pull --rebase=merges. Anstelle von a git fetch originund git merge origin/masteres wird git fetch originund git rebase -r origin/master. Dadurch werden alle lokalen Änderungen zusätzlich zu masterden neuen Änderungen neu geschrieben origin/master. -rbehält alle Zusammenschlüsse bei, die sie möglicherweise vorgenommen haben.

Ich empfehle, dies als Standardverhalten für das Ziehen festzulegen. Es ist sicher, übernimmt die Neugründung anderer und führt zu weniger unnötigen Zusammenführungen.

[pull]
        rebase = merges

1
Einverstanden und positiv bewertet. Zu meiner Verteidigung wurde meine alte Antwort von 2011 zwei Jahre vor Einführung der --force-with-leaseOption geschrieben.
VonC

Ich dachte, ich hätte das schon (gestern) gemacht: stackoverflow.com/posts/4647362/revisions
VonC

1

Ich habe ein Problem wie das Ihre mit folgenden Befehlen gelöst:

git reset --hard HEAD^
git push -f <remote> <local branch>:<remote branch> 


0

Ich wollte nur das letzte Commit aus dem Remote- und Clear-Commit-Verlauf entfernen. Das Folgende wirkte wie ein Zauber

git reset --hard HEAD^ 
git push -f 

Aber wie unterscheidet sich "das Folgende" von meiner obigen Antwort ?
VonC

0

Der Weg, um den Kopf zurückzusetzen und zum vorherigen Commit zurückzukehren, ist abgeschlossen

$ git reset HEAD^ --hard
$ git push <branchname> -f

Aber manchmal wird es in der Gegenstelle nicht akzeptiert:

To ssh:<git repo>
 ! [rejected]        develop -> develop (non-fast-forward)
error: failed to push some refs to 'ssh:<git repo>'
hint: Updates were rejected because the tip of your current branch is behind
hint: its remote counterpart. Integrate the remote changes (e.g.
hint: 'git pull ...') before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.

dann ist der andere Weg zu tun

git revert HEAD
git push <remote branch>

Das funktioniert gut.

HINWEIS: Denken Sie daran, wenn dies git push -f <force>fehlgeschlagen ist, und versuchen Sie dann, es zurückzusetzen. Machen Sie git pullvorher ein, damit Remote und Local synchron sind, und versuchen Sie es dann git revert.
Überprüfen Sie mit git log, ob sich Remote und Local mit demselben SHA1 am selben Commit-Punkt befinden.

git revert 
A --> B --> C -->D
A--> B --> C --> D --> ^D(taking out the changes and committing reverted diffs)

0

auf lokalen Master

git reflog
-- this will list all last commit
  e.g Head@{0} -- wrong push
      Head@{1} -- correct push  
git checkout Head@{1} .
  -- this will reset your last modified files

git status 
git commit -m "reverted to last best"
git push origin/master

Kein Grund zur Sorge, ob andere gezogen haben oder nicht.

Getan!


0

Wenn Sie nur das letzte Commit aus dem Remote-Repository entfernen möchten, ohne Ihr lokales Repository zu beeinträchtigen, finden Sie hier einen Einzeiler:

git push origin +origin/master~:master

Dies verwendet die folgende Syntax:

git push <remote> <refspec>

Hier <remote>ist originund <refspec>hat die folgende Struktur:

+origin/master~:master

Details finden Sie in git-push(1). Das Vorstehende +bedeutet "Druck auf diese Referenz erzwingen" und der andere Teil bedeutet "von origin/master~nach master(von entfernt origin)". Es ist nicht schwer zu wissen, dass dies origin/master~das letzte Commit zuvor ist origin/master, oder?


0

Für mich funktionieren diese beiden Befehle:

git checkout commit_id
git push origin +name_of_branch

0

Sie können dies auch tun:

git reset --hard <commit-hash>
git push -f origin master

und alle anderen, die die letzten schlechten Commits erhalten haben, zurücksetzen lassen:

git reset --hard origin/master
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.