web-dev-qa-db-fra.com

Comment transformer un répertoire existant dans un référentiel git en un sous-module git

Je suis très confus à propos des sous-modules git.

Fondamentalement, mon problème est que je ne peux pas faire comprendre à git que ~/main-project/submodule est un sous-module.


J'ai une bonne expérience des sous-modules git:
dans mon référentiel de fichiers dot J'ai créé le fichier .gitmodules dans ~/dotfiles-repo et y ai ajouté des chemins et des URL. Depuis lors, si je modifie les fichiers des sous-modules et exécute git status, j'obtiens un résultat du type: .vim/bundle/auto-complete (new commits) # in red.

J'ai créé le fichier .gitmodules dans ~/main-project mais:

  • Si j'apporte des modifications à ~/main-project/submodule et même pousse les modifications, je ne reçois pas une réponse similaire à celle de <submodule> (new commits) # in red lors de l'exécution de git status dans ~/main-projectJe viens de connaître les modifications apportées à ces répertoires
  • Lorsque je clique sur les liens des dossiers à github pour ces répertoires, cela ne me dirige pas vers les référentiels eux-mêmes, mais je reste dans le même référentiel.

    1. Peut-être que je manque le point entier. Quelles sont les principales caractéristiques des sous-modules?
    2. Pourquoi git comprend-il les sous-modules dans le dépôt de fichiers de points mais pas dans mon autre dépôt ?
    3. Est-ce parce que j'ai déjà dit à git d'ajouter les fichiers dans ~/main-project/submodule à l'index?

J'ai lu cette question qui m'a amené à cette réponse Mais je ne suis pas sûr d'avoir besoin de git-subtree. Je ne veux pas faire des choses qui pourraient faire des changements difficiles à revenir.

Edit: Cette solution de doublon suggérée n’a pas fonctionné non plus, j’ai reçu une erreur qui Updates were rejected because the remote contains work that you do not have locally. Il semble que @GabLeRoux m'a pratiquement dit de transmettre <repo-A> à l'URL de <repo-B>.

20
Doron Behar

La solution est assez simple. Il a été extrait de ici .

  1. git rm submodule-dir
    Ceci supprimera tous les fichiers que git suivait après dans submodule-dir
  2. rm -rf submoduledir
    Ceci supprimera tous les autres fichiers qui auraient pu rester dans submodule-dir car git les aurait ignorés.
  3. Maintenant, nous devons nous engager pour supprimer les fichiers de l'index:
    git commit
    Après la validation, nous avons nettoyé les fichiers suivis et non suivis par git dans le submodul-dir. Il est maintenant temps de le faire:
  4. git submodule add <remote-path-to-submodule>
    Cela rajoutera le sous-module mais comme un vrai sous-module.
  5. À ce stade, il peut être judicieux de vérifier .gitmodules et de voir si les sous-modules ont été ajoutés avec succès. Dans mon cas, j'avais déjà un fichier .gitmodules et je devais le modifier.

MODIFIER

Depuis v2.12.0-rc0 , et après ce commit , Nous avons reçu git submodule absorbgitdirs et c’est exactement ce dont j'avais besoin au moment de poser cette question.

C’est ce que fait la docs state cette commande:

Si un répertoire git d'un sous-module est à l'intérieur du sous-module, déplacez le répertoire git du sous-module dans ses superprojets $GIT_DIR/modules chemin puis connectez le répertoire git et son répertoire de travail en définissant le core.worktree et en ajoutant un fichier .git pointant vers le répertoire git incorporé dans le fichier superprojects répertoire git.

Donc, au lieu de tout recommencer, comme suggéré dans les réponses précédentes par @DomQ et moi-même, on peut simplement ajouter exécuter ce qui suit:

  1. Sans supprimer de l'index le sous-module, ajoutez l'URL du sous-module à .gitmodules et à .git/config avec
    git submodule add <url> <path>
  2. Déplacez le répertoire $GIT_DIR du sous-module (.git dans les référentiels classiques) vers .git/modules/<path> avec
    git submodule absorbgitdirs <path>
21
Doron Behar

Il n’existe fondamentalement pas de meilleur moyen que de prétendre recommencer:

  1. s'assurer que tout est engagé partout
  2. éloignez votre sous-référentiel
  3. git submodule add depuis le sous-référentiel distant
  4. cd mysubmodule
  5. git fetch ../wherever/you/stashed/the/sub-repository/in/step-1
  6. git merge FETCH_HEAD

