Я работаю над своей диссертацией, где я расширяю еще одну статью. В этой статье весь их код опубликован в репозитории X, а также используется сам подмодуль: назовем его Y.
Для моего собственного проекта я сделал собственный репозиторий Z, в который я включил X как подмодуль и, таким образом, Y как вложенный подмодуль. Однако я хотел бы внести изменения в код в X и Y, а также иметь возможность отправить это в свое собственное репо, чтобы я мог использовать его в нескольких местах. У меня нет разрешения на отправку X и Y, так как это чужое репо. Каков наилучший способ сделать это? Заранее спасибо, я запутался :D
Я попытался поместить свой собственный репозиторий в его основной каталог, но тогда он не включает код, который я изменил в подмодулях. Когда я захожу в сабмодули и коммичу там измененный код, то сначала выдал предупреждение об отсоединенной голове. Когда я исправил это, перейдя в новую ветку, теперь это дает мне:
git push --set-upstream origin new_branch
ERROR: Permission to \[repo X\] denied to \[myusername\].
fatal: Could not read from remote repository.
Please make sure you have the correct access rights
and the repository exists.
Теперь я разветвил репозиторий X и изменил URL-адрес в своих .gitmodules. Что теперь происходит с подмодулем Y?
Теперь я также изменил вилку в моем .gitmodule во вложенном репо. Но вы говорите, что если я хочу изменить содержимое двух репозиториев на бумаге, мне нужно найти другое решение? Не могли бы вы указать мне правильное направление там?
Подмодули просты, но со сложными результатами. «Подмодуль» состоит из двух частей: файла .gitmodules
и двух репозиториев Git. Один репозиторий называется суперпроект, а другой — подмодуль. Суперпроект содержит в одном или нескольких коммитах необработанный хэш-идентификатор коммита для проверки в подмодуля. Вот и вся картина — во всяком случае, до тех пор, пока мы не начнем работать.
Допустим, вы бежите:
git clone --no-recurse-submodules <url> super
cd super
Теперь у вас есть фиксация извлечения в из репозитория суперпроекта с указанием, что Git, запустив в этого суперпроекта, должен проверить фиксацию в подмодуле. Но нет никакого подмодуля. Вы клонировали только репозиторий один, а не два.
Параметр --no-recurse-submodules
гарантирует, что Git еще не клонирует подмодуль. В любом случае это значение по умолчанию, но мы сделали это здесь специально, чтобы сделать его очевидным и на случай, если вы изменили свои личные настройки, чтобы включить рекурсию.
Теперь вам нужно указать Git на полный проверку, если вы хотите, чтобы подмодуль был клонирован, а фиксация проверена. (Если вы предпочитаете вообще не возиться с подмодулем, вы можете оставить все в этом состоянии: у вас просто не будет подмодуля, даже если суперпроект требует его. Фактический шаг клонирования и проверки не является обязательным, при условии, что все, что вы делаете, не является необходимость подмодулем.Репозиторий Git для Git, например, включает в себя ссылку на подмодуль программы, которая проверяет коллизии SHA-1, но это конкретно необязательный, и вам не нужно беспокоиться об этом .)
Чтобы завершить проверку, вы теперь запускаете:
git submodule update --init
(если вы используете --recurse-submodules
в своем клоне, команда git clone
запускает эту команду для вас после шага git checkout
, шага 61).
Здесь есть проблема: это git submodule update --init
должно работать git clone
. Команде git clone
требуется URL-адрес. Откуда берется URL? Решением этой проблемы является файл .gitmodules
, который должен существовать в подтвержденном коммите в шаг 6; в этом файле должны быть перечислены URL-адреса всех подмодулей, которые должны быть клонированы в этот момент.
После того, как эти подмодули клонированы, команда git submodule update
, которую вы теперь можете использовать без флага --init
, выбирает коммит по хэш-идентификатору, который должен git checkout
в для каждого подмодуля, указанного суперпроектом. Идентификатор хэша, который команда суперпроекта Git git submodule update
извлекает в, репозиторий подмодуля — это тот, который хранится в извлеченном коммите (снова на шаге 6) — или, точнее, идентификатор хэша, который сейчас находится в Git показатель (но он попал в Git’s показатель). index через кассу на шаге 6).
Любые подмодули, которые теперь клонируются через git submodule update --init
, могут быть сами себя суперпроектами, если в них указан хэш-идентификатор коммита и имеется файл .gitmodules
. Если вы используете опцию --recursive
для git submodule update
, он войдет в каждый подмодуль и сделает его своим ходом в качестве своего суперпроекта в команде подмодулей это. Итак, это процесс, с помощью которого git clone --recurse-submodules
получает все подмодули подмодулей подмодулей подмодулей (как бы ни было глубоко вложение).
1Команда git clone
в основном является сокращением для запуска шести или семи команд, все, кроме одной, являются командами Git:
mkdir
или любая другая команда вашей системы для создания новой папки/каталога. Остальные команды выполняются в в новой папке.git init
: это создает новый, абсолютно пустой репозиторий.git remote add
: это добавляет пульт, имя которого вы можете выбрать, но все используют значение по умолчанию origin
с URL-адресом, который вы указали для git clone
.git config
(по умолчанию нет).git fetch origin
: это копирует все коммиты из программного обеспечения Git, которое отвечает на указанный вами URL-адрес. Он копирует нет ответвлений:, вместо этого их ветки становятся вашими именами для удаленного отслеживания.git checkout
: это создает одну ветку в вашем новом репозитории и проверяет коммит. Этот шаг является необязательным, так как он скрыт --no-checkout
.git submodule update --init
, если вы призвали к этому, и если есть подмодули, перечисленные в фиксации, проверенной на шаге 6. Этот шаг является необязательным и не используется по умолчанию.Представьте, что вместо только что клонируется суперпроект:
git clone --no-recurse-submodules <url> super
cd super
вы лично сначала клонируете сам суперпроект, но затем вы также лично клонируете подмодуль:
git clone --no-recurse-submodules <url1> super
cd super
mkdir -p super/sub
git clone --no-recurse-submodules <url2> super/sub
Теперь вы можете запустить git checkout
или git switch
в super
(где вы сейчас находитесь), а затем git submodule update
в super
и Git не нужно клонировать новый репозиторий. Git просто использует клон подмодуля существующий, который вы создали в суперпроекте.
При использовании этого метода содержимое файла .gitmodules
игнорируется. Таким образом, используя этот метод, вам не нужно исправлять какие-либо файлы .gitmodules
в любом суперпроекте, чтобы использовать другой URL-адрес подмодуля.
2Вы также можете запустить git submodule absorbgitdirs
после двух команд git clone
, чтобы переключиться со старой модели хранилища подмодулей Git 1.x на новую модель Git 2.x. Это не обязательный, это просто хорошая идея для несколько запутанных причин "подмодули могут приходить и уходить, а затем возвращаться снова". Когда подмодули делать удаляются — например, путем извлечения исторической фиксации — результат в настоящее время довольно уродлив: у подмодулей есть много проблем с пользовательским интерфейсом, что приводит к тому, что многие Все еще называют их модулями рыдать, несмотря на значительные улучшения в них с самого начала. дни Гита.
Что все это значит? Ну, скажем, есть какой-то существующий суперпроект, который вам не нужно трогать, но у вас есть подмодуль, или подмодуль из подмодуль, который вам делать нужно трогать, и в результате вы хотите, чтобы люди клонировали ваш подмодуль, или ваш под-под-модуль, когда они клонируют суперпроект.
Все, что вам нужно сделать, В самом делеимеют, — это сделать доступным собственный репозиторий Git. Те, кто «осведомлен», могут аккуратно клонировать подмодуль ваш и поместить его в надстройку(и), предоставленную(ые) существующим(и) суперпроектом(ами). Но если вы хотите, чтобы другие клонировали суперпроект (только удобный) и имели подмодуль git submodule update --init
клона ваш этого суперпроекта, вы должны обновить файл .gitmodules
в любом репозитории Git, который действует как суперпроект для вашего подмодуля.
Допустим, у вас изначально есть такая структура:
super <-- their superproject
super/sub1 <-- their submodule
super/sub1/sub2 <-- their sub-submodule
Есть два файла .gitmodules
: один в super/sub1/.gitmodules
, в котором указан URL-адрес, с которого можно клонировать sub2
, и один в super/.gitmodules
, в котором указан URL-адрес, с которого можно клонировать sub1
.
Поскольку вы создали новый репозиторий заменяетsub2
, теперь вы должны создать новый репозиторий заменяетsub1
, в котором .gitmodules
файл вsub1
содержит новый URL-адрес для вашей замены sub2
. Но чтобы суперпроект super
перечислил новый URL-адрес для вашей замены sub1
, теперь вы должны создать новый репозиторий заменяетsuper
, в котором .gitmodules
файл вsuper
перечисляет новый URL-адрес для вашей sub1
замены.
Другими словами, необходимость касаться .gitmodules
файлов «пузырится» от самого нижнего подмодуля через каждый промежуточный подмодуль и в конечном итоге достигает самого верхнего суперпроекта. Это неизбежно. если вы хотите, чтобы другим было удобно клонировать субмодуль нижнего уровня ваш.
Но это если. Подмодули уже ужасны; какой еще уровень ужаса здесь? Вы можете вместо того, чтобы дублировать другие репозитории только для обновления одного файла .gitmodules
в каждом из них, предоставить инструкцию, что после выполнения рекурсивного клонирования или update --init
те, кто хочет использовать ваш суб-суб-модуль, должны удалить один клон и заменить его. с твоим.
Это ваш выбор: сделать его удобным для других, сделав его неудобным для вас, или сделать его более удобным для вас, сделав его неудобным для других.
Большое спасибо за ваш супер развернутый ответ! Это дало мне лучшее понимание работы подмодулей.
С подмодулем никогда ничего не происходит. Это другой репозиторий Git. В своей вилке вы можете изменить содержимое файла
.gitmodules
, чтобы указать другой URL-адрес для еще одной вилки, если хотите, или вы можете оставить существующий URL-адрес в покое, чтобы продолжить использовать тот же другой Git-репозиторий.