¿Cómo Git rastrea el historial durante una refactorización?
refactoring hash (1)
Entiendo bien cómo Git puede admitir movimientos de archivos: como utiliza el hash de archivos, un archivo "agregado" se detecta fácilmente como el mismo que el "eliminado".
Mi pregunta es sobre la refactorización: considerando Java, la declaración del paquete cambia, por lo que el contenido del archivo NO será el mismo. En tal caso, ¿cómo determina Git que el archivo "agregado" comparte el historial con el "eliminado"? ¿Comprueba el "contenido más similar" suponiendo que solo hice cambios menores o una solución similar no determinista?
Como se mencionó en las preguntas frecuentes de Git , detectará contenido similar basado en una heurística.
Git tiene que interoperar con muchos flujos de trabajo diferentes, por ejemplo, algunos cambios pueden provenir de parches, donde la información de cambio de nombre puede no estar disponible. Confiar en el seguimiento de cambio de nombre explícito hace que sea imposible fusionar dos árboles que hayan hecho exactamente lo mismo, excepto que uno lo hizo como un parche (crear / eliminar) y otro lo hizo usando otra heurística.
En una segunda nota, el seguimiento de los nombres de los nombres es solo un caso especial de seguimiento de cómo se mueve el contenido en el árbol. En algunos casos, es posible que le interese consultar cuándo se agregó o se movió una función a un archivo diferente. Al depender solo de la capacidad de recrear esta información cuando sea necesario, Git tiene como objetivo proporcionar una manera más flexible de rastrear cómo está cambiando su árbol.
Sin embargo, esto no significa que Git no tenga soporte para renombrar.
La maquinaria diff en Git tiene soporte para la detección automática de nombres, esto se activa mediante el interruptor ''-M
'' de la familia de comandosgit-diff-*
.
La maquinaria de detección de cambio de nombre es utilizada por git-log (1) y git-whatchanged (1) , por lo que, por ejemplo, ''git log -M
'' proporcionará el historial de confirmación con información de cambio de nombre.
Git también es compatible con una forma limitada de fusión a través de los nombres.
Las dos herramientas para asignar culpar,git-blame(1)
ygit-annotate(1)
usan el código de detección de cambio de nombre automático para rastrear los nombres.
git log
te da algunos detalles sobre esa heurística:
-B[<n>][/<m>]
Rompe los cambios de reescritura completa en pares de eliminar y crear. Esto tiene dos propósitos:
Afecta la forma en que un cambio que equivale a una reescritura total de un archivo no como una serie de eliminación e inserción combinadas con unas pocas líneas que coinciden textualmente con el contexto, sino como una eliminación única de todo lo antiguo seguido de una la inserción individual de todo lo nuevo, y el número m controla este aspecto de la opción
-B
(por defecto, 60%).
-B / 70% especifica que menos del 30% del original debe permanecer en el resultado para que git lo considere una reescritura total (es decir, de lo contrario, el parche resultante será una serie de borrado e inserción mezclados con líneas de contexto).Cuando se usa con -M, un archivo totalmente reescrito también se considera como la fuente de un cambio de nombre (generalmente -M solo considera un archivo que desapareció como la fuente de un cambio de nombre), y el número n controla este aspecto de la opción -B (por defecto al 50%) .
-B20% especifica que un cambio con adición y eliminación comparado con el 20% o más del tamaño del archivo es elegible para ser recogido como una posible fuente de cambio de nombre a otro archivo.
-M[<n>]
Si está generando diffs, detecte y reporte los nombres para cada confirmación. Para ver los siguientes archivos a través de los nombres mientras recorre el historial, consulte
--follow
.
Si se especifica n, es un es un umbral en el índice de similitud (es decir, la cantidad de adiciones / eliminaciones en comparación con el tamaño del archivo).
Por ejemplo, -M90% significa que git debería considerar que un par de eliminar / agregar sea un cambio de nombre si más del 90% del archivo no ha cambiado .
Referencias adicionales:
- La última publicación de blog de la herramienta de seguimiento de contenido de Linus , por Junio C Hamano, mantenedor de Git.
- Logrando que Git reconozca archivos previamente movidos
- ¿Cómo hacer que git mark un archivo eliminado y un nuevo como un archivo mover?
- ¿Cómo resuelve Git el problema de fusión?
Nota: Con Git 2.18 (Q2 2018), el git status
ahora debería mostrar sus nombres (en lugar de eliminar / agregar archivos) cuando mueve / renombra archivos.
Consulte " Cómo decirle a Git que es el mismo directorio, solo un nombre diferente ".