GitCreating Archives (git archive)

git archive: Exporting a Project Snapshot

git archive exports a clean snapshot of your project at any commit, branch, or tag — without including the .git directory. The output is a standard tar or zip archive containing only the tracked files as they existed at that point in history. This makes git archive the right tool for release distributions, deployment packages, and CI/CD build artifacts where you want source files but not version-control metadata.

What git archive Does

When you run git archive, Git reads the tree object for the ref you specify and writes every file in that tree to an archive. The result is a reproducible snapshot: run it twice on the same ref and you get bit-for-bit identical archives. There is no .git directory, no staged changes, and no untracked files — only the committed, tracked content at that exact revision.

Basic Export: HEAD as tar.gz

Export the current HEAD to a compressed tarball

Bash
git archive --format=tar.gz HEAD > project.tar.gz

# Verify contents (no .git directory)
tar -tzf project.tar.gz | head -20

Archive contents — no .git directory

Text
README.md
package.json
tsconfig.json
src/
src/index.ts
src/components/
src/components/Button.tsx
src/utils/
src/utils/formatDate.ts
tests/
tests/Button.test.tsx
Note
There is no .git directory in the output. git archive never includes it, making the export safe to deploy directly to a server or distribute to users who should not have your history.
Export a Specific Tag as a Zip

The most common production use case is exporting a tagged release. Specify the tag name as the treeish argument and choose your preferred format and output file.

Export tag v1.0.0 as zip and as tar.gz

Bash
# Export as zip (Windows-friendly)
git archive v1.0.0 --format=zip -o release-v1.0.0.zip

# Export as tar.gz (smaller, Linux/macOS-friendly)
git archive v1.0.0 --format=tar.gz -o release-v1.0.0.tar.gz

# Verify the tag version is captured inside
unzip -p release-v1.0.0.zip package.json | grep '"version"'
# "version": "1.0.0",
Adding a Prefix (Root Folder in the Archive)

By default the archive has no root folder — all files appear at the top level of the archive. Use --prefix to wrap everything inside a named directory. This is the standard convention for open-source releases: when the user extracts the archive they get a single folder named after the project and version.

Archive with a root directory prefix

Bash
git archive --prefix=myapp-1.0/ HEAD > myapp.tar.gz

# With a specific tag and the -o flag
git archive v2.3.1 --format=tar.gz --prefix=myapp-2.3.1/ -o myapp-2.3.1.tar.gz

# Verify the prefix
tar -tzf myapp-2.3.1.tar.gz | head -5

Archive contents with prefix

Text
myapp-2.3.1/
myapp-2.3.1/README.md
myapp-2.3.1/package.json
myapp-2.3.1/src/
myapp-2.3.1/src/index.ts
Tip
Always include the trailing slash in --prefix: --prefix=myapp-2.3.1/ . Without the trailing slash, the prefix is concatenated directly onto filenames, producing broken names like myapp-2.3.1README.md instead of myapp-2.3.1/README.md.
Export a Subdirectory Only

You can archive just a subtree of the repository by appending a colon and path to your treeish argument. This is extremely useful in monorepos where you want to distribute only one package, or in CI pipelines that only need a subset of the source.

Export only the src/ subdirectory

Bash
# Export only src/ from HEAD, pipe into an output directory
git archive HEAD:src/ | tar -xf - -C output/

# Export only docs/ from a specific tag
git archive v1.0.0:docs/ --format=zip -o docs-v1.0.0.zip

# Export a monorepo package with a prefix
git archive HEAD:packages/ui/ --prefix=ui-library/ -o ui-library.tar.gz
Supported Archive Formats

Format

--format value

Typical Extension

Notes

Uncompressed tar

tar

.tar

Largest, no compression

Gzip-compressed tar

tar.gz

.tar.gz or .tgz

Most common on Linux and macOS

Bzip2-compressed tar

tar.bz2

.tar.bz2

