内外网通过git裸仓库同步项目代码
通过裸仓库作为中间仓库可以从内网推送代码到外网的远程仓库,但是外网的远程仓库代码有更改后,同步到内网会出现内网本地代码提示已是最新代码
“外网→中转裸仓库→内网”这条链路,必须让中转裸仓库的引用真正移动,内网 git pull
才会拿到新代码。
出现“已是最新”99% 是因为外网的改动并没有进入中转裸仓库,裸仓库里的分支指针原地没动,内网当然看不到变化。
问题复现路径
- 外网仓库(GitHub)被其他人直接 push 了新提交。
- 中转裸仓库 没人去更新,它仍然指向旧 commit。
- 内网
git fetch jump
拿到的就是旧引用,于是提示Already up-to-date.
解决思路:让中转裸仓库定期/手动同步外网最新引用
下面给出三种常用办法,任选其一即可。
办法 A:在外网开发机定期 mirror --mirror
推送(最简单)
外网任意一台能同时访问 GitHub 和中转机的机器上跑:
# 第一次
git clone --mirror https://github.com/xxx/project.git local_mirror.git
cd local_mirror.git
git remote add jump user@jump:/repo/mirror.git
# 以后每次同步(可放 cron/计划任务)
git fetch -p origin
git push --all jump
git push --tags jump
--mirror
会把所有分支、标签、删除都原样搬过去,保证中转裸仓库与 GitHub 完全一致。
内网再 git pull
就能拿到最新代码。
办法 B:在中转机直接 git fetch --multiple
(无需工作区)
中转裸仓库支持 fetch 进裸仓库(≥Git 2.3):
ssh user@jump
cd /repo/mirror.git
git remote add github https://github.com/xxx/project.git
# 一次性同步
git config remote.github.mirror true
git fetch github --prune # 拉取 GitHub 所有更新
以后每当你知道 GitHub 有新提交,再执行一次 git fetch github --prune
即可。
内网客户端照常 git pull jump
。
办法 C:用钩子全自动(最省心)
在中转裸仓库里放 post-receive
钩子,只要有人 push 到中转站,就自动去 GitHub 把最新代码拉回:
#!/bin/sh
# /repo/mirror.git/hooks/post-receive
exec git fetch github --prune
这样无论哪边先更新,中转站都会保持“最新聚合”状态。
检查点:确认引用真的移动了
在中转裸仓库里:
git show-ref master
# 对比 GitHub 上最新 commit-id
curl -s https://api.github.com/repos/xxx/project/commits/master | jq -r .sha
# 查看分支最新提交信息
git branch -v
* main a1b2c3d 修复登录bug
dev e4f5g6h 添加用户模块
# 查看远程分支
git branch -r
# 查看所有分支(本地 + 远程)
git branch -a
# 查看分支合并状态
git branch --merged
git branch --no-merged
# 图形化查看分支历史
git log --oneline --graph --all
两边 id 一致,说明同步成功;否则就是同步步骤没跑或失败。
一句话总结
裸仓库只是“静态文件”,不会自己长腿去外网拉代码;
必须在外网或中转机显式执行 git fetch/push --all
,让裸仓库引用移动,内网 git pull
才能感知到新提交。
本作品采用 知识共享署名-相同方式共享 4.0 国际许可协议 进行许可。