Git ne stocke pas les modifications de nom de fichier.
Chaque commettras stocke un arbre complet, par exemple, peut-être commettre 1234567...
a des fichiers README
et foo.txt
et engager fedcba9 ... a des fichiers readme.txt
et foo
. Si vous demandez à git de comparer commettre 1234567
pour commettre fedcba9
, et README
est suffisamment similaire à readme.txt
, git dira que le moyen de transformer l'un commit à l'autre est de renommer le fichier. (Si l'un commit est le parent de l'autre, git show
de l'enfant engager montrera le changement de nom, parce que git show
calcule ce changement à git show
temps.)
D'autre part, si le second fichier readme
est trop différent, mais README
est suffisamment similaire à foo
, git dira que le moyen de changer 1234567
pour atteindre fedcba9
est de renommer README
en foo
.
La clé est que git calcule que lorsque vous demandez la comparaison, et pas un instant plus tôt. Il n'y a rien entre les commits qui dit "renommer certains fichiers". Git compare simplement les commits et décide puis si les fichiers sont assez similaires. Pour vos besoins, ce que cela signifie en fin de compte, c'est que pour chaque commit de votre séquence-de-commits-à-copier-ou-partiellement-copier, vous devrez décider quels noms de chemins conserver et lesquels ignorer . Comment atteindre cela est principalement à vous. La commande git log
a un indicateur --follow
pour activer une quantité limitée de détection de renommer car il fonctionne en arrière depuis les validations enfants vers leurs parents, et git blame
essaie automatiquement de faire la même chose; vous pouvez utiliser ces (un nom de chemin à la fois) pour arriver à une cartographie de la forme:
in: commits A..B C..D E..F
use path: dir/file.ext dir/frill.txt lib/frill.next
par exemple. Mais il n'y a rien de construit pour le faire, et ce ne sera pas particulièrement facile. Je commencerais par combiner git log --follow
avec --raw
ou --name-status
sortie et de voir si il y a des Renommées intéressantes détectées.Si et quand il y en a, ce sont les limites de validation auxquelles vous voudrez changer les chemins que vous gardez et abandonner pendant que vous travaillez à travers les commits (que ce soit avec filter-branch
ou une autre méthode).
Si cela ne fonctionne pas ou si vous avez besoin de plus de contrôle, pensez à exécuter git diff --name-status
entre différentes paires de validation (avec les informations de paire de validation provenant de git rev-list
).
Tant que vous avez demandé pour la détection de changement de nom, « exactement le même » est assez similaire, comme quelque chose à environ « 50% similaires ». Vous pouvez ajuster la similarité requise avec la valeur optionnelle que vous fournissez au drapeau -M
de git diff
.
Modifier: cela semble fonctionner OK. Je l'ai utilisé sur son propre builtin/var.c
git, qui l'habitude d'avoir deux noms précédents selon cette:
$ git log --follow --raw --diff-filter=R --pretty=format:%H builtin/var.c
81b50f3ce40bfdd66e5d967bf82be001039a9a98
:100644 100644 2280518... 2280518... R100 builtin-var.c builtin/var.c
55b6745d633b9501576eb02183da0b0fb1cee964
:100644 100644 d9892f8... 2280518... R096 var.c builtin-var.c
Le --diff-filter
supprime tout sauf renomme sorties de sorte que nous pouvons voir ce qui semble engager de renommer le fichier. Transformer cela en quelque chose de plus utile nécessite un peu plus de travail, mais cela pourrait vous arriver assez loin:
git log --follow --raw --diff-filter=R --pretty=format:%H builtin/var.c |
while true; do
if ! read hash; then break; fi
IFS=$'\t' read mode_etc oldname newname
read blankline
echo in $hash, rename $oldname to $newname
done
qui produit:
in 81b50f3ce40bfdd66e5d967bf82be001039a9a98, rename builtin-var.c to builtin/var.c
in 55b6745d633b9501576eb02183da0b0fb1cee964, rename var.c to builtin-var.c
Pouvez-vous fournir un script pour la liste des noms de fichiers précédents? Je ne peux pas comprendre comment le faire, et j'ai des centaines de fichiers à traiter, donc je ne peux pas analyser manuellement les fichiers journaux à la fois. Par défaut 50% similaire est très bien pour moi. –
Grâce à vous, j'ai récupéré la liste des anciens noms de fichiers avec 'git ls-files | tandis que read -r line; do (git log --follow --raw --diff-filtre = R --pretty = format:% H "$ ligne" | while true; fait si! read hash; alors break; fi; IFS = $ '\ t 'read mode_etc oldname nouveau nom; read blankline; echo $ oldname; done); fait –