Me gustaría cambiar el nombre / mover un subárbol de proyecto en Git moviéndolo de
/project/xyz
a
/components/xyz
Si uso un plano git mv project components
, xyz project
se pierde todo el historial de confirmaciones . ¿Hay alguna manera de mover esto de tal manera que se mantenga la historia?
git mv
: stackoverflow.com/questions/1094269/whats-the-purpose-of-git-mvRespuestas:
Git detecta los cambios de nombre en lugar de persistir en la operación con la confirmación, por lo que si usa
git mv
omv
no importa.El
log
comando toma un--follow
argumento que continúa el historial antes de una operación de cambio de nombre, es decir, busca contenido similar utilizando la heurística:http://git-scm.com/docs/git-log
Para buscar el historial completo, use el siguiente comando:
fuente
git config alias.logf "log --follow"
y simplemente escribirgit logf ./path/to/file
.Es posible cambiar el nombre de un archivo y mantener el historial intacto, aunque hace que se cambie el nombre del archivo a lo largo de todo el historial del repositorio. Esto es probablemente solo para los amantes obsesivos de git-log, y tiene algunas implicaciones serias, que incluyen:
Ahora, como todavía estás conmigo, probablemente seas un desarrollador en solitario que renombra un archivo completamente aislado. ¡Muevamos un archivo usando
filter-tree
!Suponga que va a mover un archivo
old
a una carpetadir
y darle el nombrenew
Esto podría hacerse
git mv old dir/new && git add -u dir/new
, pero eso rompe la historia.En lugar:
será rehacer cada commit en el ramo, la ejecución del comando en las garrapatas para cada iteración. Muchas cosas pueden salir mal cuando haces esto. Normalmente pruebo para ver si el archivo está presente (de lo contrario, todavía no está allí para moverse) y luego realizo los pasos necesarios para calzar el árbol a mi gusto. Aquí puede atravesar archivos para alterar las referencias al archivo, etc. ¡Déjate fuera! :)
Cuando se completa, el archivo se mueve y el registro está intacto. Te sientes como un pirata ninja.
También; El directorio mkdir solo es necesario si mueve el archivo a una nueva carpeta, por supuesto. El if evitará la creación de esta carpeta antes en el historial que el archivo existente.
fuente
--index-filter
cambio de nombre será mucho más rápido ya que el árbol no tendrá que desprotegerse y volver a ingresar en cada confirmación.--index-filter
actúa directamente en cada índice de confirmación.No.
La respuesta corta es NO . No es posible cambiar el nombre de un archivo en Git y recordar el historial. Y es un dolor.
Se rumorea que
git log --follow
--find-copies-harder
funcionará, pero no funciona para mí, incluso si no hay cambios en el contenido del archivo, y los movimientos se han realizado congit mv
.(Al principio utilicé Eclipse para cambiar el nombre y los paquetes de actualización en una sola operación, que pueden haber confundido Git. Pero eso es una cosa muy común de hacer.
--follow
Parece que no funciona si sólomv
se lleva a cabo y luego unacommit
ymv
no está demasiado lejos.)Linus dice que se supone que debe comprender todo el contenido de un proyecto de software de manera integral, sin necesidad de rastrear archivos individuales. Bueno, tristemente, mi pequeño cerebro no puede hacer eso.
Es realmente molesto que tantas personas hayan repetido sin pensar la afirmación de que Git rastrea automáticamente los movimientos. Han perdido mi tiempo. Git no hace tal cosa. Por diseño (!) Git no rastrea los movimientos en absoluto.
Mi solución es cambiar el nombre de los archivos a sus ubicaciones originales. Cambie el software para que se ajuste al control de fuente. Con Git parece que solo necesitas "corregirlo" la primera vez.
Desafortunadamente, eso rompe Eclipse, que parece usar
--follow
.git log --follow
a veces no muestra el historial completo de archivos con historiales de cambio de nombre complicados, aunque logit log
hace. (No se por que.)(Hay algunos trucos demasiado inteligentes que se remontan y vuelven a comprometer el trabajo anterior, pero son bastante atemorizantes. Ver GitHub-Gist: emiller / git-mv-with-history ).
fuente
le mostrará la historia a través de cambios de nombre.
fuente
git mv
básicamente hace agit rm && git add
. Hay opciones como-M90
/--find-renames=90
para considerar que un archivo cambie de nombre cuando sea 90% idéntico.Hago:
fuente
-A
lugar? Nuevamente, vea aquí: git-scm.com/docs/git-addgit add -u
. Los documentos de Git tienden a ser inútiles, y son el último lugar donde me gustaría mirar. Aquí hay una publicación que se muestragit add -u
en acción: stackoverflow.com/a/2117202 .No (8 años después, Git 2.19, Q3 2018), porque Git detectará el cambio de nombre del directorio , y esto ahora está mejor documentado.
Consulte commit b00bf1c , commit 1634688 , commit 0661e49 , commit 4d34dff , commit 983f464 , commit c840e1a , commit 9929430 (27 de junio de 2018) y commit d4e8062 , commit 5dacd4a (25 de junio de 2018) por Elijah Newren (
newren
) .(Fusionada por Junio C Hamano -
gitster
- en commit 0ce5a69 , 24 jul 2018)Eso ahora se explica en
Documentation/technical/directory-rename-detection.txt
:Ejemplo:
Pero son muchos otros casos, como:
Para simplificar la detección de cambio de nombre de directorio, Git aplica esas reglas:
un par de reglas básicas limitan cuando se aplica la detección de cambio de nombre del directorio:
Puede ver muchas pruebas en
t/t6043-merge-rename-directories.sh
, que también señalan que:fuente
Objetivo
git am
Limitación
Resumen
git log --pretty=email -p --reverse --full-index --binary
cat extracted-history | git am --committer-date-is-author-date
1. Extraiga el historial en formato de correo electrónico
Ejemplo: historia Extracto de
file3
,file4
yfile5
Establecer / limpiar el destino
Extraiga el historial de cada archivo en formato de correo electrónico
Lamentablemente opción
--follow
o--find-copies-harder
no se puede combinar con--reverse
. Es por eso que el historial se corta cuando se cambia el nombre del archivo (o cuando se cambia el nombre de un directorio principal).Historial temporal en formato de correo electrónico:
Dan Bonachea sugiere invertir los bucles del comando git log generation en este primer paso: en lugar de ejecutar git log una vez por archivo, ejecútelo exactamente una vez con una lista de archivos en la línea de comando y genere un único registro unificado. De esta manera, las confirmaciones que modifican varios archivos siguen siendo una única confirmación en el resultado, y todas las nuevas confirmaciones mantienen su orden relativo original. Tenga en cuenta que esto también requiere cambios en el segundo paso a continuación al reescribir nombres de archivo en el registro (ahora unificado).
2. Reorganice el árbol de archivos y actualice los nombres de archivo
Suponga que desea mover estos tres archivos en este otro repositorio (puede ser el mismo repositorio).
Por lo tanto, reorganice sus archivos:
Tu historial temporal es ahora:
Cambie también los nombres de archivo dentro del historial:
3. Aplicar nuevo historial
Su otro repositorio es:
Aplicar confirmaciones de archivos de historial temporales:
--committer-date-is-author-date
conserva las marcas de tiempo de confirmación originales ( comentario de Dan Bonachea ).Su otro repositorio es ahora:
Use
git status
para ver la cantidad de confirmaciones listas para ser empujadas :-)Truco adicional: verifique los archivos renombrados / movidos dentro de su repositorio
Para enumerar los archivos que han cambiado de nombre:
Más personalizaciones: puede completar el comando
git log
con las opciones--find-copies-harder
o--reverse
. También puede eliminar las dos primeras columnas utilizandocut -f3-
y agrupando el patrón completo '{. * =>. *}'.fuente
Seguí este proceso de varios pasos para mover el código al directorio principal y retener el historial.
Paso 0: creó un 'historial' de rama desde 'maestro' para su custodia
Paso 1: Utilicé la herramienta git-filter-repo para reescribir el historial. Este comando debajo movió la carpeta 'FolderwithContentOfInterest' a un nivel superior y modificó el historial de confirmación relevante
Paso 2: En este momento, el repositorio de GitHub perdió su ruta de repositorio remoto. Referencia remota agregada
Paso 3: extraer información en el repositorio
Paso 4: conecte la rama local perdida con la rama de origen
Paso 5: solucione el conflicto de fusión de la estructura de carpetas si se le solicita
Paso 6: ¡ Empuja !
Nota: El historial modificado y la carpeta movida parecen estar ya confirmados.
enter code here
Hecho. ¡El código se mueve al directorio padre / deseado manteniendo el historial intacto!
fuente
Si bien el núcleo de Git, la plomería de Git no realiza un seguimiento de los cambios de nombre, el historial que muestra con la "porcelana" del registro de Git puede detectarlos si lo desea.
Para un
git log
uso determinado, la opción -M:Con una versión actual de Git.
Esto también funciona para otros comandos
git diff
.Hay opciones para hacer las comparaciones más o menos rigurosas. Si cambia el nombre de un archivo sin realizar cambios significativos al mismo tiempo, facilita que Git log y sus amigos detecten el cambio de nombre. Por esta razón, algunas personas cambian el nombre de los archivos en una confirmación y los cambian en otra.
Hay un costo en el uso de la CPU cada vez que le pide a Git que encuentre dónde se han renombrado los archivos, por lo tanto, si lo usa o no, y cuándo, depende de usted.
Si desea que siempre se informe su historial con la detección de cambio de nombre en un repositorio particular, puede usar:
Se detectan archivos que se mueven de un directorio a otro . Aquí hay un ejemplo:
Tenga en cuenta que esto funciona siempre que use diff, no solo con
git log
. Por ejemplo:Como prueba, realicé un pequeño cambio en un archivo en una rama de características y lo confirmé y luego en la rama maestra cambié el nombre del archivo, confirmé y luego hice un pequeño cambio en otra parte del archivo y lo confirmé. Cuando fui a la rama de características y fusioné desde master, la fusión cambió el nombre del archivo y fusionó los cambios. Aquí está el resultado de la fusión:
El resultado fue un directorio de trabajo con el archivo renombrado y ambos cambios de texto realizados. Por lo tanto, es posible que Git haga lo correcto a pesar del hecho de que no rastrea explícitamente los cambios de nombre.
Esta es una respuesta tardía a una pregunta anterior, por lo que las otras respuestas pueden haber sido correctas para la versión de Git en ese momento.
fuente
Primero cree un commit independiente con solo un cambio de nombre.
Luego, cualquier cambio eventual al contenido del archivo se coloca en la confirmación por separado.
fuente
Para cambiar el nombre de un directorio o archivo (no sé mucho sobre casos complejos, por lo que puede haber algunas advertencias):
Para cambiar el nombre de un directorio en archivos que lo mencionan (es posible usar devoluciones de llamada, pero no sé cómo):
expressions.txt
es un archivo lleno de líneas comoliteral:OLD_NAME==>NEW_NAME
(es posible usar RE con Pythonregex:
o glob conglob:
).Para cambiar el nombre de un directorio en mensajes de confirmaciones:
Las expresiones regulares de Python también son compatibles, pero deben escribirse en Python, manualmente.
Si el repositorio es original, sin control remoto, deberá agregarlo
--force
para forzar una reescritura. (Es posible que desee crear una copia de seguridad de su repositorio antes de hacer esto).Si no desea conservar las referencias (se mostrarán en el historial de ramas de la GUI de Git), deberá agregarlas
--replace-refs delete-no-add
.fuente
Simplemente mueva el archivo y el escenario con:
Antes de confirmar puede verificar el estado:
Eso mostrará:
Probé con Git versión 2.26.1.
Extraído de la página de ayuda de GitHub .
fuente
Hago mover los archivos y luego hago
que ponen en el área de almacenamiento todos los archivos borrados / nuevos. Aquí git se da cuenta de que el archivo se mueve.
No sé por qué, pero esto funciona para mí.
fuente