Git: Comment mettre à jour / extraire un seul fichier du maître d'origine distant?

363

Le scénario:

  1. Je fais quelques changements dans un seul fichier localement et je l'exécute git add, git commitetgit push
  2. Le fichier est poussé vers le référentiel maître d'origine distant
  3. J'ai un autre référentiel local qui est déployé via Capistrano avec la méthode "remote_cache" de ce référentiel distant
  4. Maintenant, je ne veux pas déployer toute l'application, mais simplement mettre à jour / extraire ce fichier unique.

Est-ce possible avec git? Je n'ai pas pu trouver quoi que ce soit qui marcherait, ni le comprendre. Avec SVN je viens de le faire svn up fileet le tour est joué.

forêt
la source
19
Vous voudrez peut-être envisager de remplacer la réponse acceptée par celle qui répond réellement à votre question. ;)
étapes
6
Après plus de 6 ans, je crois que nous pouvons sans risque supposer que cela ne se produira pas @steps ...
Félix Gagnon-Grenier
Avec Git 2.23 (août 2019), ça l'est git restore -s origin/master -- path/to/file. Voir ma réponse ci-dessous .
VonC

Réponses:

916

Il est possible de le faire (dans le référentiel déployé)

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

L'extraction télécharge toutes les modifications récentes, mais ne les place pas dans votre code d'extraction actuel (zone de travail).

La caisse mettra à jour l'arborescence de travail avec le fichier particulier des modifications téléchargées ( origin/master).

Au moins, cela fonctionne pour moi pour ces petites petites corrections de faute de frappe, où il semble étrange de créer une branche, etc. juste pour changer un mot dans un fichier.

qzio
la source
1
Super pratique, cela a très bien fonctionné. J'avais besoin d'obtenir un fichier composer.json et d'exécuter une mise à jour avant de mettre à jour le reste du site en production. Si j'avais mis manuellement les fichiers composer.json / lock en place, lorsque j'effectuais un pull, cela entrerait en conflit en disant que les fichiers existaient déjà. En procédant ainsi, git a reconnu les fichiers sans se plaindre.
David
6
C'est la réponse que je cherchais.
javadba
20
@Mymozaaa Le double tiret indique que ce qui suit est un nom de fichier. C'est pour empêcher git d'interpréter votre nom de fichier comme une branche dans le cas malheureux où vous en avez deux avec le même nom.
Joel Mellon
Le problème est que vous êtes toujours en train de chercher, et si c'est un gros dépôt, ce sera l'opération coûteuse. Je crains que la seule alternative soit d'installer gitweb sur la télécommande puis d'y accéder pour récupérer le fichier ou autre.
Christian Goetze
petite question, après avoir fait cela, je vais sur une autre machine, puis je fais vos actions listées ci-dessus, mais ensuite git statusje les vois comme Changes to be committed:- ce qui signifie, je dois les commettre à nouveau? (juste en notant que je voulais rafraîchir un seul fichier intact, mais le dépôt lui-même est touché dans une machine différente)
Ricky Levi
43

Le code suivant a fonctionné pour moi:

     git fetch
     git checkout <branch from which file needs to be fetched> <filepath> 
Shagun Pruthi
la source
19
git archive --format=zip --remote=ssh://<user>@<host>/repos/<repo name> <tag or HEAD> <filename> > <output file name>.zip
Dmitry R
la source
1
Ceci est une bonne solution pour les dépôts clonés sur ssh, mais il semble que cela ne soit pas pris en charge sur https: git archive --remote=https://github.com/git/git.git master:git/contrib/completion git-completion.bash | tar -x me donne un message d'erreur:fatal: Operation not supported by protocol.
Alderath
1
était agréable combiné avec tar: s --to-stdout,git archive --remote="gitolite3@<host>:<repo>" <tag> <file> | tar xf - --to-stdout
Puggan Se
19

Avec Git 2.23 (août 2019) et la nouvelle commande (toujours expérimentale) git restore, vue dans " Comment réinitialiser tous les fichiers du répertoire de travail mais pas de la zone de transit? ", Ce serait:

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

L'idée est: git restorene traite que des fichiers, pas des fichiers et des branches comme le git checkoutfait.
Voir " Confus pargit checkout ": c'est là git switchqu'intervient)


codersam ajoute dans les commentaires :

dans mon cas, je voulais obtenir les données de mon amont (dont j'ai bifurqué).
Donc, juste changé en:

git restore -s upstream/master -- path/to/file
VonC
la source
2
Quel soulagement que cette commande existe enfin ... Que faisaient les gens authentiques avant? Je restaurais le tout et copiais les fichiers individuels dont j'avais besoin, mais c'était douloureux.
Mike Wise
Cela a fonctionné pour moi, mais dans mon cas, je voulais obtenir les données de mon amont (dont j'ai bifurqué). Donc, juste changé engit restore -s upstream/master -- path/to/file
coderSam
@coderSam Merci pour ces commentaires. J'ai inclus votre commentaire dans la réponse pour plus de visibilité.
VonC
8

Ce que vous pouvez faire, c'est:

  1. Mettez à jour votre dépôt git local:

    git fetch

  2. Créez une succursale locale et passez votre commande dessus:

    git branch pouet && git checkout pouet

  3. Appliquez le commit que vous souhaitez sur cette branche:

    git cherry-pick abcdefabcdef

    (abcdefabcdef est le sha1 du commit que vous souhaitez appliquer)

pointe
la source
4
Soit dit en passant, votre deuxième étape peut également être effectuée en une seule commande en tant que git checkout -b pouet.
Greg Hewgill
4
'pouet' est le meilleur nom de branche pour cet exemple.
Hussard
2

Ou git stash (si vous avez des modifications) sur la branche sur laquelle vous vous trouvez, checkout master, tirez pour les dernières modifications, saisissez ce fichier sur votre bureau (ou l'application entière). Vérifiez la succursale où vous étiez. Git stash s'applique à l'état dans lequel vous vous trouviez, puis corrigez les modifications manuellement ou faites-le glisser en remplaçant le fichier.

Cette façon n'est pas tellement cool mais ça marche si vous ne pouvez rien comprendre d'autre.

jahrichie
la source
-10

Je pense avoir trouvé un hack facile.

Supprimez le fichier que vous avez sur le référentiel local (le fichier que vous souhaitez mettre à jour à partir de la dernière validation sur le serveur distant)

Et puis faites un git pull

Parce que le fichier est supprimé, il n'y aura pas de conflit

Viswadeep Sarangi
la source
Cela supprime toutes les éventuelles modifications apportées à ce fichier localement, et extrait également tous les autres fichiers, ce qui est précisément ce que l'OP ne veut pas faire.
legrojan
Au lieu de mettre à jour la branche distante, la suppression du local est une très mauvaise idée.
c0der512