Question

En tant que sous-ensemble de la question détacher-sous-répertoire déjà fait avant et compte tenu du fait que même si beaucoup de questions ont été faites au sujet du processus de dédoubler et fusionner les dépôts git, je ne pouvais pas trouver un qui touche l'objet d'une division en sous-modules sont présents.

Ainsi, dans le scénario suivant:

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

Je voudrais obtenir deux référentiels avec la structure suivante:

.git/
data/

et

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

Le premier cas ne pose aucun problème et peut être résolu facilement avec le procédé décrit dans détacher-sous-répertoire .

Le second pas tant. L'existence de sous-modules et le fait que .gitmodules contient le chemin complet pour folder/content/submoduleA et folder/content/submoduleB provoque une partie de l'histoire est incompatible depuis .gitmodules fait référence à une structure de répertoire inexistant (une fois filtre-branche est utilisé).

Je voudrais savoir s'il y a un moyen de le faire sans causer de l'histoire incohérente.

Était-ce utile?

La solution

Je soupçonne (non testé) qu'un deuxième git filter-branch aurait la possibilité de modifier le contenu de .gitmodules pour chaque commits du nouveau repo.

Mais en fait un git submodule split commande était en discussion début 2009 .

  

Utilisation proposée:

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

Remplacer submodule_dir avec un sous-module nouvellement créé, en gardant toute l'histoire de submodule_dir.
  Cette commande reformule chaque validation dans l'histoire du référentiel actuel pour inclure la révision correcte de sumodule_dir et les entrées de .gitmodules appropriées.

Cependant, je ne le vois pas dans le dernier ce qui mijote .
Le script dans le patch proposé peut vous donner une idée du type d'arbre réécriture nécessaire pour mettre à jour le fichier .gitmodules bien.

Autres conseils

J'ai eu exactement le même problème que Unode et a réussi à le résoudre avec la procédure suivante:

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

Comme vous le voyez, l'astuce consiste à renommer temporairement le fichier .gitmodules et utiliser sed pour réécrire son contenu. Vous pouvez obtenir tous les détails et cadre de cette procédure sur mon blog .

Pour des précisions sur la réponse de Kevin: en supposant qu'il n'y a pas sous-modules jamais existé en dehors cool/cavemen - le dossier étant détaché (sinon édition plus élaborée de .gitmodules sera nécessaire pour supprimer ces sections supplémentaires), cela peut être réalisé beaucoup plus rapidement et en une seule étape à l'aide d'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

Comme un avantage supplémentaire, si cool/cavemen n'existait pas dans chaque révision ou d'une branche que les révisions ou les branches qui ne contiennent cool/cavemen seront examinées.

Si tel est le cas, vous pouvez exécuter ce qui suit pour supprimer les références inchangées:

$ 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
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top