github建立日志系统的优势

喜欢分享日志的人,会经历三个阶段:

第一阶段,刚接触日志分享系统,觉得很新鲜,试着选择一个免费的日志分享托管网站来写。

第二阶段,觉得免费的博客托管网站限制太多,就自己买域名和空间,自己搭独立日志系统。

第三阶段,觉得独立日志系统的日常管理太繁琐,最好在保留控制权的前提下,让别人来管,自己只负责写日志。

大多数日志作者,都徘徊在第一和第二阶段,因为第三阶段不太容易到达:你很难找到俯首听命、愿意为你管理服务器的人。

但是不久前,情况出现变化,一些程序员利用github搭建日志系统。他们既拥有绝对管理权,又享受github带来的便利:

只要向主机同步提案,即可发布新文章。更妙的是,还是免费的,github提供无限流量,世界各地都有理想的访问速度,不用自己去和服务器机房打交道了。

github pages建网站可以说是其他技术类日志分享服务的克星,因为程序员愿意折腾。其好处:

  1. 可随意定制
  2. 方便,和程序开发库(github)直通
  3. 可控
  4. 简单自动:只需要提交
  5. 高效通用:markdown控制
  6. 免费,无限流量,无限空间

局限:

  1. 不提供 用户端-服务端 交互
  2. 国内访问速度不可保障,可能被墙?

启用 github pages:

github提供两种类型的静态网站服务,

由于 xxx.github.io 只能一个用户或者组织一个,需要新建一用户或者组织,很不方便,更常用的是项目级的,每个项目生成一个静态站,这样一个用户下可以有多个静态站,方便。

使用:

如何使用自己想要静态站生成器和插件?

几乎每种编程语言,都有若干生成静态网站的工具,可根据自己的需要和熟悉程度选用。

比如python的pelican,emacs的org-page,js的metalsmith等……

目前流行度最高的有ruby的jekyll。github就只使用了jekyll作为后台生成器,因此,如果用的是其他静态站生成器,都需要自己本地生成,然后发布到gh-pages分支。

jekyll使用方法见下一篇:使用jekyll生成静态站

注意:自己生成的话,需要在生成页面的根目录下,放一个 .nojekyll 文件关闭github的jekyll生成服务。

如何维护双库?

如果是用的其他静态站生成器,很明显,源码和生成的静态文件就分开了。

那么,如何管理呢?双库法! 生成后的静态站 仓库 只需要更新到远程的 gh-pages分支。

默认的项目仓库情况:

本地仓库 本地地址 远程对应的仓库 作用
master xxx site/origin/master 网站源码,主分支
gh-pages xxx/_site site/origin/gh-pages 分支,gh-pages只追踪和发布此文件夹下文件。

说明:如果使用github的jekyll服务,则默认本地不需要gh-pages分支,只需要发布到远程,并新建一个gh-pages的分支即可。

双库法后,项目仓库如下:

本地仓库 本地实际地址 远程对应的仓库 作用
source/master xxx source/origin/master 网站源码,主分支
site/gh-pages xxx/_site site/origin/gh-pages 分支或子模块

说明:至少需要两个远程仓库,比如我用了bitbucket的私有库来保存源码,用github的 gh-pages 来保存生成的静态站。

文件结构如下:

~/
  |-- xxx-source/       此处文件会发布到source/origin/master
  |    |-- _includes/
  |    |-- _posts/
  |    |-- index.html
  |    |-- .nojekyll
  |    |-- _config.yml
  |     ....
  |    |-- _site/ <--- 软链或子模块,此处文件会发布到site/origin/gh-pages
  |
  |-- xxx-gh-pages/  ---> 软链或子模块到 xxx-source/_site

从头开始的完整步骤:

  1. 远程开双仓库
  2. 本地新建一文件夹 xxx-source,放入源码,然后同步到远程 git@github.com:username/source.git
  3. 本地新建一文件夹 xxx-gh-pages,软链到xxx-source/_site,然后同步到远程 git@github.com:username/xxx-gh-pages.git
  4. 每次xxx-source生成后,切换到 xxx-gh-pages 同步到远程xxx-gh-pages的gh-pages分支

双仓库的准备工作

第一步,远程开双仓库。假设为如下:

第二步,关闭github服务器的jekyll编译器。

