1132 votes

Comment puis-je spécifier une branche/un tag lors de l'ajout d'un sous-module Git ?

Comment git submodule add -b travail ?

Après avoir ajouté un submodule avec une branche spécifique, un nouveau dépôt cloné (après git submodule update --init ) sera à un commit spécifique, pas à la branche elle-même ( git status sur le sous-module montre "Not currently on any branch").

Je ne peux pas trouver d'informations sur .gitmodules o .git/config de la branche du sous-module ou d'un commit spécifique, alors comment Git s'y prend-il ?

En outre, est-il possible de spécifier une étiquette au lieu d'une branche ?

J'utilise la version 1.6.5.2.

6 votes

Si vous avez un existant sous-module qui ne suit pas encore une branche mais vous souhaitez qu'il suive une branche... voir ma réponse ci-dessous

1097voto

Johnny Z Points 846

J'aimerais ajouter ici une réponse qui n'est en fait qu'un conglomérat d'autres réponses, mais je pense qu'elle est peut-être plus complète.

Vous savez que vous avez un sous-module Git lorsque vous avez ces deux choses.

  1. Votre .gitmodules a une entrée comme celle-ci :

    [submodule "SubmoduleTestRepo"]
        path = SubmoduleTestRepo
        url = https://github.com/jzaccone/SubmoduleTestRepo.git
  2. Vous avez un objet submodule (nommé SubmoduleTestRepo dans cet exemple) dans votre dépôt Git. GitHub les présente comme des objets "submodule". Ou bien git submodule status depuis une ligne de commande. Les objets sous-modules Git sont des types particuliers d'objets Git, et ils contiennent les informations SHA pour un commit spécifique.

    Chaque fois que vous faites un git submodule update il remplira votre sous-module avec le contenu du commit. Il sait où trouver le commit grâce aux informations contenues dans le fichier .gitmodules .

    Maintenant, tous les -b consiste à ajouter une ligne dans votre .gitmodules fichier. Donc, en suivant le même exemple, cela ressemblerait à ceci :

    [submodule "SubmoduleTestRepo"]
        path = SubmoduleTestRepo
        url = https://github.com/jzaccone/SubmoduleTestRepo.git
        branch = master

    Note : seul le nom de la branche est pris en charge dans un .gitmodules mais SHA et TAG ne sont pas supportés ! (au lieu de cela, le commit de la branche pour chaque module peut être suivi et mis à jour en utilisant " git add . ", par exemple comme git add ./SubmoduleTestRepo et vous n'avez pas besoin de modifier le .gitmodules chaque fois)

    L'objet submodule pointe toujours vers un commit spécifique. La seule chose que l'objet -b vous offre la possibilité d'ajouter une --remote drapeau à votre mise à jour selon la réponse de Vogella :

    git submodule update --remote

    Au lieu de remplir le contenu du sous-module avec le commit pointé par le sous-module, il remplace ce commit par le dernier commit de la branche maître, puis il remplit le sous-module avec ce commit. Ceci peut être fait en deux étapes par la réponse de djacobs7. Puisque vous avez maintenant mis à jour le commit vers lequel l'objet du submodule pointe, vous devez commiter l'objet modifié du submodule dans votre dépôt Git.

    git submodule add -b n'est pas un moyen magique de tout maintenir à jour avec une branche. Il s'agit simplement d'ajouter des informations sur une branche dans le fichier .gitmodules et vous donne l'option de mettre à jour l'objet submodule au dernier commit d'une branche spécifiée avant de le remplir.

0 votes

Bonne réponse, je suis arrivé à ce poste par un lien ailleurs. Cela me laisse perplexe : vous faites référence à l'option -b sans la mentionner auparavant ?

0 votes

Merci. -b était référencé dans la question. git submodule add [-b] est la façon dont vous ajoutez un sous-module à votre dépôt git.

38 votes

Cette réponse devrait avoir plus de votes positifs. J'ai lu de nombreux messages au cours de la dernière journée et cette réponse dissipe toute confusion. Venant du monde SVN et utilisant des externes - on veut croire que le suivi de branche du sous-module git garde magiquement tout à jour depuis la branche - mais ce n'est pas vrai ! Vous devez explicitement les mettre à jour ! Comme vous le mentionnez, vous devez commiter les objets modifiés du submodule.

959voto

djacobs7 Points 3131

Note : Git 1.8.2 a ajouté la possibilité de suivre les branches. Voir certaines des réponses ci-dessous.


Il est un peu déroutant de s'y habituer, mais les sous-modules ne sont pas sur une branche. Ils sont, comme vous le dites, juste un pointeur vers un commit particulier du dépôt du submodule.

Cela signifie que, lorsque quelqu'un d'autre extrait votre dépôt, ou tire votre code, et fait git submodule update, le submodule est extrait à ce commit particulier.

C'est très bien pour un sous-module qui ne change pas souvent, parce que tout le monde sur le projet peut avoir le sous-module au même commit.

Si vous voulez déplacer le sous-module vers une étiquette particulière :

cd submodule_directory
git checkout v1.0
cd ..
git add submodule_directory
git commit -m "moved submodule to v1.0"
git push

Ensuite, un autre développeur qui veut que submodule_directory soit changé en cette balise, fait ceci

git pull
git submodule update --init

git pull les changements de commit vers lesquels le répertoire de leur sous-module pointe. git submodule update fusionne en fait le nouveau code.

16 votes

C'est une très bonne explication, merci ! Et bien sûr, après avoir lu votre réponse, j'ai réalisé que le commit est enregistré à l'intérieur du submodule lui-même (submodule/.git/HEAD).

0 votes

Est-il possible de réaliser quelque chose comme le branchement svn mais avec des submodules ? Dans svn, vous pouvez créer une branche et la fusionner avec le tronc (et éventuellement avec d'autres branches existantes). Ensuite, vous pouvez les fusionner toutes avec le tronc. Est-ce que quelque chose comme cela est possible, mais avec des submodules Git ?

6 votes

Cela ne semble pas fonctionner sur git 1.7.4.4. cd my_submodule; git checkout [ref in submodule's repository donne fatal: reference is not a tree: ... . C'est comme si git ne fonctionnera que sur le référentiel parent.

479voto

VonC Points 414372

(Git 2.22, Q2 2019, a introduit git submodule set-branch --branch aBranch -- <submodule_path> )

Notez que si vous avez un existant sous-module qui n'est pas suivi d'une branche pour le moment alors ( si vous avez git 1.8.2+. ):

  • S'assurer que le repo parent sait que son sous-module suit maintenant une branche :

      cd /path/to/your/parent/repo
      git config -f .gitmodules submodule.<path>.branch <branch>
  • Assurez-vous que votre sous-module est bien au plus récent de cette branche :

      cd path/to/your/submodule
      git checkout -b branch --track origin/branch
        # if the master branch already exist:
        git branch -u origin/master master

         (l'"origine" étant le nom de l'unité d'origine). repo distant en amont à partir duquel le sous-module a été cloné.
         A git remote -v à l'intérieur de ce sous-module l'affichera. En général, il s'agit de "origin")

  • N'oubliez pas d'enregistrer le nouvel état de votre sous-module dans votre dépôt parent :

      cd /path/to/your/parent/repo
      git add path/to/your/submodule
      git commit -m "Make submodule tracking a branch"
  • Les mises à jour ultérieures pour ce sous-module devront utiliser le paramètre --remote option :

      # update your submodule
      # --remote will also fetch and ensure that
      # the latest commit from the branch is used
      git submodule update --remote
    
      # to avoid fetching use
      git submodule update --remote --no-fetch 

Notez qu'avec Git 2.10+. (Q3 2016), vous pouvez utiliser ' . comme nom de branche :

Le nom de la branche est enregistré comme submodule.<name>.branch sur .gitmodules para update --remote .
Une valeur spéciale de . est utilisé pour indiquer que le nom de la branche dans le sous-module doit être le même que celui de la branche courante dans le référentiel courant. .

Mais, comme commenté par LubosD

Avec git checkout si le nom de la branche à suivre est " . ", cela tuera votre travail non engagé !
Utilisez git switch à la place.

Cela signifie Git 2.23 (août 2019) ou plus.

Voir " Confus par git checkout "


Si vous voulez mettre à jour tous vos sous-modules en suivant une branche :

    git submodule update --recursive --remote

Notez que le résultat, pour chaque sous-module mis à jour, sera presque toujours être un HEAD détaché comme Dan Cameron note en sa réponse .

( Clintm notes dans les commentaires que, si vous exécutez git submodule update --remote et le sha1 résultant est le même que la branche sur laquelle le submodule est actuellement, il ne fera rien et laissera le submodule toujours "sur cette branche" et non dans l'état de tête détachée).

Pour s'assurer que la branche est effectivement extraite (et que cela ne modifiera pas le SHA1 de l'archive entrée spéciale représentant le sous-module pour le repo parent), il suggère :

git submodule foreach -q --recursive 'branch="$(git config -f $toplevel/.gitmodules submodule.$name.branch)"; git switch $branch'

Chaque sous-module référencera toujours le même SHA1, mais si vous faites de nouveaux commits, vous pourrez les pousser car ils seront référencés par la branche que vous voulez que le sous-module suive.
Après ce push dans un submodule, n'oubliez pas de retourner dans le repo parent, d'ajouter, de commiter et de pousser le nouveau SHA1 pour ces submodules modifiés.

Notez l'utilisation de $toplevel recommandé dans les commentaires par Alexander Pogrebnyak .
$toplevel a été introduit dans git1.7.2 en mai 2010 : commettre f030c96 .

il contient le chemin absolu du répertoire de niveau supérieur (où .gitmodules est).

dtmland ajoute dans les commentaires :

Le foreach script échouera à extraire les submodules qui ne suivent pas une branche.
Cependant, cette commande vous donne les deux :

 git submodule foreach -q --recursive 'branch="$(git config -f $toplevel/.gitmodules submodule.$name.branch)"; [ "$branch" = "" ] && git checkout master || git switch $branch' –

La même commande mais plus facile à lire :

git submodule foreach -q --recursive \
    'branch="$(git config -f $toplevel/.gitmodules submodule.$name.branch)"; \
     [ "$branch" = "" ] && \
     git checkout master || git switch $branch' –

umläute affine dtmland avec une version simplifiée dans les commentaires :

git submodule foreach -q --recursive 'git switch $(git config -f $toplevel/.gitmodules submodule.$name.branch || echo master)'

plusieurs lignes :

git submodule foreach -q --recursive \
  'git switch \
  $(git config -f $toplevel/.gitmodules submodule.$name.branch || echo master)'

Avant Git 2.26 (Q1 2020), un fetch qui est chargé de récupérer récursivement les mises à jour dans les submodules produit inévitablement des tonnes de données et il devient difficile de repérer les messages d'erreur.

La commande a été apprise pour énumérer les sous-modules qui avaient des erreurs à la fin de l'opération .

Voir engagement 0222540 (16 janvier 2020) par Emily Shaffer ( nasamuffin ) .
(fusionné par Junio C Hamano -- gitster -- sur commettre b5c71cc , 05 Feb 2020)

fetch : accentuer l'échec lors de la récupération du sous-module

Signé par : Emily Shaffer

Lorsqu'une recherche de sous-modules échoue alors qu'il y a de nombreux sous-modules, l'erreur liée à la seule recherche de sous-modules qui échoue est noyée sous l'activité des autres sous-modules si plusieurs recherches se sont soldées par un échec. fetch-by-oid .
Signaler un échec tardif afin que l'utilisateur sache que quelque chose s'est mal passé et à quel endroit. .

Parce que fetch_finish() n'est appelé de manière synchrone que par run_processes_parallel, le mutexing n'est pas nécessaire autour de submodules_with_errors .


Notez que, avec Git 2.28 (Q3 2020), la réécriture de certaines parties de la commande scriptée "git submodule" Porcelain se poursuit ; cette fois, il s'agit de " git submodule set-branch C'est le tour de la sous-commande ".

Voir commettre 2964d6e (02 Jun 2020) par Shourya Shukla ( periperidip ) .
(fusionné par Junio C Hamano -- gitster -- sur commettre 1046282 25 juin 2020)

submodule : sous-commande de portage 'set-branch' du shell vers C

Parrainé par : Christian Couder
Mentoré par : Kaartic Sivaraam
Assisté par : Denton Liu
Assisté par : Eric Sunshine
Aide : Đoàn Trần Công Danh
Signé par : Shourya Shukla

Convertir la sous-commande du sous-module 'set-branch' en un buildin et l'appeler via git submodule.sh .

2 votes

Question : si j'ai le dossier subModule1 et que je souhaite suivre la branche principale, la commande résultante sera-t-elle la suivante ? git config -f .gitmodules submodule.subModule1.branch master

0 votes

@BraveNewMath Si votre sous-module se trouve directement sous le Root de votre repo parent, alors oui, puisqu'il représente son chemin dans le repo parent : submodule.<path>.branch . Mais n'oubliez pas les autres étapes.

1 votes

El foreach script ne dépendra pas du code dur <path> si vous remplacez <path> con $toplevel/ .

321voto

vogella Points 4884

Git 1.8.2 a ajouté la possibilité de suivre les branches.

# add submodule to track branch_name branch
git submodule add -b branch_name URL_to_Git_repo optional_directory_rename

# update your submodule
git submodule update --remote 

Voir aussi Sous-modules Git

16 votes

Cela s'applique-t-il également aux étiquettes ?

0 votes

Il n'y a aucune utilité à suivre une balise car elle est censée être un point fixe dans le code. Pour le verrouillage d'une balise, voir l'exemple de djacobs7. réponse . - @ThorSummoner

1 votes

Comment le fait d'ajouter un sous-module de cette manière se répercute sur .gitmodules fichier ?

75voto

Johan Points 6127

Un exemple de la façon dont j'utilise les submodules Git.

  1. Créer un nouveau référentiel
  2. Puis clonez un autre dépôt en tant que sous-module
  3. Ensuite, nous avons ce sous-module qui utilise une balise appelée V3.1.2.
  4. Et puis nous nous engageons.

Et ça ressemble un peu à ça :

git init 
vi README
git add README
git commit 
git submodule add git://github.com/XXXXX/xxx.yyyy.git stm32_std_lib
git status

git submodule init
git submodule update

cd stm32_std_lib/
git reset --hard V3.1.2 
cd ..
git commit -a

git submodule status 

Peut-être que cela aide (même si j'utilise une balise et non une branche) ?

5 votes

C'est en gros la même réponse que djacobs7, mais merci quand même :)

1 votes

Devriez-vous être en mesure d'effectuer un changement après que votre git reset --hard V3.1.2 ? J'obtiens juste un "rien à commettre" avec un git status du répertoire parent.

1 votes

@Ivan : Pourriez-vous expliquer en quoi cela est identique à la réponse de djacobs7 ? D'après ce que je vois, sa réponse n'inclut même pas la commande 'submodule add', à la place le repo est ajouté directement, sans aucun lien vers le repo git original du module. En tout cas, lorsque j'ai essayé cette approche, il n'y avait pas de lien dans .gitmodules.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X