git archive 是最直接安全的导出方式,不改工作区、不依赖暂存区、不打包 .git 目录,仅从对象库读取指定 tree-ish 快照生成纯净包。

Git archive 是 Linux 下导出纯净代码包最直接、最安全的方式,不改工作区、不依赖暂存区、不打包 .git 目录 —— 只要你指定了正确的 tree-ish 和格式,就能拿到开箱即用的发布包。
导出指定 tag/commit 的 zip 包,不污染当前分支
这是最常用也最容易出错的场景。很多人先 git checkout v2.3.0,再手动 zip -r,结果工作区被切走、未提交修改丢失、甚至误打包了 .env 这类忽略文件。
-
git archive --format=zip --output=release-v2.3.0.zip v2.3.0:直接从对象库读取 v2.3.0 标签对应快照,生成干净 zip - 如果提示
fatal: Not a valid object name v2.3.0,说明本地没拉取 tag,先运行git fetch --tags - 用 commit hash 代替 tag 同样有效:
git archive --format=zip --output=hotfix.zip abc1234 - 注意:
v2.3.0必须是已存在的 tag 或分支名;不存在时会报错,不会静默 fallback 到 HEAD
只导出子目录(比如 src/ 或 frontend/),避免路径错误
想导出部分代码时,git archive 支持路径过滤,但路径写法非常敏感 —— 少斜杠、多空格、写错大小写都会失败。
- 正确写法:
git archive --format=zip --output=frontend.zip HEAD:src/frontend/(冒号分隔,末尾带斜杠) - 错误写法:
git archive ... HEAD src/frontend(漏冒号 → 报错fatal: Not a valid object name) - 错误写法:
HEAD:src/frontend(无尾部斜杠 → 可能只打包该目录下文件,不保留目录结构) - 路径区分大小写,且必须是 Git 已跟踪的路径;如果
src/frontend/下有新文件但没git add,它不会出现在归档中
解决中文文件名乱码和权限问题
Linux 下用 git archive --format=zip 生成的 zip,在 Windows 上解压常出现中文路径乱码,这不是编码设置问题,而是 ZIP 标准对 UTF-8 路径支持不一致导致的。
- 首选方案:改用
tar.gz:git archive --format=tar.gz --output=dist.tar.gz v2.3.0,Linux/macOS 原生支持,Windows 用户可用 7-Zip 或 WSL 解压 - 如必须用 zip,加
--worktree-attributes并在项目根目录配.gitattributes:* export-ignore(慎用,会全局跳过)或配合export-subst做变量替换 - 文件权限问题:tar 包默认继承 umask,若需统一设为 644/755,可配置
git config tar.umask 0022,或用tar.<format>.command</format>指定自定义压缩命令
强制打包被 .gitignore 忽略但需要发布的文件
git archive 默认只打包 Git 索引里已跟踪的文件,.gitignore 中的规则自动生效 —— 所以 config.example、README.md.tpl 这类文件不会出现,哪怕它们真实存在于磁盘上。
- 根本解法:在目标 commit 中显式
git add -f config.example,再打包该 commit - 临时补救(不推荐):用
--add-file参数追加单个文件:git archive --format=zip --output=dist.zip v2.3.0 --add-file=config.example -
--add-file不受--prefix影响,路径由参数本身决定;若需进子目录,得写成--add-file=src/config.example - 注意:
--add-file只能添加磁盘上真实存在的文件,不能添加未跟踪的子目录
真正容易被忽略的是:archive 的行为完全基于 Git 对象数据库,不是当前工作区状态。哪怕你刚删掉一个 tracked 文件但还没 git rm,它仍会出现在归档里;反之,刚新建但没 git add 的文件,永远进不了 archive —— 这不是 bug,是设计前提。


















