没有个人 Git 仓库时,怎么维护自己的内部小项目

有些小项目很难被正式归到某个业务仓库里。

它可能是一组给自己用的脚本,一个本地知识库,一套 AI 工具的 Skill,也可能是一份还没成熟到要进入团队工程体系的内部资料。它确实有价值,也确实需要长期维护,但它又不像正式业务项目那样天然有一个远端仓库可以放。

最理想的做法当然是建一个私有 Git 仓库。Git 能保留提交历史、分支、作者信息和变更差异,也方便多设备同步。

但现实里经常会遇到两个限制:

  • 公司内网有 GitLab,但普通员工不能创建个人仓库。
  • 由于合规、保密或数据边界要求,项目不能放到公网 GitHub / Gitee,即使是私有仓库也不合适。

这时就需要一个退一步但能长期使用的办法:本地仍然按项目维护,远端用「压缩包 + 飞书云盘 / 飞书云文档」保存。

它不是完整的 Git 服务器替代品,但能解决几个关键问题:电脑坏了能恢复,换设备能迁移,别人需要时能拿到一份明确版本,多次更新时也能用同一个远端文件位置替换。

先分清想保存什么

这类项目要解决的不是「怎么压缩一个文件夹」这么简单。

真正要先判断的是:远端保存的是普通文件快照,还是一个 Git 仓库备份。

如果只是想把当前目录保存下来,普通 zip 就够。如果项目已经用 Git 管理,而且只需要交付当前版本,git archive 更干净。如果希望连提交历史一起保留,后续还能 clone 回一个完整仓库,就应该用 git bundle

三种方式看起来都像「生成一个文件」,但语义完全不一样。

方案一:zip,最直接的目录压缩

zip 是最普通的压缩方式。

它的特点是简单:不要求项目本身是 Git 仓库,也不要求有提交历史。只要目录存在,就可以压缩。

在 macOS 或 Linux 上,可以这样生成:

zip -r project-backup.zip project-folder

也可以直接在 Finder 里右键目录,选择压缩。

zip 的优点是解压体验最好。拿到文件的人不需要知道 Git,直接解压就能看到目录。

它的缺点也很明显:默认会把目录里的内容都放进去。如果项目里有 node_modules、构建产物、缓存、大文件或临时日志,普通 zip 不会自动理解这些内容该不该排除。可以用 zip -x 写排除规则,但规则一多,就会变得不如 Git 自己的忽略机制清楚。

因此 zip 更适合这些情况:

  • 目录不是 Git 仓库。
  • 内容规模不大。
  • 解压后能直接使用比保留提交历史更重要。
  • 目录里没有太多需要排除的缓存和依赖目录。

如果只是备份一个本地资料夹、一个 Markdown 知识库、一个没有 Git 管理的小工具目录,zip 是成本最低的方案。

方案二:git archive,打包当前提交里的项目内容

如果项目已经用 Git 管理,但远端只需要一份「当前版本源码」,可以用 git archive

常用命令是:

git archive --format=zip --output project-snapshot.zip HEAD

它会把 HEAD 这个提交里被 Git 跟踪的文件打成 zip。被 .gitignore 忽略、没有加入版本管理的文件不会进去,比如常见的 node_modules、本地缓存、临时日志。

这比普通 zip 干净很多,因为它使用的是 Git 眼里的项目内容。

这里要注意一个细节:git archive 打包的是某个提交,不是当前工作区。已经修改但还没提交的内容不会进入 HEAD 生成的压缩包。打包前最好先看一眼:

git status --short

如果有需要进入快照的改动,先提交,再执行 git archive

不过 git archive 生成的是源码快照,不包含 .git/,也不包含提交历史。别人解压后能看到文件,但不能继续查看原来的 commit、branch 和 author 记录。

它适合这些情况:

  • 项目已经是 Git 仓库。
  • 远端只需要当前版本,不需要历史。
  • 希望自动排除未跟踪文件和被忽略文件。
  • 接收方更希望直接解压,而不是执行 git clone

把它理解成「Git 管理下的干净 zip」会比较准确。

方案三:git bundle,把 Git 仓库本身打成一个文件

如果想保留 Git 提交历史,git bundle 更合适。

常用命令是:

git bundle create project-backup.bundle --all

--all 会把当前仓库里的所有 refs 都打进去,包括分支和 tag。这个文件不是普通 zip,不能直接双击解压查看源码。它更像一个可以移动的 Git 仓库备份。

git archive 一样,bundle 保存的是 Git 历史,不保存未提交的工作区改动。打包前仍然应该先确认工作区状态,需要保留的内容先提交。

还原时用 git clone

git clone project-backup.bundle project-folder

这样还原出来的是一个正常 Git 工作目录,可以继续看提交历史、创建新提交、切分支。

如果有同事协助开发,只要他们的提交已经进入这个仓库历史,bundle 里也会保留对应的 author 和 commit 信息。它保存的是 Git 历史,不只是文件结果。

但 bundle 也有一个限制:它只是一个文件,不是在线协作服务。多人同时开发时,仍然没有 GitLab 那种 pull request、权限控制、在线 diff、冲突合并和持续集成。它适合做离线分发和备份,不适合作为高频多人协作的中心仓库。

git bundle 适合这些情况:

  • 项目已经用 Git 管理。
  • 提交历史有价值。
  • 未来可能要在另一台设备上继续开发。
  • 希望保留分支、tag、author 和 commit 记录。
  • 接收方可以接受用 git clone 还原。

如果这是一个会长期维护的个人内部项目,git bundle --all 通常是三种方案里最接近「完整仓库备份」的选择。

三种方式怎么选

可以按这个顺序判断。

如果目录没有用 Git 管理,先用 zip。它简单、直观,恢复成本低。

如果目录已经用 Git 管理,但远端只要当前源码,用 git archive。它会自动只打包 Git 跟踪的内容,生成的仍然是普通 zip。

如果目录已经用 Git 管理,而且提交历史也要保存,用 git bundle。它还原时需要 git clone,但能保留仓库历史。

可以把它们记成这张表:

方式 是否需要 Git 仓库 是否保留提交历史 接收方怎么还原 适合场景
zip 不需要 不保留 直接解压 普通目录、资料夹、小规模文件
git archive 需要 不保留 直接解压 干净源码快照、交付当前版本
git bundle 需要 保留 git clone 仓库备份、多设备迁移、保留历史

这三种方式没有绝对优劣。关键是先想清楚远端文件代表什么:普通目录、当前源码,还是完整仓库。

远端放到哪里

压缩包生成后,还需要一个稳定的远端位置。

如果内容适合让多人看到,飞书文档是一个不错的入口。可以在相关说明文档里追加附件,把压缩包和使用说明放在一起。这样读者看到背景、规则和最新附件,就能理解这个项目为什么存在、怎么恢复、什么时候更新。

如果内容主要给自己备份,飞书云盘更轻。它默认更像个人文件存储,适合放一些还没有团队化的小项目、个人工具、草稿知识库和 AI 工作流资产。

两种放法的区别可以简单理解为:

  • 飞书文档:更适合多人共同查看,适合和说明、背景、维护规则放在一起。
  • 飞书云盘:更适合个人备份,适合自己频繁替换和整理。

不管放在哪里,最好只保留一个最新文件,或者用固定文件名保留最新版本。例如:

project-name-2026-05-29.bundle
project-name-2026-05-29.zip

每次项目有更新时,重新生成文件,然后替换远端旧文件。这样远端目录不会被一堆历史压缩包淹没。

如果确实需要保留多个历史版本,也建议制定规则,比如只保留最近 3 个,或者只保留每周五的版本。否则压缩包会很快变成另一种形式的垃圾堆。

可以把生成过程脚本化

手动执行命令可以解决一次问题,但长期维护最好脚本化。

比如一个 Git 管理的小项目,可以写一个本地备份脚本:

#!/usr/bin/env bash
set -euo pipefail

project_name="project-name"
today="$(date +%F)"
output_dir="$HOME/code"

rm -f "$output_dir/${project_name}-"*.bundle
git bundle create "$output_dir/${project_name}-${today}.bundle" --all

如果只是普通目录,也可以用 zip:

#!/usr/bin/env bash
set -euo pipefail

project_name="project-name"
today="$(date +%F)"
output_dir="$HOME/code"

rm -f "$output_dir/${project_name}-"*.zip
zip -r "$output_dir/${project_name}-${today}.zip" "$project_name"

脚本的重点不是命令有多复杂,而是把两个动作固定下来:

  • 生成新压缩包。
  • 删除旧压缩包,只保留最新版本。

这样每次更新远端时,拿到的都是一个明确的最新文件。

如果还想更进一步,可以把「上传到飞书云盘并替换旧文件」也工具化。这个步骤依赖当前账号、登录态和飞书页面能力,自动化前要确认权限边界和误删恢复机制。对于确定只保留最新备份的目录,删除旧文件再上传新文件是可以接受的;对于多人共用或不可恢复资料,就不应该默认自动删除。

一个真实例子:AI 工作流资产

AI 工具里的 Skill、规则、个人知识库就是这类问题的典型例子。

它们不是业务项目,但会越来越重要。比如一套文档整理 Skill、一组前端排障规则、一批 Markdown 知识库,可能在很多项目里反复提供帮助。

这些内容如果只留在本机,电脑坏了就很麻烦;如果放到公网仓库,又可能不符合公司内部资料的合规边界;如果公司内网不允许个人创建仓库,就只剩本地维护和远端文件备份这条路。

这时可以这样处理:

  • 本地目录继续用 Git 管理,认真写 commit。
  • 定期用 git bundle create xxx.bundle --all 生成完整仓库备份。
  • 把 bundle 上传到飞书云盘或附到飞书文档里。
  • 更新时替换旧 bundle,只保留最新备份。

如果只是想给别人一份当前资料,不需要历史,可以额外生成 git archive 版本。别人直接解压就能看 Markdown,不需要理解 bundle。

这个组合比较实用:自己保留 bundle,别人看快照时给 archive。

这个方案的边界

「压缩包 + 飞书」解决的是远端保存问题,不是完整协作平台问题。

它能做到:

  • 保存当前文件。
  • 保存 Git 历史(使用 bundle 时)。
  • 放到一个公司内部可访问的位置。
  • 让电脑损坏或换设备时可以恢复。
  • 让别人按附件拿到一份明确版本。

它做不到:

  • 在线 pull request。
  • 自动合并冲突。
  • 分支权限管理。
  • issue、CI、code review。
  • 多人高频同时提交。

所以它适合个人内部项目、小范围资料维护、低频共享和备份。只要项目进入多人高频协作,还是应该推动它进入正式团队仓库。

这条边界很重要。不要因为 bundle 能保留 Git 历史,就把它当成 GitLab。它更像「Git 仓库的离线保险箱」。

最后可以形成一个固定口径

当公司不允许个人创建内部仓库,项目又不能放到公网私有仓库时,可以先采用这套口径:

本地按正常项目维护。如果需要版本历史,本地用 Git 提交。远端不用假装有一个 Git 服务,而是把项目打成压缩包,放到飞书云盘或飞书文档附件里。

普通目录用 zip,Git 当前快照用 git archive,完整仓库备份用 git bundle --all。飞书文档适合多人查看和解释背景,飞书云盘适合个人保存和频繁替换。

这个方案不优雅,但现实、低成本、合规边界也清楚。对那些还没资格进入正式仓库、但又不应该丢在本机里的内部小项目来说,它已经足够实用。