tag remove practices crear commits commands best git copy

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).