Git archive and deterministic packaging quick reference
Basic archive commands
| Goal |
Command |
| Tar archive of HEAD |
git archive --format=tar -o release.tar HEAD |
| Tar.gz with prefix directory |
git archive --prefix=app-1.0.0/ -o app-1.0.0.tar.gz v1.0.0 |
| Zip archive of branch |
git archive --format=zip --prefix=pkg/ -o pkg.zip main |
| Subdirectory archive |
git archive --prefix=api/ -o api.tar.gz HEAD:services/api |
| Specific files only |
git archive -o bundle.tar.gz HEAD src/ package.json |
.gitattributes configuration
Add to .gitattributes in the repository root:
# Exclude from release archives
.github/ export-ignore
.forgejo/ export-ignore
tests/ export-ignore
Dockerfile* export-ignore
.gitattributes export-ignore
.gitignore export-ignore
# Substitute commit metadata
src/version.json export-subst
src/version.py export-subst
src/build_info.go export-subst
| Placeholder |
Expands to |
$Format:%H$ |
Full commit hash |
$Format:%h$ |
Short commit hash |
$Format:%D$ |
Ref names and tags |
$Format:%cI$ |
Committer date (ISO 8601 strict) |
$Format:%an$ |
Author name |
$Format:%ae$ |
Author email |
$Format:%s$ |
Commit subject |
Essential recipes
Deterministic tarball with fixed timestamp
REF="v1.4.0"
COMMIT_DATE=$(git log -1 --format=%cI "$REF")
git archive --format=tar \
--prefix="${REF}/" \
--mtime="$COMMIT_DATE" \
"$REF" | gzip -n -9 > "${REF}.tar.gz"
sha256sum "${REF}.tar.gz" > "${REF}.tar.gz.sha256"
Stream archive directly into Docker build
git archive HEAD | docker build -t myapp:latest -
# Tar archive
tar -xOf release.tar.gz app-1.0.0/src/version.json
# Zip archive
unzip -p release.zip pkg/src/version.json
Verify excluded files are absent
git archive HEAD | tar -tf - | grep -E '(\.github|tests|Dockerfile)' || echo "Clean archive"