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.

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:


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.


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.


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.


Qual é o caso, comprometi A e B. Post atualizado para maior clareza.
— Mathieu Marques
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.