这篇讲把 GitHub 上的项目搬进内网 AngusGit 时,该用导入还是推送,以后怎么跟上游。看完你可以按「以后还跟不跟上游」选路:不跟、只要当前代码,就用 导入仓库;要保留历史或合并上游,就在本地克隆,把 GitHub 设为 upstream、把新建的空仓库设为 origin 再推送。导入出来的仓库和 GitHub 没有共同历史,以后合并上游会报 refusing to merge unrelated histories。
先登录 AngusGit。导入在侧栏 仓库 → 导入仓库:仓库 URL 填 HTTPS 地址,所有者 选当前账号或团队,仓库名称 手填,只给内部看时打开 设为私有仓库,再点 开始导入。推送前准备凭据。SSH:没有 ~/.ssh/id_ed25519.pub 就执行 ssh-keygen -t ed25519 -C "you@example.com",路径回车,把 cat ~/.ssh/id_ed25519.pub 里以 ssh-ed25519 开头的一行登记到 我的 → SSH密钥。用户名是 git,端口 2222。HTTPS:到 我的 → 访问令牌 点 生成新令牌,密码验证 填登录密码,勾 git:write,仓库权限 WRITE,生成后马上复制。用户名填登录名,密码填令牌。
文中导入这条路以 https://github.com/octocat/Hello-World.git 为例,导入结果是私有仓库 xlliu/hello-world-import;推送这条路给出完整命令,目标仓库需要你先在 AngusGit 上建成空仓库。实例上已有的 anguskit/AngusRepo 是制品库产品的仓库,和这次导入无关。
1. 先选路
按下表从上往下判断,先看源仓库能不能匿名读取(可见性决定谁能看到仓库,私有的要登录),再看要不要历史、要不要跟上游;前三行都不符合时,才用导入。
| 你的需求 | 用哪条路 | 原因 |
|---|---|---|
| 源仓库在 GitHub 上是私有的 | 推送 | 导入以匿名身份拉代码,读不到私有仓库 |
要保留原来的提交历史,方便 git blame 和查问题 |
推送 | 导入只带默认分支的文件,不带历史 |
| 以后还要合并上游的新版本 | 推送 | 合并上游需要两边有共同的历史,导入出来的仓库没有 |
| 只要当前代码,以后自己维护,不再跟上游 | 导入 | 最快,填一个地址就完成,不需要在本地操作 |
拿开源项目做二次开发时,大多数团队过几个月都会想合并上游的安全修复和新功能,所以拿不准的时候,选推送更稳妥。推送只多花几分钟,而导入之后再想补历史,就得整个重来一遍。
2. 只要当前代码:导入
在侧栏点 仓库,再点右上角的 导入仓库。以 Hello-World 为例,源地址填 https://github.com/octocat/Hello-World.git,所有者选 Angus / xlliu,名称填 hello-world-import,打开 设为私有仓库,最后点 开始导入。导入结果只有 main 一个分支和一条 Initial commit from https://github.com/octocat/Hello-World.git 提交,文件也只有 README;源仓库的默认分支本来叫 master,导入后分支名变成了 main。表单按开头那几项填完即可。
要注意,真正去拉代码的是 AngusGit 服务器,跟你自己的电脑无关。Hello-World 能导进来,是因为那台服务器当时访问得到 github.com。如果你的 AngusGit 部署在内网,不确定它能不能访问 GitHub,先在那台服务器上执行:
git ls-remote https://github.com/octocat/Hello-World.git
能打印出一串分支名和提交号,就说明服务器连得上 GitHub。如果命令卡住不动或报连接失败,导入也会失败,这时改用第 3 节:在你自己能访问 GitHub 的电脑上克隆,再推到 AngusGit。
3. 要历史、要跟上游:推送
推送这条路,是先在你的电脑上把 GitHub 仓库完整克隆下来,再推到 AngusGit 上一个新建的空仓库。因为以后还要同步上游,克隆下来的这个本地仓库要一直留着,以后每次同步上游都在它里面做。
在 AngusGit 建一个空仓库
在侧栏点 仓库 → 新建仓库,添加 README 文件、添加 .gitignore、选择许可证 三项都不要勾选,这样建出来的才是空仓库。勾选了任何一项,仓库里就会多出一条提交,推送时会因为两边历史对不上而被拒绝。也不要拿已有的仓库当目标,无论是已经导入的
xlliu/hello-world-import,还是已有的anguskit/AngusRepo。从 GitHub 克隆
找一台既能访问 GitHub、又能访问内网 AngusGit 的机器,在上面克隆源仓库。
把 GitHub 改名为 upstream,再加上 AngusGit
克隆下来后,
origin默认指向 GitHub。先把它改名为upstream(上游),再把 AngusGit 的空仓库加为新的origin。这样分工之后,团队日常拉取和推送都走origin,只有同步上游时才用upstream。执行git remote -v检查,应该看到两组地址:origin是 AngusGit,upstream是 GitHub。推送主分支和标签
Hello-World 的上游分支叫
master,而 AngusGit 空仓库的默认分支是main,所以先执行git branch -m master main改名,再推送main和全部标签。源仓库的主分支已经叫main时,跳过改名。
上面几步对应的完整命令如下。目标仓库 xlliu/hello-world-history 只是示例名称,推送前要先在 AngusGit 上把它建成空仓库。
git clone https://github.com/octocat/Hello-World.git hello-world-history
cd hello-world-history
git remote rename origin upstream
git branch -m master main
git remote add origin ssh://git@git.anguskit.com:2222/xlliu/hello-world-history.git
git remote -v
git push -u origin main
git push origin --tags
推送完成后,AngusGit 上的 提交 记录应该和 GitHub 一致,标签 里也能看到上游的各个版本。hello-world-history 需要你自己新建,线上目前还没有这个仓库。
上面的命令只推了 main。上游的其他分支(例如 release-1.x)只是作为远程跟踪分支留在本地,也就是本地记下的 upstream/release-1.x 这个指向上游分支的引用,并没有推到 AngusGit。需要时单独推一条:
git push origin upstream/release-1.x:refs/heads/release-1.x
示例用的是 SSH 地址;改用 HTTPS 地址推送也可以,这时密码一栏填开头生成的 git:write 访问令牌。SSH 公钥也按开头登记。
4. 以后怎么同步上游
上游发布新版本后,按下面的命令把更新合并进来。这里不直接在 main 上合并,而是先建一个同步分支,再通过拉取请求合进 main,好处有两个:同步的改动同样经过评审;main 开了分支保护时,也不会因为直接推送而被拒绝。以 Hello-World 为例,上游分支叫 master,所以合并的是 upstream/master;源仓库主分支叫 main 时,把第三行换成 git merge upstream/main。
git fetch upstream
git switch -c sync-upstream-2026-10 main
git merge upstream/master
git push -u origin sync-upstream-2026-10
这四行命令依次做了这些事:第一行把 GitHub 上的新提交拉到本地,不改动任何分支;第二行从 main 新建同步分支 sync-upstream-2026-10;第三行把上游的新提交合并进来,如果内部改过的文件上游也改了,这一步会提示冲突,按提示改好冲突文件后,再执行 git add 和 git commit;最后一行把同步分支推到 AngusGit。
推送之后,在 AngusGit 上为同步分支发起一条合并到 main 的拉取请求,评审通过后再合并。注意,这套流程只适用于推送得到的仓库:xlliu/hello-world-import 只有一条初始提交,和 GitHub 没有共同历史,在它上面执行 git merge upstream/main 只会得到 refusing to merge unrelated histories。
同步也不要拖太久。上游攒了几百条提交再合并,冲突会集中爆发;跟着上游的发版节奏同步,每次要处理的冲突会少得多。
5. .github 目录里哪些会生效
GitHub 仓库里常有一个 .github 目录。无论导入还是推送,这些文件都会原样留在仓库里,但它们在 AngusGit 上的作用各不相同:
| 文件 | 在 AngusGit 上是否生效 | 说明 |
|---|---|---|
.github/workflows/*.yml(GitHub Actions) |
不自动运行 | 流水线读的是 .anguscicd.yaml 或 .anguscicd/ |
.github/CODEOWNERS |
会被读取 | 要先打开 启用 CODEOWNERS |
.github/PULL_REQUEST_TEMPLATE.md |
创建拉取请求时会读取 | 没有这个文件时,描述不会自动填 |
.github/ISSUE_TEMPLATE |
不作为 Issue 模板 | AngusGit 不读这个目录 |
表里几项的补充说明如下。GitHub Actions 的工作流文件不会自动运行,但可以在控制台导入并转换成 AngusGit 的流水线配置,方法见文末那篇。CODEOWNERS 是按文件路径指定负责人的配置文件,在 设置 → 拉取请求 打开 启用 CODEOWNERS 后,AngusGit 会按路径指派;除了 .github/CODEOWNERS,它也认仓库根目录和 docs/CODEOWNERS,并且只解析 @用户名 这种写法。拉取请求模板同样认根目录和 docs/ 下的同名文件。Issue 模板则存放在 AngusGit 自己的模板数据里。
另外,GitHub 上的 Issue、拉取请求、Release 和 Wiki 都不存放在 Git 仓库里,所以导入和推送都带不过来。
6. 团队自己的私有 GitHub 仓库
团队自己在 GitHub 上的私有仓库,导入读不到,只能走推送。在本地克隆 GitHub 私有仓库时,密码一栏要填 GitHub 的个人访问令牌,GitHub 不接受登录密码。
如果迁移之后不再跟 GitHub 同步,就不需要保留 upstream,改用 git clone --bare 更省事。它得到的是一个裸仓库:只保存 Git 的数据,也就是全部分支、标签和提交历史,没有可编辑的工作区文件,所以能把所有分支和标签一次推过去:
git clone --bare https://github.com/<你的组织>/<仓库>.git
cd <仓库>.git
git push ssh://git@git.anguskit.com:2222/<所有者>/<仓库>.git --all
git push ssh://git@git.anguskit.com:2222/<所有者>/<仓库>.git --tags
地址里的所有者和仓库名,换成你在 AngusGit 上新建的空仓库。不要推到已经有内容的 anguskit/AngusKit 或 anguskit/AngusRepo。
推送完成后,团队每个人重新从 AngusGit clone 一份即可;也可以在自己原来的本地仓库里执行 git remote set-url origin <AngusGit 地址>,把远程地址换过来。
7. 出错时
| 你看到的 | 原因 | 怎么处理 |
|---|---|---|
fatal: refusing to merge unrelated histories |
AngusGit 上的仓库是用 导入仓库 建的,和上游没有共同历史 | 新建一个空仓库,按第 3 节重新推送;确认没人再用导入出来的仓库后,把它删除 |
推送时 ! [rejected] main -> main (fetch first) |
AngusGit 上的仓库不是空的,例如新建时勾了 添加 README 文件 | 删掉这个仓库,重新建一个三项都不勾的空仓库 |
| 导入时提示 源仓库URL「…」无效或无法正常访问 | 仓库是私有的,或者 AngusGit 服务器连不上 GitHub | 在服务器上执行 git ls-remote 确认网络;私有仓库或网络不通时,按第 3 节在本地克隆再推送 |
git merge upstream/main 提示冲突 |
内部修改和上游修改了同一处 | 打开冲突文件,保留需要的内容,git add 后 git commit。冲突很多时,先在同步分支上逐个解决,再发起拉取请求 |
| 同步分支合并时,合并卡提示需要评审 | main 开了分支保护或仓库要求代码评审 |
这是预期行为。请评审人在拉取请求里批准后再合并 |
常见问题
已经用导入建好的仓库,能补上历史吗?
最干净的做法是新建一个空仓库,按第 3 节推送,再让团队改用新仓库。导入出来的仓库只有一条提交,在上面硬塞历史容易把团队成员的本地仓库搞乱。
上游的提交作者会出现在 AngusGit 上吗?
推送这条路会。提交历史原样过去,每条提交的作者、时间和说明都和 GitHub 上一致。导入这条路不会,新仓库里只有一条由你提交的 Initial commit from …。
团队成员要各自配置 upstream 吗?
不需要。同步上游只要一个人做,他把同步分支推到 AngusGit、走完拉取请求即可。其他人照常从 origin 拉取。
源仓库用了 Git LFS 怎么办?
AngusGit 不支持 Git LFS。推送之后,LFS 管理的大文件在 AngusGit 上只有指针文件。这类文件要改成普通文件提交,或者放到制品库里。
小结
从 GitHub 搬仓库,先问以后还跟不跟上游。不跟、只要当前文件,用 导入仓库。xlliu/hello-world-import 就是这样来的。要保留历史或以后合并上游,在本地 git clone,把 GitHub 改名为 upstream,把一个新建的空仓库加为 origin。推送和同步的目标必须是新建的空仓库,不要推到已经导入的那个仓库上。
结论: 后续还需要合并 GitHub 上游更新或保留提交历史时,不要用 导入仓库,而要在本地
git clone后把 GitHub 设为upstream、把 AngusGit 空仓库设为origin推送。