2010-08-05 13 views
5

Como un subconjunto de la pregunta detach-subdirectory ya hecha anteriormente y considerando el hecho de que aunque se hicieron muchas preguntas sobre el proceso de división y fusión de repositorios de git, no pude encuentre uno que toque el tema de la división cuando los submódulos estén presentes.Dividir un subdirectorio con submódulos en un repositorio de git separado

Así, en el siguiente escenario:

.git/ 
.gitmodules 
folder/ 
    data/ 
    content/ 
     other_data/ 
     submoduleA/ 
     submoduleB/ 

me gustaría obtener dos repositorios con la siguiente estructura:

.git/ 
data/ 

y

.git/ 
.gitmodules 
content/ 
    other_data/ 
    submoduleA/ 
    submoduleB/ 

El primer caso no es una problema y se puede resolver fácilmente con el método descrito en detach-subdirectory.

El segundo no tanto. La existencia de submódulos y el hecho de que .gitmodules contiene la ruta completa para folder/content/submoduleA y folder/content/submoduleB hace que parte del historial sea incoherente, ya que .gitmodules hace referencia a una estructura de directorios inexistente (una vez que se utiliza la rama de filtro).

Así que me gustaría saber si hay una manera de hacer esto sin causar un historial incoherente.

Respuesta

1

sospecho (no probado) que una segunda git filter-branch tendría la oportunidad de modificar el contenido de cada uno se dedica .gitmodules de la nueva operación.

Pero en realidad es git submodule split command was in discussion early 2009.

uso propuesto:

git submodule split [--url submodule_repo_url] submodule_dir \ 
    [alternate_dir...] 

Reemplazar submodule_dir con un submódulo de nueva creación, mantenimiento de toda la historia de submodule_dir.
Este comando también reescribe cada confirmación en el historial del repositorio actual para incluir la revisión correcta de sumodule_dir y las entradas .gitmodules apropiadas.

Sin embargo, no lo veo en el latest what's cooking.
El script en el parche propuesto puede darle una idea del tipo de reescritura de árbol necesario para actualizar el archivo .gitmodules.

+0

El uso de un segundo comando git filter-branch yo era capaz de reescribir .gitmodules con un comando sed, sin embargo, el real Las carpetas de submódulos aún no se han tocado (ambas con index-filter y tree-filter). Solo el subdirectorio-filtro fue capaz de cambiarlos, pero luego se elimina .gitmodules. El comando dividir submódulo git parece hacer exactamente lo que intento, pero al leer el hilo tuve la impresión de que tenía algunos problemas, así que no me siento cómodo al usarlo. – Unode

+0

@Unode: lo entiendo. No creo que este parche en particular esté en desarrollo activo en este momento. – VonC

5

que tenían exactamente el mismo problema que unode y lograron resolverlo con el siguiente procedimiento:

git clone [email protected]:kdeldycke/kev-code.git 
cd kev-code 
git filter-branch --tree-filter "test -f ./.gitmodules && mv ./.gitmodules ./cool-cavemen/gitmodules || echo 'No .gitmodules file found'" -- --all 
git filter-branch --force --prune-empty --subdirectory-filter cool-cavemen --tag-name-filter cat -- --all init..HEAD 
git filter-branch --force --tree-filter "test -f ./gitmodules && mv ./gitmodules ./.gitmodules || echo 'No gitmodules file found'" -- --all 
git filter-branch --force --tree-filter "test -f ./.gitmodules && sed -i 's/cool-cavemen\///g' ./.gitmodules || echo 'No .gitmodules file found'" -- --all 
git remote rm origin 
rm -rf .git/refs/original/ 
git reflog expire --all 
git gc --aggressive --prune 
git remote add origin [email protected]:kdeldycke/cool-cavemen.git 
git push -u origin master --force --tags 

Como se ve, el truco es renombrar temporalmente el archivo .gitmodules y utilizar sed para reescribir su contenido. Puede obtener todos los detalles y el context of this procedure on my blog.

+0

Es posible que desee incluir la opción '--tag-name-filter cat' en todos los comandos de la rama de filtro para conservar las etiquetas después del filtrado. – kolyuchiy

+0

Gracias por documentar esto. Dos cosas que tuve que ajustar para que esto funcione. Primero, creo que asumes una confirmación inicial etiquetada como 'init' para el rango' init..HEAD'. En segundo lugar, tuve que agregar '-e' al comando sed, es decir:' sed -i -e 's/cool-cavemen \ /// g' ./. Gitmodules' – Von

0

Para obtener más información sobre la respuesta de Kevin: suponiendo que no haya ningún submódulo fuera de cool/cavemen - la carpeta está separada (por lo demás, edición más elaborada de.gitmodules será necesaria para eliminar esas secciones adicionales), esto se puede lograr mucho más rápido y en un solo paso utilizando un index-filter:

$ git filter-branch --subdirectory-filter cool/cavemen --index-filter $' 
hash=$(git rev-parse --verify $GIT_COMMIT:.gitmodules 2>/dev/null) && 
git update-index --add --cacheinfo 100644 $(git cat-file -p $hash | 
sed \'s/cool\\/cavemen\\///g\' | git hash-object -w --stdin) .gitmodules || 
true' --tag-name-filter cat --prune-empty -- --all 

Como beneficio adicional, si cool/cavemen no existía en cada revisión o rama única se revisarán aquellas revisiones o sucursales que sí contenían cool/cavemen.

Si este es el caso puede que desee ejecutar las siguientes acciones para eliminar las referencias sin cambios:

$ git for-each-ref --format='%(refname)' | 
grep -vF "$(git for-each-ref --format='%(refname)' refs/original | 
sed 's/refs\/original\///g')" | xargs -n 1 git update-ref -d 
Cuestiones relacionadas