Git: affiche toutes les différentes modifications apportées à une seule ligne dans un fichier spécifié sur l'ensemble de l'historique de git

112

J'ai regardé autour de moi et je ne suis pas sûr que cela soit possible, mais voici:

J'ai un fichier (javascript) (disons /lib/client.js) dans lequel j'ai un identifiant unique attribué à une variable, comme ceci: var identifier = "SOME_IDENTIFIER";

Vous pouvez considérer l'identifiant comme un numéro de version: périodiquement, nous changerons cette variable en un nouvel identifiant.

Ce que j'aimerais faire, c'est trouver tous les identifiants uniques que nous avons jamais utilisés. Comment puis-je faire cela avec git?

J'imagine qu'il pourrait y avoir un moyen de rechercher dans l'historique git et d'imprimer la ligne correspondante "var identifier =". Je pourrais déduper cette liste manuellement.

Quoi qu'il en soit, j'apprécierais tout aperçu ici. Merci.

trouverchris
la source

Réponses:

106

Depuis git 1.8.4 , il existe un moyen plus direct de répondre à votre question.

En supposant que cette ligne 110est la ligne disant var identifier = "SOME_IDENTIFIER";, alors faites ceci:

git log -L110,110:/lib/client.js

Cela retournera chaque commit qui a touché cette ligne de code.

[ Documentation Git (voir le paramètre de ligne de commande "-L")]

Alexander Bird
la source
49

Consultez la page de manuel pour git-loget gitdiffcore. Je pense que cette commande le ferait, mais ce n'est peut-être pas tout à fait correct:

git log -G "var identifier =" file.js

EDIT: Voici un début approximatif pour un script bash pour afficher les lignes réelles. C'est peut-être plus ce que vous recherchez.

for c in $(git log -G "something" --format=%H -- file.js); do
    git --no-pager grep -e "something" $c -- file.js
done

Il utilise git log -Gpour trouver les commits intéressants, en utilisant --format=%Hpour produire une liste de hachages de commit. Il itère ensuite sur chaque commit intéressant, demandant git grepd'afficher les lignes de ce commit et du fichier qui contiennent l'expression régulière, précédés du hachage de commit.


EDIT: changé pour utiliser -Gau lieu de -Scomme suggéré dans les commentaires.

Rob
la source
@Rob - merci pour cela - petite modification de votre script cependant - ne mettre que le nom de fichier montre uniquement les commits qui affectent uniquement ce fichier - si un commit fait référence à d'autres fichiers, il n'est pas répertorié
Adrian Cornish
@AdrianCornish - Heureux que cela ait été utile. Je pense que l'OP voulait simplement regarder un fichier, mais vous avez tout à fait raison de dire que la suppression du nom de fichier est probablement un script plus généralement utile.
rob
J'ai une situation plus difficile. Le fichier en question a été déplacé de paht_a / file vers path_b / file. Maintenant, quand je le fais dans path_b, cela ne montre que les changements jusqu'au moment où le fichier passe de path_a à path_b. Si je le fais dans path_a, cela me dit fatal: argument ambigu 'file': révision inconnue ou chemin non dans l'arbre de travail.
Andy Song
@AndySong - Si la chaîne que vous recherchez est suffisamment unique, vous pouvez peut-être simplement supprimer le nom du fichier et obtenir ce que vous recherchez.
rob
Était plus pratique pour moi - placez une ligne vide après chaque commit, sfile=path/to/some_file; sfind='string_to_find'; for c in $(git log -G $sfind --format=%H -- $sfile); do git --no-pager grep -e $sfind -n $c -- $sfile; echo; done
énumérez les
14

Vous pouvez également le faire avec gitk:

gitk file.js

Dans la liste déroulante «commit», choisissez «ajouter / supprimer une chaîne:» et dans la zone de texte à côté, entrez «var identifier =», et tous les commits qui ajoutent ou suppriment des lignes contenant cette chaîne seront mis en surbrillance.

Ethan Brown
la source
Cela a aidé à identifier le commit auquel la ligne contenant "var identifier =" a été ajoutée, mais il n'affiche pas les commits suivants qui ont modifié cette ligne.
findchris
2
Avez-vous essayé git blame file.jsou git gui blame file.js?
Ethan Brown
1
Je sais ce que fait git blame; Je recherche un historique complet des révisions, pas un seul diff.
findchris
1
git gui blame file.jsfera cela ... il vous montrera toutes les révisions d'un fichier et qui l'a changé; vous pouvez simplement cliquer en arrière dans l'historique.
Ethan Brown
J'ai fini par avancer visuellement avec gitk. J'imagine qu'il existe une technique git élégante pour faire cela, mais gitk était assez bon. Merci.
findchris
9

Si vous adaptez un peu la réponse de @ rob, le git logfera essentiellement pour vous, si tout ce dont vous avez besoin est une comparaison visuelle:

git log -U0 -S "var identifier =" path/to/file

-U0signifie sortie en mode patch ( -p), et affiche zéro ligne de contexte autour du patch.

Vous pouvez même faire cela entre les succursales:

git log -U0 -S "var identifier =" branchname1 branchname2 -- path/to/file

Il peut y avoir un moyen de supprimer l'en-tête de diff, mais je n'en connais pas.

Andrew
la source
A travaillé pour moi! Merci.
Roberto Bonini
3

Dans magit , vous pouvez le faire avec

l, =L

Il vous demandera ensuite le fichier et les lignes de début et de fin.

bidonvilles
la source