git to - Como modificar commits existentes e não processados?



branch desconsiderar (23)

Eu escrevi a coisa errada em uma mensagem de commit. Como alternativa, esqueci de incluir alguns arquivos.

Como posso alterar a mensagem / arquivos de commit? O commit ainda não foi enviado.


Answers

Eu uso o Git GUI o máximo que posso, e isso te dá a opção de alterar o último commit:

Além disso, git rebase -i origin/master é um bom mantra que sempre lhe apresentará os commits que você fez em cima do master, e lhe dará a opção de alterar, deletar, reordenar ou squash. Não há necessidade de se apossar desse hash primeiro.


Se você quiser apenas alterar sua última mensagem, use a sinalização --only ou seu atalho -o com commit --amend :

git commit --amend -o -m "New commit message"

Isso garante que você não aprimore acidentalmente seu commit com material preparado. Claro que é melhor ter uma configuração adequada do $EDITOR . Então você pode deixar a opção -m fora e o git preencherá previamente a mensagem de commit com a antiga. Desta forma, pode ser facilmente editado.


Se você estiver usando a ferramenta Git GUI, existe um botão denominado emendar último commit. Clique nesse botão e, em seguida, ele exibirá seus últimos arquivos e mensagens de confirmação. Apenas edite essa mensagem e você poderá confirmá-la com uma nova mensagem de confirmação.

Ou use este comando em um console / terminal:

git commit -a --amend -m "My new commit message"

Se você não empurrou o código para sua ramificação remota ( GitHub / Bitbucket ), você pode alterar a mensagem de confirmação na linha de comando, conforme abaixo.

 git commit --amend -m "Your new message"

Se você está trabalhando em um ramo específico, faça isso:

git commit --amend -m "BRANCH-NAME: new message"

Se você já enviou o código com a mensagem errada e precisa ser cuidadoso ao alterar a mensagem. Ou seja, depois de alterar a mensagem de confirmação e tentar empurrá-la novamente, você acaba tendo problemas. Para facilitar, siga estas etapas.

Por favor, leia minha resposta inteira antes de fazer isso.

git commit --amend -m "BRANCH-NAME : your new message"

git push -f origin BRANCH-NAME                # Not a best practice. Read below why?

Nota importante: Quando você usa o force push diretamente, pode acabar com problemas de código que outros desenvolvedores estão trabalhando na mesma ramificação. Então, para evitar esses conflitos, você precisa puxar o código do seu ramo antes de fazer o push force :

 git commit --amend -m "BRANCH-NAME : your new message"
 git pull origin BRANCH-NAME
 git push -f origin BRANCH-NAME

Essa é a melhor prática ao alterar a mensagem de confirmação, se já foi enviada.


Eu adicionei o alias de reci, recmpara recommit (amend)isso, agora eu posso fazer isso com git recmou git recm -m.

$ vim ~/.gitconfig

[alias]

    ......
    cm = commit
    reci = commit --amend
    recm = commit --amend
    ......

Eu prefiro assim.

git commit --amend -c <commit ID>

Caso contrário, haverá um novo commit com um novo ID de commit


Emendando a mensagem de commit mais recente

git commit --amend

irá abrir o seu editor, permitindo que você altere a mensagem de commit do commit mais recente. Além disso, você pode definir a mensagem de confirmação diretamente na linha de comando com:

git commit --amend -m "New commit message"

… No entanto, isso pode fazer com que mensagens de confirmação de várias linhas ou pequenas correções sejam mais complicadas de serem inseridas.

Certifique-se de que você não tenha nenhuma alteração na cópia de trabalho preparada antes de fazer isso ou eles também serão confirmados. (Alterações não organizadas não serão confirmadas.)

Alterando a mensagem de uma confirmação que você já enviou para sua ramificação remota

Se você já enviou sua confirmação para o seu ramo remoto, você precisará forçar o commit a:

git push <remote> <branch> --force
# Or
git push <remote> <branch> -f

Aviso: o envio forçado sobrescreve o ramo remoto com o estado do seu local . Se houver commits no branch remoto que você não tem em seu branch local, você perderá os commits.

Aviso: tenha cuidado ao alterar os commits que você já compartilhou com outras pessoas. Emendar os commits essencialmente os reescreve para ter diferentes IDs de SHA , o que representa um problema se outras pessoas tiverem cópias do commit antigo que você tenha reescrito. Qualquer um que tenha uma cópia do commit antigo precisará sincronizar seu trabalho com o commit recém-reescrito, o que às vezes pode ser difícil, então certifique-se de coordenar com os outros ao tentar reescrever o histórico de commits compartilhado, ou apenas reescrever commits compartilhados completamente.

