如何在Git中检索当前提交的哈希值?


1930

我想保留(暂时)将Git变更集链接到存储在TFS中的工作项的功能。

我已经编写了一个工具(使用Git的钩子),可以在其中将workitemidentifiers插入到Git变更集的消息中。

但是,我也想将Git提交(哈希)的标识符存储到自定义TFS工作项字段中。这样,我可以检查TFS中的工作项,并查看与该工作项相关联的Git变更集。

如何轻松地从Git的当前提交中检索哈希?

Answers:


2805

要将任意扩展对象引用转换为SHA-1,例如,只需使用git-rev-parse

git rev-parse HEAD

要么

git rev-parse --verify HEAD

旁注:如果要将引用分支标签)转换为SHA-1,则有git show-refgit for-each-ref


81
--verify暗示:The parameter given must be usable as a single, valid object name. Otherwise barf and abort.
LinusUnnebäck2011年

647
git rev-parse --short HEAD返回哈希的简短版本,以防万一有人想知道。
塔娜·布里姆霍尔

54
除了Thane所说的以外,您还可以为加上一个特定的长度--short,例如--short=12,以从哈希中获取特定数目的数字。
泰森·菲尔普

31
@TysonPhalp:--short=N大约最小位数;如果缩短的数字与缩短的其他提交没有区别,则git使用更大的数字。尝试例如git rev-parse --short=2 HEADgit log --oneline --abbrev=2
JakubNarębski2014年

36
添加到什么塔纳,泰森和的Jakub说,你可以打印完整的哈希值,但强调有必要在hexits以确定提交蓝色git rev-parse HEAD | GREP_COLORS='ms=34;1' grep $(git rev-parse --short=0 HEAD)
ZAZ

423

如果只想缩短哈希值:

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

此外,使用%H是获取长哈希的另一种方法。


106
或者,似乎在上面的rev-parse命令中添加--short似乎可行。
outofculture 2011年

15
我认为git log是瓷器并且git rev-parse在水暖。
Amedee Van Gasse

此方法的优点之一是,它将返回哈希的简短版本,将其正确的长度调整为适用于较大存储库的哈希冲突。至少在最新版本的git中。
伊利亚·西多连科

4
这是一种错误/错误的方法,因为如果您的头部分离,此方法将为您提供错误的哈希。例如,如果当前提交为12ab34 ...,而先前的提交为33aa44 ...,那么如果我执行'git checkout 33aa44',然后我运行您的命令,我仍然会返回12ab34 ...,尽管我的头实际上指向了到33aa44 ...
TheQuestionMan

3
@theQuestionMan我没有遇到您描述的行为;git checkout 33aa44; git log -n 1给我33aa44。您正在使用什么版本的git?

150

另一个,使用git log:

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

它与@outofculture的相似,但更短一些。


结果不是单引号。
crokusek

5
这是正确的答案,因为即使您签出特定的提交而不是,它也可以工作HEAD
帕萨

1
@Parsa:在签出特定提交时HEAD指向此提交,而不是称为分离头的命名分支。
ChristofSenn

124

要获得完整的SHA:

$ git rev-parse HEAD
cbf1b9a1be984a9f61b79a05f23b19f66d533537

要获得简化版本:

$ git rev-parse --short HEAD
cbf1b9a

如果两个git commit都需要哈希,如一个从branch你当前使用和master branch,你也可以使用git rev-parse FETCH_HEAD,如果你需要的哈希master commit,你merge剐到当前branch。例如,如果您有branchES masterfeature/new-feature对于给定的回购,同时feature/new-feature可以使用git fetch origin master && git merge FETCH_HEAD,然后git rev-parse --short FETCH_HEAD,如果你需要commit从散master你只是mergeD IN的任何脚本你可能有。
EVAL

72

为了完整起见,因为没有人建议过。 .git/refs/heads/master是一个仅包含一行的文件:最近提交的哈希值master。因此,您可以从那里阅读它。

或者,作为命令:

cat .git/refs/heads/master

更新:

注意,git现在支持将一些head refs存储在pack-ref文件中,而不是作为/ refs / heads /文件夹中的文件存储。 https://www.kernel.org/pub/software/scm/git/docs/git-pack-refs.html


10
假设当前分支为master,则不一定正确。
gavrie 2012年

12
确实。这就是为什么我明确地说这是针对的master
Deestan

20
.git/HEAD通常指向一个参考,如果那里有SHA1,则处于分离头模式。
eckes 2013年

8
与其他方法相比,这不是很健壮,特别是因为它假定存在.git子目录,但不一定如此。请参见手册页中的--separate-git-dir标志git init
jub0bs 2014年

