Tüm git alt modüllerinden en son çekmenin kolay yolu


1846

Geliştirdiğimiz birçok kütüphaneye bağımlı olan birkaç büyük projeyi yönetmek için git alt modüllerini kullanıyoruz. Her kütüphane, bağımlı projeye alt modül olarak getirilen ayrı bir repo. Geliştirme sırasında, genellikle her bağımlı alt modülün en son sürümünü almak istiyoruz.

Git'in bunu yapmak için yerleşik bir komutu var mı? Değilse, bunu yapabilen bir Windows toplu iş dosyası veya benzeri bir dosyaya ne dersiniz?


git-deep bu konuda yardımcı olmalı.
Mathew Kurian

9
@Brad modüllerinin kopyalarını ana projede belirtilen işleme devirleriyle güncellemek istiyor musunuz; veya her alt modülden en son HEAD taahhüdünü almak ister misiniz? Buradaki cevapların çoğu öncekilere hitap ediyor; birçok insan ikincisini istiyor.
chrisinmtown

Yanıtlar:


2464

Bir depoyu ilk kez kontrol ediyorsanız , önce kullanmanız gerekir --init:

git submodule update --init --recursive

İçin Git 1.8.2 veya üzeri, opsiyon --remoteuzak dalların son ipuçları destek güncelleme eklendi:

git submodule update --recursive --remote

