自动同步来源: NEVSTOP-LAB/GitHub-Gitee-Sync 导入规则:README 包含不少于 50 个中文字符时导入,正文保持原文。

GitHub-Gitee-Sync

Sync All the Repos(public/private) between GitHub and Gitee.

同步 GitHubGitee 账号下的全部仓库(支持公开和私有仓库)。


功能

  • 🔄 自动同步 GitHub 和 Gitee 账号下的全部仓库
  • ↔️ 支持多种同步方向:GitHub→Gitee / Gitee→GitHub / 双向同步
  • 🏢 支持个人账号和组织账号
  • 🔒 支持私有仓库同步
  • 🚫 支持排除指定仓库
  • 📦 支持同步 Releases、Wiki、Labels、Milestones 等附属信息
  • 🐳 提供 Docker 镜像,开箱即用
  • 🎬 提供 GitHub Action,一键集成到 Workflow
  • 📋 自动在目标平台创建不存在的仓库(可配置关闭)

快速开始

前置条件

使用 GitHub Action

在你的仓库中创建 .github/workflows/sync.yml

name: Sync to Gitee
on:
  schedule:
    - cron: '0 2 * * *'   # 每天 UTC 2:00 自动同步
  workflow_dispatch:        # 支持手动触发

jobs:
  sync:
    runs-on: ubuntu-latest
    steps:
      - name: Sync GitHub to Gitee
        uses: NEVSTOP-LAB/GitHub-Gitee-Sync@v1
        with:
          github-owner: ${{ github.repository_owner }}
          github-token: ${{ secrets.GH_TOKEN }}
          gitee-owner: ${{ secrets.GITEE_OWNER }}
          gitee-token: ${{ secrets.GITEE_TOKEN }}

注意:需要在仓库 Settings > Secrets 中配置 GH_TOKENGITEE_OWNERGITEE_TOKEN

使用 Python

pip install requests

python sync.py \
  --github-owner <GitHub用户名或组织名> \
  --github-token <GitHub Token> \
  --gitee-owner <Gitee用户名或组织名> \
  --gitee-token <Gitee Token>

使用 Docker

docker build -t github-gitee-sync .

docker run --rm \
  -e GITHUB_OWNER=<GitHub用户名或组织名> \
  -e GITHUB_TOKEN=<GitHub Token> \
  -e GITEE_OWNER=<Gitee用户名或组织名> \
  -e GITEE_TOKEN=<Gitee Token> \
  github-gitee-sync

# 也可以使用 .env 文件
docker run --rm --env-file .env github-gitee-sync

参数说明

