Sean's blog

任何能让你变得更好的事情,过程都是痛苦的

0%

利用git多重远程仓库抗单点故障风险

相比服务端-客户端结构的svn,分布式的git大大降低了单点故障的风险。但是(听到但是就不好了),这是建立在多人协同开发基础上的,一个人做项目同样存在单点故障风险。看到git很方便的支持多重源时,就产生了将库同时部署到多个托管站的想法。

google一下方案都相对繁琐,大都用下面的命令:
git remote add origin 库地址

这种方式会在库配置文件中生成多个仅名字不同的remote字段,需要处理库的默认名字冲突(都是非常用命令,挺麻烦的),push/pull 时还得按不同名字逐个操作,更多源仓库时太繁琐。

事实上这个需求仅仅是冗余备份,多处库内容完全相同,只要多点push,不要多点pull。
我的思路是采用本地协议在在硬盘其它目录或域局网中小型服务器上建一个镜像库,不需要修改库内名字,保持默认origin即可。pull/fetch时从本地镜像库读取,速度超快。

步骤非常简单,假如我们在GitHub上有个库 test,
地址为: git @ github.com:SeanTo/test.git
打算将它镜像到本地: g:\git\mirror.git

建立本地镜像裸库(跟空库配置有区别)

1
$git --bare init /g/git/mirror.git       # mirror 名字任取

添加镜像库到工作库配置文件

1
2
3
$cd /d/Work/test    # 到工作目录
$git pull # 先更新下本地库
$vi .git/config # 编辑库配置, 不熟悉vi用其它编辑器也行,要注意Windows下回车格式问题)

找到 remote 字段,局部如下:

1
2
3
4
5
6
[remote "origin"]
url = git@github.com:SeanTo/test.git
fetch = +refs/heads/*:refs/remotes/origin/*
[branch "master"]
remote = origin
merge = refs/heads/master

url 行是当前远程库的地址,该行上面按同样的格式添加一行(加好有两行 url):

1
2
3
4
5
6
7
[remote "origin"]
url = /g/git/mirror.git
url = git@github.com:SeanTo/test.git
fetch = +refs/heads/*:refs/remotes/origin/*
[branch "master"]
remote = origin
merge = refs/heads/master

就一行,挺简单的,附vi操作:
1.将光标定在[remote…]行上,按字母o(小写哦)进入编辑模式
2.下面会插入一个空行(大写O的话就插前面去了)
3.输入要添加的内容 url = /g/git/mirror.git
4.按 ESC 键退出编辑模式,按 :wq 后回车(保存退出)

这样设置就已经完成了,我们可以检查下

1
2
3
4
$ git remote -v
origin /g/git/test.git/ (fetch)
origin /g/git/test.git/ (push)
origin git@github.com:SeanTo/test.git (push)

可以看到一行fetch, 两行push。
如有多个源,配置中加同样加多行 url 定义也只会有一行fetch。
本地镜像库要放在最上面,它是默认的fetch源,不需要联网,速度最快。

同步到镜像库

镜像库是空的,要先推送一次,否则 pull 抓不到东西。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
$git push    # 跟普通库操作完全一样  
Enumerating objects: 3, done.
Counting objects: 100% (3/3), done.
Delta compression using up to 4 threads
Compressing objects: 100% (2/2), done.
Writing objects: 100% (2/2), 216 bytes | 216.00 KiB/s, done.
Total 2 (delta 1), reused 0 (delta 0)
To G:/git/test.git/
a0097c3..ebc12fa master -> master

Enumerating objects: 3, done.
Counting objects: 100% (3/3), done.
Delta compression using up to 4 threads
Compressing objects: 100% (2/2), done.
Writing objects: 100% (2/2), 216 bytes | 216.00 KiB/s, done.
Total 2 (delta 1), reused 0 (delta 0)
remote: Resolving deltas: 100% (1/1), completed with 1 local object.
To github.com:SeanTo/test.git
a0097c3..ebc12fa master -> master

实际输出是连续的,中间空行是为了方便看而隔开的。
上半部分推到镜像库(段落倒数第二行 To G:/git/test.git/)
下半部分推到GitHub(To github.com:SeanTo/test.git)

提醒:事实上按前面的步骤操作的话,到这里只能看到第1部分,因为工作区的库是刚从 GitHub 上抓回来的(改配置前我们 git pull 过)再推回去时没啥改变,做示例截屏时我的设置已完成,再 push 就看到向两个源操作的结果。如果有多个源,这里就有多个类似部分。

总结

想说清楚一大堆,实际上就两步

1
2
git init --bare 建镜像裸库  
config 中添加 url 指向裸库地址