Оновлення підмодуля Git


242

Мені не ясно, що означає наступне (з документації на оновлення підмодуля Git ):

... зробить підмодулі HEAD від'єднаними, якщо не вказано --rebaseабо --merge...

Як --rebase/ --mergeзмінює речі?

Головний мій варіант використання - це купа центральних сховищ, які я вбудую через підмодулі в інші сховища. Я хотів би мати можливість вдосконалитись у цих центральних сховищах, безпосередньо в їх первісному місці, або з їх вбудованих сховищ (тих, що використовують їх через підмодуль).

  • Чи можна з цих підмодулів створювати гілки / модифікації та використовувати push / pull так, як я б робив у звичайних сховищах, чи є з чим слід бути обережними?
  • Як би я перейшов до підмодулю, на який посилається фіксація, з say (помічено) 1,0 до 1,1 (навіть якщо заголовок оригінального сховища вже на рівні 2,0), або вибрати, який комітет філії використовується взагалі?

Щодо теми "відірвана голова", див. Також stackoverflow.com/questions/964876/head-and-orighead-in-git та stackoverflow.com/questions/237408/… для практичного прикладу (не пов'язаний з підмодулем, але все-таки )
VonC

"ви не можете змінювати вміст підмодулю в межах основного проекту": так, правда. І я відредагував свою відповідь, щоб пролити трохи світла на те очевидне протиріччя (неможливий для зміни підмодуль, який ви все ще можете змінити з головного репо-проекту!)
VonC

Відповіді:


304

Ця сторінка GitPro добре підсумовує наслідки оновлення підмодулю git

Під час запуску git submodule updateвін перевіряє конкретну версію проекту, але не в межах філії. Це називається мати відокремлену голову - це означає, що файл HEAD вказує безпосередньо на фіксацію, а не на символічну посилання.
Проблема полягає в тому, що ти, як правило, не хочеш працювати в окремому оточенні голови, тому що втратити зміни легко .
Якщо ви робите початкове оновлення підмодулю, виконайте введення в цьому каталозі субмодуля, не створюючи гілки для роботи, а потім знову запустіть оновлення підмодуля git із суперпроекту, не роблячи тим часом, Git замінить ваші зміни, не повідомивши вам. Технічно ви не втратите роботу, але у вас не буде гілки, що вказує на неї, тому її буде важко знайти.


Примітка березня 2013 року:

Як вже згадувалося у " останньому відстеженні субмодуля git ", підмодуль зараз (git1.8.2) може відслідковувати гілку.

# add submodule to track master branch
git submodule add -b master [URL to Git repo];

# update your submodule
git submodule update --remote 
# or (with rebase)
git submodule update --rebase --remote

Див. " git submodule update --remoteПротиgit pull ".

MindTooth «сек відповідь ілюструє оновлення вручну (без локальної конфігурації):

git submodule -q foreach git pull -q origin master

В обох випадках це призведе до зміни посилань на субмодулі ( gitlink , спеціальний запис у батьківському індексі репо ), і вам потрібно буде додати, здійснити та висунути згадані посилання з основного репо.
Наступного разу, коли ви будете клонувати це батьківське репо, воно заповнить підмодулі для відображення цих нових посилань на SHA1.

У решті цієї відповіді детально описана класична особливість субмодуля (посилання на фіксований коміт, який є всією точкою поняття субмодуля).


Щоб уникнути цієї проблеми, створіть гілку, коли ви працюєте в каталозі підмодулів з git checkout -b робота або щось подібне. Коли ви зробите оновлення підмодуля вдруге, воно все одно відновить вашу роботу, але принаймні у вас є вказівник, до якого потрібно повернутися.

Перемикання гілок з підмодулями в них також може бути складним. Якщо ви створюєте нову гілку, додаєте туди підмодуль і повертаєтесь назад до гілки без цього підмодуля, у вас все ще є каталог підмодуля як нерозподілений каталог:


Отже, щоб відповісти на ваші запитання:

чи можу я створити гілки / модифікації та використовувати push / pull так, як я б робив у звичайних репостах, чи є речі, про які варто бути обережними?

Ви можете створити гілки та виправити модифікації.

ПОПЕРЕДЖЕННЯ (з підручника Git Submodule ): Завжди публікуйте (натискайте) зміни підмодулю перед публікацією (push) змін у суперпроект, на який посилається. Якщо ви забудете опублікувати зміну підмодуля, інші не зможуть клонувати сховище.

як би я просунув підмодуль, на який посилається фіксація, від say (tagged) 1.0 до 1.1 (навіть якщо заголовок оригінального репо вже на 2.0)

Сторінка " Розуміння підмодулів " може допомогти

Підмодулі Git реалізовані за допомогою двох рухомих частин:

  • .gitmodulesфайл і
  • особливий вид деревного об’єкта.

Вони разом триагулюють конкретну редакцію конкретного сховища, яка перевіряється у певному місці вашого проекту.


З сторінки субмодуля git

ви не можете змінювати вміст підмодулю в межах основного проекту

На 100% вірно: ви не можете змінити підмодуль, посилайтеся лише на один із його елементів.

Ось чому, коли ви змінюєте підмодуль в рамках основного проекту, ви:

  • необхідно здійснити і натиснути в межах підмодуля (до модуля вище), і
  • потім перейдіть до свого основного проекту та повторно виконайте (для того, щоб цей головний проект посилався на новий підмодуль, який ви тільки що створили та натиснули)

Підмодуль дозволяє розробити підхід на основі компонентів , де основний проект посилається лише на конкретні комісії інших компонентів (тут "інші сховища Git, оголошені як підмодулі ").

Підмодуль - це маркер (фіксація) для іншого сховища Git, який не пов'язаний основним циклом розробки проекту: він ("інше" Git repo) може розвиватися незалежно.
Основний проект залежить від того іншого репо, будь-яке зобов'язання.

Однак, якщо ви хочете, щоб зручно змінити один із цих підмодулів безпосередньо з вашого основного проекту, Git дозволяє це зробити, за умови, що ви спочатку опублікуєте ці модифікації підмодулю до свого оригінального репортажу Git, а потім скористаєтесь своїм основним проектом перегляду на нова версія зазначеного субмодуля.

Але головна ідея залишається: посилання на конкретні компоненти, які:

  • мають власний життєвий цикл
  • мають власний набір тегів
  • мають власний розвиток

Перелік конкретних зобов’язань, на які ви посилаєтесь у своєму головному проекті, визначає вашу конфігурацію (саме про це і полягає у керуванні конфігурацією , що залучає просту систему управління версіями )

Якщо компонент дійсно міг би бути розроблений одночасно з вашим основним проектом (оскільки будь-яка модифікація основного проекту передбачала б зміну підкаталогу, і навпаки), то це був би не "підмодуль", а злиття підкреслень (також представлено у питанні Передача бази спадкового коду з резюме до розподіленого сховища ), пов'язуючи історію двох репортажів Git разом.

Чи допомагає це зрозуміти справжню природу Git Submodules?


77
Ого. Це довге пояснення чогось, що в основному простого, повинно бути достатньо, щоб налякати будь-якого новачка, щоб просто дотримуватися свого svn: externals. ;-)
conny

