一:前言
在日常的工作学习中,Git扮演着越来越重要的角色,渐渐的在版本管理软件中占据C位。我们已经很习惯的将代码托管于Git服务,在我们的潜意识中,当执行git push完成后,一切都完美了。代码也不会丢,还能按照不同的版本找回来,完全没有后顾之忧。
事实上也确是这样,对于Git仓库的备份有人认为很重要,有人认为完全没有必要,对于这个疑问,仁者见仁,智者见智。但我总觉得还是有备无患,所以有了这篇文章。
二:思路
简单来说,Git的备份其实就是对于文件增量的备份,注意,我说的是增量。当然,你也可以进行全量覆盖备份,不过我认为那没有必要。
在进行讲解之前,我们需要了解一个名词webhook
webhooks是一个api概念,是微服务api的使用范式之一,也被成为反向api,即:前端不主动发送请求,完全由后端推送。简单来说,WebHook就是一个接收HTTP POST(或GET,PUT,DELETE)的URL。一个实现了WebHook的API提供商就是在当事件发生的时候会向这个配置好的URL发送一条信息。与请求-响应式不同,使用WebHooks,你可以实时接受到变化。
所以,我的Git备份使用了webhook。简单来说就是在已存在的Git仓库中找到webhook的配置,配置一个接收推送的地址,然后当用户进行操作的时候,webhook会接收到本次操作并根据地址进行推送,然后使用一个项目处理接收到的数据,调用脚本进行git仓库的拉取即可。
流程大致如图:
三:实现
1.使用Github为例,github的webhook配置位置如下:
Payload URL就是我们配置接收推送的地址,地址可以等下面步骤完成后再进行配置。
2.新建Springboot项目,用于接收推送信息。完整的示例代码可以访问地址:https://github.com/tomorrowWithYou/git-backup.git 项目中包含windows和linux的脚本,简单修改执行脚本路径后可直接使用。代码为了便于阅读和使用,两种方式我直接分开写的,大家可以参考一下。
下面附上部分代码:
@PostMapping("/backupUnderLinuxReceive")
public String receive(HttpServletRequest request, HttpServletResponse response) throws IOException, InterruptedException {
log.info("请求对象:{}", request);
// 1.得到请求的所有对象
String body = readAsChars(request);
log.info("完整的参数:{}", body);
// 2.取出关键参数
JSONObject jsonObject = JSONObject.parseObject(body);
JSONObject repository = jsonObject.getJSONObject("repository");
// 得到ssh地址,需要使用ssh地址,不能使用https,因为https需要密码,ssh免密
String sshUrl = repository.getString("ssh_url");
// 仓库名称
String name = repository.getString("name");
// 3.调用sh脚本拉取代码
execShell(name, sshUrl);
return "";
}
private void execShell(String name, String url) throws IOException, InterruptedException {
String bashCommand = "/bin/sh " + shellDir + " " + workspace + " " + name + " " + url;
log.info("执行sh脚本命令:{}", bashCommand);
Runtime runtime = Runtime.getRuntime();
Process pro = runtime.exec(bashCommand);
int status = pro.waitFor();
if (status != 0) {
log.info("Failed to call shell's command ");
}
BufferedReader br = new BufferedReader(new InputStreamReader(pro.getInputStream()));
StringBuffer strbr = new StringBuffer();
String line;
while ((line = br.readLine()) != null) {
strbr.append(line).append("\n");
}
String result = strbr.toString();
log.info("执行完成:{}", result);
}
3.将clone的代码修改完成后,部署到相应的机器上。java环境配置这里就不再涉及,git也需要安装,因为要执行脚本和生成密钥。将生成好的密钥配置到Github中,配置地址如下图:
4.将部署项目接收推送的地址配置在第一步中,然后本地push代码到github上,即可触发webhooks。最后即可看见代码已经被更新下来了。尝试进行多次修改推送,脚本也同样会按照git的命令进行更新。
5.至此,一个完整的git实时备份功能就完成了。
四:扩展以及注意事项
代码中提供了shell和bat两种脚本以及对应的部署方式。windows可以参考第三步的实现进行操作。
接收推送发现代码没有被clone,可以先确认是否拥有权限,ssh配置是否正确。
由于git服务的实现比较多,比如github和aliyun的codeup进行推送时的数据结构也可能会存在差异,所以代码中需要按需进行修改。具体的数据结构可以如下图所示进行查看,在webhooks下方
结尾了,大家有什么疑问,可以在下方评论哟