remove - Archivo de copia GIT preservando el historial
git tag commits (5)
Tengo una pregunta algo confusa en GIT. Digamos, tengo un archivo dir1/A.txt
confirmado y git conserva un historial de confirmaciones
Ahora necesito (por alguna razón) copiar el archivo en dir2/A.txt
(no mover sino copiar). Sé que hay un comando git mv
pero necesito que dir2/A.txt
tenga el mismo historial de confirmaciones que dir1/A.txt
y dir1/A.txt
para permanecer allí.
No estoy planeando actualizar A.txt
una vez que se haya creado la copia y todo el trabajo futuro se realizará en dir2/A.txt
Sé que suena confuso, agregaré que esta situación está en el módulo basado en Java (proyecto mavenizado) y necesitamos crear una nueva versión de código para que nuestros clientes puedan tener 2 versiones diferentes en tiempo de ejecución, la primera la versión se eliminará eventualmente cuando se realice la alineación. Podemos usar versiones de maven, por supuesto, soy novato en GIT y tengo curiosidad sobre lo que git puede ofrecer aquí.
A diferencia de la subversión, git no tiene un historial por archivo. Si observa la estructura de datos de confirmación, solo apunta a las confirmaciones anteriores y al nuevo objeto de árbol para esta confirmación. No se almacena información explícita en el objeto de confirmación, cuyos archivos son modificados por la confirmación; ni la naturaleza de estos cambios.
Las herramientas para inspeccionar los cambios pueden detectar el cambio de nombre en función de la heurística. Por ejemplo, "git diff" tiene la opción -M que activa la detección de cambio de nombre. Entonces, en caso de cambiar el nombre, "git diff" podría mostrarle que un archivo ha sido eliminado y creado otro, mientras que "git diff -M" detectará realmente el movimiento y mostrará el cambio en consecuencia (consulte "man git diff" para detalles).
Por lo tanto, en Git no se trata de cómo se comprometen los cambios, sino cómo se observan los cambios comprometidos más adelante.
En mi caso, realicé el cambio en mi disco duro (corté / pegué aproximadamente 200 carpetas / archivos de una ruta en mi copia de trabajo a otra ruta en mi copia de trabajo), y utilicé SourceTree (2.0.20.1) para ubicar tanto el cambios (un complemento, una eliminación), y siempre que organice tanto el agregar como el eliminar juntos, se combinó automáticamente en un solo cambio con un icono de color rosa R (cambio de nombre, supongo).
Me di cuenta de que debido a que tenía una gran cantidad de cambios a la vez, SourceTree fue un poco lento detectando todos los cambios, por lo que algunos de mis archivos preparados parecen simplemente agrega (verde más) o simplemente elimina (rojo menos), pero yo mantuvo la actualización del estado del archivo y mantuvo los cambios nuevos a medida que aparecían, y después de unos minutos, toda la lista era perfecta y estaba lista para la confirmación.
Verifiqué que la historia está presente, siempre que cuando busque el historial, marque la opción "Seguir archivos renombrados".
Para completar, agregaría que, si quisiera copiar un directorio completo lleno de archivos controlados Y no controlados, podría usar lo siguiente:
git mv old new
git checkout HEAD old
Los archivos no controlados se copiarán, por lo que debe limpiarlos:
git clean -fdx new
Simplemente copie el archivo, agréguelo y confírmelo:
cp dir1/A.txt dir2/A.txt
git add dir2/A.txt
git commit -m "Duplicated file from dir1/ to dir2/"
Luego, los siguientes comandos mostrarán el historial de precopias completo:
git log --follow dir2/A.txt
Para ver las anotaciones heredadas línea por línea del archivo original, use esto:
git blame -C -C -C dir2/A.txt
Git no hace un seguimiento de las copias en el tiempo de confirmación, sino que las detecta al inspeccionar el historial con, por ejemplo, git blame
y git log
.
La mayoría de esta información proviene de las respuestas aquí: Grabar la operación de copia de archivos con Git
Todo lo que tiene que hacer es moverlo en paralelo a dos ubicaciones diferentes, fusionar y luego volver a mover una copia a la ubicación original. A continuación, puede ejecutar git blame
en cualquier copia, sin opciones especiales, y ver las mejores atribuciones históricas para ambos. También puede ejecutar git log
en el original y ver un historial completo.
En detalle, suponga que desea copiar foo / en su repositorio a bar /. Haz esto (ten en cuenta que estoy usando -n para comprometerme a evitar cualquier reescritura, etc. por ganchos):
git mv foo bar
git commit -n
SAVED=`git rev-parse HEAD`
git reset --hard HEAD^
git mv foo foo-magic
git commit -n
git merge $SAVED # This will generate conflicts
git commit -a -n # Trivially resolved like this
git mv foo-magic foo
git commit -n
Nota: utilicé git 2.1.4 en Linux
Por qué esto funciona
Terminará con un historial de revisión como este:
ORIG_HEAD
/ /
SAVED ALTERNATE
/ /
MERGED
|
RESTORED
Cuando le preguntes a git sobre la historia de ''foo'', (1) detectará el cambio de nombre de ''foo-magic'' entre MERGED y RESTORED, (2) detectará que ''foo-magic'' provino del padre ALTERNO de MERGED, y (3) detectar el cambio de nombre de ''foo'' entre ORIG_HEAD y ALTERNATE. A partir de ahí, profundizará en la historia de ''foo''.
Cuando le pregunte a git sobre el historial de ''barra'', (1) notará que no hay cambios entre FUSIONADO y RESTAURADO, (2) detectará que ''barra'' provino del padre GUARDADO de FUSIÓN, y (3) detectará el cambio de nombre de '' foo ''entre ORIG_HEAD y SAVED. A partir de ahí, profundizará en la historia de ''foo''.
Es así de simple. Solo necesitas forzar a Git a una situación de fusión donde puedas aceptar dos copias rastreables del archivo (s), y lo hacemos con un movimiento paralelo del original (que luego revertiremos).