前言
最近我从 Windows 换到了 MacBook Pro,面临一个现实问题:我有几十个项目散落在各个目录里,有 Python 的、TypeScript 的、Go 的、C# 的,有些是正经的 Git 仓库,有些是 AI 帮我生成的实验代码连 .git 都没有。
按理说,Git 仓库直接推到 remote、非 Git 项目拷贝一下就完事了。但实际上:有些仓库有未提交的改动,有些仓库压根没配 remote,还有些是 shallow clone 不能直接 bundle。一个个手动处理?简直是噩梦。
我之前试过 scp、试过 rsync,但 Windows 对这些工具的支持完全是灾难级别的,各种报错几乎没法用。那直接把项目目录压缩打包呢?也不行——每个项目里的 .venv、node_modules 动不动几个 G,一个个手动排除能把人逼疯。
所以我写了 code-porter,一个纯本地的代码工作区迁移工具。它会自动扫描项目目录,智能判断每个项目的打包策略,然后一键导出为 git bundle 或 zip 归档。导入端只需要一个 manifest 文件就能批量恢复。
为什么不用云同步?因为我的项目加起来有几十 G,iCloud 同步要等半天,而且有些项目里有
.env文件,我不想冒险传到云端。纯本地、U 盘一拷就完事,最省心。
工具概览
code-porter 的核心思路很简单:
- 扫描:遍历目录,识别项目类型和 Git 状态
- 导出:根据项目状态选择最优打包策略(bundle / zip)
- 导入:读取 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 环境或任何依赖。uvx 是 uv 自带的命令,一行搞定。
智能打包策略
这是 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
项目识别能力
工具通过查找项目标记文件来识别不同语言栈的项目:
- Python:
pyproject.toml - Node.js:
package.json - Go:
go.mod - Rust:
Cargo.toml - .NET:
*.sln
扫描时会对每个项目进行全面分析:
- 是否 Git 仓库、是否有 remote、工作区是否干净
- 目录大小、是否存在大目录(可配置阈值,默认 500MB)
- 是否命中默认排除目录(
node_modules、.venv、dist等) - 是否值得导出,以及推荐的打包策略
# 扫描并输出 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:为什么不用
rsync或scp?因为它们不知道哪些是项目、哪些是垃圾目录、哪些有未提交改动。它们只管拷贝文件,不理解"项目"这个概念。code-porter 的价值在于它理解开发者的项目结构,并据此做出智能决策。
程序设计实验室
微信公众号