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

1,162,402

Solution 1

To turn arbitrary extended object reference into SHA-1, use simply git-rev-parse, 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.

Solution 2

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

Another one, using git log:

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

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

Solution 4

To get the full SHA:

$ git rev-parse HEAD
cbf1b9a1be984a9f61b79a05f23b19f66d533537

To get the shortened version:

$ git rev-parse --short HEAD
cbf1b9a

Solution 5

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 as 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

Share:
1,162,402
Sardaukar
Author by

Sardaukar

Thinks that software development is part science, part art (is just not sure which part is bigger).

Updated on July 29, 2022

Comments

  • Sardaukar
    Sardaukar almost 2 years

    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?

  • Anonigan
    Anonigan about 15 years
    git-rev-list is about generating list of commit objects; it is git-rev-parse to translate object name (e.g. HEAD) into SHA-1
  • Linus Unnebäck
    Linus Unnebäck almost 13 years
    --verify implies that: The parameter given must be usable as a single, valid object name. Otherwise barf and abort.
  • Sardaukar
    Sardaukar almost 13 years
    Git describe returns the first TAG reachable from a commit. How does this help me get the SHA?
  • outofculture
    outofculture over 12 years
    Or, it seems, adding --short to the rev-parse command above seems to work.
  • gavrie
    gavrie over 11 years
    This assumes the current branch is master, which is not necessarily true.
  • futurecat
    futurecat over 11 years
    Indeed. That's why I explicitly said this is for master.
  • Thane Brimhall
    Thane Brimhall over 11 years
    git rev-parse --short HEAD returns the short version of the hash, just in case anyone was wondering.
  • kynan
    kynan over 11 years
    There is .git/HEAD which is a file that contains 1 line with the SHA1 of HEAD. I think that's what you meant.
  • Prashant
    Prashant about 11 years
    I like 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.
  • Prashant
    Prashant about 11 years
    .git/HEAD typically points to a ref, if you have a SHA1 in there, you are in detached head mode.
  • Tyson Phalp
    Tyson Phalp over 10 years
    Adding to what Thane said, you can also add a specific length to --short, such as --short=12, to get a specific number of digits from the hash.
  • Anonigan
    Anonigan over 10 years
    @TysonPhalp: --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.
  • jm3
    jm3 over 10 years
    While this technically works, 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.
  • Zaz
    Zaz almost 10 years
    Adding to what Thane, Tyson, and Jakub said, you can print the full hash, but highlight the hexits necessary to identify the commit blue with git rev-parse HEAD | GREP_COLORS='ms=34;1' grep $(git rev-parse --short=0 HEAD)
  • Ronny Andersson
    Ronny Andersson almost 10 years
    If no tags exist then git describe --always will "show uniquely abbreviated commit object as fallback"
  • jub0bs
    jub0bs over 9 years
    This isn't very robust compared to other approaches, in particular because it assumes that there is a .git subdirectory, which is not necessarily the case. See the --separate-git-dir flag in the git init man page.
  • wim
    wim about 9 years
    +1 because sometimes you don't want git executable installed (e.g. in your Dockerfile)
  • pushya
    pushya about 9 years
    For finding the SHA- hash of a branch .git/refs/heads/<branch-name>
  • John Tyree
    John Tyree almost 9 years
    @jm3 that's backwards. "Porcelain" commands have stable outputs that are intended for scripts. Search git help show for porcelain.
  • XP84
    XP84 almost 9 years
    Neat trick Zaz. It doesn't seem to work with the grep on my Mac, but I substituted ack for a similar effect!
  • Theodore Murdock
    Theodore Murdock over 8 years
    @Zaz That didn't work for me either, but simply git rev-parse HEAD | grep --color $(git rev-parse --short=0 HEAD) does.
  • Amedee Van Gasse
    Amedee Van Gasse over 8 years
    I think git log is porcelain and git rev-parse is plumbing.
  • Helin Wang
    Helin Wang over 8 years
    no need to install git, I like it. (my docker build image does not have git)
  • Aaron
    Aaron about 8 years
    Is there a way to do this but on a per-directory basis? For example, lets say I want the latest hash of a particular directory. Do I need to do a git log <directory> and parse it out to grab the hash?
  • Anonigan
    Anonigan about 8 years
    @Aaron: roughly speaking yes, you need to run git log <options> -- <directory>; but you can configure git-log so it returns only hash.
  • nhed
    nhed about 8 years
    +1 -and- if you don't want to necessarily pull/rebase/merge and just want to get hash post-fetch cat .git/refs/remotes/origin/master
  • Halil
    Halil about 8 years
    Adding to what @ThaneBrimhall said, you can get the full SHA-1 reference from the short version of the hash using git rev-parse ca003ae.
  • samaspin
    samaspin about 8 years
    also useful because you can run this easily from outside the git repo
  • Fordi
    Fordi almost 8 years
    I formalized this to a script for my local machine. Then, I thought, hey: the implementation I made are simple enough that it illustrates how to solve an unrelated problem (parsing arguments in raw POSIX shell scripts without external programs), but complex enough to provide a little variation and to exploit most of the features of sh. Half an hour of documentation comments later, and here's a Gist of it: gist.github.com/Fordi/29b8d6d1ef1662b306bfc2bd99151b07
  • Fordi
    Fordi almost 8 years
    Looking at it, I made a more extensive version for detecting Git and SVN, and grabbing the git hash/svn revision. Not a clean string this time, but easily command-line parsed, and usable as a version tag: gist.github.com/Fordi/8f1828efd820181f24302b292670b14e
  • Sap
    Sap almost 8 years
    Does this way work if you have a tag named "HEAD"? >:)
  • Anonigan
    Anonigan almost 8 years
    @EdRandall: git rev-parse main goal is to parse parameters and return revisions, so --short means shortened SHA-1 of revision. git log return more information, which includes SHA-1 of revisions, that can be abbreviated with --abbrev or --abbrev-commit.
  • Ilia Sidorenko
    Ilia Sidorenko over 7 years
    One of the benefits of this method is that it will return the short version of the hash with the right length adjusted to the hash collisions which happen for larger repos. At least in recent versions of git.
  • crokusek
    crokusek over 7 years
    And the result is not single-quoted.
  • theQuestionMan
    theQuestionMan almost 7 years
    This is a bad/ incorrect way of doing it because this method will give you the wrong hash if you have a detached head. For example if the current commit is 12ab34... and the previous commit was 33aa44... then if i do 'git checkout 33aa44' and then I run your command I will still be getting back 12ab34... despite my head actually pointing to 33aa44...
  • outofculture
    outofculture almost 7 years
    @theQuestionMan I don't experience the behavior you describe; git checkout 33aa44; git log -n 1 gives me 33aa44. What version of git are you using?
  • Kirk Strobeck
    Kirk Strobeck almost 7 years
    git rev-parse HEAD | pbcopy is great for quick clipboard’ing on mac
  • milkovsky
    milkovsky over 6 years
    Cool! I have even added it to alias: git config --global alias.sha 'rev-parse HEAD'. Now I can simply use git sha.
  • hakre
    hakre over 6 years
    Thanks, just stumbling over it and it spares me the one or other echo for that :)
  • sschueller
    sschueller about 6 years
    This is answer is not always correct! If the HEAD is not at the your checkout commit (detached head) what you get back is incorrect. Only git status will give you the correct commit hash.
  • Keyur Padalia
    Keyur Padalia almost 6 years
    It works for me without the --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?
  • Peter Hlavatík
    Peter Hlavatík almost 6 years
    @Thomas it won't work if you have an annotated tag anywhere in the history of the current commit. The fake tag makes sure that the describe command does not use a tag to describe the commit,
  • Mike
    Mike almost 6 years
    If two 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 merged into your current branch. e.g. if you have branches 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 merged in for any scripts you may have.
  • Pont
    Pont over 5 years
    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.’
  • Fabio says Reinstate Monica
    Fabio says Reinstate Monica over 5 years
    @JohnTyree This is a confusing subject, but jm3 was right: porcelain commands are not meant to be parsed, but rather to be human-readable. In case you need to use a porcelain command in a script and you want to have a stable format, there's sometimes (for example with git status, push and blame) an option that does just that. Unfortunately, that option is called --porcelain, which is why this is confusing. You can find the details in this great answer by VonC
  • Tom Ozx
    Tom Ozx over 5 years
    This is the correct answer, since it works even if you checkout a specific commit instead of HEAD.
  • ChristofSenn
    ChristofSenn over 4 years
    @Parsa: when checking out a specific commit HEAD points to this commit rather than a named branche know as detached head.
  • ingyhere
    ingyhere over 4 years
    I use 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.
  • Carlo Wood
    Carlo Wood over 4 years
    This is less robust because .git may always be a file containing the name of the real .git directory.
  • sij
    sij about 4 years
    +1 because this may be faster and more straightforward as you don't have to call bash just to display the commit hash in the footer of the GUI.
  • Cheruvim
    Cheruvim almost 4 years
    I find this doesn't work with non-annotated tags. If you have a non-annotated tag pointing to head, git rev-parse --short HEAD should give you the same result as git show-ref -s7 <tag> and it doesn't I got two different hashes when doing this. This is because lightweight tags will only show their ref hash not the hash of the commit they are pointing to. You need to do git rev-parse --short '<tag>^{}' for that.
  • xjcl
    xjcl over 3 years
    When do I need --verify?
  • Anonigan
    Anonigan over 3 years
    @xjcl the --verify option is useful if you use git rev-parse together with something variable, like git rev-parse --verify $branch. For git rev-parse --verify HEAD it ensures that HEAD can be turned into SHA-1 / object identifier (and for example you are not on an unborn branch).
  • Patronics
    Patronics over 3 years
    @AmedeeVanGasse if git log is porcelain and git rev-parse is plumbing, what is git status --porcelain? :P
  • Amedee Van Gasse
    Amedee Van Gasse over 3 years
    @PatrickL I don't know, this is a question from 4 years ago and I don't feel like going back to something that's behind me. I recommend that you open a new question on Stack Overflow.
  • Gabriel Staples
    Gabriel Staples over 3 years
    @AmedeeVanGasse, ah! I HAD NO IDEA this is a toilet analogy! I've been seeing 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.
  • Gabriel Staples
    Gabriel Staples over 3 years
    @PatrickL, I'd say git status is the plastic toilet seat. It's closer to the user than the porcelain, where "porcelain" refers to the porcelain bowl under the toilet seat. So, git status and git log are plastic. git log --pretty=format is porcelain, git status --porcelain is also porcelain, and git rev-parse is plumbing.
  • cdalxndr
    cdalxndr about 3 years
  • ederag
    ederag about 3 years
    From the command line, to avoid pager: git --no-pager log -1 --format="%H"
  • squall3d
    squall3d about 3 years
    If you pass this to pbcopy on mac to copy it into the clipboard, you'll get a new line at the end. To get rid of it, use git rev-parse HEAD | tr -d '\n' | pbcopy
  • spawn
    spawn about 2 years
    @Parsa Your (mistakenly upvoted?) comment is misleading as the accepted answer of jakub-narębski 'git rev-parse HEAD' works after checking out somewhere else.
  • Tom Ozx
    Tom Ozx about 2 years
    @spawn It's not a mistake. Remember that HEAD is just a pointer. As long as HEAD points to the current commit, which is commonly the case, you are fine; but if you are in a detached state, it's now pointing to a different commit than where you are.
  • spawn
    spawn about 2 years
    @Parsa - maybe we misunderstand each other: after checkout from commit a1b1 to c1d1 git rev-parse HEAD prints c1d1. So, HEAD points to the "current commit" which the OP asked for. From your upvoted comment I mistakenly concluded that git rev-parse HEAD was wrong.
  • Johannes Deml
    Johannes Deml about 2 years
    Small caveat for git rev-parse xxx: This results in SHA + \n, so it adds a new line at the very end. So if you want to get just the SHA, be sure to trim your result