Hexo+GitHub+Netlify+Cloudflare+JSDelivr搭建个人博客详细教程(小白向)

本文最后更新于:2022年4月8日 凌晨

喵喵喵喵喵

在2020年8月的一个深夜,谷月姐决定搭建自己的个人博客。

此前,谷月姐用过百度空间、网易博客、新浪博客、知乎专栏、CSDN博客、简书。百度空间和网易博客宣布停止服务,新浪博客的编辑器非常难用,知乎专栏降权,CSDN博客禁止营销,简书商业化非常严重。

有鉴于此,谷月姐决定自己另起炉灶,从头开始搞自己的个人博客。

作为一个对前端一窍不通的小白,谷月姐经过无数次比较和尝试,决定采用Hexo搭建博客,将博客源文件上传到GitHub以便多设备同步,但是将编译后的静态页面部署到Netlify以实现自动部署,并借助Cloudflare和JSDelivr加速,最后将博客登记到各大搜索引擎,让读者能搜索到博文。

并且,谷月姐将以上操作步骤记录下来,就写成了这篇文章。

读者不必担心,这篇文章会用最通俗易懂的语言详细解释操作步骤,不会有复杂艰深的计算机专业知识。即使小白也能看懂。

OK,就让我们开始吧!

Lets go!

用Hexo搭建博客

下载安装Hexo

初始化博客

谷月姐将博客文件夹放在 C:\Users\Kukmoon\kukmoon_blog 文件夹中。其中,C:\Users\Kukmoon 是用户主文件夹,在 Windows 中可以用环境变量 %userprofile% 表示,相当于 Unix/Linux/macOS 系统的 ~ 文件夹。

谷月姐使用多种命令行工具,包括 Windows Terminal、PowerShell、CMD(命令提示符)、Git Bash等。后文如果不特别指明,任何一种命令行工具都可以。

在 Git Bash中,执行以下命令,建立博客所在的文件夹:

$ cd ~
$ mkdir kukmoon_blog

然后,再执行以下命令,初始化文件夹。

$ cd kukmoon_blog
$ hexo init

以上四条命令,如果在在 Windows Terminal、PowerShell 或 CMD 中,就变成了这样:

cd %userprofile%
md kukmoon_blog
cd kukmoon_blog
hexo init

配置config.yml

写第一篇博文

预览

选择并配置主题

再次预览

博客所在文件夹的云备份

(1) 使用云盘

谷月姐使用了 7zip 的命令行程序 7z.exe,结合微软 OneDrive 来备份博客所在文件夹。

在命令行中,执行以下命令:

"C:\Program Files\7zip\7z.exe" u -mmt4 -mx9 -sccUTF-8 -scsUTF-8 C:\Users\Kukmoon\OneDrive\kukmoon_blog.7z C:\Users\Kukmoon\kukmoon_blog\

解析

  1. 这条命令是调用 7z.exe ,将博客所在文件夹压缩成一个压缩包 kukmoon_blog.7z,并将压缩包放在 OneDrive 的同步文件夹(C:\Users\Kukmoon\OneDrive) 下,让 OneDrive 把它上传到云端。
  2. 里面的 u 命令表示更新压缩文件。
  3. 里面的 -mmt4 开关表示四线程压缩,可以节约时间,建议把 4 改成读者自己的 CPU 的线程数。
  4. 里面的 -mx9 开关表示最高级别的压缩,可以节约存储空间和同步流量。
  5. 里面的 -sccUTF-8-scsUTF-8 是指对文件名用 UTF-8 编码来存储,由于谷月姐还需要在 Mac 电脑和运行 Linux 的设备上书写博客,为了避免乱码,因此在此处选择用 UTF-8 来存储文件夹名。

注意

  1. 读者可以换用自己喜欢的命令行压缩工具(例如 RAR.exePKZIP.exe……)生成压缩包。
  2. 读者也可以换用自己喜欢的云盘(例如苹果 iCloud、Google Drive、Dropbox、百度云盘……),只需要把 C:\Users\Kukmoon\OneDrive 改成你的云盘所在的本地同步文件夹的路径(例如 C:\Users\Kukmoon\iCloud )即可。
  3. 也许有读者会问,直接把博客所在文件夹建在 OneDrive 云盘的本地同步文件夹 C:\Users\Kukmoon\OneDrive 不行吗?当然可以,但是用 Hexo 搭建博客会生成大量小文件,而 OneDrive,以及其他云盘,处理大量小文件的效率是很低的。所以谷月姐建议只用云盘来同步压缩包。
  4. 在 PowerShell 中无法执行此命令,提示「表达式或语句中包含意外的标记“u”」。解决方案是:将这条命令保存为一个批处理文件,在 PowerShell 中,运行这个批处理文件。

