Como escolher as mudanças para apenas um arquivo, não todo o commit

108

Eu preciso aplicar as mudanças introduzidas em um branch para outro branch. Posso usar o cherry pick para fazer isso. No entanto, no meu caso, quero aplicar alterações que são relevantes apenas para um arquivo, não preciso selecionar o commit inteiro. Como fazer isso?

como ele
fonte

Respostas:

137

Você tem opções diferentes com base no que deseja alcançar:

Se quiser que o conteúdo do arquivo seja o mesmo do branch de destino, você pode usar git checkout <branch> -- <filename>. No entanto, isso não “selecionará” as mudanças que aconteceram em um único commit, mas apenas tomará o estado resultante do referido arquivo. Então se você adicionou uma linha em um commit, mas os commits anteriores mudaram mais, e você só quer adicionar aquela linha sem aquelas outras mudanças, então um checkout não é o que você quer.

Caso contrário, se você deseja aplicar o patch introduzido em um commit a apenas um único arquivo, você tem várias opções. Você pode executar git cherry-pick -n, ou seja, sem submetê-lo, editar o commit (por exemplo, redefinir todos os arquivos usando git reset -- .e apenas adicionar o arquivo que você realmente deseja alterar usando git add <filename>). Ou você pode criar o diff para o arquivo e aplicar o diff então:

git diff <branch>^..<branch> -- <filename> | git apply
cutucar
fonte
22

Crie um patch filee aplique-o.

git diff branchname -- filename > patchfile
git apply patchfile

EDITAR:

Já que você precisa fazer as alterações de um commit, crie o patch assim:

git show sha1 -- filename > patchfile
Sailesh
fonte
1
git diff sha1(ou git diff branch- é o mesmo se a ramificação apontar para o mesmo hash) produzirá apenas uma diferença do diretório de trabalho atual em relação a esse hash, mas não o que muda um commit introduzido por si mesmo.
cutucar
Corrigir. Editou a resposta. Obrigado.
Sailesh
1
-1 git checkoutcom um nome de arquivo é o martelo certo para este prego. Ambas as opções são desnecessariamente complexas.
Rein Henrichs
7
Para este caso específico, sim. Mas, em geral, se você quiser escolher as alterações de um commit feito em um arquivo específico, então checkoutnão funcionará, já que pode envolver outras alterações anteriores indesejadas e pode não conter alterações feitas no branch atual.
Sailesh de
11

Outra coisa útil a fazer é obter o patch localmente e usar:

git checkout {<name_of_branch>, commit's SHA} <path to the file> 

Isso não é uma escolha seletiva.

0x90
fonte
2
Atenção: como @poke diz em sua resposta, isso não copia as alterações; ele copia todo o estado do arquivo. Portanto, se você quiser adicionar as alterações de um commit ao arquivo, fazendo check-out desta forma, você acabará sobrescrevendo quaisquer alterações mais recentes, o que não é bom.
Alexander Bird
7

Git tem tudo pronto :)

Apenas use git checkout <sha> <path-to-file>

Raghotham S
fonte
4
Isso não é uma escolha acertada - isso verifica o arquivo por completo. O objetivo é fazer uma alteração específica de um commit. Freqüentemente, são a mesma coisa, mas às vezes não são.
AndrewF de
6
git checkout the_branch_with_the_change the/path/to/the/file/you/want.extension

isto funciona se você quiser que um único arquivo de outro ramo seja copiado para o ramo de trabalho atual

Ismail Iqbal
fonte
1
Tenha cuidado, as alterações feitas no arquivo que não estão na versão do outro branch serão perdidas.
Patrick Schlüter
Concordo com isso. isso é útil se você precisa apenas de uma cópia do arquivo e deseja alterá-lo no branch atual
Ismail Iqbal
1
Pode-se usar globs (caminho / *) e especificar mais de um caminho / arquivo
Todd
1

Isso é o que você está procurando:

git checkout target-branch sha1 path/to/file

sha1 é opcional

Ruslan Osipov
fonte
11
não, "escolher alterações no commit" não é "selecionar arquivo inteiro"
Abyx
1

O que costumo fazer é usar git ls-tree

apenas faça:

git ls-tree -r <commit-id> |grep 'your filename'
# there will be output that shows a SHA1 of your file
git show ${SHA1 of your file} > 'your filename'

Isso imprimirá todos os nomes de arquivo que correspondam ao seu grep e fornecerá as chaves SHA1 dos arquivos no commit.

O Git show também pode ser usado em arquivos fora do seu branch. usar >de seu shell para canalizar a saída para um arquivo fornece o resultado que você está procurando.

Alex
fonte
0

Você pode tentar fazer isso:

git show COMMIT_ID -- path/to/specific-file | git apply

Por exemplo:

git show 3feaf20 -- app/views/home/index.html | git apply
arashb31
fonte
-9
git reset HEAD~1

move os arquivos para o estágio de pré-confirmação

git stash

remove da memória

Agora seu branch está bem limpo (revertido para o commit anterior)

Venkata
fonte