Git blame - commits antérieurs?

391

Est-il possible de voir qui a édité une ligne spécifique avant le commit signalé par git blame, comme un historique des commits pour une ligne donnée?

Par exemple, je lance ce qui suit (sur le superbe uncrustifyprojet):

$ git blame -L10,+1 src/options.cpp
^fe25b6d (Ben Gardner 2009-10-17 13:13:55 -0500 10) #include "prototypes.h"

Comment savoir qui a édité cette ligne avant de valider fe25b6d? Et qui l'a édité avant ce commit?

Sedate Alien
la source
7
si la raison pour laquelle vous recherchez des validations précédentes sont des changements d'espaces, utilisez l' -woption. Il y a aussi -Mpour le code déplacé / copié
brita_
Pour rechercher tous les commits qui impliquent un mot donné, voir mon script ci
VonC
Voici un script utile pour ajouter cette fonctionnalité sur github greasyfork.org/en/scripts/…
Aaron Hoffman
3
Je ne sais pas à quoi ressemblait github lorsque @AaronHoffman a posté, mais il est beaucoup plus facile de blâmer - et d'obtenir des reproches pour les versions précédentes - dans github maintenant .
ruffin

Réponses:

389
git blame -L 10,+1 fe25b6d^ -- src/options.cpp

Vous pouvez spécifier une révision pour git blame à partir de (au lieu de la valeur par défaut de HEAD); fe25b6d^est le parent de fe25b6d.

ambre
la source
107
Pouvez-vous obtenir un historique complet, sans avoir à ressaisir la commande plusieurs fois avec des hachages différents?
Anders Zommarin
13
Je ne pense pas que Git dispose d'un moyen intégré pour obtenir chaque blâme qui a touché un numéro de ligne (ce qui est logique, car une ligne donnée peut ne pas avoir de numéro de ligne cohérent tout au long de l'historique d'un fichier en raison d'insertions et de suppressions. de lignes).
Amber
17
@Amber: Je suis presque sûr que vous avez raison que la fonctionnalité n'existe pas, mais il semble qu'elle pourrait être implémentée naïvement, simplement en faisant ce qu'un humain ferait: blâmer une fois, saisir les informations signalées, blâmer que , etc.
Cascabel
15
git gui facilite la vérification de l'historique d'une ligne car les versions sont cliquables.
Zitrax
5
@shadyabhi --est couramment utilisé comme séparateur dans les arguments de ligne de commande - dans le cas de Git, il est généralement utilisé pour séparer des éléments comme la validation des hachages d'une liste de noms de fichiers.
Amber
192

Vous pouvez utiliser git log -L pour visualiser l'évolution d'une gamme de lignes.

Par exemple :

git log -L 15,23:filename.txt

signifie "suivre l'évolution des lignes 15 à 23 dans le fichier nommé filename.txt".

Navneet
la source
12
Ceci est une réponse solide et répond à la question d'Anders Zommarin ci-dessus sur la façon de voir les modifications de lignes spécifiques au fil du temps.
bigtex777
4
Pour info: git log -L <start>, <end>: <file> nécessite Git 1.8.4+ voir: git-scm.com/docs/git-log#git-log--Lltstartgtltendgtltfilegt pour les options de syntaxe
néon
30

La réponse d'Amber est correcte mais je l'ai trouvée peu claire; La syntaxe est:

git blame {commit_id} -- {path/to/file}

Remarque: le --est utilisé pour séparer l'arborescence is1 sha1 des chemins de fichiers relatifs. 1

Par exemple:

git blame master -- index.html

Nous remercions Amber pour tout savoir! :)

ThorSummoner
la source
1
Je suis d'accord avec ton sentiment. Le système de commentaires est cependant trop restreint pour présenter clairement toutes les informations. J'ai ajouté le contenu de cette réponse dans un commentaire; cependant, j'insiste pour laisser cette réponse est un endroit pour la facilité d'accès.
ThorSummoner
1
Il doit s'agir d'un article séparé ou d'une modification. Je l'aime comme une réponse distincte.
Flimm
27

Vous voudrez peut-être vérifier:

