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

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

... сделает подмодули HEAD отсоединенными, если не указано --rebase или --merge...

Как --rebase/--merge меняет?

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

  • Могу ли я создавать ветки/модификации из этих подмодулей и использовать push/pull точно так же, как в обычных репозиториях, или есть вещи, которые следует соблюдать осторожность?
  • Как бы я продвинул коммит, на который ссылается субмодуль, скажем, с (помеченного) 1.0 до 1.1 (даже если заголовок исходного репозитория уже находится на 2.0), или выбрал, какой коммит ветки используется вообще?

Ответ 1

Эта страница 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 vs git pull ".

Ответ MindTooth иллюстрирует обновление вручную (без локальной настройки):

git submodule -q foreach git pull -q origin master

В обоих случаях это изменит ссылки на подмодули ( gitlink, специальная запись в индексе родительского репо), и вам нужно будет добавить, зафиксировать и отправить упомянутые ссылки из основного репо.
В следующий раз, когда вы будете клонировать это родительское репо, оно заполнит подмодули, чтобы отразить эти новые ссылки SHA1.

В остальной части этого ответа подробно описывается классическая функция субмодуля (ссылка на фиксированный коммит, который является основным моментом за понятием субмодуля).


Чтобы избежать этой проблемы, создайте ветку, когда вы работаете в подмодульном каталоге с работой git checkout -b или чем-то аналогичным. Когда вы обновите субмодуль во второй раз, он все равно вернет вашу работу, но, по крайней мере, у вас есть указатель для возврата.

Переключение веток с подмодулями в них также может быть сложным. Если вы создаете новую ветку, добавляете туда подмодуль и затем переключаетесь обратно на ветку без этого подмодуля, у вас все еще остается каталог подмодуля в качестве неотслеживаемого каталога:


Итак, чтобы ответить на ваши вопросы:

Могу ли я создавать ветки/модификации и использовать push/pull так же, как и в обычных репозиториях, или есть вещи, которые нужно соблюдать осторожность?

Вы можете создать ветку и нажать на изменения.

ПРЕДУПРЕЖДЕНИЕ (из учебника по Git Submodule): всегда публиковать (отправлять) изменения подмодуля, прежде чем публиковать (отправлять) изменения в суперпроект, который ссылается на него. Если вы забудете опубликовать изменение субмодуля, другие не смогут клонировать репозиторий.

как бы я продвинул коммит, на который ссылается субмодуль, с say (tagged) 1.0 до 1.1 (даже если голова исходного репо уже на 2.0)

Страница " Понимание подмодулей " может помочь

Подмодули Git реализованы с использованием двух движущихся частей:

  • файл .gitmodules и
  • особый вид дерева.

Вместе они триангулируют конкретную ревизию конкретного репозитория, которая извлекается в определенное место в вашем проекте.


Со страницы подмодуля git

Вы не можете изменять содержимое подмодуля из основного проекта

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

Вот почему, когда вы изменяете подмодуль из основного проекта, вы:

  • необходимо зафиксировать и передать в подмодуле (в модуль восходящего потока), и
  • затем перейдите в ваш основной проект и повторите коммит (чтобы этот основной проект ссылался на новый коммод подмодуля, который вы только что создали и отправили)

Подмодуль позволяет вам разрабатывать компонентный подход -b, где основной проект ссылается только на конкретные коммиты других компонентов (здесь "другие репозитории Git, объявленные как субмодули").

Подмодуль - это маркер (коммит) в другом Git-репозитории, который не связан основным циклом разработки проекта: он ("другое" Git-репо) может развиваться независимо.
Основной проект должен выбрать из этого репо то, что ему нужно.

Однако, если вы хотите, из-за удобства, изменить один из этих подмодулей непосредственно из вашего основного проекта, Git позволяет вам сделать это, при условии, что вы сначала опубликуете эти изменения подмодуля в своем исходном репозитории Git, а затем подтвердите свой основной проект, ссылаясь на новая версия указанного субмодуля.

Но основная идея остается: ссылки на конкретные компоненты, которые:

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

Список конкретных коммитов, к которым вы обращаетесь в своем основном проекте, определяет вашу конфигурацию (это то, чем занимается Configuration Management, включая простую систему контроля версий)

Если компонент действительно может быть разработан в то же время, что и ваш основной проект (потому что любая модификация основного проекта будет включать изменение подкаталога и наоборот), тогда это будет не "подмодуль", а объединение поддеревьев (также представлено в вопросе " Перенос базы устаревшего кода из cvs в распределенный репозиторий"), связывание истории двух репозиториев Git вместе.

Помогает ли это понять истинную природу подмодулей Git?

Ответ 2

Чтобы обновить каждый подмодуль, вы можете вызвать следующую команду (в корне хранилища):

git submodule -q foreach git pull -q origin master

Вы можете удалить опцию -q, чтобы проследить весь процесс.

Ответ 3

Чтобы обратиться к --rebase против --merge:

Допустим, у вас есть супер-репозиторий A и субмодуль B, и вы хотите выполнить некоторую работу в субмодуле B. Вы сделали свою домашнюю работу и знаете, что после звонка

git submodule update

вы находитесь в состоянии HEAD, поэтому к любым коммитам, которые вы делаете в этот момент, трудно вернуться. Итак, вы начали работу над новой веткой в подмодуле B

cd B
git checkout -b bestIdeaForBEver
<do work>

Между тем, кто-то еще в проекте A решил, что последняя и самая лучшая версия B - это то, что A заслуживает. Вы, по привычке, объединяете самые последние изменения и обновляете свои подмодули.

<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.)

Ответ 4

Git 1.8.2 имеет новую опцию, --remote, которая включит именно это поведение. Бег

git submodule update --rebase --remote

будет извлекать последние изменения из апстрима в каждом подмодуле, перебазировать их и проверять последнюю версию подмодуля. Как написано в документации:

--remote

Эта опция действительна только для команды обновления. Вместо использования суперпроектов, записанных SHA-1, для обновления субмодуля, используйте статус ветки удаленного отслеживания субмодулей.

Это эквивалентно запуску git pull в каждом подмодуле, что обычно именно то, что вам нужно.

(Это было скопировано из этого ответа.)