(2) 使用 GitHub

需要在 GitHub 新建一个私有仓库,用 git 命令把博客所在文件夹 C:\Users\Kukmoon\kukmoon_blog\ 里面的所有文件推送到这个私有仓库。

下次如果更新博客,只需要推送新增的文件即可。

如果要在其他电脑上撰写博客,只需要在其他电脑上安装 Git,将私有仓库克隆到本地即可。


将博客上传到GitHub

注册GitHub账号

新建仓库

配置SSH密钥

将博客的本地文件Push到GitHub


将博客部署到Netlify

注册Netlify账号

配置个人博客

自定义二级域名


注册自己的顶级域名

注册NameSilo账号

挑选域名并付费


用Cloudflare加速

注册Cloudflare账号

将你的顶级域名解析到Cloudflare


SEO优化

SEO(Search Engine Optimization):中文译为搜索引擎优化,即利用搜索引擎的规则提高网站搜索引擎内自然排名。主要通过站内优化比如网站结构调整、网站内容建设、网站代码优化等以及站外优化等方式实现。

对博客进行SEO非常重要。我们搭建的博客,无法被搜索引擎搜到,相当于一个信息孤岛,只能自娱自乐,不利于个人品牌的推广和宣传。所以,我们需要SEO,让谷歌、百度等搜索引擎搜到我们的博客。

将你的博客登记到谷歌

博客的登记与验证

用谷歌账号登录谷歌站长平台,把资源类型设置为“网域”并输入博客的域名kukmoon.com(前面不要加https://www),点击“继续”。

选择资源

接下来,谷歌要求我们通过DNS方式验证网站。

因为之前为博客启用了Cloudflare加速,所以需要在Cloudflare中设置域名解析。登录Cloudflare,找到我们的博客,点击上方导航栏的DNS按钮,然后点击“添加记录”,添加一条TXT记录,点击“保存。

因为我们的域名是在Namesilo注册的,所以还需要在Namesilo中设置域名解析。登录NameSilo,进入domain manager。

进入Domain manager

此时,它列出了我们注册的所有域名,点击kukmoon.com最右侧的蓝色地球图标。

点击蓝色地球图标

此时,我们进入DNS设置,点击TXT,添加一条TXT记录,最后点击“保存”。

添加一条TXT记录

将你的博客登记到百度

博客的登记与验证

用百度账号登录百度站长平台(现在改名叫百度搜索资源平台了),点击“用户中心”→“站点管理”→“添加网站”。

添加网站

然后,按照百度的要求,输入网站的域名:https://www.kukmoon.com,点击“下一步。”

接下来,选择站点的属性,所谓属性,就是指你的博客主要发布什么类型的文章,选好以后点击“下一步”。

接下来,要验证网站,验证网站的意思是,告诉百度,这个博客是你的。百度提供了三种验证方式:

  • 文件验证。上传一个文件到你的博客根目录。
  • HTML标签验证。在博客首页添加一段HTML代码。
  • CNAME验证。把百度给你的验证网址使用CNAME解析到ziyuan.baidu.com。

经过谷月姐本人实践,如果将博客部署到Netlify并用Cloudflare加速,这三种方法都无法通过验证。原因可能是Netlify屏蔽百度。谷月姐试了第三种方法,在Cloudflare和Netlify都设置了解析,验证通过了,但是百度始终没有收录www.kukmoon.com的内容。

直到谷月姐把博客迁移到虚拟主机上,才能让自己的网站通过百度的验证。文件验证或CNAME验证都可以通过。以下以第三种方式CNAME验证为例。

使用CNAME验证

因为我们的域名是在Namesilo注册的,所以需要在Namesilo中设置域名解析。登录NameSilo,进入domain manager。

进入Domain manager

此时,它列出了我们注册的所有域名,点击kukmoon.com最右侧的蓝色地球图标。

点击蓝色地球图标

此时,我们进入DNS设置,点击CNAME,添加一条CNAME记录,最后点击“保存”。

添加一条CNAME记录

再回到百度,点击“完成验证”即可。如果百度提示“没有找到对应的DNS CNAME记录“,这说明域名解析记录还没有生效,需要等一段时间,最多24小时。

站点地图

在博客根目录(kukmoon_blogs)安装插件hexo-generator-baidu-sitemap和hexo-generator-sitemap

npm install hexo-generator-baidu-sitemap --save
npm install hexo-generator-sitemap --save

查看Hexo根目录_config.yml文件中url的值,URL必须是我们博客在百度登记的域名。例如:

# URL
## If your site is put in a subdirectory, set url as 'http://yoursite.com/child' and root as '/child/'
url: https://www.kukmoon.com/
root: /
permalink: :abbrlink.html
permalink_defaults:
pretty_urls:
  trailing_index: true # Set to false to remove trailing 'index.html' from permalinks
  trailing_html: true # Set to false to remove trailing '.html' from permalinks

强烈建议安装Permalink插件缩短博文的URL。

然后,将博客部署到Netlify,然后访问https://www.kukmoon.com/baqidusitemap.xml就可以看到网站地图。

接下来,我们在百度站长平台点击“搜索服务”→“普通收录”。

普通收录

在“资源提交”中,点击”Sitemap“,把https://www.kukmoon.com/baidusitemap.xml复制粘贴到文本框中,点击“提交”即可。

提交Sitemap

Robots.txt

robots.txt(统一小写)是一种存放于网站根目录下的ASCII编码的文本文件,它的作用是告诉搜索引擎此网站中哪些内容是可以被爬取的,哪些是禁止爬取的。
在 source目录下增加 robots.txt 文件,网站生成后在网站的根目录(站点目录/public/)下。

User-agent: *
Allow: /
Allow: /home/
Allow: /archives/
Allow: /about/
Allow: /link/
Disallow: /vendors/
Disallow: /js/
Disallow: /css/
Disallow: /fonts/
Sitemap: http://www.kukmoon.com/sitemap.xml
Sitemap: http://www.kukmoon.com/baidusitemap.xml

但是,根据谷月姐本人实践,百度无法识别博客根目录的Robots.txt。

将博文主动推送到百度

在博客根目录(kukmoon_blogs)安装插件hexo-baidu-url-submit。

npm install hexo-baidu-url-submit --save

然后,在博客根目录的_config.yml文件里写入以下配置:

baidu_url_submit:
  count: 100                           # 提交最新的多少个链接
  host: https://www.kukmoon.com/    # 在百度站长平台中添加的域名
  token: your_token             	  # 秘钥
  path: baidu_urls.txt                # 文本文档的地址,新链接会保存在此文本文档里

注意:host的值一定要与_config.yml文件的url的值一致,都是在百度站长平台登记的域名。

# URL
## If your site is put in a subdirectory, set url as 'http://yoursite.com/child' and root as '/child/'
url: https://www.kukmoon.com/
root: /
permalink: :abbrlink.html
permalink_defaults:
pretty_urls:
  trailing_index: true # Set to false to remove trailing 'index.html' from permalinks
  trailing_html: true # Set to false to remove trailing '.html' from permalinks

但是,密钥在哪里获取呢?仍然需要登录百度站长平台,点击“搜索服务”→“普通收录”。

普通收录

在“资源提交”中,点击“API提交“,在”接口调用地址“的最后,就是token。

Token

在博客根目录的_config.yml文件里增加以下配置:

# Deployment
## Docs: https://hexo.io/docs/deployment.html
deploy:
  - type: git
    repo:
    branch:     
  - type: baidu_url_submitter

将博客部署到Netlify,无法实现主动推送。需要将博客部署到虚拟主机。

将你的博客登记到必应

将你的博客登记到360

将你的博客登记到搜狗

生成站点目录


书写并编辑博文

用NotePad++写

用Typora写

Picgo与GitHub图床

多设备(Mac、PC)同步博文


将博客部署到内地

域名备案

将博客部署到Coding

将博客部署到21云盒子

将博客部署到虚拟主机或VPS

将博客部署到虚拟主机

谷月姐经过尝试发现,如果将博客部署到Netlify,百度就无法搜索到博客,这对SEO工作是不利的。

谷月姐购买了一个香港的共享IP虚拟主机(老薛主机),尝试将博客部署到虚拟主机,以改善百度SEO结果。之所以购买香港的虚拟主机而不是内地的,原因是谷月姐不想备案。毕竟备案太麻烦。

要使用共享IP的虚拟主机部署博客,需要先绑定域名,因为共享IP的虚拟主机无法使用IP进行直接访问。

取消域名与Netlify和Cloudflare的绑定

由于谷月姐之前为部署到Netlify的博客加了Cloudflare的CDN,并且在Cloudflare设置了域名解析。现在将博客部署到虚拟主机,并且暂时不再使用Cloudflare,就需要把域名绑定到虚拟主机,不能再绑定到Cloudflare或Netlify。

所以,谷月姐需要在Cloudflare中先删除自己的站点。操作方法也很简单:

登录Cloudflare,找到自己的站点,点击进入;

找到自己的站点

找到右下角的“从Cloudflare中删除站点”。

接下来,解除域名与Netlify的绑定。

登录www.netlify.com,登录,找到自己的站点;

找到自己的站点

点击进入,点击Domain Settings,然后,在Custom Domain区域中,移除www.kukmoon.com和kukmoon.com。

将域名绑定到虚拟主机

谷月姐是在Namesilo注册的域名,要设置它,需要登录https://www.namesillo.com,点击My account→domain manager,然后在出现的页面中点击域名kukmoon.com后面的蓝色地球图标,设置DNS。

因为谷月姐之前使用了Cloudflare的CDN,所以在Namesilo中,将DNS设置为Cloudflare的DNS服务器。现在,谷月姐需要在Namesilo中DNS设为默认的DNS,即ns1.dnsowl.com、ns2.dnsowl.com和ns3.dnsowl.com。再点击“Submit“按钮,提交。

将DNS设置默认DNS

接下来,删除www.kukmoon.com的解析记录,之后,新建2条A记录,主机名分别是www.kukmoon.com和kukmoon.com,它们都指向虚拟主机提供的IP地址,其中TTL可以设为3600。点击Submit按钮,提交。

新建两条A记录

提交后,需要一段时间才能生效,最长24小时。如果ping www.kukmoon.com找不到主机名,或者得到的IP地址并不是之前配置的IP地址,说明DNS解析尚未生效,需要耐心等待。

将Hexo博客部署到虚拟主机

将Hexo博客部署到虚拟主机,主要有两种方法:

  1. 在虚拟主机安装Node.js和npm,将原始文件上传到虚拟主机,在虚拟主机中编译。前提是虚拟主机允许用户安装Node.js,而且用户要懂一些Linux命令。
  2. 用FTP方式直接将Hexo编译出的public文件夹上传到虚拟主机。

第 2 种方法又可以衍生出三种方法:

2.1 用FTP软件,例如ftp命令、FlashFXP、CuteFTP、FileZilla等软件,将public文件夹手工上传到主机。

2.2 借助Hexo的插件hexo-deployer-ftpsync来部署。

2.3 借助git-ftp,将public文件夹手工上传到主机,这种方法的好处是可以控制版本,并且可以在命令行中操作。

谷月姐介绍方法2.2。

首先,安装hexo-deployer-ftpsync。

在博客根目录运行以下命令:

npm install hexo-deployer-ftpsync --save

然后,在博客根目录中的_config.yml中添加以下内容:

(如果deploy节已经有内容,例如部署到Git,那么建议写成以下形式)

deploy:
  - type: git				#提交到git,此处保持不变
    repo: XXX				#提交到git,此处保持不变
    branch: XXX				#提交到git,此处保持不变
  - type: ftpsync			#提交到FTP
    host: <host>            #主机地址,共享IP或独站IP
    user: <user>            #虚拟主机提供商提供的FTP用户名
    pass: <password>        #FTP密码密码
    remote: [remote]        #上传到空间的指定目录。比如/public_html。默认为/
    port: [port]            #端口,默认为21
    ignore: [ignore]        #忽略的文件
    connections: [connections]  #使用的连接数,默认1
    verbose: [true|false]   #显示调试信息,默认false

hexo-deployer-ftpsync插件并非直接上传生成的静态网站,而是将remote指向的目录的目录结构同步成与本地public文件完全相同的目录结构。也就是说如果你的虚拟主机上存有一些其他文件的话也将被全部删除。所以必要时,可以填写ignore键的值。

ignore格式:

ignore: ['dir1','dir2','file1.htm']

注意:方括号不能丢掉,引号用单引号或者双引号都可以。

注意,假如你在百度搜索资源平台使用文件验证的方式验证你的博客,那么需要将百度提供的验证文件加入到ignore段。例如:

ignore: ['/cgi-bin','Baidu_XXXXXXXXXXXXXXX.html']

其中的Baidu_XXXXXXXXXXXXXXX.htm是百度提供的验证文件。

然后,就可以执行hexo cleanhexo ghexo d命令三连,部署博客了。

hexo d部署博客出错

在committing…处卡住

committing表示ftpsync插件正在将public文件夹下的内容上传到虚拟主机。但是在谷月姐的电脑上,在这一步卡住了。谷月姐用谷歌找了很久,终于找到了一个解决方案,抱着死马当活马医的心态,修改了博客目录/node-modules/ftpsync/lib/ftpsync.js文件,用npm安装了新的ftp库,居然解决了这个问题。

以下是对解决方案原文的部分引(抄)用(袭)。

解决方案(临时)

修改node_modules\ftpsync\lib\ftpsync.js

第1步 开头添加

var Client = require('ftp');
var ftpc = new Client();

第2步 sync的setup中在try里面,ftp全局对象的初始化下面添加对我上面定义的ftpc全局变量的初始化

ftpc.connect({
    host:settings.host,
    user: settings.user,
    password: settings.pass,
    port: settings.port
});

第3步 utils的upload方法中把原来的ftp.put(…… 这一句替换成使用ftpc的put

ftpc.put(local, remote, function(err) {
  if (err) {
    sync.log.error('ftp.put failed.');
    return callback(err);
  }
  if (sync.log.verbose) {
    sync.log.write('-', file, 'uploaded successfuly');
  }
  callback();
});

第4步 在utils的remove方法的最后添加关闭ftpc

ftpc.end();

第5步 安装依赖,因为我们引入了ftp,所以执行 npm install ftp --save

上传结束后卡住

按常理,在显示Deploy done和Good bye之后,上传就结束了,应该退出上传程序,出现新的提示符。但是ftpsync偏偏在此处卡住。

上传结束后卡住

实际上,ftpsync的作者已经提供了解决方案。只需要修改博客目录/node_modules/hexo-deployer-ftpsync/index.js文件,在ftpsync.run(callback)后面强行调用process.exit()即可。

ftpsync.run(callback);
  ftpsync.run(()=>{
    callback();
    process.exit();
  });
});