Use rebase interativo

Outra opção é usar o rebase interativo.
Isso permite editar qualquer mensagem que você queira atualizar, mesmo que não seja a última mensagem.

Para fazer um git squash, siga estes passos:

// X is the number of commits to the last commit you want to be able to edit
git rebase -i HEAD~X

Depois de esmagar seus commits - escolha o e/r para editar a mensagem

Nota importante sobre rebas interativo

Quando você usa a git rebase -i HEAD~X , pode haver mais de X commits. O Git irá "coletar" todos os commits nos últimos X commits e se houver uma mesclagem em algum lugar entre esse range, você verá todos os commits também, então o resultado será X +.

Boa dica:

Se você tiver que fazer isso para mais de uma única ramificação e você puder enfrentar conflitos ao alterar o conteúdo, configure o git rerere e deixe o git resolver esses conflitos automaticamente para você.

🔥 Hot-tip

Você também pode escrever uma pequena função bash para corrigir a última mensagem de commit do git e empurrá-la para o controle remoto. Me ajuda o tempo todo. Aqui está a função; coloque-o em seu arquivo .bashrc ou similar .zshrc e recarregue seu shell.

# Amend the last commit message
# Push the changes to remote by force
# USAGE: gamend "Your New Commit Msg"
function gamend() {
    git commit --amend -m "[email protected]"
    git push --force
}

Documentação


Você pode usar o git-rebase-reword

Ele é projetado para editar qualquer commit (não apenas o último) da mesma maneira que commit --amend

$ git rebase-reword <commit-or-refname>

É nomeado após a ação no rebase interativo para alterar um commit: "reword". Veja este post e man interactive mode-seção

Exemplos:

$ git rebase-reword b68f560
$ git rebase-reword HEAD^

Para corrigir a confirmação anterior, faça as alterações desejadas e organize essas alterações e, em seguida, execute

git commit --amend

Isto irá abrir um arquivo em seu editor de texto representando sua nova mensagem de commit. Começa preenchido com o texto da sua antiga mensagem de commit. Altere a mensagem de confirmação desejada, salve o arquivo e saia do editor para concluir.

Para corrigir o commit anterior e manter a mesma mensagem de log, execute

git commit --amend -C HEAD

Para corrigir o commit anterior removendo-o completamente, execute

git reset --hard HEAD^

Se você quiser editar mais de uma mensagem de confirmação, execute

git rebase -i HEAD~commit_count

(Substitua commit_count pelo número de confirmações que você deseja editar). Esse comando inicia seu editor. Marque o primeiro commit (o que você quer mudar) como “edit” em vez de “pick”, depois salve e saia do seu editor. Faça a alteração que você deseja confirmar e execute

git commit --amend
git rebase --continue

Nota: Você pode "Fazer a alteração desejada" também no editor aberto por git commit --amend


Atualize sua última mensagem de commit errada com uma nova mensagem de commit em uma linha:

git commit --amend -m "your new commit message"

Ou tente git reset como abaixo:

# You can reset your head to n number of commit
# NOT a good idea for changing last commit message
# but you can get an idea to split commit into multiple commits
git reset --soft HEAD^

# it will reset you last commit. Now, you
# can re-commit it with new commit message.

Usando reset para dividir commits em commits menores

git reset pode ajudá-lo a quebrar um commit em múltiplos commits também:

# reset your head. I am resetting to last commits:
git reset --soft HEAD^
# (you can reset multiple commit by doing HEAD~2(no. of commits)

# Now, reset your head for splitting it to multiple commits
git reset HEAD

# add and commit your files seperately to make multiple commits: e.g
git add app/
git commit -m "add all files in app directory"

git add config/
git commit -m "add all files in config directory"

Aqui você quebrou com sucesso seu último commit em dois commits.


Para quem procura uma GUI do Windows / Mac para ajudar na edição de mensagens antigas (ou seja, não apenas a mensagem mais recente), eu recomendo o SourceTree . Os passos a seguir estão abaixo.

