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

Sar*_*kar 1788 git tfs changeset tfs-workitem

我想保留(现在)能够将Git变更集链接到存储在TFS中的工作项.

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

但是,我还想将Git提交的标识符(哈希)存储到自定义TFS工作项字段中.通过这种方式,我可以检查TFS中的工作项,并查看与工作项相关联的Git更改集.

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

Jak*_*ski 2621

要打开任意扩展对象引用到SHA-1中,使用简单的git-REV-解析,例如

git rev-parse HEAD
Run Code Online (Sandbox Code Playgroud)

要么

git rev-parse --verify HEAD
Run Code Online (Sandbox Code Playgroud)

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

  • `git rev-parse --short HEAD`返回哈希的简短版本,以防有人想知道. (608认同)
  • `--verify`意味着:`给定的参数必须可用作单个有效的对象名.否则barf和abort (74认同)
  • 除了Thane所说的,您还可以为`--short`添加特定长度,例如`--short = 12`,以从散列中获取特定数量的数字. (50认同)
  • 除了Thane,Tyson和Jakub所说的,你可以打印完整的哈希,但突出显示使用`git rev-parse HEAD |识别提交蓝色所需的六角形.GREP_COLORS ='ms = 34; 1'grep $(git rev-parse --short = 0 HEAD) (33认同)
  • @TysonPhalp:`--short = N`约为**最小**位数; 如果缩短的数字将与缩短的其他提交无法区分,则git使用更多的数字.试试例如`git rev-parse --short = 2 HEAD`或`git log --oneline --abbrev = 2`. (29认同)
  • @Zaz这对我来说也不起作用,但只是`git rev-parse HEAD | grep --color $(git rev-parse --short = 0 HEAD)`的确如此. (7认同)
  • 除了@ThaneBrimhall所说的,你可以使用`git rev-parse ca003ae`从短版本的哈希中获得完整的SHA-1引用. (4认同)
  • 凉爽的!我什至将它添加到别名:`git config --global alias.sha 'rev-parse HEAD'`。现在我可以简单地使用`git sha`。 (2认同)
  • 这是答案并不总是正确的!如果 HEAD 不在您的结帐提交(分离头)中,您返回的内容是不正确的。只有`git status` 会给你正确的提交哈希。 (2认同)
  • 我发现这不适用于无注释的标签。如果你有一个指向 head 的未注释标签,`git rev-parse --short HEAD`_应该_给你与`git show-ref -s7 <tag>`相同的结果,但事实并非如此,我有两个不同的哈希值这样做时。这是因为轻量级标签只会显示它们的引用哈希值,而不是它们指向的提交的哈希值。你需要为此执行 `git rev-parse --short '<tag>^{}'` 。 (2认同)

out*_*ure 404

如果您只想要缩短哈希:

git log --pretty=format:'%h' -n 1
Run Code Online (Sandbox Code Playgroud)

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

  • 或者,似乎在上面的rev-parse命令中添加--short似乎可行. (101认同)
  • 我认为`git log`是瓷器,`git rev-parse`是管道. (12认同)
  • 这是一种不好/不正确的方法,因为如果你有一个分离的头,这个方法会给你错误的哈希.例如,如果当前提交是12ab34 ...并且之前的提交是33aa44 ...那么如果我做'git checkout 33aa44'然后我运行你的命令我仍然会回到12ab34 ...尽管我的头实际指向到33aa44 ...... (4认同)
  • @AmedeeVanGasse,啊!我不知道这是厕所的比喻!多年来我一直在“git”“man”页面中看到“porcelain”,但不知道它指的是厕所!瓷器就是马桶,它比管道“更靠近用户”(象征性地坐在这个马桶上),而管道位于较低位置,离用户更远——即:在“瓷器”下方!心碎了。 (4认同)
  • @theQuestionMan我没有遇到您描述的行为;`git checkout 33aa44; git log -n 1`给我`33aa44`。您正在使用什么版本的git? (2认同)
  • @PatrickL,我想说“git status”是塑料马桶座圈。它比瓷器更贴近使用者,这里的“瓷器”指的是马桶座圈下面的瓷碗。因此,“git status”和“git log”是可塑的。`git log --pretty=format` 是瓷器,`git status --porcelain` 也是瓷器,而 `git rev-parse` 是管道。 (2认同)

Pau*_*ijs 143

另一个,使用git日志:

git log -1 --format="%H"
Run Code Online (Sandbox Code Playgroud)

