···11+#!/bin/sh
22+33+# some git commands print to stdout, which would contaminate our JSON output
44+clean_git(){
55+ git "$@" >&2
66+}
77+88+# Remove all remote branches, remove tags not reachable from HEAD, do a full
99+# repack and then garbage collect unreferenced objects.
1010+make_deterministic_repo(){
1111+ local repo="$1"
1212+1313+ # run in sub-shell to not touch current working directory
1414+ (
1515+ cd "$repo"
1616+ # Remove files that contain timestamps or otherwise have non-deterministic
1717+ # properties.
1818+ rm -rf .git/logs/ .git/hooks/ .git/index .git/FETCH_HEAD .git/ORIG_HEAD \
1919+ .git/refs/remotes/origin/HEAD .git/config
2020+2121+ # Remove all remote branches.
2222+ git branch -r | while read -r branch; do
2323+ clean_git branch -rD "$branch"
2424+ done
2525+2626+ # Remove tags not reachable from HEAD. If we're exactly on a tag, don't
2727+ # delete it.
2828+ maybe_tag=$(git tag --points-at HEAD)
2929+ git tag --contains HEAD | while read -r tag; do
3030+ if [ "$tag" != "$maybe_tag" ]; then
3131+ clean_git tag -d "$tag"
3232+ fi
3333+ done
3434+3535+ # Do a full repack. Must run single-threaded, or else we lose determinism.
3636+ clean_git config pack.threads 1
3737+ clean_git repack -A -d -f
3838+ rm -f .git/config
3939+4040+ # Garbage collect unreferenced objects.
4141+ # Note: --keep-largest-pack prevents non-deterministic ordering of packs
4242+ # listed in .git/objects/info/packs by only using a single pack
4343+ clean_git gc --prune=all --keep-largest-pack
4444+ )
4545+}