前言

最近我从 Windows 换到了 MacBook Pro,面临一个现实问题:我有几十个项目散落在各个目录里,有 Python 的、TypeScript 的、Go 的、C# 的,有些是正经的 Git 仓库,有些是 AI 帮我生成的实验代码连 .git 都没有。

按理说,Git 仓库直接推到 remote、非 Git 项目拷贝一下就完事了。但实际上:有些仓库有未提交的改动,有些仓库压根没配 remote,还有些是 shallow clone 不能直接 bundle。一个个手动处理?简直是噩梦。

我之前试过 scp、试过 rsync,但 Windows 对这些工具的支持完全是灾难级别的,各种报错几乎没法用。那直接把项目目录压缩打包呢?也不行——每个项目里的 .venvnode_modules 动不动几个 G,一个个手动排除能把人逼疯。

所以我写了 code-porter,一个纯本地的代码工作区迁移工具。它会自动扫描项目目录,智能判断每个项目的打包策略,然后一键导出为 git bundle 或 zip 归档。导入端只需要一个 manifest 文件就能批量恢复。

为什么不用云同步?因为我的项目加起来有几十 G,iCloud 同步要等半天,而且有些项目里有 .env 文件,我不想冒险传到云端。纯本地、U 盘一拷就完事,最省心。

工具概览

code-porter 的核心思路很简单:

  1. 扫描:遍历目录,识别项目类型和 Git 状态
  2. 导出:根据项目状态选择最优打包策略(bundle / zip)
  3. 导入:读取 manifest,一键恢复到目标机器

三个命令搞定一切:

# 扫描,看看有哪些项目
uvx code-porter scan ~/code ~/lab

# 导出,打包成 bundle + zip
uvx code-porter export ~/code ~/lab ./exports/backup

# 导入,在新机器上恢复
uvx code-porter import ./exports/backup/manifest.json ~/code/imported

零安装:通过 uvx 直接运行,不需要提前装 Python 环境或任何依赖。uvxuv 自带的命令,一行搞定。

智能打包策略

这是 code-porter 最核心的设计。它不是无脑把所有东西打包成 zip,而是根据每个项目的实际状态选择最优策略:

项目状态 打包策略 说明
干净 Git 仓库(有 commit) git bundle 保留完整历史、分支、标签
脏 Git 仓库(有未提交改动) bundle + worktree overlay zip bundle 保留历史,overlay zip 保留工作区
非 Git 项目 zip 直接打包,读取 .gitignore 排除垃圾文件
空 Git 仓库(无 commit) zip bundle 没有意义,降级为 zip
浅克隆仓库 zip shallow clone 无法创建有效 bundle,降级处理

杀手锏是 overlay zip 机制:对于有未提交改动的 Git 仓库,工具会同时导出一个 bundle(包含完整 Git 历史)和一个 worktree overlay zip(包含当前工作区的文件)。导入时先 clone bundle,再把 overlay 解压覆盖上去,这样你的未提交改动也完整保留了。

# 导出后的目录结构
exports/backup/
    manifest.json           # 清单文件,记录每个项目的元数据
    artifacts/
        my-app-a1b2c3d4.bundle          # 干净仓库 → bundle
        my-app-a1b2c3d4.worktree.zip    # 脏仓库的 overlay
        experiment-e5f6g7h8.zip         # 非 Git 项目 → zip

项目识别能力

工具通过查找项目标记文件来识别不同语言栈的项目:

  • Pythonpyproject.toml
  • Node.jspackage.json
  • Gogo.mod
  • RustCargo.toml
  • .NET*.sln

扫描时会对每个项目进行全面分析:

  • 是否 Git 仓库、是否有 remote、工作区是否干净
  • 目录大小、是否存在大目录(可配置阈值,默认 500MB)
  • 是否命中默认排除目录(node_modules.venvdist 等)
  • 是否值得导出,以及推荐的打包策略
# 扫描并输出 JSON 报告,方便进一步分析
uvx code-porter scan ~/code --json-output scan-report.json

跨平台兼容

这个工具从设计之初就考虑了跨平台场景。我自己的用例就是 Windows → macOS,所以:

  • manifest 路径兼容:导出时生成的 manifest.json 中的路径,在 Windows 上是反斜杠 \,在 macOS 上是正斜杠 /。导入时会自动处理,不用手动转换。
  • CI 双平台测试:GitHub Actions 在 Ubuntu 和 Windows 上都跑测试,确保两个平台的行为一致。
  • 纯本地运行:不依赖任何网络服务,不调用任何云 API,不存储任何凭据。传输方式完全由你决定——U 盘、SMB 共享、iCloud Drive 都行。

容错设计

实际使用中,总会遇到各种意外情况。code-porter 的设计原则是 单个项目失败不影响整体流程

  • git bundle create 失败?自动降级为 zip 导出
  • 导出过程中发现是 shallow clone?降级为 zip
  • 某个项目导出失败?记录错误,继续处理下一个
  • 导入时某个包损坏?跳过,继续导入其余项目

失败的项目会在结果中标记为 failed,但不会出现在 manifest 中,所以导入端不会尝试处理它们。

默认排除列表

打包时会自动排除以下目录,避免把几个 G 的依赖包也拷走:

node_modules    # Node.js 依赖
.venv           # Python 虚拟环境
dist            # 构建产物
build           # 构建产物
target          # Rust 构建产物
.next           # Next.js 缓存
.cache          # 各种缓存
.git            # Git 元数据(bundle 已包含)

对于 zip 导出,还会读取项目根目录的 .gitignore,和默认排除列表叠加使用。也就是说,你在 .gitignore 里排除的文件,打包时也会被排除。

可以通过 --exclude 参数追加自定义排除项:

uvx code-porter export ~/code ./exports --exclude .idea --exclude .vscode

进度条

扫描、导出、导入三个命令都有 Rich 进度条,显示当前处理的项目和耗时。当项目数量多的时候,这个体验比干等着强太多。

如果不需要进度条(比如在 CI 里跑),加 --no-progress 即可。

小结

code-porter 解决的核心问题是:当你有大量散落的项目需要迁移时,手动处理太痛苦,而且容易遗漏

它不试图成为一个重量级的 DevOps 工具,就是专注做好一件事:扫描 → 智能打包 → 清单驱动导入。整个过程纯本地、零依赖、跨平台。

目前工具还处于 Alpha 阶段,但核心的扫描、导出、导入流程已经完整可用。我的实际使用场景(Windows → MacBook 迁移几十个项目)已经跑通了。

如果你也面临类似的场景——换电脑、整理项目、备份工作区——可以试试:

# 一行命令体验
uvx code-porter scan ~/code

项目开源在 GitHub:star-plan/code-porter,欢迎提 issue 和 PR。

PS:为什么不用 rsyncscp?因为它们不知道哪些是项目、哪些是垃圾目录、哪些有未提交改动。它们只管拷贝文件,不理解"项目"这个概念。code-porter 的价值在于它理解开发者的项目结构,并据此做出智能决策。