它与@outofculture非常相似,虽然有点短.

  • 这是正确的答案,因为即使您签出特定的提交而不是`HEAD`,它也可以工作。 (3认同)
  • @Parsa:当检查特定提交时,“HEAD”指向此提交,而不是称为[分离头](https://git-scm.com/docs/git-checkout#_detached_head)的命名分支。 (3认同)
  • 从命令行,避免寻呼机: `git --no-pager log -1 --format="%H"` (2认同)

Ale*_*der 105

要获得完整的SHA:

$ git rev-parse HEAD
cbf1b9a1be984a9f61b79a05f23b19f66d533537
Run Code Online (Sandbox Code Playgroud)

要获得缩短版本:

$ git rev-parse --short HEAD
cbf1b9a
Run Code Online (Sandbox Code Playgroud)


Dee*_*tan 67

为了完整起见,因为还没有人建议它. .git/refs/heads/master是一个只包含一行的文件:最新提交的哈希值master.所以你可以从那里读它.

或者,如命令:

cat .git/refs/heads/master
Run Code Online (Sandbox Code Playgroud)

更新:

请注意,git现在支持在pack-ref文件中存储一些头部引用,而不是在/ refs/heads /文件夹中存储文件. https://www.kernel.org/pub/software/scm/git/docs/git-pack-refs.html

  • `.git/HEAD`通常指向一个ref,如果你有一个SHA1,你处于分离头模式. (19认同)
  • +1因为有时你不想安装git可执行文件(例如在你的Dockerfile中) (15认同)
  • 确实.这就是为什么我明确地说这是为了'master`. (12认同)
  • 假设当前分支是"master",这不一定是真的. (8认同)
  • 与其他方法相比,这并不是非常强大,特别是因为它假定存在一个`.git`子目录,但不一定是这种情况.请参阅`git init`手册页中的`--separate-git-dir`标志. (6认同)
  • 用于查找分支`.git/refs/heads/<branch-name>`的SHA哈希 (3认同)
  • +1 - 并且- 如果您不想一定要拉/变基/合并并且只想获取哈希后提取`cat .git/refs/remotes/origin/master` (2认同)

Joh*_*ree 50

git describe有一点也好.默认情况下它会给你 -

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

  • 我喜欢`git describe --long --dirty --abbrev = 10 --tags`它会给我一些类似`7.2.0.Final-447-g65bf4ef2d4`的东西,它是在7.2.0.Final标签之后的447次提交当前HEAD的全球SHA-1的前10个摘要是"65bf4ef2d4".这对版本字符串非常有用.使用--long它将始终添加计数(-0-)和散列,即使标签恰好匹配. (40认同)
  • Git describe返回从提交可到达的第一个TAG.这有助于我获得SHA? (15认同)
  • 如果没有标签,则`git describe --always`将"显示唯一缩写的提交对象作为后备" (14认同)
  • 我使用“gitdescribe--tags--first-parent--abbrev=11--long--dirty--always”。“--always”选项意味着即使没有标签它也会提供结果(散列)。`--first-parent` 意味着它不会被合并提交混淆,并且只跟踪当前分支上的项目。另请注意,如果当前分支有未提交的更改,则“--dirty”会将“-dirty”附加到结果中。 (3认同)

ecw*_*z91 46

提交哈希

git show -s --format=%H
Run Code Online (Sandbox Code Playgroud)

缩写提交哈希

git show -s --format=%h
Run Code Online (Sandbox Code Playgroud)

点击此处查看更多git show示例.


Rob*_*anu 28

使用 git rev-list --max-count=1 HEAD

  • git-rev-list是关于生成提交对象的列表; 将对象名称(例如HEAD)转换为SHA-1是git-rev-parse (3认同)

小智 20

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

last_commit=$(git rev-parse HEAD)
Run Code Online (Sandbox Code Playgroud)

或者,如果你只想要前10个字符(比如github.com)

last_commit=$(git rev-parse HEAD | cut -c1-10) 
Run Code Online (Sandbox Code Playgroud)

  • `git rev-parse`还有`--short`或`--short = number`参数; 不需要使用管道和"切割". (26认同)

Ser*_*gei 20

git rev-parse HEAD就可以了。

如果您需要将其存储到稍后结账,而不是保存实际分支(如果有)可能更可取:

cat .git/HEAD
Run Code Online (Sandbox Code Playgroud)

输出示例:

ref: refs/heads/master
Run Code Online (Sandbox Code Playgroud)

解析它:

ref: refs/heads/master
Run Code Online (Sandbox Code Playgroud)

如果您使用的是 Windows,那么您可以考虑使用 wsl.exe:

wsl cat .git/HEAD | wsl sed "s/^.\+ \(.\+\)$/\1/g"
Run Code Online (Sandbox Code Playgroud)

输出:

refs/heads/master
Run Code Online (Sandbox Code Playgroud)

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

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

输出:

master
Run Code Online (Sandbox Code Playgroud)


Bri*_*son 14

我所知道的最简洁的方式:

git show --pretty=%h 
Run Code Online (Sandbox Code Playgroud)

如果您想要添加散列的特定位数,可以添加:

--abbrev=n
Run Code Online (Sandbox Code Playgroud)

  • 虽然这在技术上有效,但是`git show`就是所谓的瓷器命令(即面向用户),因此*不应该在脚本中使用,因为它的输出可能会发生变化.应该使用上面的答案(`git rev-parse --short HEAD`). (14认同)
  • @ jm3那是倒退的."Porcelain"命令具有稳定的输出,用于脚本.搜索`git help show`为`瓷`. (4认同)
  • @JohnTyree这是一个令人困惑的主题,但是jm3是正确的:瓷器命令不是要被解析的,而是要易于理解的。如果您需要在脚本中使用瓷器命令并且希望使用稳定的格式,有时(例如使用git status,push和blame)有一个选项可以做到这一点。不幸的是,该选项称为“-瓷器”,这就是为什么这样令人困惑的原因。您可以在[VonC的这个很好的答案](/sf/answers/488488171/)中找到详细信息。 (2认同)

mir*_*ixx 13

也许你想要一个别名,所以你不必记住所有漂亮的细节.完成以下步骤之一后,您只需键入:

$ git lastcommit
49c03fc679ab11534e1b4b35687b1225c365c630
Run Code Online (Sandbox Code Playgroud)

按照接受的答案,以下是两种设置方法:

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

 # open the git config editor
 $ git config --global --edit
 # in the alias section, add
 ...
 [alias]
   lastcommit = rev-parse HEAD
 ...
Run Code Online (Sandbox Code Playgroud)

2)或者如果你喜欢快捷方式来教git快捷方式,最近由Adrien评论:

$ git config --global alias.lastcommit "rev-parse HEAD"
Run Code Online (Sandbox Code Playgroud)

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

  • [Adrien de Sentenac](http://stackoverflow.com/users/5573195)指出,不是手动编辑git配置文件,你可以简单地做:`git config --global alias.lastcommit"rev-parse HEAD"` (3认同)

For*_*rdi 12

如果你想要超级hacky方式来做到这一点:

cat .git/`cat .git/HEAD | cut -d \  -f 2`
Run Code Online (Sandbox Code Playgroud)

基本上,git将HEAD的位置存储在表单中的.git/HEAD中ref: {path from .git}.该命令将其读出,切掉"ref:",并读出它指向的任何文件.

当然,这在分离头模式下会失败,因为HEAD不会是"ref:...",而是哈希本身 - 但是你知道,我认为你不希望你的bash中有那么多聪明人-liners.如果你不认为分号是作弊,但......

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

  • 不需要安装git,我喜欢它。(我的 docker 构建镜像没有 git) (2认同)
  • 我将其形式化为本地计算机的脚本。然后,我想,嘿:我所做的实现足够简单,它说明了如何解决一个不相关的问题(在没有外部程序的情况下解析原始 POSIX shell 脚本中的参数),但也足够复杂,可以提供一点变化并利用大部分`sh` 的特征。半小时后的文档评论,这是其要点:https://gist.github.com/Fordi/29b8d6d1ef1662b306bfc2bd99151b07 (2认同)

Rad*_*ado 9

我需要更多不同的东西:显示提交的完整sha1,但如果工作目录不干净,则在末尾添加星号.除非我想使用多个命令,否则之前答案中的所有选项都不起作用.

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

说明:描述(使用带注释的标签)当前提交,但仅包含包含"NOT A TAG"的标签.由于标签不能包含空格,因此它永远不会匹配标签,因为我们要显示结果--always,所以命令会回退显示--abbrev=0提交的full()sha1,如果工作目录是,它会附加一个星号--dirty.

如果您不想附加星号,则其效果与之前答案中的所有其他命令相同:
git describe --always --abbrev=0 --match "NOT A TAG"
结果:f5366ccb21588c0d7a5f7d9fa1d3f85e9f9d1ffe

  • 它在没有`--match "NOT A TAG"`的情况下对我有用。在 git 2.18.0 和 2.7.4 中测试。有什么情况需要这个论点吗? (2认同)
  • @Thomas如果您在当前提交历史记录中的任何位置有带注释的标签,它将不起作用。假标签确保描述命令不使用标签来描述提交, (2认同)

Den*_*nis 7

git show-ref --head --hash head
Run Code Online (Sandbox Code Playgroud)

如果你想要速度,那么Deestan提到的方法

cat .git/refs/heads/<branch-name>
Run Code Online (Sandbox Code Playgroud)

比目前为止列出的任何其他方法快得多.


jo_*_*jo_ 6

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

[alias]
sha = rev-parse HEAD
Run Code Online (Sandbox Code Playgroud)

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

$ git sha
59fbfdbadb43ad0b6154c982c997041e9e53b600
Run Code Online (Sandbox Code Playgroud)


ken*_*orb 6

这是Bash shell中的单行使用直接从git文件读取:

(head=($(<.git/HEAD)); cat .git/${head[1]})
Run Code Online (Sandbox Code Playgroud)

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

当您拥有存储库文件时,此方法很有用,但未git安装命令.

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


小智 5

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

你会看到,这些行遵循你的命令。

commit d25c95d88a5e8b7e15ba6c925a1631a5357095db .. (info about your head)

d25c95d88a5e8b7e15ba6c925a1631a5357095db, is your SHA for last commit.
Run Code Online (Sandbox Code Playgroud)