У меня есть два или более проекта (пусть я называю их ProjectFoo и ProjectBar ) с некоторым общим кодом , который я вставил в подмодуль .
Я понимаю, что если Я фиксирую изменения в подмодуле из ProjectFoo , это будет в отдельной голове, что только все клоны ProjectFoo могут видеть:
(master) $ cd ProjectFooBarCommoneSubmodule/
(master) $ git commit -am "Common code fix."
(56f21fb0...) $ git push
Everything up-to-date
Это, вероятно, потому что мастер
] ветка не изменилась. Возможно, я мог бы сделать что-то вроде git checkout master && git merge Все актуально
, но это кажется довольно уродливым. Может быть, git reset --hard master
сделал бы то же самое, но это кажется еще более уродливым.
Как сделать общий код общим для проекта, обновив из этих проектов, используя Это? Другими словами, фиксация в этом подмодуле должна обновлять все различные репозитории (не только клоны , но и клоны ), которые используют этот же подмодуль.
---- EDIT ----
Видимо, мой извлеченный репозиторий был испорчен и сломан. Он должен был с самого начала работать так (на 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
может потребоваться, если он находится на отдельной головке.
Короткий ответ:
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. Могут произойти всевозможные неприятные вещи, если изменения проекта B будут автоматически импортированы, из которых ошибки компиляции, вероятно, самые лучшие, поскольку A сразу же заметит сбои. Вот почему голова B: держится в отсоединенном состоянии.
Состояние B хранится в A (проверьте git submodule status
), и изменение ревизии должно быть сделано и зафиксировано в A, чтобы оно имело какой-либо эффект.Это то, что происходит в приведенном выше примере: A изменяет номер версии, хранящийся в репозитории, и устанавливает последнюю версию. Этот процесс необходимо будет повторить и в другом основном репо, поэтому нет автоматического переключателя «использовать мастер», AFAIK.
Кстати. Глава книги Git о подмодулях и справочная страница подмодуля содержат много полезной информации о подмодулях, как о нормальном использовании, так и о типичных ловушках. Стоит проверить.
РЕДАКТИРОВАТЬ: я попытаюсь объяснить это лучше
Я позволил себе создать примеры проектов в моей учетной записи github. Коммиты бессмысленны и содержат мусор, но установка должна быть в порядке. Пожалуйста, проверьте это, чтобы следовать.
И ProjectFoo, и ProjectBar совместно используют код в общем подмодуле.
ProjectFooBarCommoneSubmodule: мастер 6850e4e4c1fac49de398
В ProjectFoo:
git submodule status
-6850e4e4c1fac49de39890703f21486ca04b87a0 общих
В ProjectBar:
git submodule status
-6850e4e4c1fac49de39890703f21486ca04b87a0 общих
Так как точки на ту же ревизию, правильно? Хитрость заключается в том, чтобы увидеть, что ProjectFoo и ProjectBar указывают на ревизию (6850e4e4c1fac49de39890703f21486ca04b87a0) , а не на ветку (мастер), хотя это одно и то же. Первый - это отдельная голова, а другой - именованная ветвь.
Если вы хотите внести некоторые исправления в ProjectFooBarCommoneSubmodule, вы можете перейти в подкаталог, например, в ProjectFoo и выберите ветку вместо ревизии:
git checkout master
<Do your coding and pushing here>
Затем перейдите на один каталог вверх и проверьте статус подмодуля git.Он должен сказать вам, что вы сейчас не синхронизированы. Например,
git submodule status
+e24bd2bf45d52171a63b67ac05cd4be0ac965f60 common (heads/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, если они ссылаются на что-то несуществующее. Надеюсь, это объяснило это лучше