dés-sous-module un sous-module git

Comment puis-je supprimer un sous-module git (ramener tout le code dans le kernel)?

Comme dans “comment” je, comme dans “Best procedure” …

Si vous ne voulez que placer votre code de sous-module dans le référentiel principal, il vous suffit de supprimer le sous-module et de rappend les fichiers dans le référentiel principal:

 git rm --cached submodule_path # delete reference to submodule HEAD (no trailing slash) git rm .gitmodules # if you have more than one submodules, # you need to edit this file instead of deleting! rm -rf submodule_path/.git # make sure you have backup!! git add submodule_path # will add files instead of commit reference git commit -m "remove submodule" 

Si vous souhaitez également conserver l’historique du sous-module, vous pouvez effectuer une petite astuce: “fusionner” le sous-module dans le référentiel principal de sorte que le résultat soit le même qu’avant, sauf que les fichiers de sous-modules sont désormais dans le repository principal.

Dans le module principal, vous devrez effectuer les opérations suivantes:

 # Fetch the submodule commits into the main repository git remote add submodule_origin git://url/to/submodule/origin git fetch submodule_origin # Start a fake merge (won't change any files, won't commit anything) git merge -s ours --no-commit submodule_origin/master # Do the same as in the first solution git rm --cached submodule_path # delete reference to submodule HEAD git rm .gitmodules # if you have more than one submodules, # you need to edit this file instead of deleting! rm -rf submodule_path/.git # make sure you have backup!! git add submodule_path # will add files instead of commit reference # Commit and cleanup git commit -m "removed submodule" git remote rm submodule_origin 

Le repository résultant sera un peu étrange: il y aura plus d’un commit initial. Mais cela ne posera aucun problème pour git.

Dans cette seconde solution, vous aurez le gros avantage de pouvoir toujours exécuter git blame ou git log sur les fichiers qui étaient à l’origine dans les sous-modules. En fait, ce que vous avez fait ici est de renommer de nombreux fichiers dans un même référentiel, et git devrait le détecter automatiquement. Si vous avez toujours des problèmes avec git log, essayez certaines options (–follow, -M, -C) qui permettent de renommer / copier la détection.

Depuis git 1.8.5 (novembre 2013 ) ( sans conserver l’historique du sous-module ):

 mv yoursubmodule yoursubmodule_tmp git submodule deinit yourSubmodule git rm yourSubmodule mv yoursubmodule_tmp yoursubmodule git add yoursubmodule 

Cela va:

  • désenregistrer et décharger (c’est-à-dire supprimer le contenu de ) le sous-module ( deinit , donc le mv premier ),
  • nettoyer les .gitmodules pour vous ( rm ),
  • et supprimez l’ entrée spéciale représentant ce sous-module SHA1 dans l’index du référentiel parent ( rm ).

Une fois la suppression du sous-module terminée ( deinit et git rm ), vous pouvez renommer le dossier à son nom d’origine et l’append au répertoire git en tant que dossier normal.

Remarque: si le sous-module a été créé par un ancien Git (<1.8), vous devrez peut-être supprimer le dossier .git nested dans le sous-module lui-même, comme indiqué par Simon East.


Si vous devez conserver l’historique du sous-module, consultez la réponse de jsears , qui utilise git filter-branch .

J’ai créé un script qui traduira un sous-module en un simple répertoire, tout en conservant l’historique de tous les fichiers. Il ne souffre pas des problèmes git log --follow dont souffrent les autres solutions. C’est aussi une invocation très simple d’une ligne qui fait tout le travail pour vous. G’luck.

Il se base sur l’excellent travail de Lucas Jenß, décrit dans son blog ” Intégrer un sous-module dans le référentiel parent “, mais automatise l’ensemble du processus et nettoie quelques autres cas en coin.

Le dernier code sera maintenu avec des corrections de bogues sur github à l’ adresse https://github.com/jeremysears/scripts/blob/master/bin/git-submodule-rewrite , mais pour le bon protocole de réponse de stackoverflow, j’ai inclus le solution dans son intégralité ci-dessous.

