So entfernen Sie dauerhaft einige Commits aus der Remote-Verzweigung


490

Ich weiß, dass das Umschreiben der Geschichte schlecht ist, yada yada.

Aber wie kann man einige Commits dauerhaft aus dem Remote-Zweig entfernen?


96
Ja, es ist wirklich schlecht, yada yada, aber aus irgendeinem Grund muss ich es favorisieren.
James Morris

44
Ich weiß, dass dies dumm ist, aber manchmal passiert Scheiße - wie das Testen von Anmeldungen und die Verwendung von Nur-Text-Passwörtern in Ihrem Code, die echte Anmeldeinformationen sind. Und whoops ...
frhd

6
echte Anmeldeinformationen .. Yeah erinnert mich an einige Whoopos
Hallo Universum


2
Ich bin so müde von diesem akademischen Spiel darüber, wie gefährlich das ist und wie es niemals gemacht werden sollte, yada yada. Es gibt Zeiten, in denen es weitaus besser ist, Dinge aus der Git-Geschichte zu entfernen und mit den Konflikten / Brüchen anderer Entwickler umzugehen. So einfach ist das wirklich. Leute, die dies ignorieren, haben wahrscheinlich nie außerhalb eines Klassenzimmers gearbeitet.
vernichten

Antworten:


368

Sie sind git reset --hardIhr lokaler Zweig, um Änderungen aus dem Arbeitsbaum und dem Index zu entfernen, und Sie haben git push --forceIhren überarbeiteten lokalen Zweig auf die Fernbedienung. ( andere Lösung hier besteht darin, den Remote-Zweig zu löschen und erneut zu verschieben.)

Diese SO-Antwort zeigt die Gefahr eines solchen Befehls, insbesondere wenn Personen für ihre eigenen lokalen Repos von der Remote-Historie abhängig sind.
Sie müssen bereit sein , Menschen auf die darauf zu hinweisen, aus vorgelagerten REBASE RECOVERING Abschnitt der git rebaseManpage


Mit Git 2.23 (August 2019, neun Jahre später) würden Sie den neuen Befehl verwenden git switch.
Das heißt: (ersetzengit switch -C mybranch origin/mybranch~n
n durch die Anzahl der zu entfernenden Commits )

Dadurch werden der Index und der Arbeitsbaum wie gewohnt wiederhergestellt git reset --hard.


Seltsam. Ich habe das schon versucht. Zusammen mit einigen Umbasierungen - wirkt wie ein Zauber. Vielen Dank.
Arnis Lapsa

7
@Arnis: perfekt dann;) push --forceweg
VonC

