Reverter seletivamente ou verificar as alterações em um arquivo no Git?

89

Existe um comando que permite desfazer parcialmente as alterações em um arquivo (ou arquivos) no diretório de trabalho?

Suponha que você edite um arquivo muito, mas perceba que deseja desfazer algumas das alterações de volta ao estado consolidado, mas não as outras alterações.

Estou imaginando uma opção para git checkoutque funcione muito parecido git add -p, ou seja, percorre o arquivo pedaço por pedaço e pergunta se você deseja mantê-lo ou não.

1800 INFORMAÇÕES
fonte

Respostas:

85

Você poderia usar

git add -p <path>

para preparar os pedaços que você deseja manter em um arquivo específico, então

git checkout -- <path>

para descartar as alterações da árvore de trabalho que você não deseja manter, fazendo check-out da versão em estágios do arquivo.

Finalmente, você pode usar

git reset -- <path>

para reverter a versão testada do arquivo para a versão confirmada mais recente do arquivo para deixá-lo com suas alterações não testadas.

CB Bailey
fonte
Para este caso de uso simples, que todos os outros sistemas de controle de versão chamam apenas de "reverter", por que o comando Git é tão obscuro?
Jan Hettich
5
@Jan Os comandos de outros sistemas de controle de versão revertpermitem que você selecione quais alterações em um arquivo são revertidas? Perguntando genuinamente, já que só tenho experiência com CVS e Git. No Git, git checkout -- path/to/fileé um único comando que reverte todas as alterações naquele arquivo, mas não é o mesmo que o anterior.
michiakig
3
Há também git checkout --patche git reset --patchque funcionam como git add --patchno último git.
Matt Connolly
2
@Rudie, --geralmente indica o fim da análise de opções e que quaisquer argumentos que venham depois dela devem ser interpretados literalmente. Isso significa que você não teria que adicionar ./antes de qualquer nome de arquivo que comece com um sinal de menos, se o nome do arquivo vier depois --.
zrajm
quando eu uso git checkout --patcho diff parece estar ao contrário. Os símbolos de menos são ADICIONANDO texto à minha cópia de trabalho, e os símbolos de mais estão REMOVENDO linhas de minha cópia de trabalho.
Felipe Alvarez
115

Com a versão git> = 1.7.1 eu posso

git checkout -p

Não tenho certeza de quando esse recurso foi introduzido.

Thisgeek
fonte
11
Vale a pena mencionar que você também pode fazer git reset -ppara separar seletivamente as alterações da área / índice de teste. Também não sei de cara em qual versão do Git isso foi introduzido.
Esta é a resposta correta, porque não foi aceita.
wukong
1
@wukong porque essa resposta foi postada 2 anos após a pergunta. Neste momento (2009), a resposta de Charles era a melhor solução
pomeh
8

git checkout $filereverte o estado do arquivo $filepara o último estado confirmado. Acho que você pode usar git checkout SHA-1 -- $filepara reverter o arquivo para o commit identificado pelo SHA-1.

Koraktor
fonte
1
sim, não é exatamente o que eu quero, já que quero manter algumas das alterações que fiz no arquivo e reverter as outras
1800 INFORMAÇÕES
1

De quantos commits você precisa voltar e selecionar? Se for apenas um, talvez pegue um branch antes dele, faça o checkout do arquivo que você confirmou e use git add -ppara adicioná-lo como deseja. Em seguida, você pode voltar para onde estava e fazer o checkout do arquivo do branch temporário.

isso é:

git checkout -b temp troublesome-commit^
git checkout troublesome-commit -- path/to/file
git add -p path/to/file
git commit -c troublesome-commit
git checkout @{-1}
git checkout temp -- path/to/file
git commit path/to/file
git branch -D temp

Outras alternativas incluem voltar e editar o commit com git rebase -i(marcando o commit como edit, então fazer um git reset HEAD^e refazer o commit quando cair de volta no shell).

Se as mudanças que você precisa selecionar estão espalhadas por uma série de commits, pode ser melhor extraí-los como patches (ou um patch cobrindo todos eles) e editar manualmente o patch, retirando as mudanças que você deseja manter, e alimentar o resíduo em git apply --reverse.

araqnid
fonte
Na verdade, não estou querendo reverter nada do que foi confirmado, quero desfazer as alterações que estão apenas na minha cópia de trabalho
1800 INFORMAÇÕES,