在如图所示的地方插入红框中的代码

狡兔三窟:同时托管到GitHub、Netlify、云虚拟主机

在本文的最后,谷月姐尝试同时把博客托管到GitHub、Netlify和云虚拟主机。

目的是为了多重备份,以免丢失内容或与网友失联。

谷月姐要分析一下狡兔三窟的可行性:

  1. 要实现多设备同步编写博客和把博客托管到Netlify,必须要把源码上传到GitHub;
  2. 要实现把博客托管到GitHub,必须要把Hexo编译出的public目录上传到GitHub;
  3. 为了避免FTP密码、谷歌或者百度的密钥等重要信息泄露,必须把源码所在的GitHub仓库设为私有;
  4. 如果把GitHub仓库设为私有,那么将无法通过kukmoon.github.io的方式访问博客,而且谷歌也无法抓取托管到GitHub博客中的内容。

考虑到以上4条,谷月姐决定使用两个仓库,一个公开仓库kukmoon.github.io上传Hexo编译出的public目录,一个私有仓库上传源码并让Netlify与这个仓库关联。

在电脑上写完博文并且编译博客以后,用git把源码上传到私有仓库,此时Netlify会抓取源码并自动编译,再用hexo d命令将博客部署到公开仓库和虚拟主机。

但是,在之前的操作中,谷月姐把仓库kukmoon.github.io设置为私有仓库并用来上传博客源码,此时必须新建一个新的私有仓库(起名叫kukmoon_blog),将kukmoon.github.io中的内容转移到kukmoon_blog,然后清空kukmoon.github.io,再把它改成公开仓库。