16
+1,因为有时您不希望安装git可执行文件(例如,在Dockerfile中)
wim 2015年

50

提交哈希

git show -s --format=%H

缩写提交哈希

git show -s --format=%h

单击此处以获取更多git show示例。


50

总是git describe有。默认情况下,它为您提供-

john@eleanor:/dev/shm/mpd/ncmpc/pkg (master)$ git describe --always
release-0.19-11-g7a68a75

18
Git describe返回一次提交可到达的第一个TAG。这如何帮助我获得SHA?
Sardaukar 2011年

42
我喜欢git describe --long --dirty --abbrev=10 --tags它会给我类似的东西7.2.0.Final-447-g65bf4ef2d4,即7.2.0.Final标签和当前HEAD的全局SHA-1的前10个摘要为“ 65bf4ef2d4”。这对于版本字符串非常有用。使用--long,它将始终添加计数(-0-)和哈希值,即使标记恰好完全匹配也是如此。
eckes 2013年

14
如果不存在标签,git describe --always则将“将唯一缩写的提交对象显示为后备”
Ronny Andersson 2014年

我用git describe --tags --first-parent --abbrev=11 --long --dirty --always。该--always选项表示即使没有标签也提供结果(哈希)。这--first-parent意味着它不会被合并提交弄糊涂,而只会跟随当前分支上的项目。还请注意,如果当前分支具有未提交的更改,--dirty它将添加-dirty到结果中。
ingyhere


21

如果需要在脚本执行期间将哈希存储在变量中,则可以使用

last_commit=$(git rev-parse HEAD)

或者,如果您只想要前10个字符(就像github.com一样)

last_commit=$(git rev-parse HEAD | cut -c1-10) 

26
也有--short--short=number参数git rev-parse;无需使用管道和cut
朱利安·D。

15

如果您想采用超级hacky的方式来做到这一点:

cat .git/`cat .git/HEAD | cut -d \  -f 2`

基本上,git将HEAD的位置存储在.git / HEAD中ref: {path from .git}。此命令将其读出,切出“ ref:”,并读出其指向的任何文件。

当然,这在分离头模式下会失败,因为HEAD不会是“ ref:...”,但是哈希本身-但是,您知道,我认为您不希望bash中有那么多聪明-班轮。但是,如果您不认为分号在欺骗,那么...

HASH="ref: HEAD"; while [[ $HASH == ref\:* ]]; do HASH="$(cat ".git/$(echo $HASH | cut -d \  -f 2)")"; done; echo $HASH

1
不需要安装git,我喜欢。(我的docker构建映像没有git)
Helin Wang

也很有用,因为您可以从git repo外部轻松运行此文件
samaspin

我将其形式化为本地计算机的脚本。然后,我想,嘿:我所做的实现非常简单,足以说明如何解决不相关的问题(无需外部程序即可在原始POSIX shell脚本中解析参数),但又足够复杂以提供一些变化并利用大多数的特点sh。半小时后的文档评论,下面是要点:gist.github.com/Fordi/29b8d6d1ef1662b306bfc2bd99151b07
Fordi 2016年

看着它,我制作了一个更广泛的版本来检测Git和SVN,并获取git hash / svn修订版。这次不是一个干净的字符串,但是可以轻松地命令行解析,并且可以用作版本标记: gist.github.com/Fordi/8f1828efd820181f24302b292670b14e
Fordi 2016年

14

我知道的最简洁的方法是:

git show --pretty=%h 

如果您想要特定数量的哈希,可以添加:

--abbrev=n

14
虽然这种技术的工作原理,git show是什么被称为瓷命令(即面向用户),所以应该不会在脚本中使用,因为它的输出可能发生变化。git rev-parse --short HEAD应该改用()以上的答案。
2014年

4
@ jm3倒退了。“瓷器”命令具有用于脚本的稳定输出。搜索git help showporcelain
约翰·泰瑞

2
@JohnTyree这是一个令人困惑的主题,但是jm3是正确的:瓷器命令不是要被解析的,而是要易于理解的。如果您需要在脚本中使用瓷器命令并且希望使用稳定的格式,有时(例如使用git status,push和blame)有一个选项可以做到这一点。不幸的是,该选项被称为--porcelain,这就是为什么这样令人困惑的原因。您可以在VonC的精彩回答中
法比奥说Reinstate Monica

1
亲爱的上帝,决定将其命名为--porcelain我想找到它们,然后...哦,我需要使用git来找到它们,没关系
Britton Kerin

14

也许您想要一个别名,这样您就不必记住所有漂亮的细节。完成以下步骤之一之后,您将可以轻松键入:

$ git lastcommit
49c03fc679ab11534e1b4b35687b1225c365c630

