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 workitemidentifiers into the message of a Git changeset.

However, I would also like to store the identifier of the Git commit (the hash) into 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?

share|improve this question

16 Answers 16

up vote 1536 down vote accepted

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

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

share|improve this answer
42  
--verify implies that: The parameter given must be usable as a single, valid object name. Otherwise barf and abort. – Linus Unnebäck Jul 24 '11 at 17:50
370  
git rev-parse --short HEAD returns the short version of the hash, just in case anyone was wondering. – Thane Brimhall Oct 25 '12 at 21:28
29  
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. – Tyson Phalp Feb 21 '14 at 17:18
17  
@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. – Jakub Narębski Feb 21 '14 at 18:08
18  
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) – Zaz Aug 5 '14 at 16:44

If you only want the shortened hash:

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

Further, using %H is another way to get the long hash.

share|improve this answer
75  
Or, it seems, adding --short to the rev-parse command above seems to work. – outofculture Sep 30 '11 at 23:39
4  
I think git log is porcelain and git rev-parse is plumbing. – Amedee Van Gasse Jan 29 '16 at 10:40
    
Is there a way of getting the hash for just the last time the current directory was updated? – simgineer Mar 1 '16 at 1:05
    
Yeah; just pass the directory in question as an argument. – outofculture Mar 2 '16 at 19:41
    
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. – No Way Dec 22 '16 at 14:26

Another one, using git log:

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

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

share|improve this answer
    
And the result is not single-quoted. – crokusek Feb 28 at 23:11

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|improve this answer
7  
This assumes the current branch is master, which is not necessarily true. – gavrie Oct 23 '12 at 15:10
7  
Indeed. That's why I explicitly said this is for master. – Deestan Oct 23 '12 at 15:22
16  
.git/HEAD typically points to a ref, if you have a SHA1 in there, you are in detached head mode. – eckes Apr 9 '13 at 1:48
5  
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. – Jubobs Dec 29 '14 at 17:44
9  
+1 because sometimes you don't want git executable installed (e.g. in your Dockerfile) – wim Apr 7 '15 at 2:59

There's always git describe as well. By default it gives you --

john@eleanor:/dev/shm/mpd/ncmpc/pkg (master)$ git describe 
release-0.19-11-g7a68a75
share|improve this answer
10  
Git describe returns the first TAG reachable from a commit. How does this help me get the SHA? – Sardaukar Sep 9 '11 at 13:45
29  
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. – eckes Apr 9 '13 at 1:46
7  
If no tags exist then git describe --always will "show uniquely abbreviated commit object as fallback" – Ronny Andersson Sep 18 '14 at 16:57

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

share|improve this answer
3  
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 – Jakub Narębski Jun 4 '09 at 14:13

To get the full SHA:

$ git rev-parse HEAD
cbf1b9a1be984a9f61b79a05f23b19f66d533537

To get the shortened version:

$ git rev-parse --short HEAD
cbf1b9a
share|improve this answer
1  
Why would you resubmit an answer that was given, upvoted almost 1500 times and accepted 7 years before yours? If you just want to extend the answer by adding a (perhaps useful, but not requested) addition, just add a comment to the accepted answer. – P.R. Mar 8 at 14:46

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 HEAD | cut -c1-10) 
share|improve this answer
20  
There are also the --short or --short=number parameters to git rev-parse; no need to use a pipe and cut. – Julian D. Sep 13 '12 at 18:20

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
share|improve this answer
12  
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. – jm3 Mar 15 '14 at 23:45
2  
Upvote so that the answer's vote is not negative since it's correct but not applicable. – xryl669 Aug 25 '14 at 10:18
2  
@jm3 that's backwards. "Porcelain" commands have stable outputs that are intended for scripts. Search git help show for porcelain. – John Tyree Jul 6 '15 at 21:32
    
@JohnTyree doh, you're right, my mistake. – jm3 Aug 15 '15 at 21:51

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
share|improve this answer
    
no need to install git, I like it. (my docker build image does not have git) – Helin Wang Feb 15 '16 at 20:18
    
also useful because you can run this easily from outside the git repo – samaspin Jun 22 '16 at 16:30
    
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 Jun 29 '16 at 14:41
    
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 – Fordi Jun 29 '16 at 15:21

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.

share|improve this answer
1  
downvote as you like but please add a comment so I can improve the answer. thanks. – miraculixx Nov 1 '15 at 18:15
2  
Adrien de Sentenac notes that instead of manually editing the git config file, you could simply do: git config --global alias.lastcommit "rev-parse HEAD" – cgmb Nov 17 '15 at 18:35
    
@Adrien thanks, updated accordingly. – miraculixx Nov 17 '15 at 21:02
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.

share|improve this answer

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
share|improve this answer

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
share|improve this answer

Here is another way of doing it with :)

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

Commit hash

git show -s --format=%H

Abbreviated commit hash

git show -s --format=%h

Click here for more git show examples.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.