Git: Como atualizar / retirar um único arquivo do mestre de origem remota?

362

O cenário:

  1. I fazer algumas mudanças em um único arquivo localmente e executar git add, git commitegit push
  2. O arquivo é enviado ao repositório principal de origem remota
  3. Eu tenho outro repositório local que é implantado via Capistrano com o método "remote_cache" desse repositório remoto
  4. Agora, não quero implantar o aplicativo inteiro, apenas atualizar / fazer check-out desse arquivo único.

Isso é de alguma forma possível com o git? Não consegui encontrar nada que funcionasse nem consegui descobrir. Com SVN acabei de fazer svn up filee pronto.

foresth
fonte
19
Você pode considerar alterar a resposta aceita para a que realmente responde à sua pergunta. ;)
passos
6
Depois de mais de 6 anos, eu acredito que nós podemos seguramente assumir que isso não vai acontecer @steps ...
Félix Gagnon-Grenier
Com o Git 2.23 (agosto de 2019), é git restore -s origin/master -- path/to/file. Veja minha resposta abaixo .
VonC 19/09/19

Respostas:

914

É possível fazer (no repositório implantado)

git fetch
git checkout origin/master -- path/to/file

A busca fará o download de todas as alterações recentes, mas não o colocará em seu código de saída atual (área de trabalho).

O checkout atualizará a árvore de trabalho com o arquivo específico das alterações baixadas ( origin/master).

Pelo menos isso funciona para mim, para aquelas pequenas correções de erros de digitação, nas quais é estranho criar um ramo etc. apenas para alterar uma palavra em um arquivo.

qzio
fonte
11
Super útil, isso funcionou muito bem. Eu precisava obter um arquivo composer.json e executar uma atualização antes de atualizar o restante do site em produção. Se eu tivesse manualmente colocado os arquivos composer.json / lock, quando fiz um pull, haveria conflito dizendo que os arquivos já existiam. Fazendo dessa maneira, o git reconheceu os arquivos sem uma reclamação.
David
6
Esta é a resposta que eu estava procurando.
Javadba
20
@Mymozaaa O traço duplo designa que o que se segue é um nome de arquivo. É para evitar que o git interprete seu nome de arquivo como uma ramificação no caso infeliz de você ter dois com o mesmo nome.
Joel Mellon
O problema é que você ainda está buscando e, se for um repositório grande, essa será a operação cara. Receio que a única alternativa seria instalar o gitweb no controle remoto e acessá-lo para recuperar o arquivo ou algo assim.
Christian Goetze
pergunta pequena, depois de fazer isso, vou para uma máquina diferente, depois faço suas ações listadas acima, mas depois as git statusvejo como Changes to be committed:- ou seja, preciso comprometê-las novamente? (Basta notar que eu queria para atualizar um único arquivo intocado mas o repo em si é tocado em uma máquina diferente)
Ricky Levi
42

O código a seguir funcionou para mim:

     git fetch
     git checkout <branch from which file needs to be fetched> <filepath> 
Shagun Pruthi
fonte
19
git archive --format=zip --remote=ssh://<user>@<host>/repos/<repo name> <tag or HEAD> <filename> > <output file name>.zip
Dmitry R
fonte
11
Esta é uma boa solução para repositórios clonados por ssh, mas parece que isso não é suportado por https: git archive --remote=https://github.com/git/git.git master:git/contrib/completion git-completion.bash | tar -x Dá-me uma mensagem de erro:fatal: Operation not supported by protocol.
Alderath 6/18
11
foi legal combinado com tar: s --to-stdout,git archive --remote="gitolite3@<host>:<repo>" <tag> <file> | tar xf - --to-stdout
Puggan Se 28/04
19

Com o Git 2.23 (agosto de 2019) e o novo comando (ainda experimental) git restore, visto em " Como redefinir todos os arquivos do diretório de trabalho, mas não da área de preparação? ", Isso seria:

git fetch
git restore -s origin/master -- path/to/file

A idéia é: git restorelida apenas com arquivos, não com arquivos e ramificações git checkout.
Veja " Confundido porgit checkout ": é aí que git switchentra)


codersam acrescenta nos comentários :

no meu caso, eu queria obter os dados do meu upstream (do qual eu bifurquei).
Então, mudei para:

git restore -s upstream/master -- path/to/file
VonC
fonte
2
Que alívio que esse comando finalmente existe ... O que as pessoas idiotas estavam fazendo antes? Eu estava restaurando a coisa toda e copiando os arquivos individuais que precisava, mas foi doloroso.
Mike Wise
Isso funcionou para mim, mas no meu caso eu queria obter os dados do meu upstream (do qual eu bifurquei). Então apenas mudou paragit restore -s upstream/master -- path/to/file
coderSam
@coderSam Do que você por esse feedback. Incluímos seu comentário na resposta para obter mais visibilidade.
VonC
8

O que você pode fazer é:

  1. Atualize seu repositório git local:

    git fetch

  2. Crie uma filial local e faça checkout nela:

    git branch pouet && git checkout pouet

  3. Aplique a confirmação que você deseja neste ramo:

    git cherry-pick abcdefabcdef

    (abcdefabcdef é o sha1 do commit que você deseja aplicar)

entalhe
fonte
4
Como um aparte, seu segundo passo também pode ser feito em um comando como git checkout -b pouet.
Greg Hewgill
4
'pouet' é o melhor nome do ramo para este exemplo.
Hussard
2

Ou git stash (se houver alterações) no ramo em que está, checkout master, obtenha as alterações mais recentes, pegue esse arquivo na área de trabalho (ou no aplicativo inteiro). Faça o checkout da filial em que você estava. O Git stash aplica-se novamente ao estado em que você estava e, em seguida, corrija as alterações manualmente ou arraste-o substituindo o arquivo.

Dessa forma, não é tããããããão legal, mas funcionará se vocês não puderem descobrir mais nada.

jahrichie
fonte
-10

Eu acho que encontrei um truque fácil.

Exclua o arquivo que você possui no repositório local (o arquivo que você deseja atualizar a partir da confirmação mais recente no servidor remoto)

E então faça um git pull

Como o arquivo foi excluído, não haverá conflito

Viswadeep Sarangi
fonte
Isso remove todas as eventuais alterações feitas nesse arquivo localmente e também extrai todos os outros arquivos, que é especificamente o que o OP não deseja fazer.
Legrjan 17/11
Em vez de atualizar a filial remota, remover a ideia local é uma péssima idéia.
C0der512