#!/bin/sh # Print the contents of all tracked text files to stdout, # each preceded by a header with its filename # # With "-a", binary files are included as well # # With "-m", only files with unstaged modifications are printed # # With "-n", the headers are omitted # # Usage: git cat-all [-a] [-m] [-n] [ ...] set -eu # Error if we are not in a `git` repository git rev-parse --git-dir >/dev/null # Without any commit, there is nothing to print reliably git rev-parse --verify --quiet HEAD >/dev/null || { echo "fatal: no commits yet" >&2 exit 1 } _textonly=yes _lsflags= _cmd='printf "\n\n===== %s =====\n\n" "{}"; cat "{}"' _headers=yes while [ $# -gt 0 ]; do case $1 in -a) _textonly=no shift ;; -m) _lsflags=-m shift ;; -n) _cmd='printf "\n\n"; cat "{}"' _headers=no shift ;; --) shift break ;; -*) echo "Usage: git cat-all [-a] [-m] [-n] [ ...]" >&2 exit 2 ;; *) break ;; esac done # Because `git` runs scripts on the `$PATH` in the current directory cd "$(git rev-parse --show-toplevel)" # An empty file counts as text # => `grep` alone would misjudge it # because it never matches in a file without any lines if [ "$_textonly" = "yes" ]; then _cmd='if [ ! -s "{}" ] || grep -Iq "" "{}"; then '"$_cmd"'; fi' fi # `git ls-files -m` also lists files deleted from the working tree # => Skip them because `cat` would fail if [ -n "$_lsflags" ]; then _cmd='if [ -f "{}" ]; then '"$_cmd"'; fi' fi if [ "$_headers" = "yes" ]; then printf "Repository: %s\n" "$(basename "$PWD")" printf "Branch: %s @ %s\n" \ "$(git rev-parse --abbrev-ref HEAD)" \ "$(git rev-parse --short HEAD)" fi git ls-files \ -z $_lsflags \ -- \ "$@" \ | xargs -0 -I{} sh -c "$_cmd"