Gibt es eine einfache Möglichkeit, viele Commits in Git zu quetschen?

Lesezeit: 5 Minuten

Benutzer-Avatar
Pingger Shikkoken

Ich habe folgendes Problem:
Ich habe viele Commits, die gequetscht werden müssen (mehrere Tausend, wir hatten ein außer Kontrolle geratenes Skript). Diese Commits befinden sich in Gruppen zwischen 40 und 200.
Verwenden git rebase -i ist nicht machbar, da es zu arbeitsintensiv wäre. Wir haben ein Tool, das den ersten und letzten Commit eines solchen Gruppenrelativs aus dem Zweig HEAD ausgeben kann (der verwendet werden kann, um den tatsächlichen Commit anhand seines Referenzhashs zu erhalten).

Als Beispiel suche ich nach etwas, das HEAD ~ 400 bis HEAD ~ 200 in einen einzigen Commit quetschen kann. Und kann dann erneut ausgeführt werden (mit Änderungsargumenten), um HEAD~100 bis HEAD~50 in einen anderen einzelnen Commit zu quetschen.

Bearbeiten 1:
Ich habe darüber nachgedacht, einen “falschen” Editor zu erstellen, der im Wesentlichen die Interaktivität vortäuscht, indem er die Änderungen an der Rebase-Datei vornimmt. Ein abstraktes Beispielskript würde so aussehen (das ich wiederholen könnte, bis alle Gruppen gequetscht wurden):

start=$('get start of oldest group')
end=$('get end of oldest group')
git config core.editor "'~/fakeeditor' -start $start -end $end"
git rebase -i

  • Nur die Abstammung neu zu verdrahten, ist eine Frage der Einrichtung lokaler Transplantate und des Betreibens von Filterzweigen, um sie einzubacken.

    – jthill

    9. November 2020 um 20:46 Uhr

  • stackoverflow.com/questions/12394166/…

    – promov

    9. November 2020 um 20:46 Uhr

  • Du sagst, du willst nicht git rebase -i sondern ein Befehl, der Commit-Bereiche automatisch komprimiert. Warum benutzt du nicht git rebase -i und einen Befehl erstellen, der automatisch Bereiche von Commits in dieser Todo-Liste markieren kann?

    – Nils Werner

    10. November 2020 um 7:33 Uhr


  • @NilsWerner, was ich bereits vorgeschlagen habe, diesen “falschen Editor” zu verwenden

    – Pingger Shikkoken

    10. November 2020 um 23:53 Uhr

Benutzer-Avatar
eftshift0

Mein persönlicher Favorit ist die Verwendung git reset --soft.

Also, sagen Sie, Sie wollen aus squash HEAD~1000 Bis hierhin (HEAD~1000 der letzte sein überleben Commit, der nicht gequetscht wird):

git reset --soft HEAD~1000
git commit -m "Squashed a lot of stuff"

Das ist es. Sie können eine Revisions-ID anstelle von verwenden HEAD~n Verweise.

Wie ich sehe, möchten Sie es wie in Segmenten machen … also sagen wir … komprimieren wir HEAD ~ 400 zu HEAD ~ 200 … dann von HEAD ~ 200 zu HEAD ~ 100 … dann von HEAD ~ 100 zu KOPF. Lassen Sie uns also einen temporären Zweig erstellen, in dem wir unsere Arbeit erledigen.

git checkout -b temp HEAD~200
git reset --soft HEAD~400
git commit -m "squashing first segment"
# next segment
git checkout the-original-branch~100
git reset --soft temp
git commit -m "Second segment"
git branch -f temp #set temp over here
# final segment
git checkout --detach the-original-branch
git reset --soft temp
git commit -m "Final segment"
git branch -f temp #set temp over here
# if you like the result, feel free to move whatever branch over here
git branch -f whatever-branch
# and delete temp if so you want
git branch -D temp

Sehr einfach, denke ich.

Nach einem Tag habe ich (durch die Beantwortung einer anderen Frage) festgestellt, dass es viel einfacher geht:

git branch -f temp $( git commit-tree -p HEAD~400 -m "first squash" HEAD~200^{tree} )
# that set up temp on the first squash
git branch -f temp $( git commit-tree -p temp -m "second squash" HEAD~100^{tree} )
# temp has move to second squash
git branch -f temp $( git commit-tree -p temp -m "final squash" HEAD^{tree} )

Jetzt hat temp die gequetschten Commits so, wie es in meinem Beispiel angefordert wurde. Fühlen Sie sich frei, a zu tun reset --hard drüben (die übliche Warnung bei der Verwendung reset --hard).

  • Eindeutig das Werkzeug für den Job.

    – Romain Waleri

    10. November 2020 um 8:32 Uhr

Benutzer-Avatar
Cyrille Pontvieux

Erstellen Sie zunächst ein Skript zum Bearbeiten der Aufgabenliste von Git Rebase:

squash-it Datei:

#!/bin/sh
first=$(git rev-parse --short "$1")
last=$(git rev-parse --short "$2")
todo="$3"
lines=$(
sed -n "/^pick $first /,/^pick $last/{s/^pick/squash/p}" "$todo" | sed "1s/squash/pick/"
sed "/^pick $first /,/^pick $last/d" "$todo"
)
echo "$lines" > "$todo"

Verwenden Sie dann dieses Skript wie folgt:

GIT_SEQUENCE_EDITOR='sh -c "./squash-it HEAD~100 HEAD~50 $1"' GIT_EDITOR=cat git rebase -i HEAD~100^

Sie können ersetzen squash mit fixup wenn es das ist, was du willst.

Sie können diese Zeile natürlich auch in einem Skript selbst erzeugen, das sie ersetzt HEAD~100 und HEAD~50 zum Beispiel nach Belieben in einer Schleife.

  • Nun, Shebang haben #!/bin/sh und führe das Skript mit aus bash -c ist ein bisschen seltsam, oder? 🙂 Warum nicht einfach Shebang verwenden #!/usr/bin/env bash und GIT_SEQUENCE_EDITOR='./squash-it ?

    – promov

    9. November 2020 um 22:51 Uhr

  • Ok, ich ändere es so, dass es überall sh verwendet

    – Cyrille Pontvieux

    10. November 2020 um 7:26 Uhr

Sie können die gesamte Befehlsliste für generieren git rebase -i im Voraus und fügen Sie sie dann in einen Editor ein. Der Ablauf würde in etwa so aussehen:

  1. Generieren Sie für jeden Batch von Commits, die Sie quetschen möchten, eine vollständige Liste von Commit-Hashes, denen das Wort vorangestellt ist fixup; vorausgesetzt, Ihre Start- und End-Commits sind drin $start und $end: git log "$start...$end" --pretty='fixup %h'
  2. Machen Sie zwischen jedem Batch von Commits dasselbe, aber mit pick; Sie könnten das Ende einer Reihe von Kürbissen und den Elternteil vom Anfang der nächsten nehmen und dann die erste Zeile verwerfen: git log "$end...$nextStart^" --pretty='pick %h' | sed -n '2,$p'
  3. Suchen Sie den Commit vor dem ersten, den Sie quetschen möchten, und führen Sie ihn aus git rebase -i damit als Argument.
  4. Löschen Sie alle Zeilen, die git generiert, und fügen Sie Ihre vorbereitete Todo-Liste ein.
  5. Speichern und beenden Sie den Editor, und die Rebase-Tools von git werden Ihre Liste durcharbeiten.

1011060cookie-checkGibt es eine einfache Möglichkeit, viele Commits in Git zu quetschen?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy