طريقة سهلة لسحب أحدث الوحدات الفرعية لـ git
-
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
هو أحدث فرع، الخ ...
بعد ذلك، قم بإنشاء برنامج نصي بسيط يقوم بما يلي:
- يفحص
git submodule status
للمستودعات "المعدلة".الحرف الأول من خطوط الإخراج يشير إلى ذلك.إذا تم تعديل الريبو الفرعي، فقد لا ترغب في المتابعة. - لكل ريبو مدرج، قم بإدخال القرص المضغوط في دليله وتشغيله
git checkout master && git pull
.تحقق من وجود أخطاء. - في النهاية، أقترح عليك طباعة شاشة عرض للمستخدم للإشارة إلى الحالة الحالية للوحدات الفرعية - ربما تطالبه بإضافة الكل والالتزام؟
أود أن أذكر أن هذا النمط ليس في الواقع ما تم تصميم وحدات 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
الوحيد للمستودع وHEAD
s فقط من جميع الوحدات الفرعية التابعة (أي في الخروج "الجذع")، ثم يمكن للمرء أن استخدام التالية <م> لوا م> النصي. في بعض الأحيان يمكن بسيطة 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