Usage:

 $ git-submodule-rewrite  

git-submodule-rewrite:

 #!/usr/bin/env bash # This script builds on the excellent work by Lucas Jenß, described in his blog # post "Integrating a submodule into the parent repository", but automates the # entire process and cleans up a few other corner cases. # https://x3ro.de/2013/09/01/Integrating-a-submodule-into-the-parent-repository.html function usage(){ echo "Merge a submodule into a repo, retaining file history." echo "Usage: $0 " echo "" echo "options:" echo " -h, --help Print this message" echo " -v, --verbose Display verbose output" } function abort { echo "$(tput setaf 1)$1$(tput sgr0)" exit 1 } function request_confirmation { read -p "$(tput setaf 4)$1 (y/n) $(tput sgr0)" [ "$REPLY" == "y" ] || abort "Aborted!" } function warn() { cat << EOF This script will convert your "${sub}" git submodule into a simple subdirectory in the parent repository while retaining all contents and file history. The script will: * delete the ${sub} submodule configuration from .gitmodules and .git/config and commit it. * rewrite the entire history of the ${sub} submodule so that all paths are prefixed by ${path}. This ensures that git log will correctly follow the original file history. * merge the submodule into its parent repository and commit it. NOTE: This script might completely garble your repository, so PLEASE apply this only to a fresh clone of the repository where it does not matter if the repo is destroyed. It would be wise to keep a backup clone of your repository, so that you can reconstitute it if need be. You have been warned. Use at your own risk. EOF request_confirmation "Do you want to proceed?" } function git_version_lte() { OP_VERSION=$(printf "%03d%03d%03d%03d" $(echo "$1" | tr '.' '\n' | head -n 4)) GIT_VERSION=$(git version) GIT_VERSION=$(printf "%03d%03d%03d%03d" $(echo "${GIT_VERSION#git version}" | tr '.' '\n' | head -n 4)) echo -e "${GIT_VERSION}\n${OP_VERSION}" | sort | head -n1 [ ${OP_VERSION} -le ${GIT_VERSION} ] } function main() { warn if [ "${verbose}" == "true" ]; then set -x fi # Remove submodule and commit git config -f .gitmodules --remove-section "submodule.${sub}" if git config -f .git/config --get "submodule.${sub}.url"; then git config -f .git/config --remove-section "submodule.${sub}" fi rm -rf "${path}" git add -A . git commit -m "Remove submodule ${sub}" rm -rf ".git/modules/${sub}" # Rewrite submodule history local tmpdir="$(mktemp -d -t submodule-rewrite-XXXXXX)" git clone "${url}" "${tmpdir}" pushd "${tmpdir}" local tab="$(printf '\t')" local filter="git ls-files -s | sed \"s/${tab}/${tab}${path}\//\" | GIT_INDEX_FILE=\${GIT_INDEX_FILE}.new git update-index --index-info && mv \${GIT_INDEX_FILE}.new \${GIT_INDEX_FILE}" git filter-branch --index-filter "${filter}" HEAD popd # Merge in rewritten submodule history git remote add "${sub}" "${tmpdir}" git fetch "${sub}" if git_version_lte 2.8.4 then # Previous to git 2.9.0 the parameter would yield an error ALLOW_UNRELATED_HISTORIES="" else # From git 2.9.0 this parameter is required ALLOW_UNRELATED_HISTORIES="--allow-unrelated-histories" fi git merge -s ours --no-commit ${ALLOW_UNRELATED_HISTORIES} "${sub}/master" rm -rf tmpdir # Add submodule content git clone "${url}" "${path}" rm -rf "${path}/.git" git add "${path}" git commit -m "Merge submodule contents for ${sub}" git config -f .git/config --remove-section "remote.${sub}" set +x echo "$(tput setaf 2)Submodule merge complete. Push changes after review.$(tput sgr0)" } set -euo pipefail declare verbose=false while [ $# -gt 0 ]; do case "$1" in (-h|--help) usage exit 0 ;; (-v|--verbose) verbose=true ;; (*) break ;; esac shift done declare sub="${1:-}" if [ -z "${sub}" ]; then >&2 echo "Error: No submodule specified" usage exit 1 fi shift if [ -n "${1:-}" ]; then >&2 echo "Error: Unknown option: ${1:-}" usage exit 1 fi if ! [ -d ".git" ]; then >&2 echo "Error: No git repository found. Must be run from the root of a git repository" usage exit 1 fi declare path="$(git config -f .gitmodules --get "submodule.${sub}.path")" declare url="$(git config -f .gitmodules --get "submodule.${sub}.url")" if [ -z "${path}" ]; then >&2 echo "Error: Submodule not found: ${sub}" usage exit 1 fi if ! [ -d "${path}" ]; then >&2 echo "Error: Submodule path not found: ${path}" usage exit 1 fi main 
  1. git rm --cached the_submodule_path
  2. supprimer la section .submodules fichier .submodules
  3. faire un commit “sous-module enlevé xyz”
  4. git add the_submodule_path
  5. un autre commit “base de code ajoutée de xyz”

