Подтвердить что ты не робот

Как добавить репозиторий git как сам подмодуль? (Или: как программно создавать страницы GitHub?)

Я хочу начать использовать страницы GitHub для моего веб-сайта проекта. Для этого просто требуется ветвь (поддерево) с именем gh-pages в репо и служит для ее содержимого. Проблема в том, что часть веб-сайта (руководство, журнал изменений, страница загрузки...) автоматически генерируется системой сборки, поэтому я хочу найти лучший способ зафиксировать эти изменения в ветке gh-pages, в то время как основное репо остается на master (или где угодно).

Чтобы зафиксировать ветвь gh-pages, я мог написать script, который клонирует репо во временный каталог, вносит изменения, фиксирует их, а затем возвращает их обратно в основное репо. Но это звучит как процесс, подверженный ошибкам, поэтому я надеюсь, что есть более простой способ.

Друг предположил, что я могу добавить ветвь gh-pages в качестве подмодуля в основной репозиторий. Я провел небольшой эксперимент, но он не работает:

$ git init main
Initialized empty Git repository in /tmp/main/.git/
$ cd main
$ touch main.txt
$ git add .
$ git commit -m'Initial commit in main branch.'
[master (root-commit) 1c52a4e] Initial commit in main branch.
 0 files changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 main.txt
$ git symbolic-ref HEAD refs/heads/gh-pages
$ rm .git/index
$ git clean -fdx
Removing main.txt
$ touch index.html
$ git add .
$ git commit -m'Initial commit in website branch.'
[gh-pages (root-commit) 94b10f2] Initial commit in website branch.
 0 files changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 index.html
$ git checkout master
Switched to branch 'master'
$ git submodule add -b gh-pages . gh-pages
repo URL: '.' must be absolute or begin with ./|../
$ git submodule add -b gh-pages ./ gh-pages
remote (origin) does not have a url defined in .git/config

Я новичок в подмодулях; конечно, сделали некоторые чтения, но я не понимаю этого поведения. Зачем нужен пульт origin? В идеале я хочу, чтобы подмодуль всегда ссылался на репо, в котором он находится, поэтому он не должен ссылаться на origin или на любые другие пульты. Если кто-то клонирует репо и запускает git submodule init ; git submodule update, он должен идеально вытащить из вновь клонированного репо.

Можно ли добавить репо как сам подмодуль? Желательно? Есть ли какие-то подводные камни, о которых я должен знать? Есть ли лучший способ достичь того, что я хочу?

4b9b3361

Ответ 1

В этом случае поведение похоже на то, что git пытается установить происхождение исходного репозитория как начало подмодуля. Это подтверждается справочной страницей git submodule, в которой говорится [мой акцент]:

< репозиторий > является URL-адресом нового хранилища исходных подмодулей. Это может быть абсолютный URL-адрес или (если он начинается с./или../), местоположение относительно репозитория оригинала суперпроектов.

Обходной путь, который кажется мне хорошим, заключается в следующем:

# Define origin to be the absolute path to this repository - we'll remove
# this later:
$ cd /tmp/main/
$ git remote add origin /tmp/main/

# Now add the submodule:
$ git submodule add -b gh-pages ./ gh-pages
Initialized empty Git repository in /tmp/main/gh-pages/.git/
Branch gh-pages set up to track remote branch gh-pages from origin.

# Now .gitmodules looks sensible:
$ cat .gitmodules 
[submodule "gh-pages"]
    path = gh-pages
    url = ./

# However, the origin for the submodule isn't what we want:
$ cd gh-pages
$ git remote -v
origin  /tmp/main/ (fetch)
origin  /tmp/main/ (push)

# So remove it and add the right origin (just ".."):
$ git remote rm origin
$ git remote add origin ..

# Change back to the main repository and commit:
$ cd ..
$ git commit -m "Added the gh-pages branch as a submodule of this repository"
[master 6849d53] Added the gh-pages branch as a submodule of this repository
 2 files changed, 4 insertions(+), 0 deletions(-)
 create mode 100644 .gitmodules
 create mode 160000 gh-pages

Кажется, что это работает нормально - если я перехожу в другой каталог и делаю:

$ cd /var/tmp
$ git clone --recursive /tmp/main/

... подмодуль обновляется и инициализируется правильно. (Обновление: хотя, как вы отметили в комментарии ниже, origin в подмодуле будет установлен URL, который вы клонировали, а не ..)

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

Однако для вашего случая использования я считаю это довольно аккуратным решением:)

Ответ 2

Альтернатива использованию Git Подмодули для генерации Страницы GitHub использовать Git Subtree Стратегия слияния. Есть много сайтов которые показывают, как это сделать и которые утверждают плюсы и минусы Submodules vs Subtree-Merge. Существует даже новая git -subtree command, которая может быть установлена ​​или не установлена ​​с вашей версией Git. ИМО - единственное, что вам действительно нужно знать, - эти две точки.

  • Стратегия слияния поддерева совпадает с деревьями (git понятие дерева каталогов) двух репозиториев/ветвей при слиянии, чтобы посторонние файлы и папки не были объединены, а только соответствующие деревья. Это именно то, что вы хотите для Github Pages, так как оно находится в сиротской ветки, оно имеет совершенно другое дерево вашей главной ветки.

  • В общем случае слияние поддерева имеет упрощенный рабочий процесс и меньше шансов на проигрывание ревизий, чем подмодули.

