كيف يمكنني تحديد فرع/علامة عند إضافة وحدة فرعية git؟
-
21-09-2019 - |
سؤال
كيف git submodule add -b
الشغل؟
بعد إضافة وحدة فرعية مع فرع معين ، مستودع مستنسخ جديد (بعد git submodule update --init
) سيكون في التزام معين ، وليس الفرع نفسه (git status
على الجهاز الفرعي يظهر "ليس حاليًا على أي فرع").
لا يمكنني العثور على أي معلومات عن .gitmodules
أو .git/config
حول فرع الجهاز الفرعي أو أي التزام محدد ، فكيف تكتشف Git ذلك؟
أيضا ، هل من الممكن تحديد علامة بدلاً من فرع؟
أنا أستخدم الإصدار 1.6.5.2.
المحلول
ملاحظة: أضافت GIT 1.8.2 إمكانية تتبع الفروع. انظر بعض الإجابات أدناه.
إنه أمر مربك بعض الشيء التعود على هذا ، لكن العارض الفرعي ليست في فرع. إنهم ، كما تقول ، مجرد مؤشر لالتزام معين بمستودع العرض الفرعي.
هذا يعني أنه عندما يقوم شخص آخر بفحص المستودع الخاص بك ، أو يسحب الكود الخاص بك ، ويقوم بتحديث الجهاز الفرعي git ، يتم التحقق من الجهاز الفرعي إلى هذا الالتزام بالذات.
هذا أمر رائع بالنسبة للوحدة الفرعية التي لا تتغير في كثير من الأحيان ، لأن كل شخص في المشروع يمكن أن يكون لديهم الجهاز الفرعي في نفس الالتزام.
إذا كنت ترغب في نقل الجهاز الفرعي إلى علامة معينة:
cd submodule_directory
git checkout v1.0
cd ..
git add submodule_directory
git commit -m "moved submodule to v1.0"
git push
بعد ذلك ، تم تغيير مطور آخر يريد أن يكون قد تم تغيير Submodule_Directory إلى تلك العلامة ، يفعل هذا
git pull
git submodule update --init
git pull
التغييرات التي تلتزم دليل الجهاز الفرعي الخاص بهم يشير إلى. git submodule update
يندمج في الواقع في الكود الجديد.
نصائح أخرى
أرغب في إضافة إجابة هنا وهي في الحقيقة مجرد مجموعة من الإجابات الأخرى ، لكنني أعتقد أنها قد تكون أكثر اكتمالًا.
أنت تعلم أن لديك وحدة فرعية git عندما يكون لديك هذين الأمرين.
لك
.gitmodules
لديه إدخال مثل ذلك:[submodule "SubmoduleTestRepo"] path = SubmoduleTestRepo url = https://github.com/jzaccone/SubmoduleTestRepo.git
لديك كائن عرض فرعي (اسمه submoduletestrepo في هذا المثال) في مستودع GIT الخاص بك. جيثب يظهر هذه ككائنات "submodule". أو تفعل
git submodule status
من سطر الأوامر. كائنات الجهاز الفرعي GIT هي أنواع خاصة من كائنات GIT ، وهي تحمل معلومات SHA لالتزام معين.كلما فعلت
git submodule update
, ، سوف يملأ الجهاز الفرعي الخاص بك مع المحتوى من الالتزام. إنها تعرف مكان العثور على الالتزام بسبب المعلومات الموجودة في.gitmodules
.الآن ، كل
-b
هل إضافة سطر واحد في الخاص بك.gitmodules
ملف. لذا اتباع نفس المثال ، سيبدو هكذا:[submodule "SubmoduleTestRepo"] path = SubmoduleTestRepo url = https://github.com/jzaccone/SubmoduleTestRepo.git branch = master
ملحوظة: يتم دعم اسم الفرع فقط في أ
.gitmodules
ملف ، ولكن Sha و Tag غير مدعومة! (بدلاً من ذلك ، يمكن تتبع التزام الفرع بكل وحدة نمطية وتحديثه باستخدام "git add .
"، على سبيل المثال مثلgit add ./SubmoduleTestRepo
, ، ولا تحتاج إلى تغيير.gitmodules
ملف في كل مرة)لا يزال كائن الجهاز الفرعي يشير إلى التزام محدد. الشيء الوحيد الذي
-b
الخيار يشتري لك القدرة على إضافة ملف--remote
قم بإعلام التحديث الخاص بك وفقًا لإجابة Vogella:git submodule update --remote
بدلاً من ملء محتوى الجهاز الفرعي إلى الالتزام التي أشار إليها الجهاز الفرعي ، فإنه يحل محل الالتزام بأحدث الالتزام في الفرع الرئيسي ، ثم يملأ العرض الفرعي بهذا الالتزام. يمكن القيام بذلك في خطوتين بواسطة إجابة djacobs7. نظرًا لأنك قمت الآن بتحديث الالتزام الذي يشير إليه كائن الجهاز الفرعي ، يجب عليك ارتكاب كائن الجهاز الفرعي الذي تم تغييره في مستودع GIT الخاص بك.
git submodule add -b
ليست طريقة سحرية للحفاظ على كل شيء محدثًا مع فرع. إنه ببساطة يضيف معلومات حول فرع في.gitmodules
الملف ويمنحك خيار تحديث كائن الجهاز الفرعي إلى أحدث التزام بفرع محدد قبل ملءه.
(GIT 2.22 ، Q2 2019 ، قدم git submodule set-branch --branch aBranch -- <submodule_path>
)
لاحظ أن إذا كان لديك موجود الجهاز الفرعي الذي ليس تتبع فرع حتى الآن, ، ومن بعد (إذا كان لديك Git 1.8.2+):
تأكد من أن الريبو الأصل يعرف أن الجهاز الفرعي الخاص به يتتبع الآن فرعًا:
cd /path/to/your/parent/repo git config -f .gitmodules submodule.<path>.branch <branch>
تأكد
cd path/to/your/submodule git checkout -b branch --track origin/branch # if the master branch already exist: git branch -u origin/master master
(مع "الأصل" هو اسم ريبو عن بعد المنبع تم استنساخ الجهاز الفرعي.
أ git remote -v
داخل تلك الحداثة الفرعية سوف يعرضها. عادة ، هو "الأصل")
لا تنس تسجيل الحالة الجديدة للوحدة الفرعية الخاصة بك في ريبو والديك:
cd /path/to/your/parent/repo git add path/to/your/submodule git commit -m "Make submodule tracking a branch"
التحديث اللاحق لهذا الجهاز الفرعي سيتعين عليه استخدام
--remote
اختيار:# 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
لاحظ ذلك مع Git 2.10+ (Q3 2016) ، يمكنك استخدام ".
"كاسم فرع:
تم تسجيل اسم الفرع باسم
submodule.<name>.branch
في.gitmodules
إلى عن علىupdate --remote
.
قيمة خاصة.
يستخدم للإشارة إلى أن اسم الفرع في الجهاز الفرعي يجب أن يكون نفس اسم الفرع الحالي في المستودع الحالي.
إذا كنت ترغب في تحديث جميع العوامل الفرعية الخاصة بك بعد فرع:
git submodule update --recursive --remote
لاحظ أن النتيجة ، لكل وحدة فرعية محدثة ، سوف دائما تكون دائما رأس منفصل, ، كما دان كاميرون لاحظ في إجابته.
(كلنتم ملحوظات في التعليقات ذلك ، إذا قمت بتشغيل git submodule update --remote
و SHA1 الناتج هو نفسه الفرع الذي يوجد فيه الجهاز الفرعي حاليًا ، ولن يفعل أي شيء ويترك الجهاز الفرعي "على هذا الفرع" وليس في حالة رأس منفصلة.)
لضمان فحص الفرع فعليًا (ولن يعدل SHA1 من دخول خاص ويقترح: يمثل الجهاز الفرعي لإعادة الريبو الأم)
git submodule foreach -q --recursive 'branch="$(git config -f $toplevel/.gitmodules submodule.$name.branch)"; git checkout $branch'
ستظل كل وحدة فرعية تشير إلى نفس SHA1 ، ولكن إذا قمت بعمل ارتكارات جديدة ، فستتمكن من دفعها لأنه سيتم الرجوع إليها من قبل الفرع الذي تريد تتبعه للوحدة الفرعية.
بعد ذلك الضغط داخل وحدة فرعية ، لا تنس العودة إلى ريبو الأصل ، وإضافة ، والالتزام ودفع SHA1 الجديدة لتلك العزايا الفرعية المعدلة.
لاحظ استخدام $toplevel
, ، مستحسن في التعليقات بواسطة ألكساندر بوغربنياك.
$toplevel
تم تقديمه في Git1.7.2 في مايو 2010: ارتكاب F030C96.
أنه يحتوي على المسار المطلق للدليل العلوي (حيث
.gitmodules
هو).
dtmland
يضيف في التعليقات:
سيفشل البرنامج النصي foreach في الخروج من العارضات الفرعيات التي لا تتبع فرعًا.
ومع ذلك ، يمنحك هذا الأمر كلاهما:
git submodule foreach -q --recursive 'branch="$(git config -f $toplevel/.gitmodules submodule.$name.branch)"; [ "$branch" = "" ] && git checkout master || git checkout $branch' –
نفس الأمر ولكن أسهل في القراءة:
git submodule foreach -q --recursive \
'branch="$(git config -f $toplevel/.gitmodules submodule.$name.branch)"; \
[ "$branch" = "" ] && \
git checkout master || git checkout $branch' –
umläute صقل DTMLANDأمر مع نسخة مبسطة في التعليقات:
git submodule foreach -q --recursive 'git checkout $(git config -f $toplevel/.gitmodules submodule.$name.branch || echo master)'
خطوط متعددة:
git submodule foreach -q --recursive \
'git checkout \
$(git config -f $toplevel/.gitmodules submodule.$name.branch || echo master)'
وأضاف GIT 1.8.2 إمكانية تتبع الفروع.
# add submodule to track master branch
git submodule add -b branch_name URL_to_Git_repo optional_directory_rename
# update your submodule
git submodule update --remote
أنظر أيضا GIT الفرعية
مثال على كيفية استخدام الجهاز الفرعي git.
- إنشاء مستودع جديد
- ثم استنساخ مستودع آخر كوحدة فرعية
- ثم لدينا هذه الجهاز الفرعي استخدم علامة تسمى v3.1.2
- ثم نلتزم.
وهذا يبدو مثل هذا قليلاً:
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
ربما يساعد (على الرغم من أنني أستخدم علامة وليس فرعًا)؟
في تجربتي ، سيظل تبديل الفروع في المخزون الفائق أو الخروج المستقبلي يتسبب في رؤوس منفصلة من العارض الفرعي بغض النظر عما إذا كانت الجهاز الفرعي إضافة وتتبع بشكل صحيح (IE @DJACOBS7 و johnny Z الإجابات).
وبدلاً من فحص الفرع الصحيح يدويًا يدويًا أو من خلال البرنامج النصي GIT Submodule foreach من الممكن استخدامه.
سيؤدي ذلك إلى التحقق من ملف التكوين الفرعي لخاصية الفرع والخروج من فرع تعيين.
git submodule foreach -q --recursive 'branch="$(git config -f <path>.gitmodules submodule.$name.branch)"; git checkout $branch'
تعتبر الجهاز الفرعي GIT غريبًا بعض الشيء - إنها دائمًا في وضع "Detached Head" - فهي لا تحديث لأحدث الالتزام على فرع كما قد تتوقعه.
هذا أمر منطقي عندما تفكر في الأمر. لنفترض أنني أقوم بإنشاء مستودع فو مع الجهاز الفرعي شريط. أدفع التغييرات الخاصة بي وأقول لك أن تتحقق من الالتزام A7402BE من المستودع فو.
ثم تخيل أن شخصًا ما يرتكب تغييرًا في المستودع شريط قبل أن تتمكن من صنع استنساخك.
عندما تحقق من الالتزام A7402BE من المستودع فو, ، تتوقع الحصول على نفس الرمز الذي دفعته. لهذا السبب لا يتم تحديث العارض الفرعي حتى تخبرهم أن يلتزموا بشكل صريح ثم التزام جديد.
أنا شخصياً أعتقد أن العارض الفرعي هي الجزء الأكثر إرباكًا من GIT. هناك الكثير من الأماكن التي يمكن أن تفسر العلامات الفرعية بشكل أفضل مما أستطيع. انصح برو git بقلم سكوت تشاكون.
لتبديل الفرع للحصول على وحدة فرعية (على افتراض أن لديك بالفعل الجهاز الفرعي كجزء من المستودع):
cd
إلى جذر مستودعك الذي يحتوي على العارض الفرعي- فتح
.gitmodules
للتحرير - أضف السطر أدناه
path = ...
وurl = ...
هذا يقولbranch = your-branch
, ، لكل وحدة فرعية ؛ احفظ الملف.gitmodules
. - ثم بدون تغيير الدليل
$ git submodule update --remote
... يجب أن يسحب هذا الالتزامات الأخيرة على الفرع المحدد ، لكل وحدة فرعية تم تعديلها.
لدي هذا في ملف .gitConfig الخاص بي. إنها لا تزال مسودة ، لكنها أثبتت أنها مفيدة حتى الآن. يساعدني ذلك دائمًا على إعادة توحيد العارض الفرعي إلى فرعهم.
[alias]
######################
#
#Submodules aliases
#
######################
#git sm-trackbranch : places all submodules on their respective branch specified in .gitmodules
#This works if submodules are configured to track a branch, i.e if .gitmodules looks like :
#[submodule "my-submodule"]
# path = my-submodule
# url = git@wherever.you.like/my-submodule.git
# branch = my-branch
sm-trackbranch = "! git submodule foreach -q --recursive 'branch=\"$(git config -f $toplevel/.gitmodules submodule.$name.branch)\"; git checkout $branch'"
#sm-pullrebase :
# - pull --rebase on the master repo
# - sm-trackbranch on every submodule
# - pull --rebase on each submodule
#
# Important note :
#- have a clean master repo and subrepos before doing this !
#- this is *not* equivalent to getting the last committed
# master repo + its submodules: if some submodules are tracking branches
# that have evolved since the last commit in the master repo,
# they will be using those more recent commits !
#
# (Note : On the contrary, git submodule update will stick
#to the last committed SHA1 in the master repo)
#
sm-pullrebase = "! git pull --rebase; git submodule update; git sm-trackbranch ; git submodule foreach 'git pull --rebase' "
# git sm-diff will diff the master repo *and* its submodules
sm-diff = "! git diff && git submodule foreach 'git diff' "
#git sm-push will ask to push also submodules
sm-push = push --recurse-submodules=on-demand
#git alias : list all aliases
#useful in order to learn git syntax
alias = "!git config -l | grep alias | cut -c 7-"
نحن نستخدم الدجال لسحب وحدة معينة من مستودع GIT آخر. نحتاج إلى سحب التعليمات البرمجية بدون قاعدة التعليمات البرمجية بأكملها للمستودع المقدم - نحتاج إلى وحدة / ملف محدد للغاية من هذا المستودع الضخم ويجب تحديثه في كل مرة نقوم فيها بتشغيل التحديث.
لذلك حققناها بهذه الطريقة:
إنشاء التكوين
name: Project Name
modules:
local/path:
repository: https://github.com/<username>/<repo>.git
path: repo/path
branch: dev
other/local/path/filename.txt:
repository: https://github.com/<username>/<repo>.git
hexsha: 9e3e9642cfea36f4ae216d27df100134920143b9
path: repo/path/filename.txt
profiles:
init:
tasks: ['modules']
مع التكوين أعلاه ، يقوم بإنشاء دليل واحد من مستودع GitHub المقدم كما هو محدد في تكوين الوحدة الأولى ، والآخر هو سحب وإنشاء ملف من المستودع المحدد.
يحتاج المطورين الآخرون فقط إلى الجري
$ quack
ويسحب الرمز من التكوينات أعلاه.
التأثير الوحيد لاختيار فرع للوحدة الفرعية هو ذلك ، كلما مررت --remote
الخيار في git submodule update
سطر الأوامر ، سوف تحقق git في رأس منفصل الوضع (إذا كان الافتراضي --checkout
تم اختيار السلوك) أحدث التزام بهذا المحدد التحكم عن بعد فرع.
يجب أن تكون حذراً بشكل خاص عند استخدام ميزة تتبع الفرع عن بُعد للفيروسات الفرعية GIT إذا كنت تعمل مع استنساخ ضحل من العارض الفرعي. الفرع الذي تختاره لهذا الغرض في إعدادات الجهاز الفرعي ليس الشخص الذي سيتم استنساخه خلال git submodule update --remote
. إذا قمت بتمرير أيضا --depth
المعلمة و أنت لا تطلب من الفرع الذي تريد استنساخه -- وفي الواقع لا يمكنك ذلك في ال git submodule update
سطر الأوامر!! - ، سوف يتصرف ضمنيًا كما هو موضح في git-clone(1)
وثائق ل git clone --single-branch
عندما واضحة --branch
المعلمة مفقودة ، وبالتالي سوف يستنسخ الفرع الأساسي فقط.
ليس من المستغرب ، بعد مرحلة الاستنساخ التي تؤديها git submodule update
الأمر ، سيحاول أخيرًا الاطلاع على أحدث الالتزام بـ التحكم عن بعد الفرع الذي قمت بإعداده مسبقًا للوحدة الفرعية ، وإذا لم يكن هذا هو الأساسي ، فهو ليس جزءًا من استنساخ الضحل المحلي الخاص بك ، وبالتالي فسوف يفشل
قاتلة: تحتاج إلى مراجعة واحدة
غير قادر على العثور على الأصل الحالي/nottheprimarybranch مراجعة في مسار الجهاز الفرعي "mysubmodule"
الجهاز الفرعي git إضافة -b تطوير -اسم الفرع -اسم - https: //branch.git