Better compression than gzip, slower

Zip

zip

.zip

Native on Windows, no extra tools needed

XZ-compressed tar

tar.xz

.tar.xz

Best compression ratio, slowest

Export to a Remote Repository via SSH

If the remote server supports it, you can archive directly without cloning locally first. This is useful when the repository is too large to clone but you only need a snapshot.

Archive directly from a remote server

Bash
git archive --remote=git@server:repo.git HEAD > snap.tar
Note
GitHub, GitLab, and most public hosting services disable the --remote flag for security reasons. You typically need to clone first and then archive locally. Check your server configuration if you get "fatal: operation not supported by protocol".
Controlling Archive Contents with .gitattributes

You can mark files or directories to be excluded from archives by adding export-ignore to your .gitattributes file. This lets you keep test files, CI configurations, and development tooling in the repository without shipping them in release archives.

.gitattributes — exclude development files from archives

Text
# These paths will be omitted from git archive output
tests/              export-ignore
.github/            export-ignore
*.test.ts           export-ignore
jest.config.js      export-ignore
.eslintrc.json      export-ignore
docker-compose.yml  export-ignore

Build a clean distribution archive respecting export-ignore

Bash
git archive v1.0.0 --format=tar.gz --prefix=myapp-1.0.0/ -o dist.tar.gz

# Verify: tests/ and .github/ do not appear
tar -tzf dist.tar.gz | grep -E "tests/|.github/"
# (no output — they were excluded)
CI/CD Release Script

Here is a complete release script that uses git archive to produce both a tar.gz and a zip, with a prefix, checksums, and proper file naming from the latest tag.

release.sh — automated release artifact creation

Bash
#!/bin/bash
set -euo pipefail

VERSION=$(git describe --tags --abbrev=0)
ARCHIVE_NAME="myapp-${VERSION}"

echo "Building release archives for ${VERSION}..."

mkdir -p dist/

# tar.gz for Linux/macOS
git archive "${VERSION}"   --format=tar.gz   --prefix="${ARCHIVE_NAME}/"   -o "dist/${ARCHIVE_NAME}.tar.gz"

# zip for Windows
git archive "${VERSION}"   --format=zip   --prefix="${ARCHIVE_NAME}/"   -o "dist/${ARCHIVE_NAME}.zip"

# Checksums
cd dist/
sha256sum "${ARCHIVE_NAME}.tar.gz" > "${ARCHIVE_NAME}.tar.gz.sha256"
sha256sum "${ARCHIVE_NAME}.zip"    > "${ARCHIVE_NAME}.zip.sha256"
cd ..

echo "Done. Archives in dist/:"
ls -lh dist/
Comparison: git archive vs git bundle vs plain cp

Feature

git archive

git bundle

cp -r (manual copy)

Includes .git directory

No

Yes (as pack objects)

Yes (full copy)

Includes full commit history

No

Yes

Yes

Output format

tar / zip

Custom bundle format

Directory

Can git clone/fetch from it

No

Yes

Yes

Suitable for end-user release

Yes

No

No

Respects .gitattributes export-ignore

Yes

No

No

Can export a single subdirectory

Yes (HEAD:src/)

Limited

Yes (cp src/ ...)

Reproducible output

Yes

Yes

No

File size

Smallest

Small (delta-compressed)

Largest

Use Cases
  • Release distributions — ship v1.2.0.tar.gz to users without exposing your .git history

  • Deployment artifacts — upload a snapshot to a server that runs source directly

  • CI/CD packaging — create a deterministic build input artifact from a tagged commit

  • Submitting code — export to zip for sending via email or upload portals

  • Auditing — provide an auditor with an exact snapshot of code at a specific release

Warning
git archive exports the committed state of files only. Uncommitted changes in your working tree or staging area are NOT included. Always commit (or stash) your latest changes before running git archive if you want them in the output. Running git status first ensures you have a clean tree.