طريقة سهلة لسحب أحدث الوحدات الفرعية لـ git

StackOverflow https://stackoverflow.com/questions/1030169

  •  06-07-2019
  •  | 
  •  

سؤال

نحن نستخدم وحدات git الفرعية لإدارة مشروعين كبيرين يعتمدان على العديد من المكتبات الأخرى التي قمنا بتطويرها.كل مكتبة عبارة عن ريبو منفصل يتم إحضاره إلى المشروع التابع كوحدة فرعية.أثناء التطوير، غالبًا ما نرغب في الحصول على أحدث إصدار من كل وحدة فرعية تابعة.

هل لدى git أمر مضمن للقيام بذلك؟إذا لم يكن الأمر كذلك، فماذا عن ملف دفعي لنظام التشغيل Windows أو ملف مشابه يمكنه القيام بذلك؟

هل كانت مفيدة؟

المحلول

إذا كان المرة الأولى يمكنك الخروج من الريبو الذي تحتاج إلى استخدامه --init أولاً:

git submodule update --init --recursive

ل بوابة 1.8.2 أو فوق الخيار --remote تمت إضافته لدعم التحديث إلى أحدث النصائح للفروع البعيدة:

git submodule update --recursive --remote

وهذا له فائدة إضافية تتمثل في احترام أي فروع "غير افتراضية" محددة في .gitmodules أو .git/config الملفات (إذا كان لديك أي منها، فالافتراضي هو Origin/master، وفي هذه الحالة ستعمل بعض الإجابات الأخرى هنا أيضًا).

ل بوابة 1.7.3 أو ما هو أعلى يمكنك استخدامه (ولكن الأخطاء الموجودة أدناه حول التحديث الذي لا يزال ساريًا):

git submodule update --recursive

أو:

git pull --recurse-submodules

إذا كنت تريد سحب الوحدات الفرعية الخاصة بك إلى أحدث الالتزامات بدلاً من ما يشير إليه الريبو.

يرى بوابة-وحدة فرعية(1) للتفاصيل

نصائح أخرى

إذا كنت بحاجة إلى سحب العناصر الخاصة بالوحدات الفرعية إلى مستودعات الوحدات الفرعية الخاصة بك، فاستخدمها

git pull --recurse-submodules

إحدى الميزات التي تعلمتها git لأول مرة في 1.7.3.

ولكن هذا لن يؤدي إلى التحقق من الالتزامات المناسبة (تلك التي يشير إليها مستودعك الرئيسي) في الوحدات الفرعية

للتحقق من الالتزامات المناسبة في الوحدات الفرعية الخاصة بك، يجب عليك تحديثها بعد السحب باستخدام

git submodule update --recursive --remote

على الحرف الأول تشغيل الأمر التالي:

git submodule update --init --recursive
من ضمن الدليل بوابة الريبو، يعمل

وأفضل بالنسبة لي.

وهذا سيسحب جميع أحدث بما في ذلك الوحدات الفرعية.

شرح

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.

وبعد ذلك يمكنك تشغيل فقط:

git submodule update --recursive
من ضمن الدليل بوابة الريبو، يعمل

وأفضل بالنسبة لي.

وهذا سيسحب جميع أحدث بما في ذلك الوحدات الفرعية.

ملحوظة:هذا من عام 2009 وربما كان جيدًا في ذلك الوقت ولكن هناك خيارات أفضل الآن.

نحن نستخدم هذا.تسمى 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

فقط ضعه في دليل bin المناسب (/usr/local/bin).إذا كنت تستخدم نظام التشغيل Windows، فقد تحتاج إلى تعديل بناء الجملة حتى يعمل :)

تحديث:

ردًا على تعليق المؤلف الأصلي حول سحب جميع الرؤوس الخاصة بجميع الوحدات الفرعية - فهذا سؤال جيد.

أنا متأكد من ذلك git ليس لديه أمر لهذا داخليا.من أجل القيام بذلك، سوف تحتاج إلى تحديد ما هو HEAD حقًا بالنسبة للوحدة الفرعية.يمكن أن يكون الأمر بسيطًا مثل القول master هو أحدث فرع، الخ ...

بعد ذلك، قم بإنشاء برنامج نصي بسيط يقوم بما يلي:

  1. يفحص git submodule status للمستودعات "المعدلة".الحرف الأول من خطوط الإخراج يشير إلى ذلك.إذا تم تعديل الريبو الفرعي، فقد لا ترغب في المتابعة.
  2. لكل ريبو مدرج، قم بإدخال القرص المضغوط في دليله وتشغيله git checkout master && git pull.تحقق من وجود أخطاء.
  3. في النهاية، أقترح عليك طباعة شاشة عرض للمستخدم للإشارة إلى الحالة الحالية للوحدات الفرعية - ربما تطالبه بإضافة الكل والالتزام؟

أود أن أذكر أن هذا النمط ليس في الواقع ما تم تصميم وحدات git الفرعية من أجله.عادةً، تريد أن تقول أن "LibraryX" موجود في الإصدار "2.32" وسيظل على هذا النحو حتى أخبره "بالترقية".

وهذا هو، إلى حد ما، ما تفعله بالنص الموصوف، ولكن بشكل تلقائي أكثر.الرعاية مطلوبة!

التحديث 2:

إذا كنت تستخدم نظام التشغيل Windows، فقد ترغب في النظر في استخدام Python لتنفيذ البرنامج النصي لأنه قادر جدًا في هذه المجالات.إذا كنت تستخدم نظام التشغيل Unix/Linux، فأنا أقترح عليك نص bash فقط.

هل تحتاج إلى أي توضيحات؟مجرد نشر تعليق.

وهنريك هو على الطريق الصحيح. و"foreach" القيادة يمكن تنفيذ أي برنامج نصي قذيفة التعسفي. خياران لسحب جدا آخر قد يكون،

git submodule foreach git pull origin master

و

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

وهذا تكرار خلال كل <م> تهيئة الوحدات الفرعية وتشغيل الأوامر المعطاة له.

وعملت ما يلي بالنسبة لي على ويندوز.

git submodule init
git submodule update

يحرر:

وفي التعليقات تمت الإشارة إلى (بقلم فيلفريو ) أن الإصدار الأحدث مطلوب.إذا كان هناك أي وحدات فرعية متداخلة يجب أن تكون في أحدث إصدار لها:

git submodule foreach --recursive git pull

-----التعليق قديم أدناه-----

أليست هذه هي الطريقة الرسمية للقيام بذلك؟

git submodule update --init

أستخدمه في كل مرة.لا توجد مشاكل حتى الآن.

يحرر:

لقد وجدت للتو أنه يمكنك استخدام:

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

والذي سيؤدي أيضًا إلى سحب جميع الوحدات الفرعية بشكل متكرر، أيالتبعيات.

كما قد يحدث أن يكون الفرع الافتراضي لوحداتك الفرعية هو لا master, ، هذه هي الطريقة التي أقوم بها بأتمتة ترقيات وحدات 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'

لأول مرة

واستنساخ والتهيئة حدة ثانويه

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

الراحة

وخلال تنمية عادلة سحب وتحديث حدة ثانويه

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

تحديث بوابة حدة ثانويه لآخر ارتكاب على الأصل

git submodule foreach git pull origin master
وينبغي أن يكون

الطريقة المفضلة أدناه

git submodule update --remote --merge

ملاحظة: الأوامر الماضيين لها نفس السلوك

وأنا لا أعرف منذ إصدار بوابة هذا العمل، ولكن هذا ما كنت تبحث عن:

git submodule update --recursive

وأنا استخدامها مع git pull لتحديث مستودع الجذر أيضا:

git pull && git submodule update --recursive

http://lists.zerezo.com/git/msg674976.html الذي يدخل معلمة --track

والأجوبة المذكورة أعلاه هي جيدة، ومع ذلك كنا باستخدام بوابة السنانير لجعل هذا أسهل، لكن اتضح أنه في <قوية> بوابة 2.14 ، أو يمكنك تعيين <لأ href = "HTTPS: // git- scm.com/docs/git-config#git-config-submodulerecurse "يختلط =" نوفولو noreferrer "> git config submodule.recurse لصحيح لتمكين الوحدات الفرعية إلى لتحديثها عند سحب لبوابة مستودع الخاص بك.

وهذا سيكون له تأثير جانبي على دفع جميع الوحدات الفرعية تغيير لديك إذا كانت على فروع ومع ذلك، ولكن إذا كان لديك حاجة لهذا السلوك بالفعل هذا يمكن القيام بهذه المهمة.

يمكن القيام به

وباستخدام:

git config submodule.recurse true

وبوابة للنوافذ على 2.6.3 : ل

وgit submodule update --rebase --remote

فعلت ذلك عن طريق التكيف مع gahooa الصورة <لأ href = "https://stackoverflow.com / أ / 1030263/1886534 "> الجواب ما سبق :

ودمج ذلك مع [alias] بوابة ...

إذا المشروع الأصل لديه شيئا من هذا القبيل في .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 بك

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

وبعد ذلك لتحديث الوحدات الفرعية الخاصة بك، قم بتشغيل:

git updatesubs

ولدي سبيل المثال منه في بلدي البيئة الإعداد الريبو .

وهنا هو سطر الأوامر لسحب من جميع مستودعات بوابة لديك سواء كانت أو لم الوحدات الفرعية:

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

إذا تشغيله في حياتك أفضل بوابة مستودع، يمكنك استبدال "$ROOT" إلى ..

وكل ما عليك القيام به الآن هو git checkout بسيطة

وفقط للتأكد من تمكينه من خلال هذا التكوين العالمي: git config --global submodule.recurse true

ومن أعلى مستوى في الريبو:

git submodule foreach git checkout develop
git submodule foreach git pull

وهذا ستتحول جميع فروع لتطوير وسحب آخر

وأعتقد سيكون لديك لكتابة السيناريو للقيام بذلك. أن نكون صادقين، وأنا قد تثبيت بيثون للقيام بذلك بحيث يمكنك استخدام os.walk إلى cd إلى كل دليل وإصدار الأوامر المناسبة. استخدام الثعبان أو بعض أخرى لغة البرمجة، وغيرها من دفعة، من شأنها أن تسمح لك بسهولة إضافة / إزالة الفرعية مع من الحاجة إلى تعديل البرنامج النصي.

ملاحظة: الطريقة ليست سهلة للغاية، ولكن عملي ولها إيجابيات فريدة من نوعها

إذا واحد تريد استنساخ مراجعة HEAD الوحيد للمستودع وHEADs فقط من جميع الوحدات الفرعية التابعة (أي في الخروج "الجذع")، ثم يمكن للمرء أن استخدام التالية <م> لوا النصي. في بعض الأحيان يمكن بسيطة git submodule update --init --recursive --remote --no-fetch --depth=1 القيادة يؤدي إلى خطأ git غير قابل للاسترداد. في هذه الحاجة حالة واحدة لتنظيف دليل فرعي للدليل .git/modules وحدة ثانويه استنساخ يدويا باستخدام الأمر git clone --separate-git-dir. تعقيد الوحيد هو معرفة <م> URL ، مسار دليل .git من حدة ثانويه ومسار حدة ثانويه في شجرة superproject.

ملاحظة: يتم اختبار النصي فقط ضد مستودع https://github.com/boostorg/boost.git. خصوصياته: جميع الوحدات الفرعية استضافتها على نفس المضيف و.gitmodules يحتوي فقط قريب <م> URL ق

-- 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
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top