我想开始在我的项目网站上使用GitHub Pages。这只需要在repo中命名为gh-pages
的分支(子树),并提供其内容。问题是网站的一部分(手动,更改日志,下载页面......)是由构建系统自动生成的,所以我想找到将这些更改提交到gh-pages
分支的最佳方法。主要回购仍在master
(或任何地方)。
要提交gh-pages
分支,我可以编写一个脚本,将repo克隆到一个临时目录中,进行修改,提交它们,然后将它们推回到主仓库。但这听起来像一个容易出错的过程,所以我希望有一个更简单的方法。
一位朋友建议我可以将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
遥控器?理想情况下,我希望子模块始终引用它所驻留的repo,因此它不应该引用origin
或任何其他遥控器。如果有人克隆了repo并运行git submodule init ; git submodule update
,理想情况下它应该从新克隆的repo中拉出来。
是否可以将repo添加为自身的子模块?这是可取的吗?我需要注意哪些陷阱?有没有更好的方法来实现我想要的目标?
答案 0 :(得分:8)
在这种情况下,行为似乎是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
将设置为您克隆的网址而不是..
)
至于这是否是一个好主意:我曾经参与过一个过去使用类似设置并随后放弃它的项目。然而,其原因是:(a)主存储库中的备用分支是巨大的,并且即使对于不需要子模块的人也会使存储库膨胀,以及(b)它导致混淆对于那些不确定发生了什么的人。
但是,对于您的用例,我认为这是一个相当简洁的解决方案:)
答案 1 :(得分:6)
使用Git Submodules生成GitHub Pages的替代方法是使用Git Subtree Merge Strategy。 There are many sites的that show how to do this that argue和the pros and cons Submodules vs Subtree-Merge。甚至还有一个新的git-subtree command可能会或可能不会与您的Git版本一起安装。 IMO唯一需要知道的是这两点。
子树合并策略在合并时匹配两个存储库/分支的树(git的目录树的概念),以便无关的文件和&文件夹未合并,只有相关的树。这正是你想要的Github Pages,因为它在一个孤儿分支中,它有一个完全不同的树你的主分支。
通常,子树合并具有简化的工作流程,并且丢失修订的机会少于子模块。
以下是如何在Github Pages中使用子树合并策略:
如果在本地或远程repos中没有名为gh-pages
的分支,则使用--orphan
标志创建一个分支,使其为空。 Github has instructions for creating Github pages manually.。如果您使用了Automatic Page Generation,则可以跳过此步骤,但将本地分支gh-pages
替换为此帖子中其他位置的远程分支origin/gh-pages
,否则为fetch the remote branch locally。 注意:您可以跳过创建.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输出当前索引中--prefix
标志所命名的树的SHA-1。然后使用-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不允许您合并已存在的文件或您的仓库中有未提交的更改。如果要将使用自动页面生成创建的页面合并回到docs
分支中的另一个树EG: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。 NOTE: If you are not using Jekyll, and will need underscore folders/files, EG: for *.css
or *.js
files, then be sure to add a file called .nojekyll
to your html directory.
./docs $ (master) sphinx-quickstart
...
./docs $ (master) make html
./docs/_build/html $ (master) echo >> .nojekyll
使用子树合并策略(gh-pages
)更新您的-s subtree
分支,压缩所有提交,以便您的Github页面历史记录不会受到污染(--squash
)并等待直到合并提交后才能查看(--no-commit
)。注意:当您签出gh-pages
分支机构,文件& master中的文件夹可能会保留为 Untracked ,只需忽略它们并专注于索引中的实际内容。注意:如果gh-pages
中有任何未经修改或未修改的修改,Git将不结帐master
。
. $ (master) git checkout origin/gh-pages
. $ (gh-pages) git merge --no-commit --squash -s subtree master
Git使用子树合并策略最好地猜测要合并的树,但是,如果没有太多要继续,you might be better explicitly telling Git which tree to merge。
. $ (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
将此文件放入脚本或提交后挂钩中,只要您编辑文档或将其添加到Makefile
用于生成html和瞧!生成GitHub页面。