Git Basics: Export a Committed Snapshot with git archive
A source handoff sometimes needs files without Git history. git archive exports a tree from a commit. This example gives the archive a top-level directory and excludes an internal note through a committed attribute.
Prepare a scratch directory
Tested on Linux with Git 2.52.0 and GNU Bash 5.2.37. You need the named runtime, Bash, a text editor, and the standard mktemp, rm, and rmdir utilities. The script creates a second temporary fixture directory and removes only that directory through its exit trap. Run it in a normal Bash terminal, outside any Git hook or Git wrapper. No global Git configuration is changed.
Keep using the same terminal. Stop if setup fails, before saving the source:
start_dir="$PWD"
work_dir="$(mktemp -d)" || exit 1
cd -- "$work_dir" || exit 1Run the example
Save this as demonstrate-archive.sh:
#!/usr/bin/env bash
set -euo pipefail
export LC_ALL=C
fixture_dir="$(mktemp -d)"
trap 'rm -rf -- "$fixture_dir"' EXIT
export GIT_CONFIG_NOSYSTEM=1
export GIT_CONFIG_GLOBAL=/dev/null
unset GIT_DIR GIT_WORK_TREE GIT_INDEX_FILE
git init -q -b main "$fixture_dir/repo"
cd -- "$fixture_dir/repo"
git config user.name 'Practice Author'
git config user.email 'practice@example.invalid'
printf 'committed\n' > app.txt
printf 'internal\n' > private-note.txt
printf 'private-note.txt export-ignore\n' > .gitattributes
git add .
git commit -qm 'Exportable snapshot'
printf 'uncommitted\n' > app.txt
git archive --format=tar --prefix=release/ --output=../release.tar HEAD
printf 'Archive entries:\n'
tar -tf ../release.tar
printf 'Archived app:\n'
tar -xOf ../release.tar release/app.txt
test "$(tar -xOf ../release.tar release/app.txt)" = committed
if tar -tf ../release.tar | grep -q 'private-note.txt'; then
exit 1
fi
printf 'Working app:\n'
cat app.txtRun it:
bash demonstrate-archive.shObserved output:
Archive entries:
release/
release/.gitattributes
release/app.txt
Archived app:
committed
Working app:
uncommittedRead the result
HEAD selects the committed tree, so the later working-file edit does not enter the archive. --prefix=release/ puts every exported path below one directory. The committed .gitattributes marks the note with export-ignore. Listing the tar and reading one member with -xO checks the result without extracting files over a working directory.
Apply it carefully
The archive contains a snapshot, not history or a .git directory. export-ignore controls this export; it does not remove a sensitive file from Git history or provide access control. The attributes used normally come from the tree being archived. Keep generated archives outside the source tree, and inspect member names before extracting archives supplied by other people.
The official reference describes the API and its options. The checks above cover the specific fixture, not every possible input or environment.
Clean up
Remove the source and then the empty practice directory:
rm -- demonstrate-archive.sh
cd -- "$start_dir" || exit 1
rmdir -- "$work_dir"
unset start_dir work_dirIf the directory is not empty, inspect the remaining files rather than deleting unknown contents.
Acknowledgements
This post was created with assistance from AI.