git gui blame <filename>

Vous donne un bel affichage graphique des changements comme "git blame" mais avec des liens cliquables par ligne, pour passer aux commits précédents. Passez la souris sur les liens pour obtenir une fenêtre contextuelle avec les détails de validation. Pas mes crédits ... je l'ai trouvé ici:

http://zsoltfabok.com/blog/2012/02/git-blame-line-history/

git guiest une interface graphique Tcl / Tc pour git. Sans aucun autre paramètre, il démarre une application graphique assez simple mais utile pour valider des fichiers, des morceaux ou même des lignes simples et d'autres commandes similaires comme modifier, rétablir, pousser ... Cela fait partie de la suite de stock git. Sur Windows, il est inclus dans le programme d'installation. Sur debian - je ne connais pas les autres systèmes * nix - il doit être installé séparément:

apt-get install git-gui

De la documentation:

https://git-scm.com/docs/git-gui

LA DESCRIPTION

Une interface utilisateur graphique basée sur Tcl / Tk pour Git. git gui se concentre sur la possibilité pour les utilisateurs d'apporter des modifications à leur référentiel en effectuant de nouvelles validations, en modifiant celles existantes, en créant des branches, en effectuant des fusions locales et en récupérant / poussant vers des référentiels distants.

Contrairement à gitk, git gui se concentre sur la génération de commit et l'annotation de fichier unique et n'affiche pas l'historique du projet. Il fournit cependant des actions de menu pour démarrer une session gitk depuis git gui.

git gui est connu pour fonctionner sur tous les systèmes UNIX courants, Mac OS X et Windows (sous Cygwin et MSYS). Dans la mesure du possible, les directives d'interface utilisateur spécifiques au système d'exploitation sont suivies, ce qui fait de git gui une interface assez native pour les utilisateurs.

COMMANDES

faire des reproches

Démarrez une visionneuse de blâme sur le fichier spécifié sur la version donnée (ou le répertoire de travail s'il n'est pas spécifié).

navigateur

Démarrez un navigateur arborescent affichant tous les fichiers de la validation spécifiée. Les fichiers sélectionnés via le navigateur sont ouverts dans la visionneuse de blâme.

citool

Lancez git gui et organisez exactement un commit avant de quitter et de retourner au shell. L'interface se limite à ne valider que des actions, ce qui réduit légèrement le temps de démarrage de l'application et simplifie la barre de menus.

version

Affiche la version en cours d'exécution de git gui.

Holger Böhnke
la source
Ça ne marche pas pour moi. Je peux cliquer sur la modification sur la ligne donnée, mais cela modifie simplement la vue pour ce commit, et la ligne actuelle s'affiche maintenant comme suit this: mais comment voir la version précédente de la ligne et quand elle a été ajoutée?
BeeOnRope
C'est le seul cas d'utilisation que je connaisse où git gui est la meilleure solution
cambunctious
17

En s'appuyant sur la réponse précédente, ce bash one-liner devrait vous donner ce que vous recherchez. Il affiche l'historique de blâme de git pour une ligne particulière d'un fichier particulier, à travers les 5 dernières révisions:

LINE=10 FILE=src/options.cpp REVS=5; for commit in $(git rev-list -n $REVS HEAD $FILE); do git blame -n -L$LINE,+1 $commit -- $FILE; done

Dans la sortie de cette commande, vous pouvez voir le contenu de la ligne changer, ou le numéro de ligne affiché peut même changer, pour une validation particulière.

Cela indique souvent que la ligne a été ajoutée pour la première fois, après ce commit particulier. Cela pourrait également indiquer que la ligne a été déplacée d'une autre partie du fichier.

Will Sheppard
la source
5
Notez qu'il s'agit des dernières révisions $ REVS dans lesquelles $ FILE a changé, plutôt que des dernières révisions $ REVS dans lesquelles $ LINE a changé.
Max Nanasy
De quelle réponse parlez-vous?
Flimm
Je ne m'en souviens plus. J'aurais peut-être pu mieux préparer ma réponse à l'avenir.
Will Sheppard
12

