How to retrieve the hash for the current commit in Git?

GitGit Hash

Git Problem Overview


I would like to retain (for now) the ability to link Git changesets to workitems stored in TFS.

I already wrote a tool (using a hook from Git) in which I can inject workitem identifiers into the message of a Git changeset.

I would also like to store the hash of the Git commit in a custom TFS workitem field. This way I can examine a workitem in TFS and see what Git changesets are associated with the workitem.

How can I easily retrieve the hash from the current commit from Git?

Git Solutions


Solution 1 - Git

To turn arbitrary extended object reference into SHA-1, use simply [git-rev-parse][1], for example

git rev-parse HEAD

or

git rev-parse --verify HEAD

You can also retrieve the short version like this

git rev-parse --short HEAD

Sidenote: If you want to turn references (branches and tags) into SHA-1, there is git show-ref and git for-each-ref.

[1]: http://git-scm.com/docs/git-rev-parse "git-rev-parse - Pick out and massage parameters"

Solution 2 - Git

If you only want the shortened commit hash:

git log --pretty=format:'%h' -n 1

Furthermore, using %H is another way to get the long commit hash, and simply -1 can be used in place of -n 1.

Solution 3 - Git

Another one, using git log:

git log -1 --format="%H"

It's very similar to the of @outofculture though a bit shorter.

Solution 4 - Git

To get the full SHA:

$ git rev-parse HEAD
cbf1b9a1be984a9f61b79a05f23b19f66d533537

To get the shortened version:

$ git rev-parse --short HEAD
cbf1b9a

Solution 5 - Git

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.

Solution 6 - Git

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

Solution 7 - Git

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

Solution 8 - Git

Use git rev-list --max-count=1 HEAD

Solution 9 - Git

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);

Solution 10 - Git

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

Solution 11 - Git

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

Solution 12 - Git

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

Solution 13 - Git

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

Solution 14 - Git

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:

  1. Teach git the explicit way by editing the global config (my original answer):

    open the git config editor

    $ git config --global --edit

    in the alias section, add

    ... [alias] lastcommit = rev-parse HEAD ...

  2. 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.

Solution 15 - Git

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.

Solution 16 - Git

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.

Solution 17 - Git

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

Solution 18 - Git

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.

Solution 19 - Git

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

Solution 20 - Git

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()

Solution 21 - Git

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

Solution 22 - Git

Here is another way of doing it with :)

git log | grep -o '\w\{8,\}' | head -n 1

Solution 23 - Git

echo "printing last commit id# for current branch:";

 git reflog

Image to show actul results

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionSardaukarView Question on Stackoverflow
Solution 1 - GitJakub NarębskiView Answer on Stackoverflow
Solution 2 - GitoutofcultureView Answer on Stackoverflow
Solution 3 - GitPaul PladijsView Answer on Stackoverflow
Solution 4 - GitAlexanderView Answer on Stackoverflow
Solution 5 - Gitecwpz91View Answer on Stackoverflow
Solution 6 - GitDeestanView Answer on Stackoverflow
Solution 7 - GitJohn TyreeView Answer on Stackoverflow
Solution 8 - GitRobert MunteanuView Answer on Stackoverflow
Solution 9 - GitHenkView Answer on Stackoverflow
Solution 10 - GitFordiView Answer on Stackoverflow
Solution 11 - GitRadoView Answer on Stackoverflow
Solution 12 - GitBrian PetersonView Answer on Stackoverflow
Solution 13 - GitSergei KrivonosView Answer on Stackoverflow
Solution 14 - GitmiraculixxView Answer on Stackoverflow
Solution 15 - GitkenorbView Answer on Stackoverflow
Solution 16 - GitDennisView Answer on Stackoverflow
Solution 17 - Gitjo_View Answer on Stackoverflow
Solution 18 - GitBattyView Answer on Stackoverflow
Solution 19 - GitleenremmView Answer on Stackoverflow
Solution 20 - GitignorantView Answer on Stackoverflow
Solution 21 - GitDaniel AlderView Answer on Stackoverflow
Solution 22 - GitMarcelo LazaroniView Answer on Stackoverflow
Solution 23 - GitUsman Ali MaanView Answer on Stackoverflow