How do I get the hash of the current commit in Git?
git log
to retrieve recent commits, that will show full commit hash - anyone "record_commit_hash_and_build_time": "now=$(date -u \"+%Y-%m-%d %H:%M:%S\") && last_commit=$(git rev-parse HEAD) && echo \"{\\\"commit\\\": \\\"$last_commit\\\", \\\"build_time\\\": \\\"$now\\\"}\" > frontend/dist/version.json",
stackoverflow.com/a/11493416/470749 - anyone To turn any extended object reference into a hash, use git-rev-parse
:
git rev-parse HEAD
or
git rev-parse --verify HEAD
To retrieve the short hash:
git rev-parse --short HEAD
To turn references (e.g. branches and tags) into hashes, use git show-ref
and git for-each-ref
.
Answered 2023-09-20 20:27:19
--verify
implies that: The parameter given must be usable as a single, valid object name. Otherwise barf and abort.
- anyone git rev-parse --short HEAD
returns the short version of the hash, just in case anyone was wondering. - anyone --short
, such as --short=12
, to get a specific number of digits from the hash. - anyone --short=N
is about minimal number of digits; git uses larger number of digits if shortened one would be undistinguishable from shortened other commit. Try e.g. git rev-parse --short=2 HEAD
or git log --oneline --abbrev=2
. - anyone git rev-parse HEAD | GREP_COLORS='ms=34;1' grep $(git rev-parse --short=0 HEAD)
- anyone To get the shortened commit hash, use the %h
format specifier:
git log --pretty=format:'%h' -n 1
%H
represents the long commit hash. Also, -1
can be used directly in place of -n 1
.
Answered 2023-09-20 20:27:19
git log
is porcelain and git rev-parse
is plumbing. - anyone git checkout 33aa44; git log -n 1
gives me 33aa44
. What version of git are you using? - anyone porcelain
in the git
man
pages for years, but had NO idea it was referring to a toilet! The porcelain is the toilet, and it's "closer to the user" (who figuratively sits on this toilet) than the plumbing, which is lower-level and farther from the user--ie: below the "porcelain"! Mind blown. - anyone Another one, using git log:
git log -1 --format="%H"
It's very similar to the of @outofculture though a bit shorter.
Answered 2023-09-20 20:27:19
HEAD
. - anyone HEAD
points to this commit rather than a named branche know as detached head. - anyone git --no-pager log -1 --format="%H"
- anyone To get the full SHA:
$ git rev-parse HEAD
cbf1b9a1be984a9f61b79a05f23b19f66d533537
To get the shortened version:
$ git rev-parse --short HEAD
cbf1b9a
Answered 2023-09-20 20:27:19
git
commit
hashes are needed, such as one from the branch
you are currently working with and a master
branch
, you could also use git rev-parse FETCH_HEAD
if you need the hash for the master
commit
that you merge
d into your current branch
. e.g. if you have branch
es master
and feature/new-feature
for a given repo., while on feature/new-feature
you could use git fetch origin master && git merge FETCH_HEAD
and then git rev-parse --short FETCH_HEAD
if you needed the commit
hash from the master
you just merge
d in for any scripts you may have. - anyone Commit hash
git show -s --format=%H
Abbreviated commit hash
git show -s --format=%h
The -s
flag is same as --no-patch
and stands for "Suppress diff output".
Click here for more git show
examples.
Answered 2023-09-20 20:27:19
For completeness, since no one has suggested it yet. .git/refs/heads/master
is a file that contains only one line: the hash of the latest commit on master
. So you could just read it from there.
Or, as a command:
cat .git/refs/heads/master
Update:
Note that git now supports storing some head refs in the pack-ref file instead of as a file in the /refs/heads/ folder. https://www.kernel.org/pub/software/scm/git/docs/git-pack-refs.html
Answered 2023-09-20 20:27:19
master
, which is not necessarily true. - anyone master
. - anyone .git/HEAD
typically points to a ref, if you have a SHA1 in there, you are in detached head mode. - anyone .git
subdirectory, which is not necessarily the case. See the --separate-git-dir
flag in the git init
man page. - anyone There's always git describe
as well. By default it gives you --
john@eleanor:/dev/shm/mpd/ncmpc/pkg (master)$ git describe --always
release-0.19-11-g7a68a75
Answered 2023-09-20 20:27:19
git describe --long --dirty --abbrev=10 --tags
it will give me something like 7.2.0.Final-447-g65bf4ef2d4
which is 447 commits after the 7.2.0.Final tag and the first 10 digest of the global SHA-1 at the current HEAD are "65bf4ef2d4". This is very good for version strings. With --long it will always add the count (-0-) and the hash, even if the tag happens to match exactly. - anyone git describe --always
will "show uniquely abbreviated commit object as fallback" - anyone git describe --tags --first-parent --abbrev=11 --long --dirty --always
. The --always
option means it provides a result (hash) even if there are no tags. The --first-parent
means it doesn't get confused by merge commits and only follows items on the current branch. Note also that --dirty
will append -dirty
to the result if the current branch has uncommitted changes. - anyone Use git rev-list --max-count=1 HEAD
Answered 2023-09-20 20:27:19
If you need to store the hash in a variable during a script, you can use
last_commit=$(git rev-parse HEAD);
Or, if you only want the first 10 characters (like github.com does)
last_commit=$(git rev-parse --short=10 HEAD);
Answered 2023-09-20 20:27:19
now=$(date -u "+%Y-%m-%d %H:%M:%S") && last_commit=$(git rev-parse HEAD) && echo "{\"commit\": \"$last_commit\", \"build_time\": \"$now\"}" > version.json
- anyone If you want the super-hacky way to do it:
cat .git/`cat .git/HEAD | cut -d \ -f 2`
Basically, git stores the location of HEAD in .git/HEAD, in the form ref: {path from .git}
. This command reads that out, slices off the "ref: ", and reads out whatever file it pointed to.
This, of course, will fail in detached-head mode, as HEAD won't be "ref:...", but the hash itself - but you know, I don't think you expect that much smarts in your bash one-liners. If you don't think semicolons are cheating, though...
HASH="ref: HEAD"; while [[ $HASH == ref\:* ]]; do HASH="$(cat ".git/$(echo $HASH | cut -d \ -f 2)")"; done; echo $HASH
Answered 2023-09-20 20:27:19
sh
. Half an hour of documentation comments later, and here's a Gist of it: gist.github.com/Fordi/29b8d6d1ef1662b306bfc2bd99151b07 - anyone I needed something a little more different: display the full sha1 of the commit, but append an asterisk to the end if the working directory is not clean. Unless I wanted to use multiple commands, none of the options in the previous answers work.
Here is the one liner that does:
git describe --always --abbrev=0 --match "NOT A TAG" --dirty="*"
Result: f5366ccb21588c0d7a5f7d9fa1d3f85e9f9d1ffe*
Explanation: describes (using annotated tags) the current commit, but only with tags containing "NOT A TAG". Since tags cannot have spaces, this never matches a tag and since we want to show a result --always
, the command falls back displaying the full (--abbrev=0
) sha1 of the commit and it appends an asterisk if the working directory is --dirty
.
If you don't want to append the asterisk, this works like all the other commands in the previous answers:
git describe --always --abbrev=0 --match "NOT A TAG"
Result: f5366ccb21588c0d7a5f7d9fa1d3f85e9f9d1ffe
Answered 2023-09-20 20:27:19
--match "NOT A TAG"
. Tested in git 2.18.0 as well as 2.7.4. Is there any situation where this argument is needed? - anyone git rev-parse HEAD
does the trick.
If you need to store it to checkout back later than saving actual branch if any may be preferable:
cat .git/HEAD
Example output:
ref: refs/heads/master
Parse it:
cat .git/HEAD | sed "s/^.\+ \(.\+\)$/\1/g"
If you have Windows then you may consider using wsl.exe:
wsl cat .git/HEAD | wsl sed "s/^.\+ \(.\+\)$/\1/g"
Output:
refs/heads/master
This value may be used to git checkout later but it becomes pointing to its SHA. To make it to point to the actual current branch by its name do:
wsl cat .git/HEAD | wsl sed "s/^.\+ \(.\+\)$/\1/g" | wsl sed "s/^refs\///g" | wsl sed "s/^heads\///g"
Output:
master
Answered 2023-09-20 20:27:19
Perhaps you want an alias so you don't have to remember all the nifty details. After doing one of the below steps, you will be able to simply type:
$ git lastcommit
49c03fc679ab11534e1b4b35687b1225c365c630
Following up on the accepted answer, here are two ways to set this up:
# open the git config editor
$ git config --global --edit
# in the alias section, add
...
[alias]
lastcommit = rev-parse HEAD
...
Or if you like a shortcut to teach git a shortcut, as recently commented by Adrien:
$ git config --global alias.lastcommit "rev-parse HEAD"
From here on, use git lastcommit
to show the last commit's hash.
Answered 2023-09-20 20:27:19
The most succinct way I know:
git show --pretty=%h
If you want a specific number of digits of the hash you can add:
--abbrev=n
Answered 2023-09-20 20:27:19
git show
is what's known as a porcelain command (i.e. user-facing), and so should not be used in scripts because its output is subject to change. The answer above (git rev-parse --short HEAD
) should be used instead. - anyone git help show
for porcelain
. - anyone --porcelain
, which is why this is confusing. You can find the details in this great answer by VonC - anyone Here is one-liner in Bash shell using direct read from git files:
(head=($(<.git/HEAD)); cat .git/${head[1]})
You need to run above command in your git root folder.
This method can be useful when you've repository files, but git
command has been not installed.
If won't work, check in .git/refs/heads
folder what kind of heads do you have present.
Answered 2023-09-20 20:27:19
git show-ref --head --hash head
If you're going for speed though, the approach mentioned by Deestan
cat .git/refs/heads/<branch-name>
is significantly faster than any other method listed here so far.
Answered 2023-09-20 20:27:19
show-ref
seems to me to be the best option for scripting, since it's a plumbing command and thus guaranteed (or at least very likely) to remain stable in future releases: other answers use rev-parse
, show
, describe
, or log
, which are all porcelain commands. And in cases where speed is not of the essence, the note from the show-ref
manpage applies: ‘Use of this utility is encouraged in favor of directly accessing files under the .git directory.’ - anyone in your home-dir in file ".gitconfig" add the following
[alias]
sha = rev-parse HEAD
then you will have an easier command to remember:
$ git sha
59fbfdbadb43ad0b6154c982c997041e9e53b600
Answered 2023-09-20 20:27:19
On git bash, simply run $ git log -1
you will see, these lines following your command.
commit d25c95d88a5e8b7e15ba6c925a1631a5357095db .. (info about your head)
d25c95d88a5e8b7e15ba6c925a1631a5357095db, is your SHA for last commit.
Answered 2023-09-20 20:27:19
Pretty print of main git repo, and sub-modules:
echo "Main GIT repo:"
echo $(git show -s --format=%H) '(main)'
echo "Sub-modules:"
git submodule status | awk '{print $1,$2}'
Example output:
3a032b0992d7786b00a8822bbcbf192326160cf9 (main)
7de695d58f427c0887b094271ba1ae77a439084f sub-module-1
58f427c0887b01ba1ae77a439084947de695d27f sub-module-2
d58f427c0887de6957b09439084f4271ba1ae77a sub-module-3
Answered 2023-09-20 20:27:19
How I would do it in python (based on @kenorb's bash answer)
def get_git_sha():
# Which branch are we on?
branch = open(".git/HEAD", "r").read()
# Parse output "ref: refs/heads/my_branch" -> my_branch
branch = branch.strip().split("/")[-1]
# What's the latest commit in this branch?
return open(f".git/refs/heads/{branch}").read().strip()
Answered 2023-09-20 20:27:19
git status
is "clean" or "dirty"I want to see 72361c8
or 72361c8-dirty
for use in my build system version numbers injected into my program executables. Here is how:
# get a short commit hash, and see whether `git status` is clean or dirty
test -z "$(git status --porcelain)" \
&& echo "$(git rev-parse --short HEAD)" \
|| echo "$(git rev-parse --short HEAD)-dirty"
Sample output when git status
is clean (there are no uncommitted changes):
72361c8
Sample output when git status
is dirty (there are any uncommitted changes):
git add
ed) changes to tracked files, or the addition of new files72361c8-dirty
Just like git status
will show when a submodule is "clean" or "dirty" when using Git Submodules, I really want to see my short commit hash with the word -dirty
after it if git status
is dirty! I'm using this inside my build system as a version number in my software, so I can easily see exactly which software version I'm running at any moment!
So, I combined this answer (git rev-parse --short HEAD
) by @Jakub Narębski, and this answer: (test -n "$(git status --porcelain)"
) by @benzado on their answer to "Checking for a dirty index or untracked files with Git", I was able to come up with my "1-line" solution above.
The &&
part only runs if the return code to the previous command (git status --porcelain
) is 0
, meaning "success" (clean in this case), and the ||
part only runs if the return code of the previous command (git status --porcelain
) is any other error code, meaning "error" (dirty in this case).
See my bash/git_get_short_hash.sh file in my eRCaGuy_hello_world repo.
Wrap it in a git_get_short_hash
Bash function:
# Get a short commit hash, and see whether `git status` is clean or dirty.
# Example outputs:
# 1. Not in a git repo: `(not a git repo)`
# 2. In a repo which has a "dirty" `git status`: `72361c8-dirty`
# - Note that "dirty" means there are pending uncommitted changes.
# 3. In a repo which has a "clean" `git status`: `72361c8`
git_get_short_hash() {
# See: https://stackoverflow.com/a/16925062/4561887
is_git_repo="$(git rev-parse --is-inside-work-tree 2>/dev/null)"
if [ "$is_git_repo" != "true" ]; then
echo "(not a git repo)"
return $RETURN_CODE_SUCCESS
fi
# See my answer here: https://stackoverflow.com/a/76856090/4561887
test -z "$(git status --porcelain)" \
&& echo "$(git rev-parse --short HEAD)" \
|| echo "$(git rev-parse --short HEAD)-dirty"
}
Even better, here's a whole program that you can run or source:
#!/usr/bin/env bash
# This file is part of eRCaGuy_hello_world: https://github.com/ElectricRCAircraftGuy/eRCaGuy_hello_world
RETURN_CODE_SUCCESS=0
RETURN_CODE_ERROR=1
# Get a short commit hash, and see whether `git status` is clean or dirty.
# Example outputs:
# 1. Not in a git repo: `(not a git repo)`
# 2. In a repo which has a "dirty" `git status`: `72361c8-dirty`
# - Note that "dirty" means there are pending uncommitted changes.
# 3. In a repo which has a "clean" `git status`: `72361c8`
git_get_short_hash() {
# See: https://stackoverflow.com/a/16925062/4561887
is_git_repo="$(git rev-parse --is-inside-work-tree 2>/dev/null)"
if [ "$is_git_repo" != "true" ]; then
echo "(not a git repo)"
return $RETURN_CODE_SUCCESS
fi
# See my answer here: https://stackoverflow.com/a/76856090/4561887
test -z "$(git status --porcelain)" \
&& echo "$(git rev-parse --short HEAD)" \
|| echo "$(git rev-parse --short HEAD)-dirty"
}
main() {
git_get_short_hash
}
# Determine if the script is being sourced or executed (run).
# See:
# 1. "eRCaGuy_hello_world/bash/if__name__==__main___check_if_sourced_or_executed_best.sh"
# 1. My answer: https://stackoverflow.com/a/70662116/4561887
if [ "${BASH_SOURCE[0]}" = "$0" ]; then
# This script is being run.
__name__="__main__"
else
# This script is being sourced.
__name__="__source__"
fi
# Only run `main` if this script is being **run**, NOT sourced (imported).
# - See my answer: https://stackoverflow.com/a/70662116/4561887
if [ "$__name__" = "__main__" ]; then
main "$@"
fi
Sample run command and output when running it:
eRCaGuy_hello_world$ bash/git_get_short_hash.sh
fddb4ef-dirty
Sample run and output by sourcing it (see my answer here if you don't know what that means) and then running main
or git_get_short_hash
directly:
eRCaGuy_hello_world$ . bash/git_get_short_hash.sh
eRCaGuy_hello_world$ main
fddb4ef-dirty
eRCaGuy_hello_world$ git_get_short_hash
fddb4ef-dirty
For a Python version of the above program, see my file here: python/git_get_short_hash.py in my eRCaGuy_hello_world repo.
Example usage:
git_get_short_hash.py
script into another git project of yours.mylogfile
exists):import git_get_short_hash
import textwrap
# Alias the function to a shorter name
git_get_short_hash = git_get_short_hash.git_get_short_hash3
git_short_hash = git_get_short_hash()
program_info_str = textwrap.dedent(f"""\
My other program details here...
Program version: {git_short_hash}
""")
print(program_info_str)
mylogfile.write(program_info_str)
Answered 2023-09-20 20:27:19
git status --porcelain
I described here. Upvoted. - anyone Here is another direct-access implementation:
head="$(cat ".git/HEAD")"
while [ "$head" != "${head#ref: }" ]; do
head="$(cat ".git/${head#ref: }")"
done
This also works over http which is useful for local package archives (I know: for public web sites it's not recommended to make the .git directory accessable):
head="$(curl -s "$baseurl/.git/HEAD")"
while [ "$head" != "${head#ref: }" ]; do
head="$(curl -s "$baseurl/.git/${head#ref: }")"
done
Answered 2023-09-20 20:27:19
Here is another way of doing it with :)
git log | grep -o '\w\{8,\}' | head -n 1
Answered 2023-09-20 20:27:19
I wanted the newest commit on the origin/main
branch so I use
git ls-remote origin | grep main$ | cut -f 1
Answered 2023-09-20 20:27:19