处理仓库

备份本地博客目录,我在资源管理器中把本地博客目录C:\Users\Kukmoon\kukmoon_blog整个压缩成一个zip文件,放在C:\Users\Kukmoon目录。

将本地的博客目录与原来的远程仓库kukmoon.github.io取消关联。在博客目录下,执行 git remote remove origin

删除原来的远程仓库kukmoon.github.io。登录GitHub,进入远程仓库kukmoon.github.io,点击Settings,然后在Settings页面的最底部点击Delete this repository,按照网站的提示操作即可。

新建公开仓库kukmoon.github.io。登录GitHub,点击右上角的Create a new repo按钮,创建一个新仓库,取名为kukmoon.github.io,保持其他不变,点击Create repository。

创建新仓库kukmoon.github.io

新建私有仓库kukmoon_blog。登录GitHub,点击右上角的Create a new repo按钮,创建一个新仓库,取名为kukmoon_blog,把它设为Private(私有仓库),保持其他不变,点击Create repository。

创建私有仓库kukmoon_blog

将本地的博客目录kukmoon_blog与新的远程仓库kukmoon_blog建立关联。在本地博客目录kukmoon_blog下,执行git remote add origin git@github.com:kukmoon/kukmoon_blog.git

把本地博客目录下的所有内容推送到新的私有远程仓库kukmoon_blog上。在博客目录下,执行以下命令:

