Adicione alterações a uma consolidação anterior com o Magit

43

Eu tenho 2 confirmações, A e B, prontas para serem enviadas. Percebo que esqueci de adicionar algo em A.

Como posso adicionar essa alteração a A usando o Magit? Eu nem sei qual parte da documentação do Git devo olhar.

Mathieu Marques
fonte

Respostas:

68

Vamos fingir por um momento que você deseja adicionar algo ao HEADcommit, ou seja, "o segundo commit B" no seu exemplo.

O pop-up de confirmação capresenta uma ligação " aAlterar". Pressionar essa tecla "alterará" as alterações faseadas no HEADcommit. Como as confirmações não são mutáveis ​​no Git, isso realmente substituirá a confirmação antiga por uma nova confirmação. Um buffer com a mensagem de confirmação antiga será exibida, para que você possa modificá-lo caso a alteração adicionada também exija que você ajuste a mensagem. Como sempre, pressione C-c C-cquando terminar de editar a mensagem. Isso é equivalente a executar git commit --amendna linha de comando.

  • a Alterar - adicione as alterações em etapas HEADe edite sua mensagem de confirmação

Como geralmente acontece que você só precisa ajustar a alteração ou a mensagem, o Magit fornece duas variantes adicionais:

  • e Estender - adicione as alterações faseadas HEADsem editar a mensagem de confirmação
  • w Reword - altere a mensagem de HEADsem adicionar as alterações faseadas a ela

Quando você deseja editar um commit que não é HEAD, o procedimento acima não funcionará. Esses comandos sempre "modificam" (ou seja, substituem) a HEADconfirmação. O Git não fornece um único comando para modificar um commit que não seja, HEADportanto, isso é um pouco mais envolvido.

Magit não fornecer tal comando, mas porque há situações em que é preferível fazer isso em várias etapas, vamos discutir isso primeiro.

Modificar um commit diferente de HEADpode ser dividido em três etapas:

  1. Faça temporariamente esse outro commit ( A) o HEAD.
  2. Modifique o HEAD(como descrito acima), resultando em confirmação A'.
  3. Diga ao Git para reaplicar os commits a seguir A, mas ainda por cima A'.

Isso pode ser feito usando um rebase interativo. Digite rpara mostrar o pop-up rebase. Em seguida, digite mpara chamar a variante de rebase "editar uma confirmação". Um buffer com confirmações recentes é exibido. Vá para o commit que você deseja modificar e digite C-c C-cpara selecioná-lo. O Git, em seguida, rebobina o histórico para esse commit e mostra informações sobre a rebase em andamento no buffer de status.

Modifique HEADcomo descrito acima. Em seguida, diga ao Git que você terminou digitando r r. Se A'e Bconflito, o rebase será interrompido Be você deverá resolvê-lo. Depois de fazer isso, pressione r rpara continuar.

Se você souber que suas alterações Aresultarão em conflito com B, prossiga como descrito acima, caso contrário, use a seguinte abordagem.


O Git permite criar "consertos de conserto" usando git commit --fixup A. Isso cria um novo commit, que registra alterações que "deveriam ter sido feitas em outro commit". Esse commit se torna o novo HEAD. Também existe uma --squashvariante. Para obter informações sobre as diferenças, consulte a git-commitpágina do manual.

Para realmente combinar o Acommit e o novo commit A'e, em seguida, reaplicar Bem cima disso, você deve usar rebase. O Magit fornece um comando conveniente para fazer isso r f.

A principal diferença para a abordagem acima é que aqui primeiro criamos um novo commit e, em seguida, fazemos uma nova reformulação para combiná-lo com o "target" e reaplicar B. Acima, começamos com rebasear em vez de cometer.

No Magit, --fixupas --squashvariantes e estão disponíveis no pop-up commit, on fe s. Mas o Magit também fornece variantes "instantâneas" dos comandos de correção e squash em Fe S. Essas variantes criam uma nova confirmação como as variantes "não instantâneas", mas combinam instantaneamente a confirmação de correção com a confirmação de destino usando rebase, sem que você precise chamar outro comando.

"Instant fixup" ( c F) é essencialmente a mesma coisa que "extend HEAD" ( c e), exceto que funciona para qualquer confirmação, não apenas HEAD.


Leitura adicional:

tarso
fonte
Claro como cristal! Obrigado, incrível pacote BTW.
Mathieu Marques
11
Bem, acho que há algumas partes piegas na segunda metade da minha resposta. Mas, para evitar aqueles que eu teria que dobrar a extensão desta resposta já muito tempo, por isso estou contente isso funciona para você ;-)
tarsius
Obrigado por esta resposta tarsius, isso realmente funciona para mim.
Anquegi
A clareza da primeira metade desta explicação torna a leitura da segunda metade, muito mais difícil de seguir, bastante frustrante!
22618 Lynwood Headley
git-commitA página de manual redireciona para as git-rebase(1)quais tem estas linhas: A mensagem de confirmação sugerida para a confirmação dobrada é a concatenação das mensagens de confirmação da primeira confirmação e daquelas com o comando "squash", mas omite as mensagens de confirmação de confirmações com a "correção" comando. IOW, use conserto se você quiser consertar o código no commit anterior, use squash se você também desejar consertar a mensagem de commit.
Yasushi Shoji
3

git commit --amend –C HEADé o comando Git que você deseja procurar e pode fazer as pazes com o Magit C-c C-a.

Ryan
fonte
Estou usando o Magit mais recente, C-c C-aé de uma versão mais antiga (eu acho). Além disso, não vejo nenhum vestígio de "alterar" no buffer de ajuda ( ?).
Mathieu Marques
Veja a resposta de Rémi para o equivalente magit 2.x.
npostavs
3

Portanto, um fluxo de trabalho é:

  • faça a sua mudança
  • c (confirmar) f (correção - selecione confirmar sua correção)

Então

  • r (rebase) -a (eliminação automática, pode ser padronizada) i (interativo)

O autosquash moverá automaticamente todas as confirmações do! Fixup para o lugar certo e as definirá para serem esmagadas na base.

stsquad
fonte
A única coisa que fiz que você não disse foi a fase entre a sua primeira bala e a segunda. Bater ime rende Cannot rebase: Your index contains uncommitted changes. Please commit or stash them.. Exceto que não tenho alterações não confirmadas. : /
Mathieu Marques
Tentei novamente depois de puxar Proceed despite merge in rebase range? [c]ontinue, [s]elect other, [a]bort. Está tentando me dizer que minha correção pode fazer cocô na mesclagem futura?
Mathieu Marques
@MathieuMarques: "Exceto que não tenho alterações não confirmadas" - o git pensa que sim. Observe que a mensagem sugere alterações em etapas, não em etapas. Re merge in rebase:, veja erros em git help rebase. Sugiro fazer a correção antes de puxar a montante.
npostavs
1

Para emendar o último commit, é "c a". A correção é para corrigir algumas confirmações mais antigas.

Rémi
fonte
Qual é o caso, comprometi A e B. Post atualizado para maior clareza.
Mathieu Marques