Il y en a aussi recursive-blame. Il peut être installé avec

npm install -g recursive-blame
Thomas W
la source
11

Une solution très unique à ce problème consiste à utiliser git log:

git log -p -M --suivre --stat - chemin / vers / votre / fichier

Comme expliqué par Andre ici

Mannu
la source
1
J'ai créé un alias pour l'utiliser: git config --global alias.changes 'log -p -M --follow --stat --'puis je peux simplement tapergit changes path/to/your/file
Tizio Fittizio
C'est de loin la meilleure réponse et c'est exactement ce que je cherchais. Simple et élégant.
maesk
10

Si vous utilisez JetBrains Idea IDE (et dérivés), vous pouvez sélectionner plusieurs lignes, faites un clic droit pour le menu contextuel, puis Git -> Afficher l'historique pour la sélection. Vous verrez la liste des validations qui affectaient les lignes sélectionnées:

entrez la description de l'image ici

warvariuc
la source
Cela a fonctionné mieux que les autres réponses pour moi (en utilisant IntelliJ). Il a fallu un certain temps pour charger toutes les révisions mais cela valait la peine d'attendre.
Steve Chambers
2

Depuis Git 2.23, vous pouvez utiliser git blame --ignore-rev

Pour l'exemple donné dans la question, ce serait:

git blame -L10,+1 src/options.cpp --ignore-rev fe25b6d

(mais c'est une question piège car fe25b6d est la première révision du fichier!)

Michael Platings
la source
1

S'appuyant sur la réponse de Will Shepard, sa sortie comprendra des lignes en double pour les validations où il n'y a eu aucun changement, vous pouvez donc les filtrer comme suit (en utilisant cette réponse )

LINE=1 FILE=a; for commit in $(git rev-list HEAD $FILE); do git blame -n -L$LINE,+1 $commit -- $FILE; done | sed '$!N; /^\(.*\)\n\1$/!P; D'

Notez que j'ai supprimé l'argument REVS et cela revient à la validation racine. Cela est dû à l'observation de Max Nanasy ci-dessus.

DavidN
la source
1

En s'appuyant sur la réponse de DavidN et je veux suivre le fichier renommé:

LINE=8 FILE=Info.plist; for commit in $(git log --format='%h%%' --name-only --follow -- $FILE | xargs echo | perl -pe 's/\%\s/,/g'); do hash=$(echo $commit | cut -f1 -d ','); fileMayRenamed=$(echo $commit | cut -f2 -d ','); git blame -n -L$LINE,+1 $hash -- $fileMayRenamed; done | sed '$!N; /^\(.*\)\n\1$/!P; D'

ref: affiche bien l'historique des renommages de fichiers dans le journal git

Bill Chan
la source
0

J'utilise ce petit script bash pour regarder une histoire de blâme.

Premier paramètre: fichier à regarder

Paramètres suivants: transmis au blâme

#!/bin/bash
f=$1
shift
{ git log --pretty=format:%H -- "$f"; echo; } | {
  while read hash; do
    echo "--- $hash"
    git blame $@ $hash -- "$f" | sed 's/^/  /'
  done
}

Vous pouvez fournir des paramètres de blâme comme -L 70, + 10, mais il est préférable d'utiliser la recherche regex de git blame car les numéros de ligne "changent" généralement avec le temps.

paille
la source
0

S'appuyant sur la réponse de Stangls , j'ai mis ce script dans mon CHEMIN (même sous Windows) en tant que git-bh:

Cela me permet de rechercher tous les commits où un mot était impliqué:

git bh path/to/myfile myWord

Scénario:

#!/bin/bash
f=$1
shift
csha=""
{ git log --pretty=format:%H -- "$f"; echo; } | {
  while read hash; do
    res=$(git blame -L"/$1/",+1 $hash -- "$f" 2>/dev/null | sed 's/^/  /')
    sha=${res%% (*}
    if [[ "${res}" != "" && "${csha}" != "${sha}" ]]; then
      echo "--- ${hash}"
      echo "${res}"
      csha="${sha}"
    fi
  done
}
VonC
la source