Existe-t-il une commande Git rapide pour voir une ancienne version d'un fichier?

1511

Existe-t-il une commande dans Git pour voir (soit vidée sur stdout, soit dans $PAGERou $EDITOR) une version particulière d'un fichier particulier?

Mike
la source
Si vous êtes venu à cette question parce que vous voulez vérifier une ancienne version d'un fichier binaire (par exemple une image), alors mieux vaut faire un checkout à l'ancien commit, voir ce que vous devez voir, puis revenir à la TÊTE. Pour cela, faites git checkout <sha1-of-the-commit-you-need>, après,git checkout HEAD
Homero Esmeraldo

Réponses:

1732

Vous pouvez utiliser git showavec un chemin depuis la racine du référentiel ( ./ou ../pour un cheminement relatif):

$ git show REVISION:path/to/file

Remplacez REVISIONpar votre révision réelle (peut être un SHA de validation Git, un nom de balise, un nom de branche, un nom de validation relatif ou toute autre manière d'identifier une validation dans Git)

Par exemple, pour afficher la version du fichier <repository-root>/src/main.cd'il y a 4 validations, utilisez:

$ git show HEAD~4:src/main.c

Git pour Windows nécessite des barres obliques, même dans les chemins relatifs au répertoire actuel. Pour plus d'informations, consultez la page de manuel de git-show.

mipadi
la source
5
Cela ne semble pas vraiment fonctionner - l'avez-vous essayé? Pour "git show HEAD: path / to / file.c", j'obtiens une erreur "argument ambigu".
Mike
2
Doit être le chemin complet, du haut du
référentiel
20
Si vous êtes sur Windows, il peut s'agir d'un séparateur de chemin; si je montre git HEAD: dir \ subdir \ file, j'obtiens l'argument ambigu. Si je montre git HEAD: dir / subdir / file, cela fonctionne comme prévu.
Matt McMinn
12
Le chemin que vous devez fournir après le: provient de la racine du référentiel git. (cela a été donné ci-dessous comme réponse mais je pense que c'était destiné à commenter cette réponse)
MatrixFrog
9
Si vous voulez le voir dans un split Vim afin qu'ils défilent ensemble, j'ai écrit un court article de blog montrant comment faire cela.
Flaviu
257

Faire ceci par date ressemble à ceci:

git show HEAD@{2013-02-25}:./fileInCurrentDirectory.txt

Notez que cela HEAD@{2013-02-25}signifie «où HEAD se trouvait le 25/02/2013» dans ce référentiel (à l' aide du reflog ), et non «le dernier commit avant le 25/02/2013 dans cette branche de l'historique».

Jim Hunziker
la source
5
Impressionnant. Économise beaucoup de temps au lieu d'aller sur github et de regarder le commit.
Fizer Khan du
Le "point" sur le chemin du fichier était mon problème. Merci!
tomascharad
5
Cette commande est utile avec masterau lieu de HEAD@{2013-02-25}, si vous êtes sur une branche
funroll
1
Pouvez-vous inclure l'heure, à la git log --since='2016-04-28 23:59:59 +0100'?
dumbledad
7
Le fait que cette syntaxe utilise le reflog est important et doit être mis en évidence fortement, car le reflog ne contient pas tous les commits . Voir blog.endpoint.com/2014/05/git-checkout-at-specific-date.html
Alice Heaton
113

Si vous aimez les interfaces graphiques, vous pouvez utiliser gitk:

  1. lancez gitk avec:

    gitk /path/to/file
    
  2. Choisissez la révision dans la partie supérieure de l'écran, par exemple par description ou par date. Par défaut, la partie inférieure de l'écran affiche le diff pour cette révision (correspondant au bouton radio "patch").

  3. Pour voir le fichier de la révision sélectionnée:

    • Cliquez sur le bouton radio "arborescence". Cela montrera la racine de l'arborescence de fichiers à cette révision.
    • Accédez à votre fichier.
Trausti Kristjansson
la source
7
Cela fonctionne également avec tig , qui est un visualiseur de repo de curses git.
Matthew G
1
@Paul Slocum: Peut-être parce que cette commande n'est pas une commande conventionnelle, pas la commande intégrée de git. Je pense que cette commande ne fonctionne que pour Windows.
Envil
Notez que cela ne semble fonctionner que si vous démarrez à partir de la racine de votre référentiel git.
Marc
Si vous voulez vérifier contre une certaine révision avec gitk vous pouvez aussi utiliser ce raccourci: gitk REVISION /path/to/file. Cela peut être utile lorsque vous souhaitez comparer une certaine version par exemple.
Christian.D
89

Vous pouvez également spécifier un commit hash(souvent aussi appelé commit ID) avec la git showcommande .


En un mot

git show <commitHash>:/path/to/file


Pas à pas

  1. Afficher le journal de toutes les modifications pour un fichier donné avec git log /path/to/file
  2. Dans la liste des changements montrés, il montre le commit hashtel que commit 06c98...(06c98 ... étant le hachage de validation)
  3. Copiez le commit hash
  4. Exécutez la commande en git show <commitHash>:/path/to/fileutilisant les commit hashétapes 3 et path/to/file1.

Remarque: l' ajout de ./lorsque vous spécifiez un chemin relatif semble important, c'est-à-dire git show b2f8be577166577c59b55e11cfff1404baf63a84:./flight-simulation/src/main/components/nav-horiz.html.

Adrien Be
la source
1
si vous ne connaissez pas le chemin du fichier, utilisez-le git show <SHA1> --name-onlypour l'obtenir.
Tiina
cette commande op - même auto se termine automatiquement depuis la mémoire - testée sur un répertoire supprimé ... ne peut pas obtenir plus d'opérations que celle gg
treyBake
43

En plus de la réponse de Jim Hunziker ,

vous pouvez exporter le fichier de la révision comme,

git show HEAD@{2013-02-25}:./fileInCurrentDirectory.txt > old_fileInCurrentDirectory.txt

J'espère que cela t'aides :)

Ijas Ameenudeen
la source
23

Pour voir rapidement les différences avec les anciennes révisions d'un fichier:

git show -1 filename.txt > comparer avec la dernière révision du fichier

git show -2 filename.txt > comparer avec l'avant-dernière révision

git show -3 fielname.txt > comparer avec le dernier 3ème dernière révision

sachin_ur
la source
18
Ces commandes montrent les différences avec la version actuelle pour moi mais ne montrent pas le fichier entier.
Jean Paul
18

git log -pvous montrera non seulement les journaux de validation, mais aussi les différences de chaque validation (à l'exception des validations de fusion). Ensuite, vous pouvez appuyer sur /, saisir le nom du fichier et appuyer sur enter. Appuyez sur nou ppour passer à l'occurrence suivante / précédente. De cette façon, vous verrez non seulement les modifications dans le fichier, mais également les informations de validation.

sanbor
la source
3
Il semble que les git log -pmcommits de fusion soient également affichés.
sanbor
2
Vous pouvez également exécuter git log -p -- filename.txtpour limiter l'historique uniquement au fichier souhaité.
Jean Paul
3

Vous pouvez utiliser un script comme celui-ci pour vider toutes les versions d'un fichier dans des fichiers séparés:

par exemple

git_dump_all_versions_of_a_file.sh path/to/somefile.txt

Obtenez le script ici comme réponse à une autre question similaire

Brad Parks
la source
1
git_root, git_log_shortEt git_log_message_for_commitsont portés disparus.
mogsie
Bonne prise! J'ai posté cette réponse à deux endroits différents, et j'ai juste supprimé celui-ci et lié à l'autre, où les gens m'en ont parlé avant ... merci @mogsie!
Brad Parks du
Ce script est très utile!
XMAN
3

VOIE 1: (Je préfère cette façon)

  1. Trouvez l' ID de validation avec:git reflog
  2. Lister les fichiers de commit git diff-tree --no-commit-id --name-only -r <commitHash>

exemple: git diff-tree --no-commit-id --name-only -r d2f9ba4// "d2f9ba4" est l'ID de validation de "1."

  1. Ouvrez le fichier nécessaire avec la commande:

git show <commitHash>:/path/to/file

exemple: git show d2f9ba4:Src/Ext/MoreSwiftUI/ListCustom.swift// "Src / ..." est le chemin du fichier de "2."

VOIE 2:

  1. Trouvez l' ID de validation avec:git reflog
  2. effectuer une réinitialisation matérielle de ce commit: git reset --hard %commit ID%

git reset --hard c14809fa

  1. apportez des modifications inutiles et effectuez un nouveau commit dans la branche nécessaire :)
Andrew
la source
0

Aide à récupérer plusieurs fichiers d'une révision donnée

Lorsque vous essayez de résoudre des conflits de fusion, cet assistant est très utile:

#!/usr/bin/env python3

import argparse
import os
import subprocess

parser = argparse.ArgumentParser()
parser.add_argument('revision')
parser.add_argument('files', nargs='+')
args = parser.parse_args()
toplevel = subprocess.check_output(['git', 'rev-parse', '--show-toplevel']).rstrip().decode()
for path in args.files:
    file_relative = os.path.relpath(os.path.abspath(path), toplevel)
    base, ext = os.path.splitext(path)
    new_path = base + '.old' + ext
    with open(new_path, 'w') as f:
        subprocess.call(['git', 'show', '{}:./{}'.format(args.revision, path)], stdout=f)

GitHub en amont .

Usage:

git-show-save other-branch file1.c path/to/file2.cpp

Résultat: les éléments suivants contiennent les versions alternatives des fichiers:

file1.old.c
path/to/file2.old.cpp

De cette façon, vous conservez l'extension de fichier pour que votre éditeur ne se plaint pas et puisse facilement trouver l'ancien fichier juste à côté du plus récent.

Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
la source
@MickeyPerlstein si vous pouvez faire réaliser la même interface avec une meilleure implémentation, je suis à l'écoute.
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
peut-être que je ne comprends pas (et si oui, mes excuses) mais n'est-ce pas juste: "git show version: ./ path> new_path"?
Mickey Perlstein
@MickeyPerlstein salut, oui, ma commande génère cette CLI, mais elle boucle sur plusieurs fichiers et produit un nom de sortie à partir de l'entrée, vous n'avez donc pas à taper trop. Rien de révolutionnaire bien sûr, mais pratique.
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功