Root Commit in Git bearbeiten?

328

Es gibt Möglichkeiten, die Nachricht aus späteren Commits zu ändern:

git commit --amend                    # for the most recent commit
git rebase --interactive master~2     # but requires *parent*

Wie können Sie die Festschreibungsnachricht des allerersten Festschreibens ändern (das kein übergeordnetes Element hat)?

13ren
quelle
Insbesondere: die Verwendung der Umgebungsvariablen GIT_COMMIT im Skript vongit filter-branch --msg-filter
fork0
1
Siehe auch stackoverflow.com/a/2309391/264607
BlackICE

Antworten:

285

Angenommen, Sie haben einen sauberen Arbeitsbaum, können Sie Folgendes tun.

# checkout the root commit
git checkout <sha1-of-root>

# amend the commit
git commit --amend

# rebase all the other commits in master onto the amended root
git rebase --onto HEAD HEAD master
CB Bailey
quelle
23
Ich glaube das sollte sein git rebase --onto HEAD <sha1-of-root> master.
Andrew
5
Richtig, aber Sie möchten das ursprüngliche Root-Commit für den <upstream> von git rebase. git rebaseWendet Commits in <branch> ( master) an, die nicht in <upstream> enthalten sind. HEADist nicht in master, also versucht Ihre Version, alle anzuwenden master.
Andrew
7
Ja, stellen Sie sicher, dass es sich um den git rebase --onto HEAD <sha1-of-root>Master handelt, in <sha1-of-root>dem derselbe verwendet wird git checkout <sha1-of-root>. Andernfalls haben Sie 2 first commit.
Andy
2
@ Cupcake: Hast du die alte Version des Befehls getestet? Es sollte gut funktionieren. Durch die Änderung wird nur die Commit-Nachricht geändert, sodass die alten und neuen Root-Commits genau dieselben Änderungen einführen, sodass das alte Root-Commit automatisch übersprungen wird. Die zweite HEADstellt sicher, dass alle Commits berücksichtigt werden und dass wir die Zwei-Parameter-Version von Rebase verwenden können, um zurück zum Master zu gelangen. Bitte beachten Sie, dass diese Antwort vor dem Bestehen der --rootOption zum erneuten Basieren liegt.
CB Bailey
9
Die Antwort von ecdpalma unten ist viel einfacher und einfacher und hat mehr Stimmen. Scrollen Sie nach unten!
Flimm
567

Ab Git Version 1.7.12 können Sie jetzt verwenden

git rebase -i --root

Dokumentation

ecdpalma
quelle
2
Ist es möglich, die Wurzel aller Zweige mit diesem Befehl neu zu gründen? Scheint so, als würde der aktuelle Zweig von der neuen Wurzel getrennt und alle anderen Zweige bleiben auf der alten Wurzel
woojoo666
@ woojoo666 Sie müssen dann Zweige auf neue Wurzel neu gründen. wie gewöhnlich.
Berkus
@Atcold es funktioniert nicht, wenn es keine Upstream-Root gibt
Kai
Warnung: Ich habe fälschlicherweise angenommen, dass dies den Stamm meines ausgecheckten Zweigs bilden würde, aber es dauert eine Weile, bis alle Commits geladen und dann alle neu gestartet wurden.
Leo
2
@Leo was bedeutet dein Kommentar? Ich kann den Zusammenhang zwischen dem ersten und dem zweiten Teil nicht erkennen - was hat eine Weile damit zu tun?
Boycy
66

Um die Antwort von ecdpalma zu erweitern , können Sie jetzt die --rootOption verwenden, um anzugeben , rebasedass Sie das root / first commit neu schreiben möchten:

git rebase --interactive --root

Dann wird das Root-Commit in der Rebase-TODO-Liste angezeigt, und Sie können auswählen, ob Sie es bearbeiten oder umformulieren möchten:

reword <root commit sha> <original message>
pick <other commit sha> <message>
...

Dies ist die Erklärung --rootaus den Git-Rebase-Dokumenten (Hervorhebung von mir):

Setzen Sie alle erreichbaren Commits neu ein <branch>, anstatt sie mit einem einzuschränken <upstream>. Auf diese Weise können Sie die Root-Commits in einem Zweig neu festlegen .

Gemeinschaft
quelle
12

Nur um eine Alternative zu den höher bewerteten Antworten zu bieten:

Wenn Sie ein Repo erstellen und im Voraus wissen, dass Sie in Zukunft zusätzlich zu seinem "ersten" echten Commit neu aufbauen werden, können Sie dieses Problem insgesamt vermeiden, indem Sie zu Beginn ein explizites leeres Commit durchführen:

git commit --allow-empty -m "Initial commit"

und erst dann anfangen "echte" Commits zu machen. Dann können Sie das Commit beispielsweise auf die übliche Weise einfach neu aufbauengit rebase -i HEAD^

jakub.g
quelle
4
Bedeutet dies nicht, dass Sie vorausschauend (oder psychisch) sein müssen, um gleich zu Beginn Ihres Projekts ein leeres Commit zu machen, damit dies funktioniert ? Dies scheint mir äußerst situativ und im Allgemeinen nicht praktikabel zu sein . Was denken Sie? Was passiert, wenn ich bereits 100 Commits durchgeführt habe und plötzlich das Root-Commit bearbeiten muss? Funktioniert dies in diesem Fall noch, wenn ich das leere Commit zu Beginn nicht ausgeführt habe?
2
Das Bearbeiten der Nachricht des Root-Commits ist wahrscheinlich nicht das, was Sie tun würden, wenn Sie 100 davon haben. Manchmal möchte ich einfach nur ein Git-Repo haben, einige trashige Commits machen und wissen, dass ich sie zum Beispiel in einen zerquetschen und die Nachricht umformulieren würde, sobald ich einen brauchbaren Zustand erreicht habe. Wie auch immer, jetzt habe ich meine Meinung geändert und ich denke, das absolut nützlichste für das erste Commit wäre, eine .gitattributesDatei zu platzieren, anstatt ein leeres Commit durchzuführen.
Jakub.g
4

Sie könnten verwenden git filter-branch:

cd test
git init

touch initial
git add -A
git commit -m "Initial commit"

touch a
git add -A
git commit -m "a"

touch b
git add -A
git commit -m "b"

git log

-->
8e6b49e... b
945e92a... a
72fc158... Initial commit

git filter-branch --msg-filter \
"sed \"s|^Initial commit|New initial commit|g\"" -- --all

git log
-->
c5988ea... b
e0331fd... a
51995f1... New initial commit
Alexander Groß
quelle
Ich verwende Filterzweig, um den Autor / Committer zu ändern, und die -- --allOption ist in diesem Fall tatsächlich der Schlüssel, um auch das Root-Commit verarbeiten zu können.
Sschuberth