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

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

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

Как --rebase/--merge изменить вещи?

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

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

4 ответа

Решение

Эта страница 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 work или чем-то аналогичным. Когда вы обновите субмодуль во второй раз, он все равно вернет вашу работу, но, по крайней мере, у вас есть указатель, к которому можно вернуться.

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


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

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

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

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

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

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

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

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

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


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

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

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

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

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

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

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

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

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

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

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

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

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

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

git submodule -q foreach git pull -q origin master

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

Чтобы обратиться к опции --rebase vs --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.)

Git 1.8.2 имеет новую опцию --remote это позволит именно это поведение. Бег

git submodule update --rebase --remote

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

--дистанционный пульт

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

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

(Скопировано из этого ответа)

Другие вопросы по тегам