ver tipos tag qué modificados existen etiquetas crear comando archivos git git-log

tipos - git ver archivos modificados



Mueva el archivo y el directorio a un subdirectorio junto con el historial de confirmaciones (4)

¿Cómo puedo mover un directorio y archivos a un subdirectorio junto con el historial de compromisos?

Por ejemplo:

  • Estructura del directorio de origen: [project]/x/[files & sub-dirs]

  • Estructura de directorio de destino: [project]/x/p/q/[files & sub-dirs]


El comando git mv es la forma más simple. Sin embargo, al menos en mi caja de Linux, necesitaba proporcionar el distintivo -k para evitar que se repitiera un error que una carpeta no se puede mover a sí misma. Pude realizar la acción usando ...

mkdir subdirectory git mv -k ./* ./subdirectory # check to make sure everything moved (see below) git commit

Como advertencia, esto omitirá todos los movimientos que podrían llevar a una condición de error, por lo que es probable que desee comprobar que todo funcionó correctamente después del traslado y antes de una confirmación.


Git hace un muy buen trabajo para rastrear contenido incluso si se mueve, por lo que git mv es claramente el camino a seguir si mueves archivos porque solían pertenecer a x , pero ahora pertenecen a x/p/q porque el proyecto evolucionado de esa manera.

A veces, sin embargo, hay una razón para mover archivos a un subdirectorio a lo largo de la historia de un proyecto. Por ejemplo, si los archivos se han colocado en algún lugar por error y se han realizado más commits desde entonces, pero los commits intermitentes ni siquiera tienen sentido con los archivos en el lugar equivocado. Si todo lo que sucedió en una sucursal local, queremos limpiar el desorden antes de presionar.

La pregunta dice "junto con el historial de compromiso", que interpreto como la reescritura de la historia exactamente de esa manera. Esto se puede hacer con

git filter-branch --tree-filter "cd x; mkdir -p p/q; mv [files & sub-dirs] p/q" HEAD

Los archivos aparecen en el subdirectorio p/q largo del historial.

Tenga en cuenta que el resultado no debe enviarse a un servidor público si la reescritura toca confirmaciones que ya fueron presionadas anteriormente.


Para agregar al bmargulies de bmargulies , la secuencia completa es:

mkdir -p x/p/q # make sure the parent directories exist first git mv x/* x/p/q # move folder, with history preserved git commit -m "changed the foldername x into x/p/q"

Pruébelo primero para ver una vista previa de la mudanza:

git mv -n x/* x/p/q

Wolfgang comments :

Si está utilizando bash, puede evitar el problema de tratar de mover una carpeta dentro de sí mismo utilizando un globo extendido como ese (usando el shopt incorporado ):

shopt -s extglob; git mv !(folder) folder

El Capitán Man informa en los comentarios que tiene que hacer:

mkdir temp git mv x/* temp mkdir -p x/p/q git mv temp x/p/q rmdir temp;

Contexto:

Estoy en Windows con Cygwin.
Me acabo de dar cuenta de que hice mal el ejemplo de las shopt -s extglob así que puede que no sea necesario, pero normalmente uso zsh en lugar de bash, y no tenía el comando shopt -s extglob (aunque estoy seguro de que es una alternativa), por lo que este enfoque debería funcionar a través de las conchas ( rmdir el mkdir y rmdir tu shell si es especialmente extraño)

Como alternativa, spanky menciona en los comentarios la opción -k de git mv :

Omitir movimiento o cambiar el nombre de las acciones que conducirían a una condición de error.

git mv -k * target/

Eso evitaría el error " can not move directory into itself ".


Puedo ver que esta es una vieja pregunta, pero aún me siento obligado a responder Con mi solución actual al problema, que he derivado de uno de los ejemplos en el libro de git . En lugar de usar un ineficiente --tree-filter muevo los archivos directamente en el índice con un --index-filter índice.

git filter-branch -f --index-filter ''PATHS=`git ls-files -s | sed "s/^<old_location>/<new_location>/"`;GIT_INDEX_FILE=$GIT_INDEX_FILE.new; echo -n $PATHS | git update-index --index-info && if [ -e "$GIT_INDEX_FILE.new" ]; then mv "$GIT_INDEX_FILE.new" "$GIT_INDEX_FILE; fi"'' -- --all`

esta es una especialización de uno de los ejemplos del libro. También he usado el mismo ejemplo para cambiar el nombre de los archivos en el historial de commit en un caso especial. si mueve archivos en subdirectorios: recuerde escaparse del / carácter en las rutas Con a / para hacer que el comando sed funcione como se espera.

Ejemplo:

Project Directory |-a | |-a1.txt | |-b | | |-b1.txt

para mover el directorio b a la raíz del proyecto:

git filter-branch -f --index-filter ''PATHS=`git ls-files -s | sed "s/a//b///b///"`;GIT_INDEX_FILE=$GIT_INDEX_FILE.new; echo -n $PATHS | git update-index --index-info && if [ -e "$GIT_INDEX_FILE.new" ]; then mv "$GIT_INDEX_FILE.new" "$GIT_INDEX_FILE; fi"'' -- --all

Resultado:

Project Directory |-a | |-a1.txt | |-b | |-b1.txt