Pregunta

Como subconjunto de la pregunta separar el subdirectorio Ya se hicieron antes y considerando el hecho de que, aunque se hicieron muchas preguntas sobre el proceso de división y fusión de repositorios GIT, no pude encontrar una que toque el tema de la división cuando hay submódulos presentes.

Entonces, 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 un problema y se puede resolver fácilmente con el método descrito en separar el subdirectorio.

El segundo no tanto. La existencia de submódulos y el hecho de que .gitModules contiene el camino completo para folder/content/submoduleA y folder/content/submoduleB Hace que parte de la historia sea inconsistente ya que .GitModules se refiere a una estructura de directorio inexistente (una vez que se usa la rama de filtro).

Por lo tanto, me gustaría saber si hay una manera de hacer esto sin causar una historia inconsistente.

¿Fue útil?

Solución

Sospecho (no probado) que un segundo git filter-branch tendría la oportunidad de modificar el .gitmodules Contenido para cada compromiso del nuevo repositorio.

Pero en realidad un git submodule split El comando fue en discusión a principios de 2009.

Uso propuesto:

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

Reemplazar submodule_dir con un submódulo recién creado, manteniendo toda la historia de submodule_dir.
Este comando también reescribe cada compromiso en el historial del repositorio actual para incluir la revisión correcta de sumodule_dir y el apropiado .gitmodules entradas.

Sin embargo, no lo veo en el Último lo que está cocinando.
El script en el parche propuesto puede darle una idea del tipo de reescritura de árboles necesaria para actualizar el .gitmodules Archivo.

Otros consejos

Tuve exactamente el mismo problema que Unode y logré resolverlo con el siguiente procedimiento:

git clone git@github.com: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 git@github.com:kdeldycke/cool-cavemen.git
git push -u origin master --force --tags

Como puede ver, el truco es cambiar temporalmente el nombre del .gitmodules archivo y usar sed para reescribir su contenido. Puedes obtener todos los detalles y el contexto de este procedimiento en mi blog.

Para elaborar la respuesta de Kevin: suponiendo que nunca existieran submódulos afuera cool/cavemen - La carpeta que se separa (de lo contrario, se necesitará una edición más elaborada de .gitModules para eliminar esas secciones adicionales), esto se puede lograr mucho más rápido y en un paso usando 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 todas las revisiones o ramas solo en aquellas revisiones o ramas que contenían cool/cavemen será visto.

Si este es el caso, es posible que desee ejecutar lo siguiente para eliminar 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
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top