git archive导出的包不含.git目录和开发配置文件,因其本质是打包指定提交的快照,仅包含git跟踪的文件,自动排除.git目录、.gitignore内文件、ide配置等未暂存内容,这是设计使然而非bug。

git archive 导出的包为什么没有 .git 目录和开发配置文件
因为 git archive 本质是打包 Git 仓库的某一提交(或分支)的「快照」,只包含被 Git 跟踪的文件,所有未 git add 的文件、.git 目录、.gitignore 本身、.gitattributes、本地 hooks、IDE 配置(如 .vscode/、.idea/)默认都不在归档范围内——这是它“纯净”的根本原因,不是 bug,是设计使然。
但这也意味着:如果你依赖 .env.example 或 docker-compose.yml 这类被 .gitignore 排除的文件,它们不会自动出现。常见补救方式是临时取消忽略:
- 用
git add -f .env.example强制暂存(导出后记得git reset) - 或改用
--worktree-attributes+ 自定义.gitattributes标记导出文件(更稳妥) - 更推荐:在脚本里用
tar合并补充文件,而非强改 Git 状态
如何用 git archive 生成带版本号的 tar.gz 包
直接调用 git archive 只能输出裸数据流,要生成带命名规范的压缩包,必须配合 tar 或重定向。最简可靠写法:
git archive --format=tar.gz --prefix=myapp-$(git describe --tags --abbrev=0 2>/dev/null || git rev-parse --short HEAD)/ HEAD > myapp-$(git describe --tags --abbrev=0 2>/dev/null || git rev-parse --short HEAD).tar.gz
关键点:
-
--prefix控制解压后顶层目录名,避免文件散落根目录 -
git describe --tags --abbrev=0取最近轻量 tag;失败时 fallback 到短 commit hash,保证命名总有效 - 别用
git rev-parse --short HEAD单独做版本名——它不唯一,不同分支可能冲突 - Windows 下需用 Git Bash 或 WSL,原生 cmd 对
$()和重定向支持差
排除特定文件或目录的三种真实可用方式
git archive 本身不支持 --exclude,但可通过以下任一方式实现排除:
GitHub 仓库备份技能 - 将 OpenClaw 工作空间自动或手动备份至 GitHub 私有仓库。支持自动定时备份和手动交互式配置,引导完成 Token 配置、仓库创建、首次备份及定时任务设置。用途:(1) 首次设置 (2) 日常备份。
- 在
.gitattributes中写:docs/** export-ignore(注意:需提前git add .gitattributes) - 用
git ls-tree -r --name-only HEAD | grep -v '^docs/' | xargs -r tar -czf out.tar.gz --transform 's/^/myapp-1.2.0\//'(绕过 archive,手动构建文件列表) - 导出后用
tar --delete删除(仅 GNU tar 支持,且不能删目录,得先删文件再删空目录)
第一种最干净,但要求所有目标仓库都维护 .gitattributes;第二种灵活但丧失 Git 权限/符号链接保留能力;第三种易出错,不建议用于生产。
CI 环境中执行 git archive 的权限与路径陷阱
GitHub Actions / GitLab CI 默认 checkout 是 fetch-depth: 1,导致 git describe 失败、tag 不可见、git archive 报 fatal: Not a valid object name HEAD。
必须显式配置:
- GitHub Actions:加
fetch-depth: 0(全量克隆)或fetch-tags: true - GitLab CI:用
git fetch --prune --unshallow(如果 depth 被限制) - 始终用
cd $CI_PROJECT_DIR显式切换路径,避免因 runner 工作目录非仓库根而失败 - 别信
pwd输出——某些 runner 会在子 shell 执行脚本,当前路径可能已变
导出路径也容易踩坑:CI 中 tar -C 指定解压目录时,若目标不存在会静默失败,务必先 mkdir -p dist/。










