Skip to content

Instantly share code, notes, and snippets.

@hborders
Last active January 7, 2023 13:56
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 4 You must be signed in to fork a gist
  • Save hborders/87eecb5874169f76cfacb26dc4223575 to your computer and use it in GitHub Desktop.
Save hborders/87eecb5874169f76cfacb26dc4223575 to your computer and use it in GitHub Desktop.
Print the given git hash + a prepended "1" in decimal form
#!/bin/bash -euo pipefail
if [ ${#} -eq 0 ]
then
# read from STDIN
MAYBE_GIT_HASH=$( cat )
else
MAYBE_GIT_HASH="${1}"
fi
LEGAL_GIT_HASH_CHARACTERS="0123456789ABCDEFabcdef"
# grep regex doesn't allow + metacharacter :(
HASH_GREP_REGEX='^['"${LEGAL_GIT_HASH_CHARACTERS}"']['"${LEGAL_GIT_HASH_CHARACTERS}"']*$'
GIT_HASH=$( echo "${MAYBE_GIT_HASH}" | grep "${HASH_GREP_REGEX}" ) || {
echo "\"${MAYBE_GIT_HASH}\" doesnt look like a git hash. A git hash should have only: \"${LEGAL_GIT_HASH_CHARACTERS}\"" >&2
exit 1
}
# We must prefix the git hash with a 1
# If it starts with a zero, when we decimalize it,
# and later hexify it, we'll lose the zero.
ONE_PREFIXED_GIT_HASH=1"${GIT_HASH}"
# bc requires hex to be uppercase because
# lowercase letters are reserved for bc variables
UPPERCASE_ONE_PREFIXED_GIT_HASH=$( echo "${ONE_PREFIXED_GIT_HASH}" | tr "[:lower:]" "[:upper:]" )
# convert to decimal
# See "with bc": http://stackoverflow.com/a/13280173/9636
echo "ibase=16;obase=A;${UPPERCASE_ONE_PREFIXED_GIT_HASH}" | bc
@thirdwheel
Copy link

thirdwheel commented Aug 17, 2018

There's an easier way to convert git hashes to decimal. I have included my method for collecting the hash from git as well:

IFS="v-." read empty major minor patch distance hash <<<"$(git describe)"
# so if `git describe` returns v1.8.21-41-gc0ffee1, this will produce the following variables:
# empty | major | minor | patch | distance | hash
#       | 1     | 8     | 21    | 41       | gc0ffee1

# Add the one like you did above, for completeness' sake, and remove the 'g' prefix in one fell swoop:
hash="${hash/g/1}"

# Generate the decimal representation
printf "%d" 0x$hash

Or, in condensed form:

IFS="v-." read empty major minor patch distance hash <<<"$(git describe)"
printf "%d" 0x"${hash/g/1}"

EDIT: One final revision, using the method you use for getting the hash (pays to keep reading!):

hash=$(git rev-parse --short=7 HEAD)
printf "%d" 0x1"${hash}"

Condense it even more:

printf "%d" 0x1"$(git rev-parse --short=7 HEAD)"

Not all distributions/BSDs/etc come withbcpre-installed, but even busybox's ash hasprintf.

@andrewvmail
Copy link

There's an easier way to convert git hashes to decimal. I have included my method for collecting the hash from git as well:

IFS="v-." read empty major minor patch distance hash <<<"$(git describe)"
# so if `git describe` returns v1.8.21-41-gc0ffee1, this will produce the following variables:
# empty | major | minor | patch | distance | hash
#       | 1     | 8     | 21    | 41       | gc0ffee1

# Add the one like you did above, for completeness' sake, and remove the 'g' prefix in one fell swoop:
hash="${hash/g/1}"

# Generate the decimal representation
printf "%d" 0x$hash

Or, in condensed form:

IFS="v-." read empty major minor patch distance hash <<<"$(git describe)"
printf "%d" 0x"${hash/g/1}"

EDIT: One final revision, using the method you use for getting the hash (pays to keep reading!):

hash=$(git rev-parse --short=7 HEAD)
printf "%d" 0x1"${hash}"

Condense it even more:

printf "%d" 0x1"$(git rev-parse --short=7 HEAD)"

Not all distributions/BSDs/etc come withbcpre-installed, but even busybox's ash hasprintf.

@thirdwheel how do you reverse the process?

@andrewvmail
Copy link

didnt realize its just hex to dec conversion, got it echo "obase=16; 348379070" | bc

@thirdwheel
Copy link

thirdwheel commented Aug 5, 2019

@thirdwheel how do you reverse the process?

@andrewvmail sorry for the late reply, see below.

$ printf "%d" 0xd3ac43f
221955135
$ printf "0x%x" 221955135
0xd3ac43f

@andrewvmail
Copy link

andrewvmail commented Aug 6, 2019 via email

@rogerluan
Copy link

Very interesting, @andrewvmail! Thanks for the alternative and way cleaner way to do this.

One single caveat about your technique is that that method can't decimalize the whole hash, only the short (7-char) ones. But I think we're all using only the hash prefix, so it's not a big deal 😁

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment