J'ai un fichier a.txt
.
cat a.txt
> hello
Le contenu de a.txt
est "bonjour".
Je m'engage.
git add a.txt
git commit -m "first commit"
Je déplace ensuite a.txt
dans un répertoire test
.
mkdir test
mv a.txt test
Je fais alors mon deuxième commit.
git add -A
git commit -m "second commit"
Enfin, je modifie a.txt
pour dire "au revoir" à la place.
cat a.txt
> goodbye
Je fais mon dernier engagement.
git add a.txt
git commit -m "final commit"
Maintenant voici ma question:
Comment différencier le contenu de a.txt
entre mon dernier commit et mon premier commit?
J'ai essayé: git diff HEAD^^..HEAD -M a.txt
, mais cela n'a pas fonctionné. git log --follow a.txt
détecte correctement le changement de nom, mais je ne trouve pas d'équivalent pour git diff
. Est-ce qu'il y a un?
Le problème avec la différence entre HEAD^^
et HEAD
est que vous avez un a.txt
dans les deux commits. Par conséquent, si vous tenez compte de ces deux commits (ce que fait diff), il n'y a pas de changement de nom, il y a une copie et une modification.
Pour détecter les copies, vous pouvez utiliser -C
:
git diff -C HEAD^^ HEAD
Résultat:
index ce01362..dd7e1c6 100644
--- a/a.txt
+++ b/a.txt
@@ -1 +1 @@
-hello
+goodbye
diff --git a/a.txt b/test/a.txt
similarity index 100%
copy from a.txt
copy to test/a.txt
Incidemment, si vous limitez votre diff à un seul chemin (comme dans git diff HEAD^^ HEAD a.txt
, vous ne verrez jamais les renommés ou les copies car vous avez tout exclu du chemin et les renommés ou les copies - par définition - impliquent deux chemins.
Pour différer en renommant un fichier spécifique, utilisez -M -- <old-path> <new-path>
(-C
fonctionne également).
Donc si vous avez renommé et tous les deux ont changé un fichier lors de la dernière validation, vous pouvez voir les modifications avec:
git diff HEAD^ HEAD -M -- a.txt test/a.txt
Cela produit:
diff --git a/a.txt b/test/a.txt
similarity index 55%
rename from a.txt
rename to test/a.txt
index 3f855b5..949dd15 100644
--- a/a.txt
+++ b/test/a.txt
@@ -1,3 +1,3 @@
// a.txt
-hello
+goodbye
(// a.txt
lignes ajoutées pour aider git à détecter le changement de nom)
Si git ne détecte pas le changement de nom, vous pouvez spécifier un seuil de similarité faible avec -M[=n]
, par exemple 1%:
git diff HEAD^ HEAD -M01 -- a.txt test/a.txt
À partir de les documents diff git :
-M [<n>] --find-renames [= <n>]
Détecter renomme. Si
n
est spécifié, il s’agit d’un seuil de l’indice de similarité (c’est-à-dire le nombre d’additions/suppressions .__ par rapport à la taille du fichier). Par exemple,-M90%
signifie que Git devrait considérer qu'une paire supprimer/ajouter est un changement de nom si plus de 90% du fichier n'a pas changé. Sans le signe%
, le numéro doit être lu comme un fraction, avec un point décimal avant. C'est-à-dire,-M5
devient 0.5, et est donc identique à-M50%
. De même,-M05
est identique à-M5%
. À Limitez la détection à un renommage exact, utilisez-M100%
. La similarité par défaut l'indice est 50%.
Vous pouvez aussi faire:
git diff rev1:file1 rev2:file2
qui, pour votre exemple, serait
git diff HEAD^^:./a.txt HEAD:./test/a.txt
Notez le ./
explicite - ce format suppose par ailleurs que les chemins soient relatifs à la racine du référentiel. (Si vous êtes à la racine du repo, vous pouvez bien sûr l'omettre.)
Cela ne dépend pas du tout de la détection de renommage, car l'utilisateur indique explicitement exactement ce qu'il faut comparer. (Par conséquent, il est également utile dans certaines circonstances, telles que la comparaison de fichiers entre différentes branches svn dans un environnement git-svn.)
Si votre engagement de renommer est effectué mais n'est pas encore validé, vous pouvez utiliser:
git diff --cached -M -- file.txt renamed_file.txt