Здесь, как использовать стратегию слияния поддерева с страницами Github:

  • Если у вас нет ветки с именем gh-pages в локальном или удаленном репозитории, создайте ее с помощью флага --orphan, чтобы он был пустым. В Github есть инструкции по созданию страниц Github вручную.. Если вы использовали Automatic Generation Generation, вы можете пропустить этот шаг, но замените локальную ветвь gh-pages на удаленную ветвь origin/gh-pages везде в этом сообщении, иначе локально удалите удаленную ветку. ПРИМЕЧАНИЕ. Вы можете пропустить создание файла .nojekyll, но вы должны удалить все файлы из сиротской ветки и зафиксировать его, или он не будет создан.

    . $ (master) git checkout --orphan gh-pages
    . $ (gh-pages) git rm -rf. 
    . $ (gh-pages) echo >> .nojekyll
    . $ (gh-pages) git add .nojekyll
    . $ (gh-pages) git commit -m "create github pages, ignore jekyll"
    

    Если у вас есть документация в поддереве в вашей основной ветке, вы можете ее потянуть и зафиксировать с помощью git-read-tree прямо сейчас, но вам нужно знать древовидную. Предположительно, вы могли бы сначала использовать git-write-tree, который выведет SHA-1 дерева, названного флагом --prefix в текущем индексе. Затем используйте флаг -u, чтобы обновить ветвь gh-pages с изменениями из основной ветки и зафиксировать изменения.

    . $ (master) git write-tree --prefix=docs/_build/html master
    abcdefghijklmnopqrstuvwxyz1234567890abcd
    . $ (master) git checkout gh-pages
    . $ (gh-pages) git read-tree abcdefghijklmnopqrstuvwxyz1234567890abcd
    . $ (gh-pages) git commit -m "update gh-pages html from master docs"
    
  • Оформить заказ master и использовать git-read-tree для копирования рабочей копии ветки gh-pages на некоторый путь в master, EG: ./docs/_build/html. Флаг -u обновляет файлы в рабочей копии, если слияние выполнено успешно. Этот шаг может оказаться ненужным, если в ветке gh-pages нет файлов, которые вы хотите объединить с мастером, но если они есть, это может помочь стратегии слияния поддерева определить, в каком дереве ваши файлы. Как обычно, Git не позволит вам объединять файлы, которые уже существуют, или если в вашем репо отсутствуют незафиксированные изменения. Используйте этот шаг, если вы хотите объединить созданные вами страницы с помощью автоматического создания страницы обратно в другое дерево, EG: docs в ветки master. Не забудьте зафиксировать новые файлы в ветке master.

    . $ (gh-pages) git checkout master
    . $ (master) git read-tree --prefix=docs/_build/html -u gh-pages
    . $ (master) git commit -m "read gh-pages tree into master at ./docs/_build/html"
    
  • Внесите изменения в свою документацию и создайте какой-либо html любым способом, который вы предпочитаете. EG: Jekyll, Pelican или Sphinx. ПРИМЕЧАНИЕ. Если вы не используете Jekyll и вам понадобятся папки/файлы подчёркивания, файлы EG: для *.css или *.js, тогда обязательно добавьте файл с именем .nojekyll в ваш каталог html.

    ./docs $ (master) sphinx-quickstart
    ...
    ./docs $ (master) make html
    ./docs/_build/html $ (master) echo >> .nojekyll
    
  • Обновите ветвь gh-pages, используя стратегию слияния поддерева (-s subtree), сквойте все коммиты, чтобы ваша страница страниц Github не была загрязнена (--squash) и подождите, пока слияние не будет выполнено поэтому вы можете просмотреть (--no-commit). ПРИМЕЧАНИЕ. Когда вы заказываете ветвь gh-pages, файлы и папки от мастера, вероятно, останутся неизмененными, просто игнорируйте их и сосредоточьтесь на том, что на самом деле находится в индексе. ПРИМЕЧАНИЕ. Git будет не checkout gh-pages, если в master есть какие-то неуправляемые или неработающие изменения.

    . $ (master) git checkout origin/gh-pages
    . $ (gh-pages) git merge --no-commit --squash -s subtree master
    

    Git делает все возможное, чтобы узнать, какие деревья вы хотите объединить, используя стратегию слияния поддерева, однако, если не так много, возможно, вам лучше указать Git, какое дерево будет объединяться.

    . $ (gh-pages) git merge --no-commit --squash -s recursive -Xsubtree=docs/_build/html/ master
    
  • Просмотрите свои изменения и зафиксируйте. Merge генерирует сообщение для вас, содержащее короткий журнал всех объединений, которые будут объединены.

    . $ (gh-pages) git commit
    
  • Нажатие вашего ветвления gh-pages развертывает ваш сайт GitHub Pages.

    . $ (gh-pages) git push origin gh-pages
    
  • Вернитесь к master.

    . $ (gh-pages) git checkout master
    
  • Если вам по какой-либо причине нужно потянуть изменения со своего gh-pages, используйте стратегию слияния поддерева в противоположном направлении. EG git merge --squash --no-commit -s subtree gh-pages

  • Чтобы выполнить различие двух ветвей, соответствующих деревьям, используйте diff-tree

    . $ git diff-tree master gh-pages
    
  • Поместите это в script или после фиксации, который запускается всякий раз, когда вы редактируете свои документы или добавляете его в Makefile, который вы используете для генерации html и voila! программно созданных страниц GitHub.