Para confirmações que ainda não foram enviadas para um controle remoto:

  1. Certifique-se de ter confirmado ou armazenado todas as alterações atuais (ou seja, para que não haja arquivos listados na guia "Status do arquivo") - isso não funcionará de outra forma.
  2. Na aba "Log / Histórico", clique com o botão direito do mouse na entrada com uma linha adjacente no gráfico um abaixo do (s) commit (s) que você deseja editar e selecione "Rebase children of <commit ref> interativamente ..."
  3. Selecione a linha inteira da mensagem de commit que você deseja alterar ( isto é, clique na coluna "Message" ).
  4. Clique no botão "Editar mensagem".
  5. Edite a mensagem como desejado na caixa de diálogo que aparece e clique em OK.
  6. Repita as etapas 3 a 4 se houver outras mensagens de confirmação a serem alteradas.
  7. Clique em OK: o re-lançamento começará. Se tudo estiver bem, a saída terminará "Concluído com sucesso".

... Ou ... para commits que já foram enviados:

Siga os passos nesta resposta , que são semelhantes aos acima, mas requerem um comando adicional para ser executado a partir da linha de comando para forçar o ramo a ser lido - leia tudo e aplique o cuidado necessário!


Se você estiver usando a GUI do Git, você pode alterar o último commit que não foi enviado:

Commit/Amend Last Commit

Se é o seu último commit, apenas altere o commit:

git commit --amend -o -m "New commit message"

(usando o --only -o ( --only ) para garantir que você altere apenas a mensagem de confirmação)


Se é um commit enterrado, use o ótimo repositório interativo :

git rebase -i @~9   # Show the last 9 commits in a text editor

Encontre o commit desejado, altere pick para r ( reword ) e salve e feche o arquivo. Feito!


Tutorial de vim em miniatura (ou, como rebase com apenas 8 pressionamentos de tecla 3j cw r Esc ZZ ):

  • Corra vimtutor se você tiver tempo
  • h j k l correspondem às teclas de movimento
  • Todos os comandos podem ser prefixados com um "intervalo", por exemplo, 3j se move para baixo 3 linhas
  • i para entrar no modo de inserção - o texto digitado aparecerá no arquivo
  • Esc ou Ctrl c para sair do modo de inserção e retornar ao modo "normal"
  • u para desfazer
  • Ctrl r para refazer
  • dd , dw , dl para excluir uma linha, palavra ou letra, respectivamente
  • cc , cw , cl para alterar uma linha, palavra ou letra, respectivamente (o mesmo que dd i )
  • yy , yw , yl para copiar ("yank") uma linha, palavra ou letra, respectivamente
  • p ou P para colar depois ou antes da posição atual, respectivamente
  • :w Enter para salvar (gravar) um arquivo
  • :q! Entre para sair sem salvar
  • :wq Enter ou ZZ para salvar e sair

Se você editar bastante o texto, mude para o layout do teclado Dvorak, aprenda a digitar e aprenda o vim. Vale a pena o esforço? Sim.


ProTip ™: Não tenha medo de experimentar comandos "perigosos" que reescrevem o histórico * - o Git não exclui seus commits por 90 dias por padrão; você pode encontrá-los no reflog:

$ git reset @~3   # go back 3 commits
$ git reflog
c4f708b [email protected]{0}: reset: moving to @~3
2c52489 [email protected]{1}: commit: more changes
4a5246d [email protected]{2}: commit: make important changes
e8571e4 [email protected]{3}: commit: make some changes
... earlier commits ...
$ git reset 2c52489
... and you're back where you started

* Cuidado com opções como --hard e --force - eles podem descartar dados.
* Além disso, não reescreva o histórico em nenhum ramo em que você esteja colaborando.


Usar

git commit --amend

Para entender em detalhes, um excelente post é 4. Reescrevendo a História do Git . Ele também fala sobre quando não usar o git commit --amend .


Eu percebi que eu tinha empurrado um commit com um erro de digitação. Para desfazer, fiz o seguinte:

git commit --amend -m "T-1000, advanced prototype"
git push --force

Aviso: a força que forçar as alterações substituirá a ramificação remota pela sua local. Certifique-se de que você não vai sobrescrever nada que você queira manter. Também seja cauteloso em forçar um commit (reescrito) alterado se alguém compartilhar o branch com você, porque eles precisarão reescrever seu próprio histórico se tiverem a cópia antiga do commit que você acabou de reescrever.


Se você precisar alterar uma mensagem de confirmação antiga em várias ramificações (isto é, a confirmação com a mensagem incorreta estiver presente em várias ramificações), convém usar:

git filter-branch -f --msg-filter \
'sed "s/<old message>/<new message>/g"' -- --all

