Un moyen facile de tirer le dernier de tous les sous-modules git
-
06-07-2019 - |
Question
Nous utilisons des sous-modules git pour gérer deux projets volumineux qui dépendent de nombreuses autres bibliothèques que nous avons développées. Chaque bibliothèque est un rapport distinct introduit dans le projet dépendant en tant que sous-module. Pendant le développement, nous souhaitons souvent simplement récupérer la dernière version de chaque sous-module dépendant.
Git a-t-il une commande intégrée pour le faire? Si ce n’est pas le cas, qu’en est-il un fichier de commandes Windows ou similaire capable de le faire?
La solution
Si c'est la première fois que vous extrayez un dépôt, vous devez d'abord utiliser - init
:
git submodule update --init --recursive
Pour git 1.8.2 ou supérieure, l'option - remote
a été ajoutée pour permettre la mise à jour des derniers conseils des branches distantes:
git submodule update --recursive --remote
Cela présente l’avantage supplémentaire de respecter les options "" non default". branches spécifiées dans les fichiers .gitmodules
ou .git / config
(si vous en avez, par défaut, origine / maître, auquel cas certaines des autres réponses ici seraient fonctionne également).
Pour git 1.7.3 ou supérieur, vous pouvez utiliser (mais les pièges ci-dessous s'appliquent à la mise à jour qui s'applique toujours):
git submodule update --recursive
ou:
git pull --recurse-submodules
si vous souhaitez extraire vos sous-modules des derniers commits et de ce que le repo pointe vers.
Voir git-submodule (1) pour plus de détails
Autres conseils
Si vous devez extraire des éléments pour les sous-modules dans vos référentiels de sous-modules, utilisez
git pull --recurse-submodules
une fonctionnalité que Git a apprise pour la première fois en 1.7.3.
Mais cela ne permet pas de vérifier les commits appropriés (ceux sur lesquels pointe votre référentiel principal) dans les sous-modules
.Pour valider les commits appropriés dans vos sous-modules, vous devez les mettre à jour après avoir extrait à l'aide de
.git submodule update --recursive --remote
Sur init, exécutez la commande suivante:
git submodule update --init --recursive
dans le répertoire git repo, me convient le mieux.
Ceci extraira tous les derniers sous-modules, y compris.
a expliqué
git - the base command to perform any git command
submodule - Inspects, updates and manages submodules.
update - Update the registered submodules to match what the superproject
expects by cloning missing submodules and updating the working tree of the
submodules. The "updating" can be done in several ways depending on command
line options and the value of submodule.<name>.update configuration variable.
--init without the explicit init step if you do not intend to customize
any submodule locations.
--recursive is specified, this command will recurse into the registered
submodules, and update any nested submodules within.
Après cela, vous pouvez simplement exécuter:
git submodule update --recursive
dans le répertoire git repo, me convient le mieux.
Ceci extraira tous les derniers sous-modules, y compris.
Remarque: cela date de 2009 et a peut-être été une bonne chose à ce moment-là, mais il existe maintenant de meilleures options.
Nous l'utilisons. Cela s'appelle git-pup
:
#!/bin/bash
# Exists to fully update the git repo that you are sitting in...
git pull && git submodule init && git submodule update && git submodule status
Il suffit de le placer dans un répertoire bin approprié (/ usr / local / bin). Si vous utilisez Windows, vous devrez peut-être modifier la syntaxe pour que cela fonctionne:)
Mise à jour:
En réponse au commentaire de l’auteur original sur l’inclusion de tous les HEADs de tous les sous-modules - c’est une bonne question.
Je suis à peu près sûr que git
n'a pas de commande pour cela en interne. Pour ce faire, vous devez identifier ce que HEAD est réellement pour un sous-module. Cela pourrait être aussi simple que de dire que master
est la branche la plus récente, etc ...
Ensuite, créez un script simple qui effectue les opérations suivantes:
- vérifiez
le statut du sous-module git
pour " modifié " les dépôts. Le premier caractère des lignes de sortie l'indique. Si un sous-dépôt est modifié, vous ne voudrez peut-être PAS continuer. - pour chaque référentiel répertorié, cd dans son répertoire et exécutez
git checkout master & amp; & amp; git pull
. Recherchez les erreurs. - À la fin, je vous suggère d’imprimer un écran à l’utilisateur pour indiquer l’état actuel des sous-modules - peut-être lui demander d’ajouter tout et de valider?
Je voudrais mentionner que ce style n’est pas vraiment ce pour quoi les sous-modules git ont été conçus. En règle générale, vous souhaitez dire " LibraryX " est à la version " 2.32 " et restera ainsi jusqu'à ce que je le dise à "mettre à niveau".
En un sens, c’est ce que vous faites avec le script décrit, mais plus automatiquement. Des soins sont nécessaires!
Mise à jour 2:
Si vous êtes sur une plate-forme Windows, vous voudrez peut-être utiliser Python pour implémenter le script car il est très capable dans ces domaines. Si vous utilisez unix / linux, je vous suggère simplement un script bash.
Besoin de précisions? Il suffit de poster un commentaire.
Henrik est sur la bonne voie. La commande 'foreach' peut exécuter n'importe quel script shell. Deux options pour tirer le dernier parti pourrait être,
git submodule foreach git pull origin master
et
git submodule foreach /path/to/some/cool/script.sh
Cela va parcourir tous les sous-modules initialisés et exécuter les commandes données.
Ce qui suit a fonctionné pour moi sous Windows.
git submodule init
git submodule update
Modifier :
Dans les commentaires, il a été souligné (par philfreo ) que la dernière version est requise. S'il existe des sous-modules imbriqués qui doivent figurer dans leur dernière version:
git submodule foreach --recursive git pull
----- Commentaire dépassé ci-dessous -----
N'est-ce pas la manière officielle de le faire?
git submodule update --init
Je l'utilise à chaque fois. Aucun problème jusqu'à présent.
Modifier:
Je viens de découvrir que vous pouvez utiliser:
git submodule foreach --recursive git submodule update --init
Qui va également extraire récursivement tous les sous-modules, c'est-à-dire les dépendances.
Comme il peut arriver que la branche par défaut de vos sous-modules soit pas , maître
, voici comment j'automatise les mises à niveau complètes des sous-modules Git:
git submodule init
git submodule update
git submodule foreach 'git fetch origin; git checkout $(git rev-parse --abbrev-ref HEAD); git reset --hard origin/$(git rev-parse --abbrev-ref HEAD); git submodule update --recursive; git clean -dfx'
Première fois
Sous-module Clone and Init
git clone git@github.com:speedovation/kiwi-resources.git resources
git submodule init
Reste
Pendant le développement, extrayez et mettez à jour le sous-module
git pull --recurse-submodules && git submodule update --recursive
Mettre à jour le sous-module Git avec la dernière validation d'origine
git submodule foreach git pull origin master
Le chemin préféré doit être inférieur à
.git submodule update --remote --merge
note: les deux dernières commandes ont le même comportement
Je ne sais pas depuis quelle version de git cela fonctionne, mais c'est ce que vous recherchez:
git submodule update --recursive
Je l'utilise avec git pull
pour mettre à jour le référentiel racine également:
git pull && git submodule update --recursive
Regardez http://lists.zerezo.com/git/msg674976.html qui introduit un paramètre --track
Les réponses ci-dessus sont bonnes, bien que nous utilisions git-hooks pour simplifier les choses, mais il s'avère que dans git 2.14 , vous pouvez définir git config submodule.recurse
sur true pour permettre aux sous-modules d'être mis à jour lors de l'extraction dans votre référentiel git.
Cela aura pour effet secondaire de pousser tous les changements de sous-modules que vous avez s'ils sont sur des branches, mais si vous avez déjà besoin de ce comportement, cela pourrait faire l'affaire.
Peut être fait en utilisant:
git config submodule.recurse true
Git pour Windows 2.6.3 :
Mise à jour du sous-module git --rebase --remote
Je l’ai fait en adaptant les gahooa au réponse ci-dessus :
Intégrez-le avec un git [alias]
...
Si votre projet parent a quelque chose comme ceci dans .gitmodules
:
[submodule "opt/submodules/solarized"]
path = opt/submodules/solarized
url = git@github.com:altercation/solarized.git
[submodule "opt/submodules/intellij-colors-solarized"]
path = opt/submodules/intellij-colors-solarized
url = git@github.com:jkaving/intellij-colors-solarized.git
Ajoutez quelque chose comme ceci dans votre .gitconfig
[alias]
updatesubs = "!sh -c \"git submodule init && git submodule update && git submodule status\" "
Ensuite, pour mettre à jour vos sous-modules, exécutez:
git updatesubs
J'ai un exemple dans celui-ci Mon référentiel de configuration de l'environnement .
Voici la ligne de commande à extraire de tous vos référentiels git, qu'ils soient ou non des sous-modules:
ROOT=$(git rev-parse --show-toplevel 2> /dev/null)
find "$ROOT" -name .git -type d -execdir git pull -v ';'
Si vous l'exécutez dans votre référentiel git supérieur, vous pouvez remplacer "$ ROOT"
par .
.
Tout ce que vous avez à faire maintenant est un simple git checkout
Assurez-vous simplement de l'activer via cette configuration globale: git config --global submodule.recurse true
Depuis le niveau supérieur du référentiel:
git submodule foreach git checkout develop
git submodule foreach git pull
Ceci basculera toutes les branches pour développer et extraire les dernières
Je pense que vous devrez écrire un script pour le faire. Pour être honnête, il se peut que j'installe python afin de pouvoir utiliser os.walk
pour cd
dans chaque répertoire et exécuter les commandes appropriées. Utiliser python ou un autre langage de script, autre que batch, vous permettrait d’ajouter / supprimer facilement des sous-projets sans devoir modifier le script.
Remarque: pas très facile, mais réalisable et il a ses propres avantages.
Si l'on veut cloner uniquement la révision HEAD
d'un référentiel et uniquement les HEAD
de tous ses sous-modules (c.-à-d. pour le commander, "trunk"), on peut utilisez le script Lua suivant. Parfois, une simple commande mise à jour du sous-module git --init --recursive --remote --no-fetch --depth = 1
peut entraîner une erreur irrécupérable git
. Dans ce cas, vous devez nettoyer le sous-répertoire du répertoire .git / modules
et cloner le sous-module manuellement à l'aide de la commande git clone --separate-git-dir
. La seule complexité est de rechercher URL , chemin du répertoire .git
du sous-module et chemin du sous-module dans l'arborescence du superprojet.
Remarque: le script est uniquement testé sur le référentiel https://github.com/boostorg/boost.git
. Ses particularités: tous les sous-modules hébergés sur le même hôte et .gitmodules
ne contiennent que des URL relatives.
-- mkdir boost ; cd boost ; lua ../git-submodules-clone-HEAD.lua https://github.com/boostorg/boost.git .
local module_url = arg[1] or 'https://github.com/boostorg/boost.git'
local module = arg[2] or module_url:match('.+/([_%d%a]+)%.git')
local branch = arg[3] or 'master'
function execute(command)
print('# ' .. command)
return os.execute(command)
end
-- execute('rm -rf ' .. module)
if not execute('git clone --single-branch --branch master --depth=1 ' .. module_url .. ' ' .. module) then
io.stderr:write('can\'t clone repository from ' .. module_url .. ' to ' .. module .. '\n')
return 1
end
-- cd $module ; git submodule update --init --recursive --remote --no-fetch --depth=1
execute('mkdir -p ' .. module .. '/.git/modules')
assert(io.input(module .. '/.gitmodules'))
local lines = {}
for line in io.lines() do
table.insert(lines, line)
end
local submodule
local path
local submodule_url
for _, line in ipairs(lines) do
local submodule_ = line:match('^%[submodule %"([_%d%a]-)%"%])
if submodule_ then
submodule = submodule_
path = nil
submodule_url = nil
else
local path_ = line:match('^%s*path = (.+))
if path_ then
path = path_
else
submodule_url = line:match('^%s*url = (.+))
end
if submodule and path and submodule_url then
-- execute('rm -rf ' .. path)
local git_dir = module .. '/.git/modules/' .. path:match('^.-/(.+))
-- execute('rm -rf ' .. git_dir)
execute('mkdir -p $(dirname "' .. git_dir .. '")')
if not execute('git clone --depth=1 --single-branch --branch=' .. branch .. ' --separate-git-dir ' .. git_dir .. ' ' .. module_url .. '/' .. submodule_url .. ' ' .. module .. '/' .. path) then
io.stderr:write('can\'t clone submodule ' .. submodule .. '\n')
return 1
end
path = nil
submodule_url = nil
end
end
end