How to archive repository in Git

Git archive creates compressed snapshots of repository contents without version control metadata, perfect for distribution packages and deployment artifacts. As the creator of CoreUI with 26 years of development experience, I’ve used git archive to generate release packages for applications serving millions of users, creating clean distribution files without .git directories that reduce package size by 90%.

The most reliable approach uses git archive with compression for specific commits or branches.

Basic Archive Creation

# Archive current branch as zip
git archive --format=zip --output=project.zip HEAD

# Archive as tar.gz
git archive --format=tar.gz --output=project.tar.gz HEAD

# Archive as tar
git archive --format=tar --output=project.tar HEAD

# Verify archive
unzip -l project.zip
tar -tzf project.tar.gz

Archive Specific Branch

# Archive main branch
git archive --format=zip --output=main.zip main

# Archive feature branch
git archive --format=zip --output=feature.zip feature/new-ui

# Archive remote branch
git archive --format=zip --output=origin-main.zip origin/main

Archive Specific Commit

# Archive by commit hash
git archive --format=zip --output=v1.0.0.zip abc1234

# Archive by tag
git archive --format=zip --output=v1.0.0.zip v1.0.0

# Archive by relative reference
git archive --format=zip --output=previous.zip HEAD~5

Archive Specific Directory

# Archive only src directory
git archive --format=zip --output=src.zip HEAD:src

# Archive multiple directories
git archive --format=tar HEAD src docs | gzip > selected.tar.gz

# Archive with path prefix
git archive --format=zip --prefix=myproject/ --output=project.zip HEAD
# Extracts to myproject/ directory

Add Prefix to Archive

# Add project name as prefix
git archive --format=tar.gz --prefix=myproject-v1.0/ --output=myproject-v1.0.tar.gz HEAD

# Extract creates myproject-v1.0/ directory
tar -xzf myproject-v1.0.tar.gz
ls
# myproject-v1.0/

# Useful for preventing file conflicts when extracting

Archive with Compression Levels

# Maximum compression (slower, smaller)
git archive --format=tar HEAD | gzip -9 > project.tar.gz

# Fast compression (faster, larger)
git archive --format=tar HEAD | gzip -1 > project.tar.gz

# bzip2 compression (better ratio)
git archive --format=tar HEAD | bzip2 > project.tar.bz2

# xz compression (best ratio, slowest)
git archive --format=tar HEAD | xz > project.tar.xz

Archive Excluding Files

# Use .gitattributes to exclude files
echo "tests/ export-ignore" >> .gitattributes
echo "*.test.js export-ignore" >> .gitattributes
echo ".github/ export-ignore" >> .gitattributes
echo "docs/ export-ignore" >> .gitattributes

git add .gitattributes
git commit -m "Configure archive exports"

# Archive excludes these files
git archive --format=zip --output=production.zip HEAD

# Verify exclusions
unzip -l production.zip | grep tests
# (no results)

Automated Release Archives

#!/bin/bash
# create-release.sh

VERSION=$1
if [ -z "$VERSION" ]; then
  echo "Usage: ./create-release.sh <version>"
  exit 1
fi

# Create tag
git tag -a "v$VERSION" -m "Release v$VERSION"

# Create archives
git archive --format=zip --prefix="myproject-$VERSION/" --output="releases/myproject-$VERSION.zip" "v$VERSION"
git archive --format=tar.gz --prefix="myproject-$VERSION/" --output="releases/myproject-$VERSION.tar.gz" "v$VERSION"

# Create checksums
cd releases
sha256sum "myproject-$VERSION.zip" > "myproject-$VERSION.zip.sha256"
sha256sum "myproject-$VERSION.tar.gz" > "myproject-$VERSION.tar.gz.sha256"
cd ..

echo "✓ Release v$VERSION created:"
ls -lh releases/myproject-$VERSION.*

# Push tag
git push origin "v$VERSION"
# Usage
chmod +x create-release.sh
./create-release.sh 1.0.0

Archive vs Bundle

# git archive - snapshot only (no history)
git archive --format=zip --output=snapshot.zip HEAD
unzip snapshot.zip
# No .git directory, cannot commit or push

# git bundle - full repository (with history)
git bundle create repo.bundle --all
git clone repo.bundle cloned-repo
cd cloned-repo
git log # Full history available
git commit # Can commit
git push # Can push (if remote configured)

# Use archive for: deployment, distribution, releases
# Use bundle for: backup, offline transfer, full repository copy

CI/CD Archive Generation