Bunun, dosyalarda .gitmodulesveya .git/configdosyalarda belirtilen "varsayılan olmayan" dallara saygı duymanın ek bir yararı vardır (varsa, varsayılan kaynak / master'tır, bu durumda buradaki diğer yanıtların bazıları da işe yarayabilir).

İçin Git 1.7.3 kullanabilirsiniz veya yukarıdaki (ancak güncelleme hala geçerlidir neyi etrafında FRİKİKLERİNDEN altında):

git submodule update --recursive

veya:

git pull --recurse-submodules

Eğer alt modüllerinizi mevcut taahhüt yerine en son taahhütlere çekmek istiyorsanız, repo puanları.

Ayrıntılar için git-submodule (1) 'e bakınız.


299
Muhtemelen git submodule update --recursivebugünlerde kullanmalısın .
Jens Kohl

38
Performans iyileştirme:git submodule foreach "(git checkout master; git pull)&"
Bogdan Gusiev

18
Güncelleme her alt modülü belirtilen revizyona güncelleyecek, o havuz için en son sürüme güncellemeyecektir.
Peter DeWeese

21
Eklemek origin mastergerekirse, bazı alt modülleriniz belirli alt modülün farklı bir dalını veya konum adını izliyorsa, bu komutun sonuna körü körüne yapışmak beklenmedik sonuçlar doğurabilir. Bazılarına açık, ama muhtemelen herkese açık değil.
Nathan Hornby

31
Sadece herkese açıklık getirmek için. git submodule update --recursiveana veri havuzunun her alt modül için hangi revizyonu sakladığını görür, ardından her alt modüldeki bu revizyonu kontrol eder. Bu mu DEĞİL her alt modülün en son kaydedilmesini çekin. git submodule foreach git pull origin masterya git pull origin master --recurse-submodulesda her alt modülü kendi kaynak havuzlarındaki en son sürüme güncellemek istiyorsanız istediğiniz şeydir. Ancak bundan sonra, alt modüller için güncellenmiş düzeltme karmalarıyla üst repoda bekleyen değişiklikler alırsınız. Bunları kontrol edin ve iyisiniz.
Chev

636
git pull --recurse-submodules --jobs=10

1.8.5'te ilk öğrenilen bir özellik.

Hata düzeltilene kadar, ilk kez çalıştırmanız gerekir

git submodule güncellemesi --init - recursive


29
oy verildi, bunu kullanıyorum: alias update_submodules = 'git pull --recurse-submodules && git submodule update'
Stephen C

3
Bu, eğer alt-modüller en az bir kez çekilmişse, ama hiç kontrol edilmemiş alt-modüller için, aşağıdaki gahooa'nın cevabına bakınız.
Matt Browne

8
Bu, üst repo'nun belirttiği sürüme kadar yükselir; KAFA çekmiyor. Örneğin, TopRepo, SubRepo için HEAD'in arkasında bir sürüm 2 belirtirse, bu, SubRepo'yu 2'nin arkasında olan sürümle çeker. Buradaki diğer cevaplar SubRepo'daki HEAD'i çekiyor.
Chris Moschini

11
Ne o Not git pull --recurse-submodulesne de git submodule update --recursiveyok değil initialize yeni submodules ekledi. Onları başlatmak için koşmanız gerekir git submodule update --recursive --init. El kitabından alıntı : Alt modül henüz başlatılmadıysa ve ayarı sadece .gitmodules'de saklandığı gibi kullanmak istiyorsanız, alt modülü otomatik olarak --init seçeneğiyle başlatabilirsiniz.
patryk.beza

1
belki git submodule update --recursive --remotede saklanan SHA-1 yerine en son uzak revizyona alt modülleri güncelleyen bir ipucu ekleyin .
Hanno S.

386

İnit üzerinde aşağıdaki komutu çalıştırarak:

git submodule update --init --recursive

git repo dizini içinden benim için en iyi sonucu verir.

Bu, alt modüller dahil olmak üzere en son çekimleri yapar.

Açıklaması

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.

Bundan sonra şunları çalıştırabilirsiniz:

git submodule update --recursive

git repo dizini içinden benim için en iyi sonucu verir.

Bu, alt modüller dahil olmak üzere en son çekimleri yapar.


10
Evet - oylanan en yüksek cevap bunu '09'da yapmanın en iyi yoluydu, ama bu şimdi kesinlikle daha basit ve daha sezgisel.
Michael Scott Cuthbert

2
@MichaelScottCuthbert teşekkürler, eminim 3 yıl içinde bu komut da deli olacak
abc123

5
Bununla birlikte, bu, alt modüldeki en son revizyonu değil, sadece ebeveynin izlediği en son revizyonu kontrol etmez.
Nathan Osman

4
@NathanOsman istediğiniz budur ... ebeveyn revizyon takibini takip etmeyerek kırık kod ile sonuçlanacak. Ebeveynin bakıcısıysanız, bunları kendiniz güncelleyebilir ve taahhüt edebilirsiniz.
abc123

2
Evet, ama benim anlayışımdan, OP'nin istediği bu değildi.
Nathan Osman

305

Not: Bu 2009'dan beri ve o zaman iyi olabilirdi ama şimdi daha iyi seçenekler var.

Bunu kullanıyoruz. Adı 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

Sadece uygun bir bin dizinine (/ usr / local / bin) koyun. Windows'da çalışıyorsanız, sözdizimini değiştirmeniz gerekebilir :)

Güncelleme:

Orijinal yazarın tüm alt modüllerin tüm HEAD'lerini çekme hakkındaki yorumuna yanıt olarak - bu iyi bir soru.

Bunun gitdahili olarak bir komutu olmadığından eminim . Bunu yapmak için, bir alt modül için HEAD'in gerçekte ne olduğunu tanımlamanız gerekir. Bu masteren güncel şube, vb demek kadar basit olabilir ...

Bunu takiben, aşağıdakileri yapan basit bir komut dosyası oluşturun:

  1. git submodule status"değiştirilmiş" depoları kontrol edin . Çıktı çizgilerinin ilk karakteri bunu gösterir. Bir alt repo değiştirilirse, devam etmek istemeyebilirsiniz.
  2. listelenen her repo için, dizinine cd ve çalıştırın git checkout master && git pull. Hataları kontrol edin.
  3. Sonunda, alt modüllerin mevcut durumunu belirtmek için kullanıcıya bir ekran yazdırmanızı öneririm - belki de hepsini eklemelerini ve taahhüt etmelerini ister misiniz?

Bu stilin git submodüllerinin tasarlandığı şey olmadığını belirtmek isterim. Genellikle, "LibraryX" "2.32" sürümünde olduğunu söylemek istiyorum ve ben "yükseltme" söyleyene kadar bu şekilde kalacaktır.

Bu, bir anlamda, açıklanan komut dosyasıyla ne yaptığınızı, ancak daha otomatik olarak. Bakım gerekli!

Güncelleme 2:

Bir Windows platformundaysanız, bu alanlarda çok yetenekli olduğu için komut dosyasını uygulamak için Python kullanmaya bakmak isteyebilirsiniz. Eğer unix / linux kullanıyorsanız, o zaman sadece bir bash betiği öneririm.

Herhangi bir açıklamaya mı ihtiyacınız var? Sadece bir yorum gönderin.


İstediğimi sanmıyorum. Bu, süper projenin son işlendiği alt modüllerin versiyonunu çekmeyecek mi? Tüm alt modüllerin kafa versiyonunu çekmek istiyorum.
Brad Robinson

3
Bu harika çalışıyor ve sadece alt modülleri güncellemek için değil, ihtiyacınız olan şeyse onları ilk kez getirmek için de çalışıyor.
Matt Browne

Sadece "Şube için izleme bilgisi yok. Lütfen hangi şubeyle birleştirmek istediğinizi belirtin." Ne denediğim önemli değil: /
Nathan Hornby

9
Neden bunun için bir takma ad oluşturmuyorsunuz? git config --global alias.pup '!git pull && git submodule init && git submodule update && git submodule status've git pupherhangi bir komut dosyası olmadan kullanın .
fracz

Git 1.9.1 olsa bile, bir sebepten dolayı teşekkür ederim. Alt git submodule initmodülleri içeren ilk çekmeden sonra yapmak zorunda kaldım, böylece her şey düzgün çalışmaya başlayacaktı.
Ben Usman

164

Henrik doğru yolda. 'Foreach' komutu herhangi bir rastgele kabuk betiği yürütebilir. En sonuncuyu çekmek için iki seçenek olabilir,

git submodule foreach git pull origin master

ve,

git submodule foreach /path/to/some/cool/script.sh

Bu, başlatılan tüm alt modülleri tekrarlar ve verilen komutları çalıştırır.


144

Aşağıdakiler Windows'ta benim için çalıştı.

git submodule init
git submodule update

6
OP'nin istediği bu değil. Yalnızca ilgili alt modül taahhüdüne güncellenir, en son sürüm değil.
Patrick

52
Ancak bu, bir repoya ilk kez baktığımda alt modülleri çekmek için
gitmiş

2
Ayrıca kullanabilirsiniz: git submodule update --init --recursive (özellikle söz konusu alt modül taze bir klondan RestKit ise)
HCdev

33

Düzenle :

Yorumlarda ( philfreo tarafından ) son sürümün gerekli olduğuna dikkat çekildi . En son sürümlerinde olması gereken iç içe geçmiş alt modüller varsa:

git submodule foreach --recursive git pull

----- Aşağıda eski yorum -----

Bunu yapmanın resmi yolu bu değil mi?

git submodule update --init

Her seferinde kullanıyorum. Şimdiye kadar sorun yok.

Düzenle:

Sadece kullanabileceğinizi buldum:

git submodule foreach --recursive git submodule update --init 

Hangi ayrıca tüm alt modülleri, yani bağımlılıkları tekrar tekrar çekecek.


5
Cevabınız OP'nin sorusuna cevap vermiyor, ancak önerdiğiniz şeyi yapmak için şunu söyleyebilirsinizgit submodule update --init --recursive
philfreo

2
Görüyorum ki, en son sürüm gerekli. Yuvalanmış alt modüller varsa, bu yararlı olabilir: git submodule foreach --recursive git pull
antitoksik

1
Bunların hiçbirini aslında hiçbir şey indiremedim - "git submodule update --init --recursive" benim için çalıştı.
BrainSlugs83

33

Alt modüllerinizin varsayılan dalı olmadığından master , tam Git alt modül yükseltmelerini otomatik olarak şöyle yaparım:

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'

birçok soruya verilen birçok
cevaptan

30

İlk kez

Klon ve Başlangıç ​​Alt Modülü

git clone git@github.com:speedovation/kiwi-resources.git resources
git submodule init

Dinlenme

Geliştirme sırasında sadece alt modülü çekin ve güncelleyin

git pull --recurse-submodules  && git submodule update --recursive

Git alt modülünü en son başlangıç ​​noktasında güncelleyin

git submodule foreach git pull origin master

Tercih edilen yol aşağıda olmalıdır

git submodule update --remote --merge

not: son iki komut aynı davranışa sahiptir


Yanlışlıkla alt modülleri olmayan bir git klonu yaptım ve diğer tüm seçenekler işe yaramadı, hiç kimse alt klonları klonlamadı. Seninkini kullanarak git submodule update, hile yaptı. Şimdi klonun ilk adımında eksik olan alt modül verilerini indiriyorum. Teşekkür ederim.
Git'te

Bu anser aslında burada bir soru sormak için çok iyi bir cevap: neden ".. - recursive-submodules .." ve daha sonra ek olarak "... update ..." ve hatta ".. .foreach ... "daha sonra en son taahhüdü almak için? Bütün bunlar GIT gibi görünmüyor! "Güncelleme" ne yapıyor ve neden çekmek için her bir modüle manuel olarak gitmem gerekiyor? "... - söylem-submodüller .." böyle yapmıyor mu? İpucu var mı?
Peter Branforn

20

Git'in hangi sürümünün çalıştığını bilmiyorum, ama aradığınız şey bu:

git submodule update --recursive

Ben git pullde kök deposunu güncellemek için kullanın :

git pull && git submodule update --recursive

10

Yukarıdaki cevaplar iyidir, ancak bunu kolaylaştırmak için git-hooks kullanıyorduk, ancak git 2.14'tegit config submodule.recurse git deponuza çektiğinizde alt modüllerin güncellenmesini sağlamak için true olarak ayarlayabileceğiniz ortaya çıkıyor .

Bu, dallardaysa sahip olduğunuz tüm alt modül değişikliklerini itmenin yan etkisi olacaktır, ancak bu davranışa ihtiyacınız varsa, bu zaten işi yapabilir.

Aşağıdakiler kullanılarak yapılabilir:

git config submodule.recurse true

Bu seçeneği sevmeliyim, maalesef hala git submodule initalt modülünüz henüz başlatılmadıysa yine de elden önce kullanmanız gerekir .
Pelet

5

Windows 2.6.3 için Git :

git submodule update --rebase --remote


Benim için çalışan tek kişi bu. Alt modül işaretçisi artık uzaktan kumandada olmayan bir sürüme işaret ettiği için başlatamadım veya güncelleyemedim
Pavel P

4

Repodaki en üst seviyeden:

git submodule foreach git checkout develop
git submodule foreach git pull

Bu, tüm şubeleri en son gelişmeleri ve çekimleri


2
Git 2.7 ile benim için çalışmıyor.
Bruno Haible

Ağaçtaki tüm proje referanslarını ekleyen Everything sln dosyası gibi bir şeyiniz var mı? Ayrıca hangi hatayı görüyorsunuz? Gitignore dosyanızı da kontrol edebilir misiniz
Srayan Guhathakurta

1
git submodule foreach git pull origin masterAlmak istediğim dalı eklemek zorunda kaldım. bunun dışında mükemmel çalıştı.
Torxed

3

Ben uyarlayarak bunu gahooa 'ın yukarıdaki cevabı :

Bir git ile entegre edin [alias]...

Ana projenizde şuna benzer bir şey varsa .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

.Gitconfig'inize böyle bir şey ekleyin

[alias]
    updatesubs = "!sh -c \"git submodule init && git submodule update && git submodule status\" "

Ardından alt modüllerinizi güncellemek için şunu çalıştırın:

git updatesubs

Çevre kurulum deposumda bunun bir örneği var .


3

Şimdi tek yapmanız gereken basit git checkout

Sadece bu global yapılandırma ile etkinleştirdiğinizden emin olun: git config --global submodule.recurse true


2

Alt modül olsun ya da olmasın tüm git depolarınızdan çekilecek komut satırı:

ROOT=$(git rev-parse --show-toplevel 2> /dev/null)
find "$ROOT" -name .git -type d -execdir git pull -v ';'

Eğer üst git deposunda çalıştırmaya varsa, yerine "$ROOT"içine ..


1

Bunu yapmak için bir senaryo yazmanız gerektiğini düşünüyorum. Dürüst olmak gerekirse, ben bu yüzden kullanabileceği bunu yapmak için Python yükleyebilir os.walkiçin cdher dizine ve uygun komutlar vermek. Python veya toplu iş dışında başka bir komut dosyası dili kullanmak, komut dosyasını değiştirmek zorunda kalmadan alt projeleri kolayca eklemenizi / kaldırmanızı sağlar.


1

Not: çok kolay bir yol değil, uygulanabilir ve kendi benzersiz artıları var.

Eğer bir havuzun sadece HEADrevizyonunu ve HEADtüm alt modüllerinin sadece sini klonlamak istiyorsa (yani “trunk” ı kontrol etmek için), o zaman aşağıdaki Lua betiğini kullanabilirsiniz . Bazen basit komut git submodule update --init --recursive --remote --no-fetch --depth=1kurtarılamaz bir githataya neden olabilir . Bu durumda, .git/modulesdizin kullanarak alt dizini ve klon alt modülünü el ile temizlemek gerekir git clone --separate-git-dir. Tek karmaşıklık URL'yi , yolunu bulmaktır.git alt modül dizininin yolunu ve süper proje ağacındaki alt modül .

Not: komut dosyası yalnızca https://github.com/boostorg/boost.gitdepoya karşı test edilir . Özellikleri: aynı ana bilgisayarda barındırılan tüm alt modüller ve .gitmodulessadece göreli URL'ler içerir .

-- 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
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.