1033 votes

Comment récupérer un fichier unique à partir d'une révision spécifique dans Git ?

J'ai un dépôt Git et j'aimerais voir à quoi ressemblaient certains fichiers il y a quelques mois. J'ai trouvé la révision à cette date ; c'est 27cf8e84bb88e24ae4b4b3df2b77aab91a3735d8 . J'ai besoin de voir à quoi ressemble un fichier, et de l'enregistrer comme un ("nouveau") fichier.

J'ai réussi à voir le fichier en utilisant gitk mais il n'y a pas d'option pour l'enregistrer. J'ai essayé avec des outils en ligne de commande, le plus proche que j'ai obtenu était :

git-show 27cf8e84bb88e24ae4b4b3df2b77aab91a3735d8 my_file.txt

Cependant, cette commande affiche un diff, et non le contenu du fichier. Je sais que je peux utiliser ultérieurement quelque chose comme PAGER=cat et rediriger la sortie vers un fichier, mais je ne sais pas comment accéder au contenu réel du fichier.

En gros, je cherche quelque chose comme chat svn .

102 votes

La clé ici : git show utilise (de manière peu utile) une syntaxe différente avec un deux-points. git show 2c7cf:my_file.txt

4 votes

Pour clarifier davantage, la commande ci-dessus demande à git d'afficher deux objets distincts, une révision et un fichier. La réponse acceptée ci-dessous, qui utilise un deux-points entre les deux objets, demande un fichier spécifique à une révision spécifique.

2 votes

Sur *nix, vous n'avez pas besoin de PAGER, il suffit de rediriger la sortie du shell avec >

971voto

VonC Points 414372

Utilisation de git show

Pour compléter votre propre réponse, la syntaxe est en effet

git show object
git show $REV:$FILE
git show somebranch:from/the/root/myfile.txt
git show HEAD^^^:test/test.py

La commande prend le style habituel de révision, ce qui signifie que vous pouvez utiliser n'importe lequel des éléments suivants :

  1. le nom de la branche (comme Proposition de par cendres )
  2. HEAD + x nombre de ^ caractères
  3. Le hachage SHA1 d'une révision donnée
  4. Les quelques premiers caractères (peut-être 5) d'un hachage SHA1 donné

Conseil Il est important de se rappeler que lorsque vous utilisez " git show ", Toujours spécifier un chemin à partir de la racine du référentiel. et non la position actuelle de votre répertoire.

(Bien que Mike Morearty mentionne que, au moins avec git 1.7.5.4, vous pouvez spécifier un chemin relatif en mettant " ./ "au début du chemin. Par exemple :

git show HEAD^^:./test.py

)

Utilisation de git restore

Avec Git 2.23+ (août 2019), vous pouvez également utiliser git restore qui remplace la confusion git checkout commande

git restore -s <SHA1>     -- afile
git restore -s somebranch -- afile

Cela permettrait de restaurer sur l'arbre de travail uniquement le fichier tel qu'il est présent dans le fichier "source" ( -s ) commit SHA1 ou branch somebranch .
Pour restaurer également l'index :

git restore -s <SHA1> -SW -- afile

( -SW : abréviation de --staged --worktree )


Comme indiqué dans les commentaires par starwarswii

Il vous permet de placer le contenu dans un fichier, ce qui est idéal si vous voulez simplement comparer rapidement les fichiers d'un commit.

Par exemple, vous pouvez le faire :

git show 1234:path/to/file.txt > new.txt 
git show 1234~:path/to/file.txt > old.txt

puis les comparer.


Utilisation des commandes de bas niveau de git plumbing

Avant git1.5.x, ceci était fait avec un peu de plomberie :

git ls-tree <rev>
afficher une liste d'un ou plusieurs objets 'blob' dans un commit

git cat-file blob <file-SHA1>
cat un fichier tel qu'il a été livré dans une révision spécifique (similaire à svn cat). utiliser git ls-tree pour récupérer la valeur d'un fichier-sha1 donné

git cat-file -p $(git-ls-tree $REV $file | cut -d " " -f 3 | cut -f 1)::

git-ls-tree liste l'ID de l'objet pour $file en révision $REV ce qui est coupé de la sortie et utilisé comme un argument à git-cat-file qui devrait en fait s'appeler git-cat-object et jette simplement cet objet dans stdout .