git add .
git commit -m "Restore My Blog"
git push -u origin master

设置Netlify,让Netlify监视仓库kukmoon_blog并生成博客。登录Netlify,找到自己的网站,点击Site settings,在左侧导航栏找到Build & deploy,在右侧的Build settings区域中找到Edit Settings,把仓库从github.com/Kukmoon/kukmoon.github.io改成github/Kukmoon/kukmoon_blog就可以了。待编译结束后,可以访问http://kukmoon.netlify.app,查看是否编译成功。

设置Netlify

修改_config.yml,让Hexo把博客部署到远程仓库kukmoon.github.io

改域名

谷月姐听从了一位公司老总的建议,把博客的域名改成了blog.kukmoon.com,然后把www.kukmoon.com留待日后使用。

这样,需要执行以下步骤:

  1. 首先要把博客目录/_config.yaml中的所有www.kukmoon.com替换成blog.kukmoon.com;

  2. 把Robots.txt中所有www.kukmoon.com替换成blog.kukmoon.com;

  3. 在Namesillo中新增一条域名解析记录,让blog.kukmoon.com指向主机的IP地址;

  4. 在各大搜索引擎网站修改网站登记信息,把www.kukmoon.com修改成blog.kukmoon.com。


参考文献

https://easyhexo.com

https://blog.csdn.net/liangllhahaha/article/details/105343008

https://www.jianshu.com/p/c20bb9df1867

http://www.yuan-ji.me/Hexo-%E4%BC%98%E5%8C%96%EF%BC%9A%E6%8F%90%E4%BA%A4sitemap%E5%8F%8A%E8%A7%A3%E5%86%B3%E7%99%BE%E5%BA%A6%E7%88%AC%E8%99%AB%E6%8A%93%E5%8F%96-GitHub-Pages-%E9%97%AE%E9%A2%98/

https://www.jianshu.com/p/c20bb9df1867

https://www.cnblogs.com/lfri/p/12219639.html

https://blog.csdn.net/q871063970/article/details/52459183

https://blog.csdn.net/u014792304/article/details/78688424

http://www.jeepxie.net/article/311871.html

https://hexo.io/docs/deployment.html

https://zhuanlan.zhihu.com/p/86961133

https://help.laoxuehost.com/domain-name/add-a-record.html

https://segmentfault.com/a/1190000015332130

http://k99k.com/2015/hexo-ftpsync-bug/

https://es2q.com/blog/2019/05/12/Hexo-ftpsync-bug/

http://k99k.com/2015/hexo-ftpsync-bug/

https://github.com/hexojs/hexo-deployer-ftpsync/pull/28/commits/80815cbc83aebc3b68b641c856040fe343af9f70

https://blog.csdn.net/wsycsdn19930512/article/details/50574217

https://www.liaoxuefeng.com/wiki/896043488029600/898732864121440

https://blog.csdn.net/u014203449/article/details/79974857

https://yuhongjun.github.io/tech/2017/04/28/git%E4%BB%93%E5%BA%93%E5%88%A0%E9%99%A4%E6%89%80%E6%9C%89%E6%8F%90%E4%BA%A4%E5%8E%86%E5%8F%B2%E8%AE%B0%E5%BD%95-%E6%88%90%E4%B8%BA%E4%B8%80%E4%B8%AA%E5%B9%B2%E5%87%80%E7%9A%84%E6%96%B0%E4%BB%93%E5%BA%93.html

https://www.cnblogs.com/kaerxifa/p/11211956.html