Como alterar o último commit para remover um arquivo?

108

Eu modifiquei dois arquivos a, bno último commit. Mas o arquivo bnão deve ser confirmado. Qual é o fluxo de trabalho para corrigir isso?

Xiè Jìléi
fonte

Respostas:

109

Atualização (alguns anos depois)

Jan Hudec

É trivial removê-lo apenas do índice.

Verdadeiro: você pode redefinir um arquivo para o seu índice facilmente, como sugere a resposta mais recente (escrita por Matt Connolly ):

git reset HEAD^ path/to/file/to/revert

HEAD^permite que o arquivo acesse seu conteúdo na confirmação anterior antes da última.

Então você pode git commit --amend, como escrevi originalmente abaixo.


Com o Git 2.23 (agosto de 2019), você pode usar o novo git restorecomando

 git restore --source=HEAD^ --staged  -- path/to/file/to/revert

mais curta:

 git restore -s@^ -S -- path/to/file/to/revert

Novamente, você pode git commit --amend, como escrevi originalmente abaixo.


Resposta original (janeiro de 2011)

Se este é seu último commit (e você não o enviou a lugar nenhum), você pode corrigi- lo:
(primeiro stash ou save b)

 git commit --amend

Em seguida, exclua b, reconecte. Restaure be pronto.

--amend

Usado para alterar a ponta do ramo atual.
Prepare o objeto em árvore que você deseja substituir a confirmação mais recente, como de costume (isso inclui os caminhos -i / -o e explícitos usuais), e o editor de log de confirmação é propagado com a mensagem de confirmação da ponta da ramificação atual.
A confirmação que você cria substitui a dica atual - se foi uma mesclagem, os pais da dica atual serão pais - então a confirmação superior atual é descartada.

VonC
fonte
... Then stash/delete b, re-commit.., Aqui não deve a palavra Thenser after? - --amendapós stach / apagar b, ...
Xie Jìléi
@ 谢 继 雷: em outras palavras, salve b primeiro, depois confirme --amend e depois restaure? Verdadeiro. Eu atualizei a resposta.
VonC
Com o poder do índice git, dizer a alguém para esconder / salvar o arquivo é simplesmente bobo (-1). É trivial removê-lo apenas do índice.
Jan Hudec
1
@JanHudec True, editei a resposta de acordo. Eu não segui essa resposta antiga tão de perto quanto no Stack Overflow. 99% das perguntas git no SU devem ser migradas no SO de qualquer maneira.
VonC
66
  1. git diff --name-only HEAD^ - (opcional) use para listar os arquivos que foram alterados na última confirmação.
  2. git reset HEAD^ path/to/file/to/revert- redefinir o índice para a última versão, mantendo a cópia de trabalho intocada.
  3. git commit --amend- alterar o último commit para incluir as alterações no índice
Matt Connolly
fonte
9
Acho que é uma resposta muito melhor do que a aceita.
Mk01aj
1
Observe que você não deve usar git commit -a --amend(ou seja, não adicionar arquivos) para a etapa 3, ou irá confirmar suas alterações na cópia de trabalho, que são as edições que você está tentando remover. Uma etapa opcional 2.5 também pode ser git checkout path/to/file/to/reverta sua cópia de trabalho.
DMND
1
Como alternativa, git rm --cached path/to/file/to/revertdesinstale o arquivo sem excluí-lo da árvore.
Jan Hudec
13

Como alternativa, se você estiver usando git gui, basta selecionar a opção "Alterar última confirmação", o arquivo adicionado aparecerá na lista "Estágios", clique no ícone para movê-lo para a lista "Não estágios" e confirmar.

Jan Hudec
fonte
1
@VonC: Editar e dividir patches é uma operação bastante comum para usuários pesados ​​de git; portanto, o gui foi projetado para facilitar e é a melhor ferramenta da IMO.
Jan Hudec
Aquele funciona! Não tive sucesso com outras opções para essa tarefa em particular. Obrigado pela dica!
Serguzest
10

Se você deseja excluir b do seu último commit

git rm --cached b (will preserve the file in the working tree but remove it from the index)
git commit --amend

Se você deseja remover todas as alterações eb em sua última confirmação

(backup b)
(modify b to state before incorrect commit)
git commit --amend
(restore b)
pingo
fonte
git rm --cachede elimine a dança de backup / restauração (-1).
Jan Hudec
Obrigado por apontar isso. Eu queria compartilhar como fiz isso, porque essa era a abordagem com a qual me sentia mais confortável, mesmo depois de ler todo o tópico.
Pingo
4

Uma alternativa que não requer invasão de índice, mas preserva a antiga mensagem de confirmação:

$ git reset HEAD^
$ git add <all the files you want, excluding the one you don't want>
$ git commit -C HEAD@{1}

Gosto disso porque (a) ele usa comandos que uso regularmente e (b) posso fazer git add -ppara descobrir exatamente o que quero confirmar.

Justin L.
fonte