Je n’ai pas trouvé de moyen plus facile encore. Vous pouvez compresser 3-5 en une seule étape via git commit -a – une question de goût.

Il nous est arrivé de créer 2 référentiels pour 2 projets tellement couplés qu’il n’était pas logique de les séparer. Nous les avons donc fusionnés.

Je vais vous montrer comment fusionner les twigs principales en premier et ensuite, je vous expliquerai comment étendre cela à toutes les twigs que vous avez, en espérant que cela vous aidera.

Si le sous-module fonctionne et que vous voulez le convertir en un répertoire en place, vous pouvez:

 git clone project_uri project_name 

Ici nous faisons un clone propre pour fonctionner. Pour ce processus, vous n’avez pas besoin d’initialiser ou de mettre à jour les sous-modules. Ignorez-le.

 cd project_name vim .gitmodules 

Modifiez les .gitmodules avec votre éditeur favori (ou Vim) pour supprimer le sous-module que vous souhaitez remplacer. Les lignes à supprimer doivent ressembler à ceci:

 [submodule "lib/asi-http-request"] path = lib/asi-http-request url = https://github.com/pokeb/asi-http-request.git 

Après avoir enregistré le fichier,

 git rm --cached directory_of_submodule git commit -am "Removed submodule_name as submodule" rm -rf directory_of_submodule 

Ici, nous supprimons complètement la relation de sous-module afin que nous puissions créer l’autre repo dans le projet sur place.

 git remote add -f submodule_origin submodule_uri git fetch submodel_origin/master 

Ici, nous récupérons le référentiel de sous-modules à fusionner.

 git merge -s ours --no-commit submodule_origin/master 

Ici, nous commençons une opération de fusion des 2 référentiels, mais nous nous arrêtons avant la validation.

 git read-tree --prefix=directory_of_submodule/ -u submodule_origin/master 

Ici, nous envoyons le contenu de master dans le sous-module dans le répertoire où il se trouvait avant de préfixer un nom de répertoire

 git commit -am "submodule_name is now part of main project" 

Ici, nous complétons la procédure en effectuant une validation des modifications dans la fusion.

Après avoir terminé ceci, vous pouvez appuyer sur, et recommencer avec n’importe quelle autre twig à fusionner, il suffit de récupérer la twig dans votre référentiel qui recevra les modifications et changera la twig dans laquelle vous apporterez les opérations de fusion et de lecture.

Beaucoup de réponses ici mais toutes semblent trop complexes et ne font probablement pas ce que vous voulez. Je suis sûr que la plupart des gens veulent garder leur histoire.

Pour cet exemple, le git@site.com:main/main.git sera git@site.com:main/main.git et le repo du sous-module sera git@site.com:main/child.git . Cela suppose que le sous-module se trouve dans le répertoire racine du repository parent. Ajustez les instructions si nécessaire.

Commencez par cloner le référentiel parent et en supprimant l’ancien.

 git clone git@site.com:main/main.git git submodule deinit child git rm child git add --all git commit -m "remove child submodule" 

