git blame
es ideal para líneas modificadas y agregadas, pero ¿cómo puedo encontrar cuando una línea que existía en una confirmación previa específica finalmente se eliminó? Estoy pensando bisect
, pero esperaba algo más útil.
(Antes de preguntar: en este caso, acabo de hacer una git log -p
búsqueda de la línea de código y (a) un idiota acababa de eliminar la línea vital en el commit anterior y (b) yo era ese idiota).
git log -S<string> /path/to/file
quiere una-c
o-cc
así para mostrar el traslado durante la fusión (conflictos)-c
y--cc
. @Steen: Correcto, ¡gracias por señalarlo! Estúpido descuido. Ojalá pudiera editar el comentario. Agregar uno nuevo, luego eliminar el mío, luego eliminar el tuyo es demasiado engorroso, supongo :)git blame
tener una opción para mostrar líneas eliminadas (con quizás tachado o texto rojo) con la revisión en la que se eliminaron.Respuestas:
Si conoce el contenido de la línea, este es un caso de uso ideal para:
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! Consulteman git-log
y busque las opciones-G
y-S
, o piqueta (el nombre descriptivo de estas funciones) para obtener más información.La
-S
opción también se menciona en el encabezado de la página degit-blame
manual, en la sección de descripción, donde da un ejemplo usandogit log -S...
.fuente
git blame --reverse
embargo, el método lo encontró.)-c
opción adicionalmente.Creo que lo que realmente quieres es
Desde la página del manual :
Con
git blame reverse
, puede encontrar el último commit en el que apareció la línea. Todavía necesita obtener el commit que viene después.Puede usar el siguiente comando para mostrar un registro git invertido. La primera confirmación mostrada será la última vez que aparezca esa línea, y la próxima confirmación será cuando se cambie o elimine.
fuente
git blame --reverse
mostrará la revisión antes de la fusión que fue cronológicamente Por último, no la revisión antes de la fusión inicial donde se tomó la decisión de no tomar la línea. ¿Hay alguna forma de encontrar la primera revisión donde la línea dejó de existir en lugar de la más reciente?Solo para completar la respuesta de Cascabel :
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 fusionó nuevamente con ella, eliminando efectivamente la línea en cuestión. La
--full-history
bandera evita saltear esas confirmaciones.fuente
git culpa --reverse puede conseguir que cerca de 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 la línea estaba presente . Entonces, si la siguiente revisión es una confirmación simple, tienes suerte y obtuviste la revisión de eliminación. OTOH, si la siguiente revisión es una confirmación de fusión , entonces las cosas pueden ponerse un poco locas.
Como parte del esfuerzo para crear difflame , abordé este mismo problema, por lo que si ya tiene Python instalado en su caja y está dispuesto a probarlo, no espere más y dígame cómo funciona.
https://github.com/eantoranz/difflame
fuente
Para cambios ocultos en commits de fusión
Las confirmaciones de fusión tienen sus cambios ocultos automáticamente en la salida del registro de Git. Tanto el pico como la culpa inversa no encontraron el cambio. Así que la línea que quería había sido agregada y luego eliminada y quería encontrar la fusión que la eliminó. El
git log -p -- path/file
historial del archivo solo mostró que se estaba agregando. Aquí está la mejor manera que encontré para encontrarlo:git log -p -U9999 -- path/file
Busque el cambio, luego busque "^ commit" hacia atrás: el primer "^ commit" es el commit donde el archivo tuvo esa última línea. El segundo "^ commit" es después de que desapareció. El segundo commit podría ser el que lo eliminó. los
-U9999
está destinado a mostrar el contenido completo del archivo (después de cada vez que el archivo se ha cambiado), suponiendo que sus archivos están todos max 9999 líneas.Encuentra cualquier fusión relacionada a través de la fuerza bruta (diferencie cada posible compromiso de fusión con su primer padre, ejecute 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 me encontré con problemas y no recomiendo esto. Los cambios de agregar / quitar que estaba buscando estaban en diferentes ramas que se fusionaron en diferentes momentos y A ... B no incluyó cuando los cambios se fusionaron en la línea principal).
Mostrar un árbol 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 la primera confirmación anterior, B es la segunda confirmación 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 forma más lineal en lugar del árbol de historial de Git normal; sin embargo, prefiero el árbol de historial de Git normal):
Tres, no dos puntos: tres puntos significa "r1 r2 --no $ (git merge-base --all r1 r2). Es el conjunto de commits a los que se puede acceder desde cualquiera de r1 (lado izquierdo) o r2 (derecha lado), pero no de ambos ". - fuente: "hombre gitrevisions"
fuente