一、需求背景
我们公司用gitea搭建了一个git服务器,其中支持win7的最高版本是v1.20.6。
我们公司的电脑在任何时候都不能连接外网,但是希望将一些开源的仓库移植到内网的服务器来。一是有相关代码使用的需求,二是可以建设一个内网能够查阅的资料库。
外网的仓库是在不断更新的,我们不但希望下载到当时版本仓库的内容,还要有方法可以同步后续更新的内容。
我们自己也有可能对项目做出修改,但是这一部分是和开源项目不一致的内容,我们不希望这一部分也被推送。或者说是否同步我们希望自己来决定。
所以总共有这3种使用场景:
二、解决问题
以分布式管理为著称的git,自然是可以在无广域网的情况下将本地仓库推送到内网服务器的。但是具体怎么操作呢?
2.1 不可行的方法
使用 git push origin
是常规的做法,但是只能推送本地分支。当然我可以将远端分支先检出到本地同名分支,然后再次推送。但是如果检出之前已经有了本地分支呢?我检出的时候不是破坏了已有的本地分支?
如果使用 git push origin origin/master
,会将本地的 origin/master
分支,推送到服务器上的 origin/master
分支,这么做在Git服务浏览器上是看不到的,将来再次克隆的时候也拉不下来。
如果使用 git push origin --mirror
参数推送,会将仓库的所有分支推送到 gitea 服务器上,但是在Git服务器上啥也看不见。我推测这种方式推送是一比一平移,在服务器上存在的 origin/master
分支是看不到的,必须是 master
这样的分支才能在服务器中看到。
如果使用 git clone --bare
命令克隆裸仓库,然后用 git push --mirror
命令推送到内网,这种方法是可行的。但是克隆到本地的裸仓库没有办法继续开发,而且克隆的时候如果不是裸仓库呢?难道要再克隆一遍吗?
2.2 可行的解决方法
前面的方法不可行,是因为我将本地的本地分支,推送到了远端的本地分支(所以未检出到本地的远端分支,推送不到远端)。
或者是将本地的远端分支,推送到了远端的远端分支(所以在远端服务器上看不到)。
而解决我们的需求,需要将本地的远端分支,推送到远端的本地分支。
如果在推送命令中添加一个冒号,例如:git push origin master:main
,就可以将本地的 master
分支推送到远端的 main
分支。
那么能不能将本地的 origin/master
分支,推送到远端的 master
分支呢:
git push <URL> origin/master:master
运行报错:
错误提示我们没有使用完整引用名称( full refname
)。
改为使用完整引用名称,然后将分支名 master
替换成通配符 *
,再加上推送标签的参数 --tags
:
git push --tags <URL> refs/remotes/origin/*:refs/heads/*
就可以把所有本地的远端分支、以及标签,一起推送到内网服务器:
在网页端查看,已经将所有分支和标签全都推送成功:
这样做不需要在本地检出或者创建新分支。
但是会把 HEAD
作为一个分支名也推送上去。。唯一的一点遗憾了。
三、自动化脚本
我写了一个自动化脚本,命名 git-push-remotes.bat
:
@echo off
REM 读取文件夹名和拼接服务器网址
for %%i in ("%cd%") do set name=%%~ni
set url=http://<URL>/repos/%name%.git
REM 将本地的所有远端分支推送到远端的本地分支上
git push --tags %url% refs/remotes/origin/*:refs/heads/*
echo.
pause
将文件复制到已克隆的本地仓库,然后双击运行。
就可以自动获取当前文件夹的名称,拼接成URL,然后推送到同名的内网服务器仓库中。