参数 & 环境变量CLI 参数必填默认值说明
GitHub 账号 GITHUB_OWNER--github-owner-GitHub 用户名或组织名
GitHub Token GITHUB_TOKEN--github-token-GitHub Personal Access Token
Gitee 账号 GITEE_OWNER--gitee-owner-Gitee 用户名或组织名
Gitee Token GITEE_TOKEN--gitee-token-Gitee Personal Access Token
账号类型 ACCOUNT_TYPE--account-typeuseruser(个人)或 org(组织),同时应用于 GitHub 和 Gitee 两侧
包含私有仓库 INCLUDE_PRIVATE--include-privatetrue是否同步私有仓库
指定仓库(允许列表) INCLUDE_REPOS--include-repos逗号分隔的仓库名列表;设置后仅同步这些仓库,优先于排除列表
排除仓库 EXCLUDE_REPOS--exclude-repos逗号分隔的仓库名列表;当 include-repos 已设置时此参数被忽略
同步方向 SYNC_DIRECTION--directiongithub2giteegithub2gitee / gitee2github / both / github2local / gitee2local*2local 模式将仓库同步到 --local-path 指定的本地目录(裸仓库形式)
创建不存在的仓库 CREATE_MISSING_REPOS--create-missing-repostrue目标仓库不存在时是否自动创建(local target 下控制是否自动 git init --bare
附属信息同步 SYNC_EXTRA--sync-extra逗号分隔:releases,wiki,labels,milestones,issues(local target 下不支持,会被忽略)
干运行模式 DRY_RUN--dry-runfalse运行全部逻辑但不实际同步,用于调试和测试
可见性过滤 VISIBILITY--visibilityallall / public / private,在 include/exclude 过滤之后再次按可见性过滤仓库
显示私有仓库名 SHOW_PRIVATE_REPO_NAMES--show-private-repo-namesfalse日志中私有仓库名的显示方式:false 隐藏为 [private]true 显示完整名称;正整数 N 显示前 N 个字符(如 3[CSM****]
Git 超时时间 GIT_TIMEOUT--git-timeout900单次 git 操作的超时秒数(默认 15 分钟);超时后自动重试一次
本地目标路径 LOCAL_PATH--local-path*2local 方向必填同步到本地的目录路径,支持 Windows(C:\repos)和 Linux/macOS(/var/repos)格式;目录不存在会自动创建,每个仓库存放为 <local-path>/<repo>.git 裸仓库

数据安全与同步策略

本工具采用增量同步策略,确保同步操作不会删除目标仓库上的独有内容。以下是各项同步的安全保证:

代码同步(分支与标签)

场景行为说明
源平台有新分支/标签✅ 推送到目标目标平台自动获得新分支/标签
目标平台有独有分支✅ 保留不删除同步不会影响目标平台独有的分支
目标平台有独有标签✅ 保留不删除同步不会影响目标平台独有的标签
两端都有同名分支⚡ 以源平台为准源平台的变更会强制覆盖到目标平台

技术实现: 使用 git push --all --force + git push --tags --force 代替 git push --mirror,确保只推送分支和标签,不会删除目标端独有的引用。

Wiki 同步

场景行为说明
源平台有 Wiki 内容✅ 推送到目标目标平台自动获得 Wiki 内容
目标平台有独有 Wiki 页面✅ 保留不删除同步不会影响目标平台独有的页面
源平台无 Wiki⏭️ 静默跳过不会影响目标平台已有的 Wiki

附属信息同步

类型同步策略目标独有内容说明
Releases增量同步✅ 保留按 tag_name 匹配,创建新的、更新已有的,不删除目标独有 release
Labels增量同步✅ 保留按名称匹配,创建新的、更新颜色和描述,不删除目标独有标签
Milestones增量同步✅ 保留按标题匹配,创建新的、更新状态和描述,不删除目标独有里程碑
Issues增量同步✅ 保留仅同步源平台 Open 状态的 issue,通过内嵌标记避免重复创建

Token 与凭据安全

  • GIT_ASKPASS 认证:Git 操作使用临时 askpass 脚本传递 Token,不会将 Token 内联到 URL 中,降低凭据泄露风险。
  • Token 自动脱敏:日志输出自动过滤 ghp_gho_github_pat_ 等格式的 Token,以及 URL 中嵌入的凭据信息。
  • 临时文件清理:同步完成后自动清理临时克隆目录和 askpass 脚本。
  • 最小权限原则:GitHub Token 只需 repo 权限,Gitee Token 只需 projects 权限。

Dry-Run 模式

建议首次使用时启用 --dry-run 模式,运行全部逻辑但不实际执行同步操作,可以预览将要同步的仓库列表和操作,确认无误后再正式运行。


使用示例

# 反向同步:Gitee → GitHub
- uses: NEVSTOP-LAB/GitHub-Gitee-Sync@v1
  with:
    github-owner: myuser
    github-token: ${{ secrets.GH_TOKEN }}
    gitee-owner: myuser
    gitee-token: ${{ secrets.GITEE_TOKEN }}
    direction: gitee2github

# 双向同步
- uses: NEVSTOP-LAB/GitHub-Gitee-Sync@v1
  with:
    github-owner: myuser
    github-token: ${{ secrets.GH_TOKEN }}
    gitee-owner: myuser
    gitee-token: ${{ secrets.GITEE_TOKEN }}
    direction: both

# 仅同步指定的仓库(允许列表)
- uses: NEVSTOP-LAB/GitHub-Gitee-Sync@v1
  with:
    github-owner: myuser
    github-token: ${{ secrets.GH_TOKEN }}
    gitee-owner: myuser
    gitee-token: ${{ secrets.GITEE_TOKEN }}
    include-repos: 'repo-a,repo-b'

# 同步组织仓库,排除部分仓库
- uses: NEVSTOP-LAB/GitHub-Gitee-Sync@v1
  with:
    github-owner: my-org
    github-token: ${{ secrets.GH_TOKEN }}
    gitee-owner: my-org
    gitee-token: ${{ secrets.GITEE_TOKEN }}
    account-type: org
    exclude-repos: 'old-repo,deprecated-repo'

注意account-type 参数同时应用于 GitHub 和 Gitee 两侧,不支持非对称配置(例如 GitHub 为个人账号而 Gitee 为组织账号)。如需同步组织仓库,两侧均须为组织账号。 同步组织仓库时,GitHub Token 需要额外的 read:org 权限。

# 同步 Releases 和 Wiki,读取 Action 输出
- uses: NEVSTOP-LAB/GitHub-Gitee-Sync@v1
  id: sync
  with:
    github-owner: myuser
    github-token: ${{ secrets.GH_TOKEN }}
    gitee-owner: myuser
    gitee-token: ${{ secrets.GITEE_TOKEN }}
    sync-extra: 'releases,wiki'
- run: echo "Synced ${{ steps.sync.outputs['synced-count'] }} repos"

同步到本地目录(local target)

通过 direction=github2localdirection=gitee2local,可以将仓库镜像同步到本地目录,每个仓库以裸仓库(<local-path>/<repo>.git)的形式存放。local-path 同时支持 Windows 和 Linux/macOS 路径格式。

# GitHub → 本地目录
- uses: NEVSTOP-LAB/GitHub-Gitee-Sync@v1
  with:
    github-owner: myuser
    github-token: ${{ secrets.GH_TOKEN }}
    gitee-owner: ''        # local target 不需要 Gitee 凭据
    gitee-token: ''
    direction: github2local
    local-path: /var/backup/repos       # Linux/macOS
    # local-path: 'C:\repos\backup'     # Windows
# 命令行: Gitee → 本地目录
python sync.py \
  --gitee-owner myuser \
  --gitee-token <Gitee Token> \
  --github-owner '' --github-token '' \
  --direction gitee2local \
  --local-path /var/backup/repos

说明

  • 目录不存在时会自动创建;每次同步执行 git clone --mirror + git push --all/--tags --force 增量更新本地裸仓库。
  • local target 没有 API,因此 sync-extra(releases/wiki/labels 等)和元信息同步会被跳过。
  • create-missing-repos=true(默认)时,目标本地裸仓库不存在会自动 git init --bare 创建;设为 false 则只同步本地已存在的仓库。

Action Outputs

Output说明
synced-count成功同步的仓库数量
failed-count同步失败的仓库数量
skipped-count跳过的仓库数量

退出码

退出码含义
0全部成功
1部分仓库失败
2全部失败
3致命错误(认证失败、环境异常)

文档


License

MIT