O Git irá criar um diretório temporário para reescrever e adicionalmente fazer backup de referências antigas em refs/original/ .

  • -f reforçará a execução da operação. Isso é necessário se o diretório temporário já estiver presente ou se já houver referências armazenadas em refs/original . Se esse não for o caso, você pode soltar esse sinalizador.

  • -- separa opções de ramificação de filtro das opções de revisão.

  • --all irá certificar-se de que todos os ramos e tags são reescritos.

Devido ao backup de suas referências antigas, você pode facilmente voltar ao estado antes de executar o comando.

Digamos que você queira recuperar seu mestre e acessá-lo no branch old_master :

git checkout -b old_master refs/original/refs/heads/master

Se a confirmação que você deseja corrigir não for a mais recente:

  1. git rebase --interactive $parent_of_flawed_commit

    Se você quiser consertar vários commits falhos, passe o pai do mais antigo deles.

  2. Um editor aparecerá, com uma lista de todos os commits desde o que você deu.

    1. Alterar pick para reword (ou em versões antigas do Git, para edit ) na frente de qualquer confirmação que você deseja corrigir.
    2. Depois de salvar, o Git irá repetir os commits listados.

  3. Para cada commit que você quer reescrever , o Git irá retornar ao seu editor. Para cada consolidação que você deseja editar , o Git coloca você no shell. Se você está no shell:

    1. Altere o commit da maneira que desejar.
    2. git commit --amend
    3. git rebase --continue

A maior parte desta seqüência será explicada a você pela saída dos vários comandos. É muito fácil, você não precisa memorizá-lo - lembre-se que o git rebase --interactive permite corrigir os commits não importa há quanto tempo eles foram.

Observe que você não desejará alterar os commits que você já enviou. Ou talvez você faça, mas nesse caso você terá que tomar muito cuidado para se comunicar com todos que podem ter tirado seus commits e feito trabalhos em cima deles. Como faço para recuperar / ressincronizar depois que alguém envia um rebase ou redefine para uma ramificação publicada?


  1. Se você quiser apenas modificar sua última mensagem de commit, faça:

    git commit --amend
    

    Isso vai deixá-lo cair no seu exitor de texto e permitir que você altere a última mensagem de commit.

  2. Se você quiser alterar as últimas 3 mensagens de commit, ou qualquer uma das mensagens de commit até esse ponto, forneça HEAD~3 ao comando git rebase -i :

    git rebase -i HEAD~3
    

Como já foi mencionado, git commit --amend é a maneira de sobrescrever o último commit. Uma nota: se você quiser também sobrescrever os arquivos , o comando será

git commit -a --amend -m "My new commit message"

Você também pode usar git filter-branch para isso.

git filter-branch -f --msg-filter "sed 's/errror/error/'" $flawed_commit..HEAD

Não é tão fácil quanto um git commit --amend trivial, mas é especialmente útil, se você já tiver algumas mesclagens depois de sua mensagem errônea de commit.

Note que isto irá tentar reescrever TODOS os commit entre HEAD e o commit falho, então você deve escolher o seu comando msg-filter maneira muito sensata ;-)


Uau, então há muitas maneiras de fazer isso.

Ainda outra maneira de fazer isso é excluir o último commit, mas manter as alterações para que você não perca seu trabalho. Você pode então fazer outro commit com a mensagem corrigida. Isso seria algo parecido com isto:

git reset --soft HEAD~1
git commit -m 'New and corrected commit message'

Eu sempre faço isso se esqueço de adicionar um arquivo ou fazer uma alteração.

Lembre - se de especificar --soft invés de --hard , senão você perderá esse commit inteiramente.


Alterar

Você tem algumas opções aqui. Você pode fazer

git commit --amend

contanto que seja seu último commit.

Rebase interativo

Caso contrário, se não for o seu último commit, você pode fazer um rebase interativo,

git rebase -i [branched_from] [hash before commit]

Então, dentro do rebase interativo, você simplesmente adiciona edit a esse commit. Quando isso acontecer, faça um git commit --amend e modifique a mensagem de commit. Se você quiser reverter antes desse ponto de commit você também pode usar o git reflog e deletar o commit. Então você acabou de fazer um git commit novamente.


Se a sua mesclagem e os commits correspondentes ainda não foram enviados, você pode alternar para outra ramificação, excluir a original e recriá-la.

Por exemplo, eu acidentalmente mesclei uma ramificação de desenvolvimento em mestre e queria desfazer isso. Usando as seguintes etapas:

git checkout develop
git branch -D master
git branch -t master origin/master

Voila! O mestre está no mesmo estágio da origem e seu estado mal fundido é apagado.





git git-commit git-rewrite-history amend