Comment différencier le même fichier entre deux validations différentes sur la même branche?


1144

Dans Git, comment comparer le même fichier entre deux validations différentes (non contiguës) sur la même branche (master par exemple)?

Je recherche une fonctionnalité de comparaison comme celle de Visual SourceSafe (VSS) ou Team Foundation Server (TFS).
Est-ce possible à Git?

Réponses:


1476

Depuis la git-diffpage de manuel:

git diff [--options] <commit> <commit> [--] [<path>...]

Par exemple, pour voir la différence pour un fichier "main.c" entre maintenant et deux validations, voici trois commandes équivalentes:

$ git diff HEAD^^ HEAD main.c
$ git diff HEAD^^..HEAD -- main.c
$ git diff HEAD~2 HEAD -- main.c

43
Ce ..n'est pas vraiment nécessaire, bien que cela fonctionne avec (sauf dans les versions assez anciennes, peut-être). Vous pouvez également utiliser git logou gitkpour trouver des SHA1 à utiliser, si les deux validations sont très éloignées. gitka également un "diff sélectionné -> ce" et "diff ce -> sélectionné" dans son menu contextuel.
Cascabel

17
Est-ce que cela fonctionnera même si le nom du fichier a été modifié entre les 2 validations?
reubenjohn

26
Alors, quel est le but du "-"
user64141

29
@ user64141 Le --est utile, par exemple lorsque vous avez un fichier nommé -p. Bon à utiliser dans les scripts, seulement dans de rares cas nécessaires dans la pratique.
Palec

13
Remarque: vous devez utiliser des chemins relatifs à la racine du référentiel. Les chemins relatifs au répertoire de travail actuel ne fonctionneront pas.
Kevin Wheeler

281

Vous pouvez également comparer deux fichiers différents dans deux révisions différentes, comme ceci:

git diff <revision_1>:<file_1> <revision_2>:<file_2>


25
notez qu'il semble que si <file_1>et se <file_2>trouvent dans le répertoire courant, et non dans le répertoire git de niveau supérieur, il faut ajouter un préfixe ./sur Unix:<revision_1>:./filename_1
Andre Holzner

7
<révision>: peut être omis, vous pouvez donc faire la différence avec un fichier qui n'a pas encore été validé.
Yaroslav Nikitenko

2
Notez que sous Windows, il faut utiliser '/' pour les chemins de fichier, pas '\'.
np8

88

Si vous avez configuré le "difftool", vous pouvez utiliser

git difftool revision_1:file_1 revision_2:file_2

Exemple: comparaison d'un fichier de son dernier commit à son commit précédent sur la même branche: en supposant que si vous êtes dans le dossier racine de votre projet

$git difftool HEAD:src/main/java/com.xyz.test/MyApp.java HEAD^:src/main/java/com.xyz.test/MyApp.java

Vous devriez avoir les entrées suivantes dans votre fichier ~ / .gitconfig ou dans le fichier project / .git / config. Installez le p4merge [Ceci est mon outil de diff et de fusion préféré]

[merge]
    tool = p4merge
    keepBackup = false
[diff]
    tool = p4merge
    keepBackup = false
[difftool "p4merge"]
    path = C:/Program Files (x86)/Perforce/p4merge.exe
[mergetool]
    keepBackup = false
[difftool]
    keepBackup = false
[mergetool "p4merge"]
    path = C:/Program Files (x86)/Perforce/p4merge.exe
    cmd = p4merge.exe \"$BASE\" \"$LOCAL\" \"$REMOTE\" \"$MERGED\"

50

Vérifiez $ git log, copiez l' ID SHA-1 des deux validations différentes et exécutez la git diffcommande avec ces ID. par exemple:

$ git diff (sha-id-one) (sha-id-two)

18
Si vous voulez le diff pour un fichier spécifique, ajoutez le chemin d'accès à la fin de la commande.
hBrent

Faites également un "git pull" pour télécharger les informations complètes de l'arborescence si les deux validations sont à travers différentes branches. Sinon, vous obtiendrez une erreur "fatal: mauvais objet".
user238607

4
git diff (sha-id-one) (sha-id-two) -- filename.ext sans le nom de fichier, il répertoriera les différences de tous les fichiers de ces deux validations.
SherylHohman

40

Si vous souhaitez voir toutes les modifications apportées au fichier entre les deux validations sur une base de validation par validation, vous pouvez également effectuer

git log -u $start_commit..$end_commit -- path/to/file


