How to add a git repo as a submodule of itself? (Or: How to generate GitHub Pages programmatically?)
我想开始为我的项目的网站使用Github页面。这只需要回购中名为
为了提交到
一位朋友建议我将
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | $ 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 |
我不熟悉子模块;当然,我读过一些书,但我不理解这种行为。为什么需要
是否可以添加回购作为其子模块?它是可取的吗?有什么陷阱需要我注意吗?有没有更好的方法来实现我想要的?
在这种情况下,行为似乎是Git试图将原始存储库的源代码设置为子模块的源代码。这一点得到了
is the URL of the new submodule’s origin repository. This may be either an absolute URL, or (if it begins with ./ or ../), the location relative to the superproject’s origin repository.
号
一个对我来说很好的解决方法是:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | # 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 |
这似乎没问题-如果我换到另一个目录并执行以下操作:
1 2 | $ cd /var/tmp $ git clone --recursive /tmp/main/ |
号
…子模块已正确更新和初始化。(更新:尽管正如您在下面的注释中指出的,子模块中的
至于这是否是一个好主意:我曾经做过一个项目,在过去使用过类似的设置,后来放弃了它。然而,造成这种情况的原因是:(a)主存储库中的可选分支非常庞大,甚至对于不需要子模块的人来说,存储库也会膨胀;(b)它给不确定发生了什么事情的人造成了混乱。
但是,对于您的用例,我认为这是一个相当好的解决方案:)
使用git子模块生成github页面的另一种方法是使用git子树合并策略。有许多网站展示了如何做到这一点,并认为子模块与子树合并的优缺点。甚至有一个新的git子树命令,可能与您的git版本一起安装,也可能不一起安装。在我看来,你真正需要知道的只有这两点。好的。
子树合并策略在合并时与两个存储库/分支的树(Git的目录树概念)相匹配,这样就不会合并无关的文件和文件夹,而只合并相关的树。这正是您想要的Github页面,因为它在一个孤立的分支中,它有一个完全不同的树,您的主分支。好的。
通常,与子模块相比,子树合并具有简化的工作流程,并且丢失修订的机会更少。好的。
以下是如何将子树合并策略与Github页面结合使用:好的。
如果在本地或远程回购中没有名为
1 2 3 4 5 | . $ (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将其拉入并提交,但是您必须了解tree-ish。假设您可以首先使用git-write树,它将输出当前索引中由
1 2 3 4 5 | . $ (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" |
号
检查
1 2 3 | . $ (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。例如:杰基尔、鹈鹕或斯芬克斯。注意:如果您不使用jekyll,并且需要下划线的文件夹/文件,例如:对于
1 2 3 4 | ./docs $ (master) sphinx-quickstart ... ./docs $ (master) make html ./docs/_build/html $ (master) echo >> .nojekyll |
号
使用子树合并策略(
1 2 | . $ (master) git checkout origin/gh-pages . $ (gh-pages) git merge --no-commit --squash -s subtree master |
Git使用子树合并策略对要合并的树进行了最佳猜测,但是,如果没有太多要进行的操作,则最好明确地告诉Git要合并的树。好的。
1 | . $ (gh-pages) git merge --no-commit --squash -s recursive -Xsubtree=docs/_build/html/ master |
。
检查您的更改并提交。合并为您生成一条消息,其中包含要合并的所有提交的简短日志。好的。
1 | . $ (gh-pages) git commit |
推你的
1 | . $ (gh-pages) git push origin gh-pages |
。
返回
1 | . $ (gh-pages) git checkout master |
。
如果出于任何原因需要从
要对匹配树的两个分支执行diff,请使用diff树好的。
1 | . $ git diff-tree master gh-pages |
把它放到一个脚本或提交后钩子中,每当您编辑文档或将其添加到用于生成HTML和Voila的
好啊。