# .github/workflows/release.yml
name: Create Release

on:
  push:
    tags:
      - 'v*'

jobs:
  release:
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v2

      - name: Get version from tag
        id: tag_name
        run: echo "VERSION=${GITHUB_REF#refs/tags/v}" >> $GITHUB_OUTPUT

      - name: Create archives
        run: |
          mkdir releases
          git archive --format=zip --prefix="myproject-${{ steps.tag_name.outputs.VERSION }}/" --output="releases/myproject-${{ steps.tag_name.outputs.VERSION }}.zip" HEAD
          git archive --format=tar.gz --prefix="myproject-${{ steps.tag_name.outputs.VERSION }}/" --output="releases/myproject-${{ steps.tag_name.outputs.VERSION }}.tar.gz" HEAD

      - name: Create checksums
        run: |
          cd releases
          sha256sum *.zip > checksums.txt
          sha256sum *.tar.gz >> checksums.txt

      - name: Create Release
        uses: softprops/action-gh-release@v1
        with:
          files: releases/*
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

Archive for Deployment

#!/bin/bash
# deploy-archive.sh

# Archive production-ready code
git archive --format=tar HEAD | gzip > deploy.tar.gz

# Upload to server
scp deploy.tar.gz user@server:/tmp/

# SSH and extract
ssh user@server << 'EOF'
  cd /var/www/myapp
  tar -xzf /tmp/deploy.tar.gz
  rm /tmp/deploy.tar.gz

  # Install dependencies
  npm ci --production

  # Restart service
  sudo systemctl restart myapp
EOF

echo "✓ Deployment complete"

Archive with .gitattributes

# .gitattributes

# Exclude development files
.github/ export-ignore
.vscode/ export-ignore
tests/ export-ignore
*.test.js export-ignore

# Exclude config files
.eslintrc.js export-ignore
.prettierrc.js export-ignore
jest.config.js export-ignore

# Exclude documentation
docs/ export-ignore
*.md export-ignore

# Exclude CI files
.gitlab-ci.yml export-ignore
.travis.yml export-ignore
Jenkinsfile export-ignore

Archive Multiple Branches

#!/bin/bash
# archive-all-branches.sh

BRANCHES=$(git branch | sed 's/\*/ /' | sed 's/^ //')

for BRANCH in $BRANCHES; do
  FILENAME="${BRANCH//\//-}.zip"
  git archive --format=zip --prefix="$BRANCH/" --output="archives/$FILENAME" "$BRANCH"
  echo "✓ Created: archives/$FILENAME"
done

echo "✓ Archived ${#BRANCHES[@]} branches"

Archive with Timestamp

# Create timestamped archive
DATE=$(date +%Y%m%d-%H%M%S)
git archive --format=tar.gz --prefix="backup-$DATE/" --output="backup-$DATE.tar.gz" HEAD

# List timestamped archives
ls -lh backup-*.tar.gz

# Cleanup old archives (keep last 10)
ls -t backup-*.tar.gz | tail -n +11 | xargs rm -f

Extract and Verify Archive

# Create archive
git archive --format=zip --output=project.zip HEAD

# Extract to test directory
mkdir test-extract
unzip project.zip -d test-extract

# Verify contents
cd test-extract
ls -la

# Run tests
npm install
npm test

# If tests pass, archive is good
cd ..
rm -rf test-extract

Best Practice Note

This is how we create release archives across all CoreUI repositories for clean distribution packages. Git archive creates snapshots without version control metadata, perfect for deployment and distribution. Use .gitattributes with export-ignore to exclude development files, add version prefixes to archive paths for clean extraction, create both zip and tar.gz formats for cross-platform compatibility, and generate checksums for integrity verification. Unlike bundles which preserve full Git history, archives provide clean code snapshots ideal for deployment and end-user distribution.

For related Git operations, check out how to bundle a repository in Git and how to create release tags in Git.


Speed up your responsive apps and websites with fully-featured, ready-to-use open-source admin panel templates—free to use and built for efficiency.


About the Author

Subscribe to our newsletter
Get early information about new products, product updates and blog posts.
CSS Selector for Parent Element
CSS Selector for Parent Element

How to loop inside React JSX
How to loop inside React JSX

How to Manage Date and Time in Specific Timezones Using JavaScript
How to Manage Date and Time in Specific Timezones Using JavaScript

How to dynamically add, remove, and toggle CSS classes in React.js
How to dynamically add, remove, and toggle CSS classes in React.js

Answers by CoreUI Core Team