原理:在上传到gh-pages分支上的文件根目录下,创建一个名为 .nojekyll 的文件,即可关闭github的jekyll编译器。

方法:修改 _config.yml,加入如下两行,让其生成的文件中,带 .nojekyll文件:(后面有需要,还可以加入更多的,此处先加这个最基本的)

include:
- .nojekyll

一些有关操作

远程删除或者添加分支

# 删除远程分支
git push origin :gh-pages
# 添加远程分支
git push origin gh-pages

生成孤立分支:先克隆源码站,然后生成孤立分支 gh-pages (带参数 --orphan 没有历史记录,是一个完全独立背景干净的分支),如有需要,可清空里面所有内容

git clone git@github.com:username/site.git
cd repository

git checkout --orphan gh-pages

git rm -rf .

加入独有内容后,推送到服务器

git push origin gh-pages

.htacess呢? 不行! redirects呢?

问题:如何在同一目录,但互相监控不同的文件夹?同一目录双库?

先本地建完主分支master,然后新建小分支gh-pages

git branch gh-pages
git push -u origin --all

一起推向服务器端

然后切换到分支gh-pages。把.git文件全部放入_site中,然后转到_site中,提交。

git branch gh-pages
git push -u origin --all

git remote add origin ssh://git@github.com/username/site.git
git push -u origin master
git checkout gh-pages
git push -u origin gh-pages

可选步骤:删掉主分支,以免混淆。

git branch -d master
git branch

软链双库法

前提:操作系统是linux,因为需要利用到一个linux才有的特性:软链

其中,_site 文件夹是个软链,本地生成的文件实际是放到硬盘另一个地方,生成后再转入此文件夹,把文件上传到github的origin/gh-pages。

下面不用软链时的操作(由于此法通用于windows下,所以此处也提供出来): /xxx-source 和 /xxx-gh-pages

# 新建文件夹 xxx-gh-pages
mkdir xxx-gh-pages
cd xxx-gh-pages
git clone git@github.com:username/site.git

接下来,再在 xxx-gh-pages下面,添加 .gitignore 文件, 把一些不要监控的文件添加进去。

发布:

cd ~/xxx-source
# 此处是把源码发布到源码仓库
git add .
git commit -am "发表文章"
git push
# 生成
jekyll build
cd ~/xxx-source/_site/
cp _site/* ~/xxx-gh-pages
cd ~/xxx-gh-pages
git add .
git commit "发表文章"
git push

浓缩为:(此处省去源码也发布部分,多个shell命令可以用 ;或者 && 连接起来)

alias build_blog="cd ~/xxx-source; jekyll;cp -r ~/xxx-source/_site/* ~/xxx-gh-pages;cd ~/xxx-gh-pages;git add .;git commit -am '发表文章';git push"
alias bb="build_blog"

总要去复制文件,还不够省俭,如果是linux下,则可以更省俭:使用软链!

把xxx-gh-pages软链到~/xxx-source/_site:

# 软链到xxx-source/_site
cd ..
cd xxx-source
ln -s ~/xxx-gh-pages _site

最后批处理之:

alias build_blog="cd ~/xxx-source; jekyll;cd ~/xxx-gh-pages;git add .;git commit -am '发表文章';git push"
alias bb="build_blog"

参考此文

子模块双库法:submodules

全过程:

注意:为减少过程所需时间,在完成新建子模块前,尽可能在两个分支里面保留最少的文件,以减少新建子模块时间。

  1. 开两仓库。
  2. 清空 xxx-gh-pages 的内容,并且提交到远程。清空的目的是减少克隆和提交时间。
  3. 切换到 xxx-source 分支,把 xxx-source 分支也同步到github。
  4. 接着,把xxx-gh-pages指为子模块,并挂载到 _site目录下。

注意,此处不要有 _site 文件,下面的命令会自动克隆原有 site 到此处。

$ git checkout master
$ git push -u origin --all

$ git submodule add -b master git@github.com:username/site.git _site

xxx-source 分支,看看情况:

$ git status
要提交的变更:
  (使用 "git reset HEAD <file>..." 撤出暂存区)

        new file:   .gitmodules
        new file:   _site

接着输入下面命令,提案并同步github上的source仓库:

$ git commit -m "把xxx-gh-pages变成xxx-source的子模块"
$ git push

初始化子模块,并看看其指向哪?

$ git submodule init
Submodule '_site' (git@github.com:username/site.git) registered for path '_site'
$ git submodule 
4aac2028817a9de3e31f2c1b84f5783b9d837150 _site (heads/master)

接着,把还没被jekyll生成的源文件都搬到source的目录下,并全部纳入追踪名单。

$ git add .
$ git commit -m "全部纳入追踪名单"

修改 _config.yml,让其生成的文件中,带 .nojekyll文件。

include:
- .nojekyll

用jekyll生成网站,

$ jekyll build
$ git status

移动到 _site 目录下,此时,会发现,已经不是在source仓库了,而是自动到了site仓库,看下分支情况:

$ cd _site
$ git status

_site 下文件全部纳入管理,提交,同步到github的site仓库

$ git add .
$ git commit -m "首次生成"
$ git push origin master

移动到source目录,提交更改,同步到于github的source仓库

$ cd ..
$ git commit -a -m "建站完毕"
$ git push origin source

到此步已经完成,可以上github的网站看看结果。

总结:以后,整个发布流程变成了:

  1. 修改文件
  2. 运行 jekyll 生成
  3. 看下生成结果: _site
  4. 子目录 _site下: add, commit and push changes
  5. 源码目录,包括_site: add, commit and push changes
  6. 不断重复这个过程

变为一命令:

jekyll build && cd _site && git add ./ && git commit -m '发布' && git push origin master

可以写成一个批处理文件

#!/bin/bash
set -e
message=$1

jekyll build
cd _site
git add ./
git commit -m '$message'
git push origin master

域名指向:使用其他域名

Github Pages会为站点分配类似 用户名或组织名.github.io 或者 用户名或组织名.github.io/项目名 的二级/三级域名。

不够简洁,还是申请顶级域名吧。

申请域名:免费的域名(.tk)可以在此申请.tk 是南太平洋岛国托克劳的国家域名,支持域名转发(可隐藏原URL)、电邮转发、A记录解析、CNAME别名记录、MX邮件记录、设置DNS服务器等服务。

收费的域名到处有,自己去买吧。

域名解析服务

一般来说域名提供商会提供简单的解析服务,也支持将解析服务指向到其他域名解析服务提供者。

国外的如 上帝他爹,可能被墙。 国内的如DNSPod,有免费版。

配置:

  1. 在github站点中增加CNAME文件,里面第一行写上要使用的域名(注:一行只能一个)
  2. 配置域名解析指向,分两种情况:
    • 如果用的顶级域名,在域名解析服务提供商那里将A记录指向github提供的ip地址
    • 如果使用二级域名,在域名解析服务提供商那里增加CNAME记录,指向github提供的ip地址

使 www.域名 生效,需要咋办? 在CNAME中加入一行,例如:

jobinson.ga www.jobinson.ga

注意:

  1. CNAME中的顺序,如果www.jobinson.ga放在上面,则jobinson.ga会跳转到www.jobinson.ga。否则,则www.jobinson.ga会跳转到jobinson.ga
  2. 如果用 *.域名,这样别的github用户可以用你的子域名。
  3. 项目级的域名解析稍微有点不同:无法通过域名转向 同时使用 任意子域名(非www)+顶级域名。

博客搬家

可能需要两步:

  1. (如果博客已经是wordpress则跳过此步)第一步使用blogstowordpress导入任意博客为wordpress类型
  2. 第二步则是利用jekyll-import导入到jekyll,或者利用exitwp导出为markdown。

Jekyll提供了一个插件 jekyll-import(需要安装),可以将wordpress的博客导入到Jekyll。

~ $ gem install jekyll jekyll-import
~ $ jekyll new my-awesome-site
~ $ cd my-awesome-site
~/my-awesome-site $ jekyll import wordpressdotcom --source wordpress.xml
~/my-awesome-site $ jekyll serve
# => 浏览器上察看结果 http://localhost:4000

exitwp是一个用python开发的工具,号称是将wordpress的博客导出并转换成markdown,但实际上 任何能导出rss/atom的博客都可以用这个工具进行转换。

git clone https://github.com/thomasf/exitwp
sudo pip install --upgrade  -r pip_requirements.txt
cd exitwp/wordpress-xml/
wget http://your/atom/file/xml
cd ..
python exitwp.py