问题
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?
回答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
Sidenote: If you want to turn references (branches and tags) into SHA-1, there is git show-ref
and git for-each-ref
.
回答2:
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.
回答3:
Another one, using git log:
git log -1 --format="%H"
It's very similar to the of @outofculture though a bit shorter.
回答4:
To get the full SHA:
$ git rev-parse HEAD
cbf1b9a1be984a9f61b79a05f23b19f66d533537
To get the shortened version:
$ git rev-parse --short HEAD
cbf1b9a
回答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
回答6:
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
回答7:
Commit hash
git show -s --format=%H
Abbreviated commit hash
git show -s --format=%h
Click here for more git show
examples.
回答8:
Use git rev-list --max-count=1 HEAD
回答9:
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)
回答10:
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
回答11:
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.
回答12:
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
回答13:
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
回答14:
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.
回答15:
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.
回答16:
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
回答17:
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
回答18:
Here is another way of doing it with :)
git log | grep -o '\w\{8,\}' | head -n 1
回答19:
cat .git/HEAD
Note: its output has '.' symbol at its end.
来源:https://stackoverflow.com/questions/949314/how-to-retrieve-the-hash-for-the-current-commit-in-git