web-dev-qa-db-fra.com

fichier renommé git diff

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?

95
Ken Hirakawa

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.

103
CB Bailey

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

71
Nolan Amy

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

22
benkc

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
1
Mr-IDE