Remarque : depuis Git 2.11 (Q4 2016), vous pouvez appliquer un filtre de contenu à l' git cat-file sortie.

Voir commettre 3214594 , commit 7bcf341 (09 Sep 2016), commit 7bcf341 (09 Sep 2016), et commettre b9e62f6 , commettre 16dcc29 (24 août 2016) par Johannes Schindelin ( dscho ) .
(fusionné par Junio C Hamano -- gitster -- en commettre 7889ed2 , 21 Sep 2016)

git config diff.txt.textconv "tr A-Za-z N-ZA-Mn-za-m <"
git cat-file --textconv --batch

Note : " git cat-file --textconv " a commencé à se mettre en défaut récemment (2017), ce qui a été corrigé dans Git 2.15 (Q4 2017).

Véase commettre cc0ea7c (21 Sep 2017) par Jeff King ( peff ) .
(fusionné par Junio C Hamano -- gitster -- en commettre bfbc2fc , 28 Sep 2017)

0 votes

Comment sauvegarder ce qui est retourné par git show ? Je veux essentiellement faire un "save as" dessus au lieu d'écraser mon fichier local non validé.

8 votes

@Oscar depuis git show vidant essentiellement le contenu sur le stdout (sortie standard), vous pouvez simplement rediriger cette sortie vers le fichier de votre choix ( tldp.org/LDP/abs/html/io-redirection.html ).

0 votes

N'y a-t-il pas un moyen sans redirection ?

549voto

c-a Points 1639

Si vous souhaitez remplacer/supprimer le contenu d'un fichier dans votre branche actuelle avec le contenu du fichier d'un commit précédent ou d'une branche différente, vous pouvez le faire avec ces commandes :

git checkout 08618129e66127921fbfcbc205a06153c92622fe path/to/file.txt

o

git checkout mybranchname path/to/file.txt

Vous devrez ensuite valider ces changements pour qu'ils soient effectifs dans la branche actuelle.

5 votes

La solution la plus simple et c'est pour cela que git-checkout a été conçu - spécifier le nom du chemin signifie que seul le fichier correspondant est extrait. Extrait de la page de manuel de git-checkout : git checkout master~2 Makefile

1 votes

Alors, comment revenir à l'état précédent avant d'exécuter cette commande ?

0 votes

@Flint si vous venez de l'état HEAD, ce serait aussi simple que git checkout HEAD -- [chemin complet].

165voto

Milan Babuškov Points 20423

Vous devez fournir le chemin d'accès complet au fichier :

git show 27cf8e84bb88e24ae4b4b3df2b77aab91a3735d8:full/repo/path/to/my_file.txt

10 votes

N'a pas besoin d'être un chemin complet. Chemin depuis le répertoire racine de git (ceux qui sont venus en git show --name-only est également suffisant

9 votes

Erm, le chemin complet depuis la racine du dépôt. Regardez mieux l'exemple que j'ai donné. Il n'y a pas de barre oblique avant "full".

8 votes

Pour info, si vous êtes dans un sous-répertoire, vous pouvez aussi utiliser ./nomdufichier.ext avec succès.

8voto

Mr_and_Mrs_D Points 4569

Et pour le vider joliment dans un fichier (sous Windows au moins) - Git Bash :

$ echo "`git show 60d8bdfc:src/services/LocationMonitor.java`" >> LM_60d8bdfc.java

En " Les guillemets sont nécessaires pour préserver les nouvelles lignes.

0 votes

Joli. +1. Bon ajout sur le git show syntaxe que je mentionne ci-dessus.

0 votes

@Mike : êtes-vous sous Windows ?

0 votes

git show 60d8bdfc:./src/services/LocationMonitor.java > LM_60d8bdfc.java fonctionne pour moi dans Ubuntu bash. Notez le ./ après :

5voto

Adrian Gunawan Points 1035

Cela vous aidera à obtenir tous les fichiers supprimés entre les commits sans spécifier le chemin, utile s'il y a beaucoup de fichiers supprimés.

git diff --name-only --diff-filter=D $commit~1 $commit | xargs git checkout $commit~1

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X