Nous allons maintenant append les pensions de pension en amont du repository principal.

 git remote add upstream git@site.com:main/child.git git fetch upstream git checkout -b merge-prep upstream/master 

L’étape suivante suppose que vous souhaitiez déplacer les fichiers de la twig merge-prep vers le même emplacement que le sous-module, bien que vous puissiez facilement modifier l’emplacement en modifiant le chemin du fichier.

 mkdir child 

déplacez tous les dossiers et fichiers à l’exception du dossier .git dans le dossier enfant.

 git add --all git commit -m "merge prep" 

Maintenant, vous pouvez simplement fusionner vos fichiers dans la twig principale.

 git checkout master git merge merge-prep # --allow-unrelated-histories merge-prep flag may be required 

Regardez autour de vous et assurez-vous que tout semble bon avant de lancer git push

La seule chose dont vous devez vous souvenir maintenant est que git log ne suit pas par défaut les fichiers déplacés. Cependant, en exécutant git log --follow filename vous pouvez voir l’historique complet de vos fichiers.

La meilleure réponse à cette question est la suivante:

http://x3ro.de/2013/09/01/Integrating-a-submodule-into-the-parent-repository.html

Cet article explique très bien la procédure.

Lorsque

 git rm [-r] --cached submodule_path 

résultats

 fatal: pathspec 'emr/normalizers/' did not match any files 

Contexte: J’ai fait rm -r .git* dans mes dossiers de sous-modules avant de me rendre compte qu’ils devaient être dé-décomposés dans le projet principal auquel je venais de les append. J’ai eu l’erreur ci-dessus lors de la sous-modulation de certains, mais pas tous. Quoi qu’il en soit, je les ai corrigés en cours d’exécution (après, bien sûr, le rm -r .git* )

 mv submodule_path submodule_path.temp git add -A . git commit -m "De-submodulization phase 1/2" mv submodule_path.temp submodule_path git add -A . git commit -m "De-submodulization phase 2/2" 

Notez que cela ne préserve pas l’histoire.

Voici une version légèrement améliorée (IMHO) de la top-réponse actuelle:

Dans un répertoire séparé (pour faciliter le nettoyage et réessayer), jetez un œil à la fois au repo supérieur et au sous-ordre.

 git clone ../main_repo main.tmp git clone ../main_repo/sub_repo sub.tmp 

Commencez par éditer le sous-ordre pour déplacer tous les fichiers dans le sous-répertoire souhaité.

 cd sub.tmp mkdir sub_repo_path git mv `ls | grep -v sub_repo_path` sub_repo_path/ git commit -m "Moved entire subrepo into sub_repo_path" 

Prenez note de la tête

 SUBREPO_HEAD=`git reflog | awk '{ print $1; exit; }'` 

Maintenant, retirez la sous-liste du repository principal

 cd ../main.tmp rmdir sub_repo_path vi .gitmodules # remove config for submodule git add -A git commit -m "Removed submodule sub_repo_path in preparation for merge" 

Et finalement, il suffit de les fusionner

 git fetch ../sub.tmp git merge $SUBREPO_HEAD 

Et fait! En toute sécurité et sans magie.

Sur la base de la réponse de VonC , j’ai créé un simple script bash. L’ add à la fin doit utiliser des caractères génériques, sinon il annulera le rm précédent pour le sous-module lui-même. Il est important d’append le contenu du répertoire du sous-module et de ne pas nommer le répertoire lui-même dans la commande add .

Dans un fichier appelé git-integrate-submodule :

 #!/usr/bin/env bash mv "$1" "${1}_" git submodule deinit "$1" git rm "$1" mv "${1}_" "$1" git add "$1/**" 

J’ai trouvé plus pratique de récupérer (également?) Des données de validation locales du sous-module, car sinon je les perdrais. (Impossible de les pousser car je n’ai pas access à cette télécommande). J’ai donc ajouté submodule / .git comme remote_origin2, récupéré et fusionné depuis cette twig. Je ne suis pas sûr d’avoir encore besoin du sous-module distant, car je ne connais pas encore suffisamment git.