Skip to content

Instantly share code, notes, and snippets.

@zambonin
Created November 18, 2020 04:29
Show Gist options
  • Save zambonin/1a852d79aa4c9399a513583bca88561c to your computer and use it in GitHub Desktop.
Save zambonin/1a852d79aa4c9399a513583bca88561c to your computer and use it in GitHub Desktop.
File size vs time as given by a Git repository. Inspired by http://phdcomics.com/comics/archive.php?comicid=1915.
#!/usr/bin/env bash
# shellcheck disable=SC2214
#
# A shell script that shows the size of a file in each commit that modifies it,
# alongside the timestamp taken from the author of the commit. This is useful
# to visualize the size evolution of a file.
#
# It accepts a single option to customize its behavior, described as
# follows. The last argument must be a valid file tracked by its respective
# repository, with the first file obtained from git-ls-files(1) as default.
#
# -C, --directory=<path>
# Pass the path of the desired directory to Git tools.
#
# For instance, to visualize the size breakdown of file "bar" inside directory
# "foo" in a graph, one can use the command below.
#
# $ bash git-size-history.sh -C foo bar \
# | gnuplot -e 'set term dumb; set xdata time; set timefmt "%s";
# plot "-" using 1:2 with lines notitle'
#
# Parsing of long options is adapted from https://stackoverflow.com/a/28466267.
DIR_PATH="."
while getopts C:-: OPT ; do
if [ "$OPT" = "-" ] ; then
OPT="${OPTARG%%=*}"
OPTARG="${OPTARG#$OPT}"
OPTARG="${OPTARG#=}"
fi
case "$OPT" in
C | directory ) DIR_PATH="${OPTARG:-$DIR_PATH}" ;;
??* ) exit 1 ;;
\? ) exit 2 ;;
esac
done
shift $((OPTIND-1))
FILE_PATH="${1:-$(git -C "$DIR_PATH" ls-files | head -1)}"
if ! git -C "$DIR_PATH" ls-files --error-unmatch "$FILE_PATH" >/dev/null ; then
cat <<-EOF
Usage: sh ${0##*/} [options] [file]
-C, --directory=<path>
EOF
exit 1
fi
paste \
<(git -C "$DIR_PATH" rev-list --all "$FILE_PATH" \
| sed -e "s/$/:$FILE_PATH/g" \
| git -C "$DIR_PATH" cat-file --batch-check) \
<(git -C "$DIR_PATH" --no-pager log --format="%at" "$FILE_PATH") \
| awk '{print $(NF), $(NF - 1) }'
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment