Edite o commit raiz no Git?


328

Existem maneiras de alterar a mensagem de confirmações posteriores:

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

Como você pode alterar a mensagem de confirmação do primeiro commit (que não tem pai)?



Em particular: o uso de variável de ambiente GIT_COMMIT no script degit filter-branch --msg-filter
fork0

Respostas:


284

Supondo que você tenha uma árvore de trabalho limpa, você pode fazer o seguinte.

# 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

23
Eu acredito que deveria ser git rebase --onto HEAD <sha1-of-root> master.
Andrew Andrew

5
Certo, mas você deseja o commit raiz original para o <upstream> de git rebase. git rebaseaplica confirmações em <branch> ( master) que não estão em <upstream>; HEADnão está presente master, então sua versão tenta aplicar tudo master.
Andrew

7
Sim, verifique se é git rebase --onto HEAD <sha1-of-root>mestre, onde <sha1-of-root>é o mesmo usado git checkout <sha1-of-root>. Caso contrário, você terá 2 first commit's.
Andy

2
@ Cupcake: Você testou a versão antiga do comando? Deve funcionar bem. A alteração está alterando apenas a mensagem de confirmação, para que as confirmações de raiz antiga e nova introduzam exatamente as mesmas alterações, para que a confirmação de raiz antiga seja ignorada automaticamente. O segundo HEADgarante que todas as confirmações sejam consideradas e que possamos usar a versão de dois parâmetros do rebase para retornar ao master. Observe que esta resposta é anterior à existência da --rootopção de rebase.
CB Bailey

9
A resposta de ecdpalma abaixo é muito mais fácil e mais simples e tem mais votos, role as pessoas para baixo!
Flimm

567

A partir da versão Git 1.7.12 , agora você pode usar

git rebase -i --root

Documentação


2
é possível rebase a raiz de todas as ramificações usando este comando? Parece que isso irá separar o ramo atual para a nova raiz e todos os outros ramos vai ficar na raiz de idade
woojoo666

@ woojoo666 você terá que refazer as ramificações para uma nova raiz. como sempre.
Berkus

@Atcold ele não funciona se não houver nenhuma raiz a montante
Kai

Aviso: Eu assumi erroneamente que isso faria a raiz do meu ramo de check-out, mas leva um tempo para carregar todas as confirmações e depois refazê-las todas.
Leo

2
@ Leo, o que seu comentário significa? Não consigo ver o link entre a primeira parte e a segunda - o que leva um tempo a ver com isso?
boycy

66

Para expandir a resposta do ecdpalma , agora você pode usar a --rootopção para dizer rebaseque deseja reescrever o root / first commit:

git rebase --interactive --root

Em seguida, o commit raiz será exibido na lista rebase TODO e você poderá editar ou reformular:

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

Esta é a explicação dos docs Git REBASE (grifo meu):--root

Rebase todos os commits acessíveis a partir de <branch>, em vez de limitá-los com um <upstream>. Isso permite que você reestruture os commit raiz em uma ramificação .


12

Apenas para fornecer uma alternativa às respostas de classificação mais alta:

Se você estiver criando um repositório e souber antecipadamente que estará refazendo o "primeiro" commit real no futuro, poderá evitar esse problema completamente fazendo um commit vazio explícito no início:

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

e só então comece a fazer confirmações "reais". Em seguida, você pode refazer com facilidade a confirmação padrão, por exemplogit rebase -i HEAD^


4
Isso não significa que, para que isso funcione, você precisa ter a previsão (ou ser psíquica) para fazer um commit vazio logo no início do seu projeto ? Isso parece ser extremamente situacional para mim e geralmente não é prático . O que você acha? O que acontece se eu já fiz 100 confirmações e de repente preciso editar a confirmação raiz. Isso ainda funcionará, nesse caso, se eu não fizesse esse commit vazio no início?

2
Editar a mensagem do commit raiz provavelmente não é algo que você faria depois de ter centenas deles. Às vezes, eu só quero ter um repositório Git, realizando alguns trashy commits, sabendo que quando chego a um estado utilizável, os agrupo em um, por exemplo, e reformulo a mensagem. Enfim, agora mudei de idéia e acho que a coisa mais útil para o primeiro commit seria colocar o .gitattributesarquivo em vez de fazer um commit vazio.
jakub.g

4

Você poderia usar 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

Eu estou usando filter-branch mudar o autor / -- --allcommit , e a opção de fato é a chave neste caso para poder também manipular o commit root.
214148 sschuberth
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.