Pour expliquer pourquoi, il me semble qu’une compréhension plus approfondie des sous-modules are est nécessaire, que ce que l’on peut extraire de la page de manuel git-submodule(1) (ou même du pertinent)). chapitre du livre Git ). J'ai trouvé quelques explications plus détaillées sur cet article , mais comme cet article est un peu long, je prends la liberté de les résumer ici.

À un niveau bas, un sous-module git comprend les éléments suivants,

  • Un objet commit en haut de l'arborescence des sous-modules,
  • (Dans les versions récentes de Git) Un sous-répertoire dans .git/modules pour héberger les objets Git du sous-module,
  • Une entrée dans le fichier de configuration .gitmodules.

L'objet commit est contenu (ou plus précisément, référencé par SHA1) dans l'objet arbre parent. Ceci est inhabituel, car les choses (généralement } _ se produisent dans l'autre sens, mais cela explique pourquoi vous voyez un répertoire apparaître dans le git status du référentiel principal après que vous ayez effectué une validation dans le sous-module. Vous pouvez également créer quelques expériences avec git ls-tree pour observer cet objet commit plus en détail.

Le sous-répertoire dans .git/modules correspond à un sous-répertoire .git dans le sous-module; et en fait, il y a un .gitfichier dans le sous-module qui pointe vers l'ancien en utilisant une ligne gitdir:. C'est le comportement par défaut depuis la version 1.7.8 de Git . Vous ne savez pas pourquoi tout ne fonctionnerait pas si vous gardiez un répertoire .git séparé, sauf indication contraire dans les notes de mise à jour, vous rencontrerez probablement des problèmes lors du passage d'une branche contenant le sous-module à une autre.

Le fichier .gitmodules fournit l'URL que git submodule update --remote et ses amis doivent extraire; qui est évidemment distinct de l'ensemble des télécommandes du référentiel principal. Notez également que .gitmodules est partiellement copié dans .git/config par la commande git submodule sync et les autres commandes l’appelant en arrière-plan.

Bien qu'il soit assez facile de faire les modifications nécessaires manuellement pour .gitmodules + .git/config, et aussi pour .git/modules + mysubmodule/.git (et en fait, il existe même git submodule absorbgitdirs pour ce dernier), il n'y a pas vraiment de porcelaine pour créer uniquement le objet de validation in-tree. D'où la solution proposée en déplaçant + refaisant les modifications présentées ci-dessus.

3
DomQ

Pour répondre à vos questions dans l'ordre:

  1. Le but des sous-modules selon GitHub. En termes de fonctionnalités, il a été conçu pour être conceptualisé comme un référentiel enfant (qui peut presque être traité comme tout autre fichier), c'est-à-dire contrôlé par la version d'un référentiel parent, où le parent suit l'ID de validation actuel du sous-module ) plutôt que de contenu.
  2. C'est probablement parce que vous avez déjà ajouté les fichiers à l'index du référentiel. Dans ce cas, la solution consiste à git rm --cached submodule-name/. Créez ensuite une validation intermédiaire, suivie de l'ajout du dossier en tant que référentiel: git add submodule-name (notez qu'il y a no slash final après le nom du sous-module dans le cas des sous-modules).
  3. Oui :)

La réponse que vous avez mentionnée peut également corriger l’historique de vos commits:

  1. Avantages:

Ce dossier sera traité comme un sous-module dans l'ensemble de votre historique de validation, pas seulement dans tous les futurs commits. Cela évite toute complication si vous passez à une version précédente dans laquelle elle était traitée comme un dossier. Ceci est une complication, car lorsque vous revenez au sommet de votre branche, vous devrez peut-être également entrer votre sous-module et vérifier le dernier commit pour restaurer tous les fichiers (qui peuvent être supprimés de votre répertoire de travail). Cela pourrait être évité en effectuant une sorte de vérification récursive de votre dernier commit.

  1. Désavantages:

Si l'historique de validation est modifié, tous les autres contributeurs devront également re-cloner le projet, car ils auront des conflits de fusion ou une situation pire. réintroduire le problème engage à nouveau dans le projet.

1
reubenjohn