跟踪已接受的答案,以下是两种设置方法:

1)通过编辑全局配置(我的原始答案)以显式方式教git:

 # open the git config editor
 $ git config --global --edit
 # in the alias section, add
 ...
 [alias]
   lastcommit = rev-parse HEAD
 ...

2)或者,如果您喜欢捷径教git捷径,正如Adrien最近评论的那样:

$ git config --global alias.lastcommit "rev-parse HEAD"

从这里开始,用于git lastcommit显示最后一次提交的哈希值。


3
Adrien de Sentenac指出,除了手动编辑git config文件外,您还可以执行以下操作:git config --global alias.lastcommit "rev-parse HEAD"
cgmb 2015年

12

我需要一些不同的东西:显示提交的完整sha1,但是如果工作目录不干净,则在末尾附加一个星号。除非我想使用多个命令,否则以上答案中的所有选项均无效。

这是一个做的衬板:
git describe --always --abbrev=0 --match "NOT A TAG" --dirty="*"
结果:f5366ccb21588c0d7a5f7d9fa1d3f85e9f9d1ffe*

说明:描述(使用带注释的标签)当前提交,但仅使用包含“ NOT A TAG”的标签。由于标记不能有空格,因此它永远不会与标记匹配,并且由于我们想显示结果--always,因此该命令将回退以显示--abbrev=0提交的完整()sha1,如果工作目录为,则该命令将附加一个星号--dirty

如果您不想附加星号,则该方法的作用类似于先前答案中的所有其他命令:
git describe --always --abbrev=0 --match "NOT A TAG"
结果:f5366ccb21588c0d7a5f7d9fa1d3f85e9f9d1ffe


谢谢,只是跌跌撞撞地在上面,这让我
免于

1
它对我有用而没有--match "NOT A TAG"。在git 2.18.0和2.7.4中进行了测试。在任何情况下都需要此参数吗?
托马斯

@Thomas如果您在当前提交的历史记录中的任何地方都有带注释的标签,它将无法正常工作。假标签可确保describe命令不使用标签来描述提交,
Rado

8
git show-ref --head --hash head

如果您要提高速度,那么Deestan提到的方法

cat .git/refs/heads/<branch-name>

到目前为止比这里列出的任何其他方法都快得多。


show-ref在我看来,对于脚本是最好的选择,因为它是一个管道命令,并从而保证(或至少非常可能)保持稳定在将来的版本:其他答案使用rev-parseshowdescribe,或者log,这些都是瓷器命令。而且在速度不是很重要的情况下,请参考show-ref联机帮助页上的注释:“鼓励使用此实用程序,以便直接访问.git目录下的文件。”

6

这是使用直接从git文件读取的Bash shell中的一线代码:

(head=($(<.git/HEAD)); cat .git/${head[1]})

您需要在git根文件夹中运行以上命令。

存储库文件但git尚未安装命令时,此方法很有用。

如果不起作用,请在.git/refs/heads文件夹中检查您有什么样的头。


5

在文件“ .gitconfig”的主目录中添加以下内容

[alias]
sha = rev-parse HEAD

那么您将有一个更容易记住的命令:

$ git sha
59fbfdbadb43ad0b6154c982c997041e9e53b600

3

在git bash上,只需运行$ git log -1

您会在命令后看到以下几行。

commit d25c95d88a5e8b7e15ba6c925a1631a5357095db .. (info about your head)

d25c95d88a5e8b7e15ba6c925a1631a5357095db, is your SHA for last commit.

0

这是另一个直接访问的实现:

head="$(cat ".git/HEAD")"
while [ "$head" != "${head#ref: }" ]; do
  head="$(cat ".git/${head#ref: }")"
done

这也可以通过http工作,这对本地软件包归档很有用(我知道:对于公共网站,不建议使.git目录可访问):

head="$(curl -s "$baseurl/.git/HEAD")"
while [ "$head" != "${head#ref: }" ]; do
  head="$(curl -s "$baseurl/.git/${head#ref: }")"
done


0
cat .git/HEAD

输出示例:

ref: refs/heads/master

解析它:

cat .git/HEAD | sed "s/^.\+ \(.\+\)$/\1/g"

如果您有Windows,则可以考虑使用wsl.exe:

wsl cat .git/HEAD | wsl sed "s/^.\+ \(.\+\)$/\1/g"

输出:

refs/heads/master

此值以后可以用于git checkout,但它指向其SHA。要使其名称指向实际的当前分支,请执行以下操作:

wsl cat .git/HEAD | wsl sed "s/^.\+ \(.\+\)$/\1/g" | wsl sed "s/^refs\///g" | wsl sed "s/^heads\///g"

输出:

master

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.