Frage

Angenommen, Ihr Git-Verlauf sieht so aus:

1 2 3 4 5

1–5 sind separate Überarbeitungen.Sie müssen 3 entfernen und gleichzeitig 1, 2, 4 und 5 behalten.Wie kann das gemacht werden?

Gibt es eine effiziente Methode, wenn nach der zu löschenden Revision Hunderte von Revisionen vorliegen?

War es hilfreich?

Lösung

Um Revision 3 und 4 in einer einzigen Revision zu kombinieren, können Sie Git Rebase verwenden.Wenn Sie die Änderungen in Revision 3 entfernen möchten, müssen Sie den Bearbeitungsbefehl im interaktiven Rebase-Modus verwenden.Wenn Sie die Änderungen in einer einzigen Revision zusammenfassen möchten, verwenden Sie Squash.

Ich habe diese Squash-Technik erfolgreich eingesetzt, musste aber noch nie eine Revision entfernen.Die Git-Rebase-Dokumentation unter „Commits aufteilen“ sollte Ihnen hoffentlich genügend Ideen geben, um es herauszufinden.(Oder jemand anderes weiß es vielleicht).

Von dem Git-Dokumentation:

Beginnen Sie mit dem ältesten Commit, das Sie unverändert beibehalten möchten:

git rebase -i <after-this-commit>

Ein Editor wird mit allen Commits in Ihrem aktuellen Zweig gestartet (Merge-Commits werden ignoriert), die nach dem angegebenen Commit kommen.Sie können die Commits in dieser Liste nach Herzenslust neu anordnen und entfernen.Die Liste sieht ungefähr so ​​aus:

pick deadbee The oneline of this commit
pick fa1afe1 The oneline of the next commit
...

Die Online-Beschreibungen dienen ausschließlich Ihrem Vergnügen;git-rebase betrachtet sie nicht, sondern die Commit-Namen („deadbee“ und „fa1afe1“ in diesem Beispiel), also löschen oder bearbeiten Sie die Namen nicht.

Indem Sie den Befehl „pick“ durch den Befehl „edit“ ersetzen, können Sie git-rebase anweisen, nach der Anwendung dieses Commits anzuhalten, sodass Sie die Dateien und/oder die Commit-Nachricht bearbeiten, den Commit ändern und mit dem Rebasing fortfahren können.

Wenn Sie zwei oder mehr Commits zu einem zusammenfassen möchten, ersetzen Sie den Befehl „pick“ durch „squash“ für den zweiten und nachfolgenden Commit.Wenn die Commits unterschiedliche Autoren hatten, wird der gestauchte Commit dem Autor des ersten Commits zugeordnet.

Andere Tipps

Hier ist eine Möglichkeit, ein bestimmtes Element nicht interaktiv zu entfernen <commit-id>, nur das kennen <commit-id> Sie möchten Folgendes entfernen:

git rebase --onto <commit-id>^ <commit-id> HEAD

Pro dieser Kommentar (und ich habe überprüft, ob das wahr ist), Rados Antwort kommt sehr nahe, lässt Git jedoch in einem losgelösten Kopfzustand zurück.Stattdessen entfernen HEAD und verwenden Sie diese zum Entfernen <commit-id> aus der Filiale, in der Sie sich befinden:

git rebase --onto <commit-id>^ <commit-id>

Wie bereits erwähnt git-rebase(1) ist dein Freund.Vorausgesetzt, die Commits liegen in Ihrem master Zweig, würden Sie Folgendes tun:

git rebase --onto master~3 master~2 master

Vor:

1---2---3---4---5  master

Nach:

1---2---4'---5' master

Von git-rebase(1):

Eine Reihe von Commits könnte ebenfalls mit Rebase entfernt werden.Wenn wir die folgende Situation haben:

E---F---G---H---I---J  topicA

dann der Befehl

git rebase --onto topicA~5 topicA~3 topicA

würde zur Entfernung von Commits F und G führen:

E---H'---I'---J'  topicA

Dies ist nützlich, wenn F und G in einigen Bereichen fehlerhaft waren oder sollte nicht Teil von Thema A sein.Beachten Sie, dass das Argument für --upon und Der Parameter kann ein beliebiger Parameter sein gültiger Commit-ish.

Wenn Sie lediglich die in Revision 3 vorgenommenen Änderungen entfernen möchten, können Sie git revert verwenden.

Git Revert erstellt einfach eine neue Revision mit Änderungen, die alle Änderungen in der Revision, die Sie zurücksetzen, rückgängig machen.

