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 lasshopt -s extglob
así que puede que no sea necesario, pero normalmente uso zsh en lugar de bash, y no tenía el comandoshopt -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
elmkdir
yrmdir
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