Modifier le commit racine dans Git?

328

Il existe des moyens de modifier le message à partir de validations ultérieures:

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

Comment pouvez-vous changer le message de validation du tout premier commit (qui n'a pas de parent)?

13ren
la source
En particulier: l'utilisation de la variable d'environnement GIT_COMMIT dans le script degit filter-branch --msg-filter
fork0
1
voir aussi stackoverflow.com/a/2309391/264607
BlackICE

Réponses:

284

En supposant que vous disposez d'un arbre de travail propre, vous pouvez effectuer les opérations suivantes.

# 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
la source
23
Je pense que cela devrait l'être git rebase --onto HEAD <sha1-of-root> master.
Andrew
5
C'est vrai, mais vous voulez que le commit racine d' origine pour le <upstream> de git rebase. git rebaseapplique des validations dans <branch> ( master) qui ne sont pas dans <upstream>; HEADn'est pas dedans master, donc votre version essaie de tout appliquer master.
Andrew
7
Oui, assurez-vous qu'il est git rebase --onto HEAD <sha1-of-root>maître, où <sha1-of-root>est le même utilisé git checkout <sha1-of-root>. Sinon, vous en aurez 2 first commit.
Andy
2
@Cupcake: Avez-vous testé l'ancienne version de la commande? Cela devrait bien fonctionner. La modification modifie uniquement le message de validation afin que les anciennes et nouvelles validations de racine introduisent exactement les mêmes modifications afin que l'ancienne validation de racine soit ignorée automatiquement. La seconde HEADgarantit que toutes les validations sont prises en compte et que nous pouvons utiliser la version à deux paramètres de rebase pour revenir sur master. Veuillez noter que cette réponse est antérieure à l'existence de l' --rootoption de rebase.
CB Bailey
9
La réponse d'ecdpalma ci-dessous est beaucoup plus facile et simple et a plus de votes, faites défiler les gens!
Flimm
567

Depuis Git version 1.7.12 , vous pouvez maintenant utiliser

git rebase -i --root

Documentation

ecdpalma
la source
2
est-il possible de rebaser la racine de toutes les branches en utilisant cette commande? On dirait que cela détachera la branche actuelle sur la nouvelle racine et toutes les autres branches resteront sur l'ancienne racine
woojoo666
@ woojoo666 vous devrez alors rebaser les branches sur une nouvelle racine. comme d'habitude.
berkus
@Atcold cela ne fonctionne pas s'il n'y a pas de racine en amont
Kai
Avertissement: j'ai supposé à tort que cela ferait la racine de ma branche extraite, mais cela prend un certain temps pour charger tous les commits, puis les rebaser.
Leo
2
@Leo, que signifie votre commentaire? Je ne vois pas le lien entre la première partie et la seconde - qu'est-ce que cela prend du temps?
boycy
66

Pour développer la réponse d'ecdpalma , vous pouvez maintenant utiliser l' --rootoption pour indiquer rebaseque vous souhaitez réécrire la racine / le premier commit:

git rebase --interactive --root

Ensuite, le commit racine apparaîtra dans la liste de rebase TODO, et vous pouvez choisir de le modifier ou de le reformuler:

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

Telle est l'explication de --rootde la documentation de rebasage Git (Souligné par l'auteur ):

Rebase tous les commits accessibles depuis <branch>, au lieu de les limiter avec un <upstream>. Cela vous permet de rebaser les validations racine sur une branche .

Communauté
la source
12

Juste pour fournir une alternative aux réponses les mieux notées:

Si vous créez un référentiel et que vous savez d'avance que vous rebaserez sur son "premier" vrai commit à l'avenir, vous pouvez éviter complètement ce problème en faisant un commit explicite vide au début:

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

et alors seulement commencer à faire des "vrais" commits. Ensuite, vous pouvez facilement rebaser au-dessus de ce commit de la manière standard, par exemplegit rebase -i HEAD^

jakub.g
la source
4
Cela ne signifie-t-il pas que, pour que cela fonctionne, vous devez avoir la clairvoyance (ou être psychique) pour faire un commit vide au tout début de votre projet ? Cela me semble extrêmement situationnel et généralement peu pratique . Qu'est-ce que tu penses? Que se passe-t-il si j'ai déjà effectué 100 validations et que je dois soudainement modifier la validation racine. Est-ce que cela fonctionnera toujours, dans ce cas, si je n'ai pas fait ce commit vide au début?
2
Modifier le message du commit racine n'est probablement pas quelque chose que vous feriez après en avoir des centaines. Il m'arrive parfois de vouloir simplement avoir un dépôt git, faire des commits trash, sachant qu'une fois que j'atteins un état utilisable, je les écrase en un par exemple, et reformule le message. Quoi qu'il en soit, maintenant j'ai changé d'avis et je pense que la chose la plus utile pour le premier commit serait de mettre un .gitattributesfichier au lieu de faire un commit vide.
jakub.g
4

Vous pouvez utiliser 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ß
la source
J'utilise filter-branch change l'auteur / committer, et l' -- --alloption est en effet la clé dans ce cas pour pouvoir également gérer le commit racine.
sschuberth