Das bedeutet, dass Sie Informationen sowohl über den unerwünschten Commit als auch über den Commit, der diese Änderungen entfernt, behalten.

Dies ist wahrscheinlich viel benutzerfreundlicher, wenn es überhaupt möglich ist, dass jemand in der Zwischenzeit etwas aus Ihrem Repository abgerufen hat, da das Zurücksetzen im Grunde nur ein Standard-Commit ist.

Alle bisherigen Antworten gehen nicht auf das folgende Problem ein:

Gibt es eine effiziente Methode, wenn es Hunderte von Revisionen gibt? nach dem zu löschenden?

Es folgen die Schritte, aber als Referenz gehen wir von folgendem Verlauf aus:

[master] -> [hundreds-of-commits-including-merges] -> [C] -> [R] -> [B]

C:Commit direkt nach dem Commit, das entfernt werden soll (sauber)

R:Der zu entfernende Commit

B:Commit direkt vor dem zu entfernenden Commit (Basis)

Aufgrund der Einschränkung „Hunderte von Revisionen“ gehe ich von folgenden Voraussetzungen aus:

  1. Es gibt einen peinlichen Commit, von dem Sie sich wünschen, dass er nie existiert hätte
  2. Es gibt NULL nachfolgende Commits, die tatsächlich von diesem peinlichen Commit abhängen (keine Konflikte beim Zurücksetzen).
  3. Es ist Ihnen egal, dass Sie als „Committer“ der Hunderten von dazwischen liegenden Commits aufgeführt werden („Autor“ bleibt erhalten).
  4. Sie haben das Repository noch nie freigegeben
    • Oder Sie haben tatsächlich genug Einfluss auf alle Menschen, die jemals einen Verlauf mit diesem Commit geklont haben, um sie davon zu überzeugen, Ihren neuen Verlauf zu verwenden
    • Und du ist mir egal um Geschichte neu schreiben

Dies ist ein ziemlich restriktiver Satz von Einschränkungen, aber es gibt eine interessante Antwort, die in diesem Eckfall tatsächlich funktioniert.

Hier sind die Schritte:

  1. git branch base B
  2. git branch remove-me R
  3. git branch save
  4. git rebase --preserve-merges --onto base remove-me

Wenn wirklich keine Konflikte vorliegen, sollte dies ohne weitere Unterbrechungen erfolgen.Wenn es Konflikte gibt, können Sie diese lösen und rebase --continue oder beschließen, einfach mit der Peinlichkeit zu leben und rebase --abort.

Jetzt sollten Sie dran sein master das hat kein Commit mehr R drin.Der save Die Verzweigung verweist auf die Stelle, an der Sie sich zuvor befanden, falls Sie eine Versöhnung durchführen möchten.

Wie Sie die Übertragung aller anderen Personen auf Ihre neue Historie gestalten möchten, bleibt Ihnen überlassen.Sie müssen sich damit vertraut machen stash, reset --hard, Und cherry-pick.Und Sie können das löschen base, remove-me, Und save Geäst

Hier ist das Szenario, mit dem ich konfrontiert war, und wie ich es gelöst habe.

[branch-a]

[Hundreds of commits] -> [R] -> [I]

Hier R ist der Commit, den ich entfernen musste, und I ist ein einzelnes Commit, das danach kommt R

Ich habe einen Revert-Commit durchgeführt und sie zusammengequetscht

git revert [commit id of R]
git rebase -i HEAD~3

Während des interaktiven Rebase-Squashs werden die letzten beiden Commits komprimiert.

Ich bin auch in einer ähnlichen Situation gelandet.Verwenden Sie den interaktiven Rebase mit dem folgenden Befehl und lassen Sie beim Auswählen das dritte Commit fallen.

git rebase -i remote/branch

Die Antworten von Rado und Kareem bringen mir nichts (es erscheint nur die Meldung „Der aktuelle Zweig ist auf dem neuesten Stand.“).Möglicherweise liegt das daran, dass das Symbol „^“ in der Windows-Konsole nicht funktioniert.Allerdings gem Das Kommentar: Das Ersetzen von „^“ durch „~1“ löst das Problem.

git rebase --onto <commit-id>^ <commit-id>

So entfernen Sie den alten Commit-Verlauf aus dem Git-Repo:

Zuerst unter cmd ausführen

rm -rf .git

- Repo aus dem aktuellen neu erstellen

git init                                                                           
git add .                                                  
git commit -m "first commit"

-- Push zu den Github-Remote-Repos

git remote add origin git@github.com<your git mail>   
git push -u --force origin master
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top