Ich denke, die Wurzel des Problems ist, dass Git (und Versionskontrolle im Allgemeinen) Sie zwingt, in Sequenzen von Änderungen zu denken, aber ein Changeset oder ein Feature-Branch oder wie auch immer Sie eine zusammenhängende Gruppe von zusammenhängenden Änderungen nennen, ist im Allgemeinen nicht logisch sequentiell. Die Reihenfolge, in der der Code geschrieben wurde, ist zufällig und hat nicht unbedingt etwas mit der Reihenfolge zu tun, in der er gelesen werden sollte.
Ich habe keine Lösung für dieses Problem, aber ich habe ein Perl-Skript um den Prozess des Umschreibens der Geschichte zu automatisieren. Es ähnelt dem Python-Skript von @MikaEloranta, das ich noch nicht gesehen hatte, als ich es schrieb.
commit --fixup
y rebase --autosquash
sind großartig, aber sie tun nicht genug. Wenn ich eine Folge von Übertragungen habe A-B-C
und ich schreibe weitere Änderungen in meinem Arbeitsbaum, die in einen oder mehrere dieser bestehenden Commits gehören, muss ich mir die Historie manuell ansehen, entscheiden, welche Änderungen in welche Commits gehören, sie einordnen und die fixup!
bindet. Aber Git hat bereits Zugriff auf genug Informationen, um all das für mich zu tun.
Für jeden Brocken in git diff
verwendet das Skript git blame
um den Commit zu finden, der die betreffenden Zeilen zuletzt berührt hat, und ruft git commit --fixup
um die entsprechenden fixup!
Commits, was im Wesentlichen dasselbe ist, was ich vorher manuell gemacht habe.
Wenn das Skript einen Hunk nicht in einen einzelnen, eindeutigen Commit auflösen kann, wird es ihn als fehlgeschlagenen Hunk melden und Sie müssen auf die manuelle Vorgehensweise zurückgreifen. Wenn Sie eine Zeile zweimal in zwei verschiedenen Commits geändert haben, wird das Skript eine Änderung in dieser Zeile in den jüngsten dieser Commits auflösen, was nicht immer die richtige Auflösung ist. IMHO sollte man in einem "normalen" Feature-Branch eine Zeile nicht zweimal in zwei verschiedenen Commits ändern, jeder Commit sollte die endgültige Version der Zeilen, die er berührt, präsentieren, um den Reviewer(n) zu helfen. Es kann jedoch in einem Bugfix-Zweig passieren, um ein Beispiel zu erfinden, die Zeile foo(bar());
könnte durch die Übergabe A berührt werden (Umbenennung foo
a fox
) und B übertragen (umbenennen bar
a baz
).
Wenn Sie das Skript nützlich finden, können Sie es gerne verbessern und weiterentwickeln, und vielleicht werden wir eines Tages eine solche Funktion einbauen git
richtig. Ich würde gerne ein Werkzeug sehen, das versteht, wie ein Merge-Konflikt aufgelöst werden sollte, wenn er durch ein interaktives Rebase entstanden ist.
1 Stimmen
Warum diese seltsame Anforderung, dass fixA in A zusammengeführt werden muss?
12 Stimmen
Weil es von vornherein in A hätte stehen müssen.
4 Stimmen
Ich tue dasselbe; ich weiß nicht, warum die Leute das für seltsam halten. Wenn Sie versuchen, Commits in kleine, logisch gruppierte Teile zu organisieren, dann ist es natürlich, dass Sie mehrere unveröffentlichte Commits gleichzeitig vorbereiten. (Man weiß vielleicht nicht, ob man wirklich mit A fertig ist, bis man C fertig hat).
0 Stimmen
Ich mache auch immer dasselbe - und ich habe mich nach so etwas gesehnt (ich nenne es gerne
git fixup <rev>
) seit geraumer Zeit.0 Stimmen
Ähnlich: stackoverflow.com/questions/3103589/