Git commit для общего подмодуля (основная ветка) - PullRequest
54 голосов
/ 28 августа 2010

У меня два или более проектов (назовем их ProjectFoo и ProjectBar ), имеющих некоторый общий код , который я вставил в подмодуль .

Насколько я понимаю, если я зафиксирую изменения в подмодуле из ProjectFoo , это будет в отдельной голове, что только все клоны ProjectFoo смогут увидеть:

(master) $ cd ProjectFooBarCommoneSubmodule/
(master) $ git commit -am "Common code fix."
(56f21fb0...) $ git push
Everything up-to-date

Это, вероятно, потому что ветвь master не изменилась. Я мог бы, вероятно, сделать что-то вроде git checkout master && git merge Everything up-to-date, но это кажется довольно уродливым. Может быть, git reset --hard master будет делать то же самое, но это кажется еще страшнее.

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

---- РЕДАКТИРОВАТЬ ----

Видимо, мой проверенный репозиторий был испорчен и сломан. Он должен был с самого начала работать так (на ProjectFoo в этом примере):

(master) $ cd ProjectFooBarCommoneSubmodule/
(master) $ git commit -am "Common code fix."
(master) $ git push
....
   fbfdd71..0acce63  master -> master
(master) $ cd ..
(master) $ git add ProjectFooBarCommoneSubmodule
(master) $ git commit -m "Submodule update."

Затем, чтобы получить это изменение от других проектов, таких как ProjectBar :

(master) $ cd ProjectFooBarCommoneSubmodule/
(master) $ git pull

Будет ли обновляться до последнего общего кода. git checkout master может потребоваться, если он находится на отсоединенной головке.

Ответы [ 6 ]

66 голосов
/ 29 августа 2010

Краткий ответ:

cd ProjectFooBarCommoneSubmodule
git checkout master
<Do your editing>
git commit --all -m "Lots of fixes"
git push submodule_origin master
cd ..

git add ProjectFooBarCommoneSubmodule
git commit -m "Bumped up the revision of ProjectFooBarCommoneSubmodule"
git push origin master

Чем дольше:

Подмодули Git - это механизм зависимостей, в котором основной проект (скажем, A) определяет указанную ревизию в подпроекте (скажем, B), который будет использоваться при создании проекта A. Чтобы инструмент был полезным, поведение имеет быть предсказуемым с точки зрения A: s. Зависимости не могут измениться, если кто-то не решит включить изменение в проект А. Могли бы произойти все виды неприятностей, если бы автоматически импортировались изменения проекта В, из которых ошибки компиляции, вероятно, являются лучшими, поскольку А немедленно заметил бы сбои. Вот почему голова B: находится в отсоединенном состоянии.

Состояние B сохраняется в A (см. git submodule status), и изменение A должно быть сделано и зафиксировано в A, чтобы оно имело какой-либо эффект. Это то, что происходит в приведенном выше примере. A изменяет номер редакции, хранящийся в репо, и увеличивает версию до последней. Процесс придется повторить и в другом главном репо, поэтому автоматический переключатель «использовать мастер» AFAIK отсутствует.

КСТАТИ. Глава Git book по подмодулям и справочная страница субмодуля содержат много полезной информации о подмодулях, как обычном использовании, так и типичных подводных камнях. Стоит проверить.


РЕДАКТИРОВАТЬ: я постараюсь объяснить это лучше

Я позволил себе создать примеры проектов на моей учетной записи github . Коммиты не имеют смысла и содержат мусор, но настройка должна быть в порядке. Пожалуйста, проверьте это, чтобы следовать.

И ProjectFoo, и ProjectBar совместно используют код в общем подмодуле.

ProjectFooBarCommoneSubmodule: master - это 6850e4e4c1fac49de398

В ProjectFoo:

git submodule status

-6850e4e4c1fac49de39890703f21486ca04b87a0 common

В ProjectBar:

git submodule status

-6850e4e4c1fac49de39890703f21486ca04b87a0 common

То есть оба указывают на одну и ту же ревизию, верно? Хитрость заключается в том, чтобы увидеть, что ProjectFoo и ProjectBar указывают на ревизию (6850e4e4c1fac49de39890703f21486ca04b87a0) , а не на ветку (master), хотя это одно и то же. Первая - это оторванная голова, а другая - именованная ветвь.

Если вы хотите внести исправления в ProjectFooBarCommoneSubmodule, вы можете перейти к подкаталогу, например, в. ProjectFoo и выбирают ветку вместо ревизии :

git checkout master 
<Do your coding and pushing here>

Затем перейдите на один каталог вверх и проверьте состояние подмодуля git. Это должно сказать вам, что вы сейчас не синхронизированы. * 1051 например *

git submodule status

+ e24bd2bf45d52171a63b67ac05cd4be0ac965f60 common (головки / master-1-ge24bd2b)

Теперь вы можете сделать git add, чтобы установить ссылку на этот конкретный коммит (ge24bd ...), сделать коммит, и после этого ссылка на подмодуль указывает на эту ревизию, которая также является главной в ProjectFooBarCommoneSubmodule.

Теперь вам нужно обновить ссылку и в ProjectBar. Перейдите в ProjectBar / common и выполните git fetch origin (это ускоренное слияние), выполните

git checkout master 
cd ..
git add common
git commit -m "Bumped up the revision"
git push origin master # to publish the revision bump to everybody else

Так что, как и в любом git-репозитории, вам не нужно работать на отдельной голове. Вы можете либо работать над мастером, либо создать именованную ветку. В любом случае, убедитесь, что апстрим содержит изменения ProjectFooBarCommoneSubmodule, или вы нарушите оба ProjectFoo и ProjectBar, если они ссылаются на то, что не существует. Надеюсь, это объяснило это лучше

3 голосов
/ 14 апреля 2016

На submodule: git push origin HEAD:master

0 голосов
/ 17 мая 2018

Примечание:

git submodule foreach 'git commit -a'

завершится ошибкой, если один из подмодулей не содержит коммитов для выполнения.

Чтобы избавиться от этого, вы должны принудительно установить результат команды в 0.

git submodule foreach "git commit -am 'your comment' || echo ' '"

Используя эхо-канал, вы заставляете всю команду возвращаться с 0 и продолжаете выполнять команду фиксации для других подмодулей

0 голосов
/ 07 июля 2017

Я просто делаю:

git submodule foreach git push -u origin master

0 голосов
/ 14 января 2017

Чтобы объединить измененный из отсоединенного заголовка в мастер, запустите:

git rebase HEAD master

затем мастер проверки (используйте -f для силы):

git checkout master

Если у вас есть несколько подмодулей, используйте: git submodule foreach, например,

git submodule foreach git pull origin master -r
0 голосов
/ 03 ноября 2016

Если вы хотите зафиксировать и отправить все подмодули одновременно, выполните:

git submodule foreach 'git commit -a' ;
git submodule foreach 'git push --all' ;
git commit -a && \
git push --all --recurse-submodules=on-demand
...