¿Cómo puedo "culpar" a una línea eliminada?
git blame
es excelente para líneas modificadas y agregadas, pero ¿cómo puedo saber cuándo finalmente se eliminó una línea que existía en una confirmación anterior específica? estoy pensandobisect
, pero esperaba algo más útil.
(Antes de que preguntes: en este caso, simplemente hice git log -p
y busqué la línea de código y (a) algún idiota acababa de eliminar la línea vital en la confirmación anterior y (b) yo era ese idiota).
Si conoce el contenido de la línea, este es un caso de uso ideal para:
git log -S <string> path/to/file
que muestra confirmaciones que introducen o eliminan una instancia de esa cadena. ¡ También está el -G<regex>
que hace lo mismo con las expresiones regulares! Consulte man git-log
y busque las opciones -G
y -S
, o pico (el nombre descriptivo de estas funciones) para obtener más información.
De hecho, la -S
opción también se menciona en el encabezado de la git-blame
página de manual, en la sección de descripción, donde se ofrece un ejemplo de uso git log -S...
.
Creo que lo que realmente quieres es
git blame --reverse START..END filename
Desde la página de manual :
Hacer avanzar la historia en lugar de retroceder. En lugar de mostrar la revisión en la que apareció una línea, muestra la última revisión en la que existió una línea. Esto requiere una variedad de revisiones como START..END donde el camino a la culpa existe en START.
Con git blame reverse
, puede encontrar la última confirmación en la que apareció la línea. Aún necesita obtener la confirmación que viene después.
Puede utilizar el siguiente comando para mostrar un registro de git invertido. La primera confirmación que se muestra será la última vez que aparezca esa línea, y la siguiente confirmación será cuando se cambie o elimine.
git log --reverse --ancestry-path COMMIT^..master
Sólo para completar la respuesta de Cascabel :
git log --full-history -S <string> path/to/file
Tuve el mismo problema que se menciona aquí, pero resultó que faltaba la línea, porque una confirmación de fusión de una rama se revirtió y luego se volvió a fusionar, eliminando efectivamente la línea en cuestión. La --full-history
bandera evita omitir esas confirmaciones.
git seek --reverse puede acercarte al lugar donde se elimina la línea. Pero en realidad no apunta a la revisión donde se elimina la línea. Apunta a la última revisión donde estaba presente la línea . Entonces, si la siguiente revisión es una confirmación simple, tiene suerte y obtuvo la revisión eliminada. OTOH, si la siguiente revisión es una confirmación de fusión , entonces las cosas pueden volverse un poco locas.
Como parte del esfuerzo para crear difflame, abordé este mismo problema, así que si ya tienes Python instalado en tu equipo y estás dispuesto a probarlo, no esperes más y cuéntame cómo te va.
https://github.com/eantoranz/difflame
Para cambios ocultos en confirmaciones de fusión
Las confirmaciones de fusión automáticamente ocultan sus cambios de la salida del registro de Git. Tanto el pico como la culpa inversa no encontraron el cambio. Entonces, la línea que quería se agregó y luego se eliminó y quería encontrar la combinación que la eliminó. El git log -p -- path/file
historial del archivo solo mostró que se agregó. Esta es la mejor manera que encontré para encontrarlo:
git log -p -U9999 -- path/file
Busque el cambio, luego busque hacia atrás "^commit"; el primer "^commit" es la confirmación donde el archivo tenía esa línea por última vez. El segundo "^commit" es después de que desapareció. La segunda confirmación podría ser la que lo eliminó. Está -U9999
destinado a mostrar el contenido completo del archivo (después de cada cambio del archivo), suponiendo que sus archivos tengan un máximo de 9999 líneas.
Encuentra cualquier fusión relacionada mediante fuerza bruta (diferencia cada posible confirmación de fusión con su primer padre, ejecútala contra toneladas de confirmaciones)
git log --merges --pretty=format:"git diff %h^...%h | grep target_text" HEAD ^$(git merge-base A B) | sh -v 2>&1 | less
(Intenté restringir más el filtro de revisión, pero tuve problemas y no lo recomiendo. Los cambios de agregar/eliminar que estaba buscando estaban en diferentes ramas que se fusionaron en diferentes momentos y A...B no incluía cuando los cambios realmente se fusionaron en la línea principal).
Muestre un árbol de Git con estas dos confirmaciones (y gran parte del complejo historial de Git eliminado):
git log --graph --oneline A B ^$(git merge-base A B)
(A es el primer compromiso anterior, B es el segundo compromiso anterior)
Muestra el historial de A y el historial de B menos el historial de A y B.
Versión alternativa (parece mostrar la ruta de manera más lineal en lugar del árbol de historial de Git normal; sin embargo, prefiero el árbol de historial de Git normal):
git log --graph --oneline A...B
Tres, no dos puntos: tres puntos significa "r1 r2 --no $(git merge-base --all r1 r2). Es el conjunto de confirmaciones a las que se puede acceder desde r1 (lado izquierdo) o r2 (lado derecho). lado), pero no de ambos." - fuente: "hombre gitrevisions"