Reverter alterações em um arquivo em uma confirmação

126

Quero reverter as alterações feitas por um commit específico em um determinado arquivo.

Posso usar o comando git revert para isso?

Alguma outra maneira simples de fazer isso?

Lakshman Prasad
fonte
Estranho ... por que a mudança depois de todos esses anos?
VonC 5/17/17

Respostas:

222

A maneira mais limpa que eu já vi de fazer isso é descrita aqui

git show some_commit_sha1 -- some_file.c | git apply -R

Semelhante à resposta do VonC, mas usando git showe git apply.

mgalgs
fonte
10
Bem feito. A solução de script é um exagero para isso. Por que não pode haver apenas o nome de arquivo git revert sha-1?
Mark Edington
16
Isso funciona no meu Mac, mas no Windows (no Cygwin) ele me dá:fatal: unrecognized input
Kedar Mhaswade 16/07/2015
1
@MerhawiFissehaye: Eu acho que o git checkout só reverterá as alterações novamente para voltar ao estado em que estava o commit. Eu adicionei o nome do arquivo; git commit --amend 'para remover o arquivo do commit.
ViFI 18/10/16
3
Apenas uma dica, eu quase sempre tenho que adicionar a -3flag ao git request para mesclagem de três vias quando o patch falha, pois geralmente estou corrigindo uma alteração um pouco no tempo.
Angularsen 17/11
2
Talvez óbvio para a maioria, mas garantir some_file.cinclui o caminho para o arquivo, se houver um caso contrário você vai silenciosamente remendo nada :)
Warpling
35

Supondo que não há problema em alterar o histórico de consolidação, aqui está um fluxo de trabalho para reverter alterações em um único arquivo em uma consolidação anterior:

Por exemplo, você deseja reverter as alterações em 1 arquivo ( badfile.txt) no commit aaa222:

aaa333 Good commit
aaa222 Problem commit containing badfile.txt
aaa111 Base commit

Rebase na confirmação básica, corrija a confirmação do problema e continue.

1) Inicie o rebase interativo:

git rebase -i aaa111

2) Marque o problema de confirmação para edição no editor, alterando pickpara e(para edição):

e aaa222
pick aaa333

3) Reverta as alterações no arquivo incorreto:

git show -- badfile.txt | git apply -R

4) Adicione as alterações e corrija o commit:

git add badfile.txt
git commit --amend

5) Termine o rebase:

git rebase --continue
tee
fonte
Só quero ressaltar que isso pressupõe que você pode editar o histórico do git. Algumas respostas acima criam um novo commit que reverte a alteração específica sem editar o histórico, o que nem sempre é possível / permitido.
Angularsen 17/11/16
Fantástico. Era exatamente isso que eu estava procurando. Eu já tinha essa ideia, mas fiquei confuso ao fazer o rebase interativo de que os arquivos ao fazer o editnão estavam aparecendo como alterados. Mas git show -- badfile.txt | git apply -Rdeu a resposta que eu precisava <3
mraxus 15/03/19
se eu entendo esse git aplicar -R remove o commit nesse arquivo, configurando-o novamente para o estado original alterado?
DaImTo
19

git revert é para todo o conteúdo do arquivo em uma consolidação.

Para um único arquivo, você pode escrevê-lo :

#!/bin/bash

function output_help {
    echo "usage: git-revert-single-file <sha1> <file>"
}

sha1=$1
file=$2

if [[ $sha1 ]]; then
git diff $sha1..$sha1^ -- $file | patch -p1
else
output_help
fi

(Nos utilitários git-shell-scripts da smtlaissezfaire )


Nota:

Outra maneira é descrita aqui se você ainda não confirmou sua modificação atual.

git checkout -- filename

git checkout possui algumas opções para um arquivo, modificando o arquivo de HEAD, substituindo sua alteração.


Dropped.on.Caprica menciona nos comentários :

Você pode adicionar um alias ao git para fazer isso git revert-file <hash> <file-loc>e reverter esse arquivo específico.
Veja esta essência .

[alias]
  revert-file = !sh /home/some-user/git-file-revert.sh
VonC
fonte
Apenas para adicionar à discussão aqui, você pode adicionar um alias ao git para fazer isso git revert-file <hash> <file-loc>e reverter esse arquivo específico. Eu tirei essa resposta (embora eu tenha que fazer algumas edições para funcionar corretamente). Você pode encontrar uma cópia do meu .gitconfige roteiro editado aqui: gist.github.com/droppedoncaprica/5b67ec0021371a0ad438
AlbertEngelB
@ Dropped.on.Caprica bom ponto. Eu o incluí na resposta para obter mais visibilidade.
VonC
12

Eu simplesmente usaria a --no-commitopção para git-revertremover os arquivos que você não deseja reverter do índice antes de finalmente enviá-lo. Aqui está um exemplo mostrando como reverter facilmente apenas as alterações para foo.c no segundo commit mais recente:

$ git revert --no-commit HEAD~1
$ git reset HEAD
$ git add foo.c
$ git commit -m "Reverting recent change to foo.c"
$ git reset --hard HEAD

O primeiro git-reset"desestabiliza" todos os arquivos, para que possamos adicionar novamente apenas o arquivo que queremos reverter. A final git-reset --hardse livra do arquivo restante revertido que não queremos manter.

Dan Moulding
fonte
9

Muito mais simples:

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

então

git commit --amend   

e depois

git push -f

o arquivo se foi e confirma o hash, a mensagem etc. é a mesma.

Forrest
fonte
Para ser completo, você precisa de um git checkout -- path/to/file/to/revertpasso? Além disso, não é verdade que o hash é o mesmo depois, certo? A última frase pode ser melhor como algo como: "O resultado é que a última confirmação é substituída por uma nova que difere apenas no fato de não conter as alterações no arquivo revertido".
Kevin
@ Kevin você provavelmente está certo. Vou ter que checar essa última linha, mas olhando para trás de alguns anos atrás, ficaria surpreso se o hash de confirmação não fosse alterado.
Forrest
6
git reset HEAD^ path/to/file/to/revert/in/commit

O comando acima retirará o arquivo do commit, mas ele será refletido no git status.

git checkout path/to/file/to/revert/in/commit

O comando acima reverterá as alterações (como resultado, você obtém o mesmo arquivo que HEAD).

git commit

(Passe --amendpara alterar o commit.)

git push

Com isso, o arquivo que já está no commit é removido e revertido.

As etapas acima devem ser seguidas na ramificação em que a confirmação é feita.

Bharath TS
fonte
5

Você pode seguir este procedimento:

  1. git revert -n <*commit*>( -nreverta todas as alterações, mas não as confirma)
  2. git add <*filename*> (nome do (s) arquivo (s) que você deseja reverter e confirmar)
  3. git commit -m 'reverted message' (adicione uma mensagem para reverter)
  4. depois de confirmar, descartar os outros arquivos alterados para que eles fiquem atualizados com as alterações confirmadas antes da reversão
Imran Sahil
fonte
1

Se você deseja redefinir as alterações em um arquivo a partir do seu último commit, é isso que geralmente estou usando. Eu acho que essa é a solução mais simples.

Observe que o arquivo será adicionado à área de preparação.

git checkout <prev_commit_hash> -- <path_to_your_file>

Espero que ajude :)

Gabeeka
fonte