Qu'est-ce que "$ start_commit" et "$ end_commit"? Sont-ils littéraux, ou sinon, pouvez-vous donner un exemple?
Peter Mortensen le

Ce sont des variables shell qui contiennent les révisions de début et de fin, qui peuvent à la place être des littéraux sha1 ou des références
cxreg

21

Voici un script Perl qui imprime les commandes Git diff pour un fichier donné comme dans une commande de journal Git.

Par exemple

git log pom.xml | perl gldiff.pl 3 pom.xml

Rendements:

git diff 5cc287:pom.xml e8e420:pom.xml
git diff 3aa914:pom.xml 7476e1:pom.xml
git diff 422bfd:pom.xml f92ad8:pom.xml

qui pourrait ensuite être coupé et collé dans une session de fenêtre shell ou redirigé vers /bin/sh.

Remarques:

  1. le nombre (3 dans ce cas) spécifie le nombre de lignes à imprimer
  2. le fichier (pom.xml dans ce cas) doit être d'accord aux deux endroits (vous pouvez l'envelopper dans une fonction shell pour fournir le même fichier aux deux endroits) ou le placer dans un répertoire binaire en tant que script shell

Code:

# gldiff.pl
use strict;

my $max  = shift;
my $file = shift;

die "not a number" unless $max =~ m/\d+/;
die "not a file"   unless -f $file;

my $count;
my @lines;

while (<>) {
    chomp;
    next unless s/^commit\s+(.*)//;
    my $commit = $1;
    push @lines, sprintf "%s:%s", substr($commit,0,6),$file;
    if (@lines == 2) {
        printf "git diff %s %s\n", @lines;
        @lines = ();
    }
    last if ++$count >= $max *2;
}

14

Si vous voulez faire un diff avec plus d'un fichier, avec la méthode spécifiée par @mipadi:

Par exemple, diff entre HEADet votre master, pour trouver tous les .coffeefichiers:

git diff master..HEAD -- `find your_search_folder/ -name '*.coffee'`

Cela recherchera récursivement your_search_folder/tous vos .coffeefichiers et fera une différence entre eux et leurs masterversions.


13

Si vous avez plusieurs fichiers ou répertoires et que vous souhaitez comparer les validations non continues, vous pouvez le faire:

Créer une branche temporaire ( "révision" dans cet exemple)

git checkout -b revision

Rembobiner vers la première cible de validation

git reset --hard <commit_target>

Cherry picking sur ceux qui s'engagent intéressés

git cherry-pick <commit_interested> ...

Appliquer diff

git diff <commit-target>^

Quand tu as fini

git branch -D revision

2
Merci pour cette solution. Cela a bien fonctionné pour mon cas d'utilisation. La seule chose que je mettrais à jour, c'est que lorsque vous avez terminé, vous ne pouvez pas supprimer la branche jusqu'à ce que vous la désactiviez.
Steven Dix

9

Juste une autre façon d'utiliser la génialité de Git ...

git difftool HEAD HEAD@{N} /PATH/FILE.ext

J'ai défini un alias à partir de cette réponse qui fonctionne avec bash:difftool-file = "!git difftool HEAD@{\"$2\"} HEAD \"$1\" #"
blueogive

2

Si vous voulez une comparaison visuelle simple sur Windows telle que vous pouvez l'obtenir dans Visual SourceSafe ou Team Foundation Server (TFS), essayez ceci:

  • faites un clic droit sur le fichier dans l'Explorateur de fichiers
  • sélectionnez 'Git History'

Remarque: Après la mise à niveau vers Windows 10, j'ai perdu les options du menu contextuel Git. Cependant, vous pouvez réaliser la même chose en utilisant 'gitk' ou 'gitk filename' dans une fenêtre de commande.

Une fois que vous appelez «Git History», l'outil Git GUI démarre, avec un historique du fichier dans le volet supérieur gauche. Sélectionnez l'une des versions que vous souhaitez comparer. Cliquez ensuite avec le bouton droit sur la deuxième version et choisissez soit

Diff this -> sélectionné

ou

Diff sélectionné -> ce

Des différences codées par couleur apparaîtront dans le volet inférieur gauche.


Note aux downvoters: il s'agit d'une solution simple, facile à mettre en œuvre et qui résout le problème du PO. Il fonctionne sur Windows que l'OP utilise clairement (voir les références à TFS et VSS dans la question).
Ressource du
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.