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é.


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.


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> 

19
git archive --format=zip --remote=ssh://<user>@<host>/repos/<repo name> <tag or HEAD> <filename> > <output file name>.zip

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

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)


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.


-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


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
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.