2
@conny: але, як я детально розповідаю у " Чому підмодулі git несумісні із зовнішніми версіями svn? ", підмодулі принципово різні та не сумісні із svn:externals.
VonC

1
Вибачте, щоб відповісти на моє власне запитання, я збираю cd'ing в підмодуль і git checkout a sha, або git pull / fetch буде добре. Тоді робиться оновлення у локальному сховищі.
Генрік

2
@hced: Ви також можете відразу потрапити на всі підмодулі, використовуючиgit submodule foreach
Dav Clark,

1
.. все одно не отримуючи. чи є дещо простіше пояснення в Інтернеті?
Євген

135

Щоб оновити кожен підмодуль, ви можете викликати таку команду (у корені сховища):

git submodule -q foreach git pull -q origin master

Ви можете видалити опцію -q, щоб слідкувати за усім процесом.


15
Якщо ви просто запустите git submodule update --init --recursiveз кореня, він отримає всі рекурсивно та ініціалізує їх, якщо їх ще немає.
Сем Соффс

10
@SamSoffes Це повністю виконує іншу мету. Оновлення підмодулів перевіряє підмодулі на коміті, на який вони вказують в даний момент (не обов'язково останнє введення). Рішення у наведеній вище відповіді оновлює присвоєння кожного підмодулю останньому HEAD від початку / master.
indragie

7
Мій новий метод:git submodule update --rebase --remote
MindTooth

19

Щоб вирішити варіант --rebaseпроти --merge:

Скажімо, у вас є супер сховище A і підмодуль B і хочете виконати деяку роботу в підмодулі B. Ви зробили домашнє завдання і знаєте, що після виклику

git submodule update

ви перебуваєте в стані, що не має головки, тому до будь-яких зобов'язань, які ви зробите в цей момент, важко повернутися. Отже, ви почали роботу над новою гілкою в підмодулі B

cd B
git checkout -b bestIdeaForBEver
<do work>

Тим часом хтось із проекту A вирішив, що остання та найкраща версія B - це дійсно те, чого заслуговує А. Ви за звичкою об'єднуєте останні зміни та оновлюєте свої підмодулі.

<in A>
git merge develop
git submodule update

О, ні! Ви знову в безголовому стані, ймовірно, тому, що B зараз вказує на SHA, пов’язану з новою підказкою B, або іншим комітетом. Якби у вас були:

git merge develop
git submodule update --rebase

Fast-forwarded bestIdeaForBEver to b798edfdsf1191f8b140ea325685c4da19a9d437.
Submodule path 'B': rebased into 'b798ecsdf71191f8b140ea325685c4da19a9d437'

Тепер, коли найкраща ідея B колись була перетворена на новий комітет, і що ще важливіше, ви все ще знаходитесь у вашій галузі розвитку для B, а не в безголовому стані!

(Зміни --mergeбуде об'єднано зміни від beforeUpdateSHA до afterUpdateSHA у вашу робочу гілку, на відміну від повторної передачі змін у afterUpdateSHA.)


7

У Git 1.8.2 є нова опція --remote, яка дозволить саме таку поведінку. Біг

git submodule update --rebase --remote

отримає останні зміни з висхідного потоку в кожному підмодулі, перезавантажить їх і перевірить останню редакцію підмодуля. Як зазначено в документації :

--ремонт

Ця опція діє лише для команди оновлення. Замість використання записаного SHA-1 надпроекту для оновлення підмодулю використовуйте стан відділення дистанційного відстеження підмодуля.

Це еквівалентно запуску git pullв кожному підмодулі, що, як правило, саме те, що ви хочете.

(Це було скопійовано з цієї відповіді .)


Якщо ви вирішите відповісти на старіші запитання, на які є чітко встановлені та правильні відповіді, додавання нової відповіді в кінці дня може не отримати вам жодної заслуги. Якщо у вас є якась нова відмінна інформація, або ви переконані, що інші відповіді невірні, будь-ласка, додайте нову відповідь, але "ще одна відповідь", що дає ту саму основну інформацію довгий час після того, як питання було зазвичай, виграно " t заробляєш багато кредиту. Немає пояснень, що це робить - навіть посилання на зовнішню документацію (що було б недостатньо).
Джонатан Леффлер

2
Це не "ще одна відповідь", оскільки НІ інша відповідь не має цієї команди (доведіть мене неправильно). Інші відповіді для мене не спрацювали, цей коментар зробив, тому я вирішив опублікувати його як відповідь, передаючи кредит первинному власнику. Тож розгляньте питання про видалення вашої головної програми.
Юліан Онофрей

Там є коментар по MindTooth з 2015 року говорить , що це те , що вони роблять зараз. Ви не даєте пояснення, що це робить (хоча ви згадуєте MindTooth, але немає реального пояснення того, що ви маєте на увазі під цим - вбудовування URL-адрес, як у цьому коментарі, допомогло б). Ви не кажете, чому це гарна ідея. Ви не даєте жодних застережень. На мій погляд, це не є корисною відповіддю, оскільки вона викликає більше питань, ніж вирішує.
Джонатан Леффлер

1
Під цим я мав на увазі, що він працює замість того, щоб не працювати. Повірте, якби більше людей побачили цю відповідь, вони були б раді, бо це працює . Такі речі, більшість людей просто хочуть знати команду, яка оновлює підмодуль git, а не те, як вона реалізована.
Юліан Онофрей

Я редагував відповідь, щоб довести свою помилку, також, stackoverflow.com/questions/1979167/git-submodule-update/… !!!
Юліан Онофрей
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.