Ich habe BFG Repo-Cleaner verwendet , um einige vertrauliche Daten zu entfernen. Dadurch blieb mir ein "unbenannter" Zweig mit der Originaldatei übrig. Nach dem Zurücksetzen auf das zuletzt gewünschte Commit und dem harten Druck auf den Ursprung ging alles in Ordnung (:
Rodrirokr

Beachten Sie, dass die URL des Commits (zumindest für einige Zeit) noch aktiv ist. Wenn also jemand die URL des Commits hat (Sie haben sie Gott weiß warum gegeben), kann er auf den Code zugreifen.
Mosh Feu

1
@MoshFeu True: Wird git gcauf der Remote-Seite nicht immer oft genug ausgeführt. Zum Beispiel auf GitHub: twitter.com/githubhelp/status/387926738161774592?lang=es
VonC

248

Beachten Sie einfach last_working_commit_id, dass Sie beim Zurücksetzen eines nicht funktionierenden Commits das verwenden müssen

git reset --hard <last_working_commit_id>

Wir dürfen also nicht auf das zurücksetzen, commit_idwas wir nicht wollen.

Dann müssen wir sicher zum Remote-Zweig pushen:

git push --force

10
Perfekte, elegante und einfachste Antwort. Ich bin gerade zu dem letzten Stabe-Commit zurückgekehrt, das ich sowohl auf Remote- als auch auf lokaler
Ebene

2
Dies führte dazu, dass ich auch meine lokalen Änderungen verlor. Das habe ich nicht erwartet. Aber meh, besser als dein persönliches Passwort für das Repo festzulegen.
Airwavezx

3
Sie können Ihre lokalen Änderungen mit Git Stash speichern .... einige Dinge machen .... und Git Stash Pop (Ihre lokalen Änderungen sind zurück)
MonTea

Dies gibt mir den Fehler "remote: error: Verweigern von Refs / Heads / Master mit nicht schnellem Vorlauf (Sie sollten zuerst ziehen)"
Saurabhcdt

@ Airwavezx das git reset --hardsoll man machen.
Luke

146

Wichtig: Stellen Sie sicher, dass Sie angeben, welche Zweige auf "git push -f" sind, da Sie sonst möglicherweise versehentlich andere Zweige ändern! [*]

In diesem Tutorial werden drei Optionen angezeigt . Falls der Link bricht, lasse ich die Hauptschritte hier.

  1. Setzen Sie das vollständige Commit zurück
  2. Löschen Sie das letzte Commit
  3. Commit aus einer Liste löschen

1 Setzen Sie das vollständige Commit zurück

git revert dd61ab23

2 Löschen Sie das letzte Commit

git push <<remote>> +dd61ab23^:<<BRANCH_NAME_HERE>>

oder, wenn der Zweig lokal verfügbar ist

git reset HEAD^ --hard
git push <<remote>> -f

Dabei ist + dd61 ... Ihr Commit-Hash und git interpretiert x ^ als übergeordnetes Element von x und + als erzwungenen, nicht schnell vorgeschobenen Push.

3 Löschen Sie das Commit aus einer Liste

git rebase -i dd61ab23^

Dies wird geöffnet und der Editor zeigt eine Liste aller Commits an. Löschen Sie den, den Sie entfernen möchten. Beenden Sie den Rebase und drücken Sie die Kraft, um das Repo durchzuführen.

git rebase --continue
git push <remote_repo> <remote_branch> -f

5
Stellen Sie sicher, dass Sie angeben, welche Zweige auf "git push <remote_repo> <remote_branch> -f" sind, oder dass Sie versehentlich andere Zweige ändern könnten!
Nigel Sheridan-Smith

Nur die Schritte 1 und 2 haben die Arbeit erledigt und die ursprüngliche Frage beantwortet. (Führen Sie Schritt 3 nicht aus)
Saad Benbouzid

Dies sind Optionen für verschiedene Szenarien, keine Schritte. In meinem Fall hat die interaktive Rebase (Option 3) das getan, wonach ich gesucht habe.
Steve Blackwell

Ich musste allerdings Schritt 3 machen. Warum sollten Sie dieses @Saad nicht ausführen? Zum Glück war mein << remote >> einfach der Standard-Ursprung und <remote_branch> der Standard-Master
Bart

30

Wenn Sie beispielsweise die letzten 3Commits löschen möchten , führen Sie den folgenden Befehl aus, um die Änderungen aus dem Dateisystem (Arbeitsbaum) und dem Commit-Verlauf (Index) in Ihrem lokalen Zweig zu entfernen:

git reset --hard HEAD~3

Führen Sie dann den folgenden Befehl (auf Ihrem lokalen Computer) aus, um den Remote-Zweig zu zwingen, seinen Verlauf neu zu schreiben:

git push --force

Herzliche Glückwünsche! Alles erledigt!

Einige Notizen:

Sie können die gewünschte Festschreibungs-ID durch Ausführen abrufen

git log

Dann können Sie ersetzen HEAD~Nmit <desired-commit-id>wie folgt aus :

git reset --hard <desired-commit-id>

Wenn Sie Änderungen im Dateisystem beibehalten und nur den Index (Commit-Verlauf) ändern möchten, verwenden Sie das --softFlag like git reset --soft HEAD~3. Dann haben Sie die Möglichkeit, Ihre neuesten Änderungen zu überprüfen und alle oder Teile davon zu behalten oder zu löschen. Im letzteren Fall git statuszeigt runnig die seitdem geänderten Dateien an <desired-commit-id>. Wenn Sie die --hardOption verwenden, git statuserfahren Sie, dass Ihre lokale Niederlassung genau mit der Remote-Niederlassung identisch ist. Wenn Sie nicht verwenden , --hardnoch --softwird der Standardmodus verwendet , das ist --mixed. In diesem Modus git help resetsagt:

Setzt den Index, aber nicht den Arbeitsbaum zurück (dh die geänderten Dateien werden beibehalten, aber nicht für das Festschreiben markiert) und meldet, was nicht aktualisiert wurde.


10

Das mag zu spät sein, aber was mir geholfen hat, ist die cool klingende "nukleare" Option. Grundsätzlich mit dem Befehlfilter-branch Dateien entfernen oder etwas über eine große Anzahl von Dateien während Ihres gesamten Git-Verlaufs ändern.

Es wird am besten erklärt hier .


9
Es ist nicht zu spät.
Könnte

9

Vereinfachung der Antwort von pctroll, ähnlich basierend auf diesem Blog-Beitrag .

# look up the commit id in git log or on github, e.g. 42480f3, then do
git checkout master
git checkout your_branch
git revert 42480f3
# a text editor will open, close it with ctrl+x (editor dependent)
git push origin your_branch
# or replace origin with your remote

2
Funktioniert für mich, danke. Und ich möchte ein Commit (z. B. enthält pwd) dauerhaft aus dem Verlauf der Remote-Verzweigung löschen. Wie geht das?
Smiles

1
Funktioniert auch für mich, aber ich habe die gleiche Frage wie Smiles. Ich möchte nicht, dass jemand mein Commit / Rever in der Geschichte sieht. Wie entferne ich das?
Roberto Rodriguez

4

Manchmal ist es am einfachsten, dieses Problem zu beheben, indem Sie an der Stelle, an der Sie wissen, dass der Code gut ist, einen neuen Zweig erstellen. Dann können Sie den fehlerhaften Zweigverlauf in Ruhe lassen, falls Sie später andere Commits daraus auswählen müssen. Dies stellt auch sicher, dass Sie keinen Commit-Verlauf verloren haben.

Von Ihrer lokalen fehlerhaften Niederlassung:

git log

Kopieren Sie den Commit-Hash, an dem sich der Zweig befinden soll, und beenden Sie das Git-Protokoll

git checkout theHashYouJustCopied
git checkout -b your_new_awesome_branch

Jetzt haben Sie einen neuen Zweig genau so, wie Sie es möchten.

Wenn Sie auch ein bestimmtes Commit aus dem fehlerhaften Zweig behalten müssen, der sich nicht in Ihrem neuen Zweig befindet, können Sie einfach das gewünschte Commit auswählen:

git checkout the_errant_branch
git log

Kopieren Sie den Commit-Hash des einen Commits, den Sie benötigen, um in den guten Zweig zu ziehen und das Git-Protokoll zu beenden.

git checkout your_new_awesome_branch
git cherry-pick theHashYouJustCopied

Klopfe dir auf den Rücken.


sehr einfach und wen interessiert es, wenn Sie einen Ast mit toten Beinen haben? mache einen neuen Zweig und sei fertig damit!
Andrew Fox

Dies ist eine wirklich hervorragende Antwort. Ich bin froh, dass ich dies getan habe, anstatt Commits zu pflücken oder den Remote-Zweig zu manipulieren.
Magnilex

0
 git reset --soft commit_id
 git stash save "message"
 git reset --hard commit_id
 git stash apply stash stash@{0}
 git push --force
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.