Ich musste eine ähnliche Neuschreibung in einem unnötig großen Repository durchführen, während der Repo offline war. Der Ansatz, den ich nahm, war automatisierte "interaktive" Rebase unter Verwendung GIT_SEQUENCE_EDITOR
, die in this answer von @ James-Foucar & @pfalcon abgedeckt ist.
Damit dies gut funktioniert, habe ich zuerst die Merges aus dem neu geschriebenen Abschnitt des Verlaufs entfernt. Für meinen eigenen Fall wurde dies mit einer Menge von git rebase --onto
gemacht, die ausführlich in anderen Fragen zu StackOverflow behandelt wird.
Ich habe eine small script generate-similiar-commit-squashes.sh
die pick
& squash
Befehle zu erzeugen, so dass aufeinanderfolgende ähnliche Festschreibungen gestaucht würde. Ich habe Autor-date-and-shortlog verwendet, um ähnliche Commits zu finden, aber Sie brauchen nur den Autor (mein Gist hat einen Kommentar darüber, wie man ihn nur für den Autor anpassen kann).
$ generate-similiar-commit-squashes.sh > /tmp/git-rebase-todo-list
Die Ausgabe sieht aus wie
...
pick aaff1c556004539a54a7a33ce2fb859af0c4238c [email protected]
squash aa190ea2323ece42f1cd212041bf61b94d751d5c [email protected]
pick aab8c98981a8d824d2bc0d5278d59bc1a22cc7b0 [email protected]_config.yml
Das Repository auch von voll war selbst kehrt mit dem gleichen Stil ‚Update xyz‘ Nachrichten begehen. Wenn sie zerquetscht wurden, führten sie zu leeren Commits.
Die Commits, die ich zusammengeführt habe, hatten identische Commit-Nachrichten. git rebase -i
bietet eine überarbeitete Commit-Nachricht mit allen komprimierten Commit-Nachrichten, die sich wiederholt haben. Um das zu beheben, habe ich ein kleines Perl-Skript von this answer verwendet, um doppelte Zeilen von der Commit-Nachricht zu entfernen, die von git rebase
angeboten wird. Es ist besser in einer Datei, da es in einer Shell-Variable verwendet wird.
$ echo 'print if ! $x{$_}++' > /tmp/strip-seen-lines.pl
Jetzt für den letzten Schritt:
$ GIT_EDITOR='perl -i -n -f /tmp/strip-seen-lines.pl ' \
GIT_SEQUENCE_EDITOR='cat /tmp/git-rebase-todo-list >' \
git rebase --keep-empty -i $(git rev-list --max-parents=0 HEAD)
Trotz --keep-empty
mit beschwerte git
ein paar Mal durch diesen Prozess über leere Commits. Es würde mich mit einem unvollständigen git rebase
auf die Konsole werfen. Um die leere Commit- und Resume-Verarbeitung zu überspringen, wurden die folgenden zwei Befehle benötigt (in meinem Fall eher häufig).
$ git reset HEAD^
$ GIT_EDITOR='perl -i -n -f /tmp/strip-seen-lines.pl ' git rebase --continue
Wieder trotz --keep-empty
, fand ich, dass ich had no empty commits in der letzten git Geschichte, so über die Resets sie alle entfernt worden. Ich nehme an, dass etwas mit meinem Git, Version 2.14.1, nicht stimmt. Die Verarbeitung von ~ 10000 Commits wie diese dauerte etwas mehr als 10 Minuten auf einem beschissenen Laptop.
Das klingt, als könnte es zu viel unnötiger Anstrengung führen. Das heißt, wenn Commits eines bestimmten Autors nicht konsekutiv sind, dann wird das Quetschen von ihnen viel manuellen Eingriff erfordern. Es wäre besser, wenn Ihre vielen Autoren jeweils in einer eigenen Branche arbeiten. – larsks