I have a bash script which accepts a string of either a branch name (e.g., "master", or "feature/foo") or a commit hash (e.g. "1234abcd").
I have the repository checked out, so I can call git.
What is the best way to determine whether the string is a branch name or a commit hash?
#!/bin/bash
commit_or_branch="$1"
cd /path/to/my_repo
git fetch
if <is_branch $commit_or_branch>
then
echo "it's a branch"
else
echo "it's a commit"
fi
To pull up a list of your commits and their associated hashes, you can run the git log command. To checkout a previous commit, you will use the Git checkout command followed by the commit hash you retrieved from your Git log.
Retrieving the hash If you want to turn references (branches and tags) into hash, you can use git show-ref and git for-each-ref commands. Using the git reflog command is also used if you want to have the history on the head of your branches.
If you would like a robust mechanism to tell relative names (e.g. you SHA1 is possibly one or so commits behind a named branch), you can use git name-rev
to resolve it.
Examples:
$ git config remote.upstream.url
https://github.com/RobotLocomotion/drake.git
$ git log --oneline -n 5
7530a95 Merge pull request #5743 from soonho-tri/pr-reformat-mathematical_program
ebc8f25 Suppresses console output of speed_bump.obj genrule. (#5726)
d8b9a0b Merge pull request #5735 from david-german-tri/namespaces
79e10e8 Remove redundant 'symbolic::' prefix from mathematical_program code
b68b590 Clean up mathematical_program code by adding using std::*
$ git name-rev HEAD
HEAD master
$ git name-rev 79e10e8
79e10e8 master^2
$ git name-rev HEAD~20
HEAD~20 remotes/origin/issue/5646_return_binding~3
Reference: Git Tips (old commit)
UPDATE: As @kporter mentioned, there is also the --name-only
flag (with new commits as of 2020/04/21):
$ git name-rev HEAD
HEAD tags/last_sha_with_original_matlab~313
$ git name-rev --name-only HEAD~20
tags/last_sha_with_original_matlab~333
Command-Line Reference: git name-rev
You can use git show-ref
:
git show-ref --head | grep refs
If it is empty, it is a SHA1 (or an invalid object, which isn't good).
If not, it is a branch name.
A better technique comes from "Validate if commit exists", using git merge-base
:
A branch name will result in a different string (the SHA1)
C:\Users\vonc\prog\b2d>git merge-base master master
de4accfd28c5f25fcc057d56996b83450be5dc60
a SHA1 will result in the same result (or at least starts with the same result):
C:\Users\vonc\prog\b2d>git merge-base 03949c3d3f88a378c6a08e57daa97059b52813f1 03949c3d3f88a378c6a08e57daa97059b52813f1
03949c3d3f88a378c6a08e57daa97059b52813f1
foobar will fail:
C:\Users\vonc\prog\b2d>git merge-base xxx xxx
fatal: Not a valid object name xxx
That means something like:
if [[ git merge-base $string $string ]]; then
if [[ $(git merge-base $string $string) == $string* ]]; then
echo "SHA1"
else
echo "branch"
fi
else
echo "Not a valid object name '$string'"
fi
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With