Skip to content

Instantly share code, notes, and snippets.

@maage
Forked from april/git-log-json.sh
Last active November 25, 2022 20:23
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save maage/f4853041435f49d521ccaa78017ca428 to your computer and use it in GitHub Desktop.
Save maage/f4853041435f49d521ccaa78017ca428 to your computer and use it in GitHub Desktop.
bash function for git log as JSON
# attempting to be the most robust solution for outputting git log as JSON,
# using only bash shell syntax, `git`, `sed` and `tr`.
# - uses traditional JSON camelCase
# - includes every major field that git log can output, including the body
# - proper sections for author, committer, and signature
# - multiple date formats (one for reading, ISO for parsing)
# - properly handle body values, even those that contain quotation marks and
# escaped characters
# - outputs as minimized JSON, can be piped to `jq` for pretty printing
# - can run against the current directory as `git-log-json` or against a file
# or folder with `git-log-json foo`
# - easily piped into `jq`, e.g. this will get all the commit subjects:
# $ git-log-json foo | jq -r '.[] | .subject'
# - accept any option git log accepts, --pretty etc does not make sense but accepted
# - requires support for en_US.UTF-8 locale, needed to support \0 as delim
# credit to @nsisodiya, @varemenos, @overengineer, and others for the
# original working code:
# https://gist.github.com/varemenos/e95c2e098e657c7688fd
git-log-json() {
local a
for a in "$@"; do
case "${a}" in
--) break ;;
--format=*|--pretty|--pretty=*|--oneline|-p|-u|--patch)
>&2 echo "ERROR: git-log-json does not accept ${a} as option"
return 1
;;
esac
done
local LANG=en_US.UTF-8
# Force UTF-8 to handle \0 as native
git log --pretty=format:"$(
{
# Normalize, handle delims between keys and values and entries
tr -d '\r\n ' | sed -E 's/"([^"]*)"/%x00\1%x00/g;s/$/,%x00/'
} << 'EOF'
{
"author":
{
"name": "%aN",
"email": "%aE",
"date": "%aD",
"dateISO8601": "%aI"
},
"body": "%b",
"commitHash": "%H",
"commitHashAbbreviated": "%h",
"committer":
{
"name": "%cN",
"email": "%cE",
"date": "%cD",
"dateISO8601": "%cI"
},
"encoding": "%e",
"notes": "%N",
"parent": "%P",
"parentAbbreviated": "%p",
"refs": "%D",
"signature":
{
"key": "%GK",
"signer": "%GS",
"verificationFlag": "%G?"
},
"subject": "%s",
"subjectSanitized": "%f",
"tree": "%T",
"treeAbbreviated": "%t"
}
EOF
)" "$@" | \
# Force UTF-8 to handle \0 as native
sed -E '
# Slurp all into memory
:a
N
$!ba
# Handle quotations
s/\\/\\\\/g
s/"/\\"/g
# Join entries, drop \n so it does not mess later
s/(\x00[}],)\x00\n([{]\x00)/\1\2/g
# Handle \n\r\t
s/\r//g
s/\n/\\n/g
s/\t/\\t/g
# Wrap with [ ], drops last entry delim
s/^(.*),\x00$/[\1]/
# Handle key/value delims
s/\x00/"/g;
'
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment