Culpa de Git – compromisos previos?

Me encanta el command de git blame , es muy útil para rastrear a personas que no son dueñas de escribir código. 🙂

Sin embargo, ¿es posible ver quién editó una línea específica antes de la confirmación reportada por git blame , por ejemplo, un historial de confirmaciones para una línea determinada?

Por ejemplo, ejecuto lo siguiente (en el magnífico proyecto sin uncrustify ):

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

¿Cómo puedo averiguar quién editó esa línea antes de cometer fe25b6d ? ¿Y quién lo editó antes de comprometerse? Estoy seguro de que esto sería posible, pero mi git-fu es débil.

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

Puede especificar una revisión para que git blame mire hacia atrás a partir de (en lugar del valor pnetworkingeterminado de HEAD ); fe25b6d^ es el padre de fe25b6d .

Puede usar git log -L para ver la evolución de un range de líneas.

Por ejemplo :

 git log -L 15,23:filename.txt 

significa "rastrear la evolución de las líneas 15 a 23 en el file llamado filename.txt".

Sobre la base de la respuesta anterior, este bash one-liner debería darle lo que está buscando. Muestra el historial de culpabilidad de git para una línea particular de un file en particular, a través de las últimas 5 revisiones:

 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 

En la salida de este command, es posible que vea el contenido del cambio de línea, o el número de línea que se muestra podría incluso cambiar, para una confirmación en particular.

Esto a menudo indica que la línea se agregó por primera vez, después de esa confirmación en particular. También podría indicar que la línea se movió desde otra parte del file.

La respuesta de Amber es correcta, pero la encontré poco clara; La syntax es:

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

Nota: el -- se usa para separar el tree-ish sha1 de las routes de files relativas. 1

Por ejemplo:

 git blame master -- index.html 

¡Todo el crédito para Amber por saber todas las cosas! 🙂

También hay recursive-blame . Se puede instalar con

 npm install -g recursive-blame 

Una solución única para este problema es usar git log:

git log -p -M –sigue –stat – path / to / your / file

Como lo explica Andre aquí

Es posible que desee verificar:

 git gui blame <filename> 

Te da una buena pantalla gráfica de cambios como "culpa de git" pero con enlaces clicables por línea, para pasar a confirmaciones anteriores. Desplácese sobre los enlaces para get una window emergente con detalles de confirmación. No mis créditos … lo encontré aquí:

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

Basándose en la respuesta de Will Shepard, su resultado includeá líneas duplicadas para commits donde no hubo cambios, por lo que puede filtrarlos de la siguiente manera (usando esta respuesta )

 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' 

Tenga en count que eliminé el argumento REVS y esto vuelve a la confirmación raíz. Esto se debe a la observación anterior de Max Nanasy.

Basándome en la respuesta de DavidN y quiero seguir el file renombrado:

 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: muestra muy bien el historial de renombrado de files en el logging de git

Uso este pequeño script bash para ver el historial de culpas.

Primer parámetro: file para mirar

Parámetros posteriores: pasó a ser culpable

 #!/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 } 

Puede proporcionar parameters de culpa como -L 70, + 10 pero es mejor usar la búsqueda de expresiones regulares de git blame porque los numbers de línea típicamente "cambian" con el time.

Basándome en la respuesta de stangls , puse este script en mi PATH (incluso en Windows) como git-bh:

Eso me permite search todas las confirmaciones en las que estuvo involucrada una palabra:

 git bh path/to/myfile myWord 

Guión:

 #!/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 }