# Easily Create Clean Compressed Tarballs of Your Git Repository

Ideally, you could refer the whole world — or at least, the significant portion thereof that want your code — to your (public mirror) Git repository. But unfortunately, the whole world does not (yet) use Git (“I know it was you Fredo, I know it was you, and it breaks my heart.“). Sad. Sooooo sad. But true. So the only recourse is for you to send these tortured souls an archived snapshot of your code via e-mail. I’ll pause now to let you finish retching/sobbing/lamenting/venting. …

Back?

Anyway, Git has a neat “archive” command that helps you create the required archive, but perhaps it does not have the most friendliest interface in the world. I’ve written some scripts to wrap the Git command to facilitate its use, which I share here.

Update 2011-07-07: I have re-written the original three scripts previously described here as a single script, incorporating some of the excellent suggestions that kind folks provided in the comments. Immediately below this is the new, unified, all-bells-and-whistles-included script. Simply name it something like “git-makedist”, switch on its executable bit, and place it somewhere on your system path. Reasonable names, filepaths, prefixes, etc. are all provided if you do not explicitly specify them. All of which means that, in most cases, once installed, simply invoking the command “git makedist” without any options or arguments from within a Git repository “just works ™”, resulting in a sensibly-named compressed archive of the current HEAD ready for distribution. At the same time, various flags and options allow you to fine-tune the operations, e.g. determine the compression/archive method, the path prefixes, the archive name, etc.

Update 2011-07-22, Excluding Files: Sometimes, not all files need to make it out to an archive. You can use the “.gitattributes” file to control which files get archived. Simply add the paths/names/globs of the files or directories you would like to exclude, and add a “export-ignore” after it. For example:

.gitattributes export-ignore
.gitignore export-ignore
*.tmp export-ignore

Note that the “.gitattributes” file has to be committed for it to have an effect.

#! /bin/bash

compose_name()

function usage

NOPREFIX=0
while [ -n $1 ]; do case$1 in
-f|--format)
FORMAT=$2 shift 2 ;; -r|--revision) REVISION=$2
shift 2
;;
--no-prefix)
NOPREFIX=1
shift
;;
-p|--prefix)
PREFIX=$2 shift 2 ;; -n|--name) REPONAME=$2
shift 2
;;
-o|--output)
OUTPUTDIR=$2 shift 2 ;; -h|--help) usage ;; *) break ;; esac done if [[ -z$FORMAT ]]
then
FORMAT="targz"
fi

if [[ -z "$REVISION" ]] then REVISION="HEAD" fi if [[ -z$REPONAME ]]
then
REPONAME=$(compose_name) if [[ -z$REPONAME ]]
then
echo "FATAL: not a Git repository, or could not parse repository name (supply using '-p'/'--prefix' flag)"
exit 1
fi
fi

if [[ -z "$OUTPUTDIR" ]] then OUTPUTDIR="." fi if [[$FORMAT == "zip" ]]
then
GITARCHIVEFORMAT="zip"
EXT=".zip"
else
GITARCHIVEFORMAT="tar"
if [[ $FORMAT == "tarbz" ]] then EXT=".tar.bz2" COMPRESS="bzip2" elif [[$FORMAT == "targz" ]]
then
EXT=".tar.gz"
COMPRESS="gzip"
else
echo "FATAL: Unrecognized format '$FORMAT'" exit 1 fi fi if [[$NOPREFIX == 1 ]]
then
PREFIXCOMMAND=""
elif [[ -z "$PREFIX" ]] then PREFIXCOMMAND="--prefix=$REPONAME/"
else
PREFIXCOMMAND="--prefix=$PREFIX/" fi ARCHIVEBASENAME="$REPONAME-$(git describe --always)" OUTPUTPATH="$OUTPUTDIR/$ARCHIVEBASENAME$EXT"
if [[ $FORMAT == "zip" ]] then git archive --format="$GITARCHIVEFORMAT" $PREFIXCOMMAND$REVISION > $OUTPUTPATH else git archive --format="$GITARCHIVEFORMAT" $PREFIXCOMMAND$REVISION | $COMPRESS >$OUTPUTPATH
fi
Share