ChatGPT解决这个技术问题 Extra ChatGPT

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

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

我已经编写了一个工具(使用来自 Git 的钩子),我可以在其中将工作项标识符注入到 Git 变更集的消息中。

我还想将 Git 提交的哈希存储在自定义 TFS 工作项字段中。通过这种方式,我可以检查 TFS 中的工作项并查看哪些 Git 变更集与该工作项相关联。

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

使用 git log 检索最近的提交,这将显示完整的提交哈希

m
maxcountryman

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

git rev-parse HEAD

或者

git rev-parse --verify HEAD

您也可以像这样检索简短版本

git rev-parse --short HEAD

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


--verify 意味着:The parameter given must be usable as a single, valid object name. Otherwise barf and abort.
git rev-parse --short HEAD 返回哈希的简短版本,以防万一有人想知道。
除了 Thane 所说,您还可以将特定长度添加到 --short,例如 --short=12,以从哈希中获取特定数量的数字。
@TysonPhalp:--short=N 大约是 最小 位数;如果缩短的数字与缩短的其他提交无法区分,则 git 使用更多的数字。尝试例如 git rev-parse --short=2 HEADgit log --oneline --abbrev=2
除了 Thane、Tyson 和 Jakub 所说的之外,您可以打印完整的哈希,但突出显示用 git rev-parse HEAD | GREP_COLORS='ms=34;1' grep $(git rev-parse --short=0 HEAD) 标识提交蓝色所需的十六进制
G
Gabriel Staples

如果您只想要缩短的提交哈希:

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

此外,使用 %H 是获取长提交哈希的另一种方法,只需使用 -1 代替 -n 1


或者,似乎在上面的 rev-parse 命令中添加 --short 似乎有效。
我认为 git log 是瓷器,而 git rev-parse 是管道。
这是一种不好/不正确的做法,因为如果你有一个分离的头,这种方法会给你错误的哈希值。例如,如果当前提交是 12ab34... 而之前的提交是 33aa44... 那么如果我执行 'git checkout 33aa44' 然后运行您的命令,我仍然会返回 12ab34... 尽管我的头实际上指向到 33aa44...
@theQuestionMan 我没有遇到您描述的行为; git checkout 33aa44; git log -n 1 给了我33aa44。你用的是什么版本的git?
@AmedeeVanGasse,啊!我不知道这是一个厕所的比喻!多年来,我一直在 git man 页中看到 porcelain,但不知道它指的是厕所!瓷器是马桶,它比水管“更接近使用者”(形象地坐在这个马桶上),而水管是较低级别的,距离使用者更远——即:在“瓷器”之下!脑洞大开。
P
Paul Pladijs

另一个,使用 git log:

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

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


结果不是单引号。
这是正确的答案,因为即使您签出特定提交而不是 HEAD,它也可以工作。
@Parsa:签出特定提交时,HEAD 指向此提交,而不是称为 detached head 的命名分支。
从命令行,避免寻呼机:git --no-pager log -1 --format="%H"
@Parsa您的(错误地赞成?)评论具有误导性,因为 jakub-narębski 'git rev-parse HEAD' 的公认答案在检查其他地方后有效。
A
Alexander

要获得完整的 SHA:

$ git rev-parse HEAD
cbf1b9a1be984a9f61b79a05f23b19f66d533537

要获得缩短版本:

$ git rev-parse --short HEAD
cbf1b9a

如果需要两个 git commit 哈希,例如一个来自您当前使用的 branch 和一个 master branch,如果您需要 master 的哈希,您也可以使用 git rev-parse FETCH_HEAD } commitmerge加入当前的 branch。例如,如果您有给定 repo 的 branches masterfeature/new-feature。而在 feature/new-feature 上,如果您需要 master 中的 commit 哈希,您可以使用 git fetch origin master && git merge FETCH_HEAD 然后 git rev-parse --short FETCH_HEAD您只需merge输入您可能拥有的任何脚本。
n
np8

提交哈希

git show -s --format=%H

缩写提交哈希

git show -s --format=%h

-s 标志与 --no-patch 相同,代表“抑制差异输出”。

点击 here 查看更多 git show 示例。


P
Pang

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

或者,作为命令:

cat .git/refs/heads/master

更新:

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


这假设当前分支是 master,这不一定是真的。
的确。这就是为什么我明确表示这是针对 master
.git/HEAD 通常指向一个 ref,如果你有一个 SHA1,你就处于分离头模式。
与其他方法相比,这不是很健壮,特别是因为它假设有一个 .git 子目录,但不一定是这种情况。请参阅 git init 手册页中的 --separate-git-dir 标志。
+1 因为有时你不想安装 git 可执行文件(例如在你的 Dockerfile 中)
k
kayleeFrye_onDeck

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

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

Git describe 返回从提交中可到达的第一个 TAG。这如何帮助我获得 SHA?
我喜欢 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-)和哈希,即使标签恰好匹配。
如果不存在标签,则 git describe --always 将“将唯一缩写的提交对象显示为后备”
我使用 git describe --tags --first-parent --abbrev=11 --long --dirty --always--always 选项意味着即使没有标签,它也会提供结果(散列)。 --first-parent 表示它不会被合并提交弄糊涂,只会跟随当前分支上的项目。另请注意,如果当前分支有未提交的更改,--dirty 会将 -dirty 附加到结果中。
R
Robert Munteanu

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


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

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

last_commit=$(git rev-parse HEAD);

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

last_commit=$(git rev-parse --short=10 HEAD);

d
dave1010

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

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

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

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

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

不需要安装git,我喜欢。 (我的 docker build 镜像没有 git)
也很有用,因为您可以从 git repo 外部轻松运行它
我将其形式化为本地机器的脚本。然后,我想,嘿:我所做的实现足够简单,它说明了如何解决一个不相关的问题(在没有外部程序的情况下解析原始 POSIX shell 脚本中的参数),但足够复杂,可以提供一些变化并利用大多数sh 的特征。半小时后的文档评论,这里是它的要点:gist.github.com/Fordi/29b8d6d1ef1662b306bfc2bd99151b07
看着它,我做了一个更广泛的版本来检测 Git 和 SVN,并抓取 git hash/svn 修订版。这次不是一个干净的字符串,但很容易被命令行解析,并可用作版本标记:gist.github.com/Fordi/8f1828efd820181f24302b292670b14e
R
Rado

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

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

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

如果您不想附加星号,这与前面答案中的所有其他命令一样工作:
git describe --always --abbrev=0 --match "NOT A TAG"
结果:f5366ccb21588c0d7a5f7d9fa1d3f85e9f9d1ffe


谢谢,只是绊倒它,它让我免于为此而产生一个或其他的回声:)
没有 --match "NOT A TAG" 它对我有用。在 git 2.18.0 和 2.7.4 中测试。有没有需要这个论点的情况?
@Thomas 如果您在当前提交的历史记录中的任何地方都有带注释的标签,它将不起作用。 fake 标签确保 describe 命令不使用标签来描述提交,
s
sdgfsdh

git rev-parse HEAD 可以解决问题。

如果您需要在保存实际分支(如果有的话)之后将其存储以便结帐,则可能更可取:

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

B
Brian Peterson

我知道的最简洁的方法:

git show --pretty=%h 

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

--abbrev=n

虽然这在技术上可行,但 git show 是所谓的瓷命令(即面向用户),因此不应在脚本中使用 ,因为它的输出可能会发生变化。应该使用上面的答案 (git rev-parse --short HEAD)。
@jm3 这是倒退的。 “Porcelain”命令具有用于脚本的稳定输出。在 git help show 中搜索 porcelain
@JohnTyree 这是一个令人困惑的主题,但 jm3 是对的:瓷器命令不是要被解析的,而是要人类可读的。如果您需要在脚本中使用瓷器命令并且您希望有一个稳定的格式,有时(例如使用 git status、push 和 blame)一个选项可以做到这一点。不幸的是,该选项被称为 --porcelain,这就是令人困惑的原因。您可以在 this great answer by VonC 中找到详细信息
C
Community

也许您想要一个别名,这样您就不必记住所有漂亮的细节。执行以下步骤之一后,您将能够简单地键入:

$ git lastcommit
49c03fc679ab11534e1b4b35687b1225c365c630

跟进 accepted answer,这里有两种设置方法:

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 显示最后一次提交的哈希。


k
kenorb

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

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

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

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

如果不起作用,请在 .git/refs/heads 文件夹中检查您有哪些类型的头像。


C
Community
git show-ref --head --hash head

如果您追求速度,the approach mentioned by Deestan

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

比迄今为止此处列出的任何其他方法都要快得多。


show-ref 在我看来是编写脚本的最佳选择,因为它是一个管道命令,因此保证(或至少很可能)在未来版本中保持稳定:其他答案使用 rev-parseshowdescribelog,它们都是瓷器命令。如果速度不是的本质,则适用于 show-ref 手册页中的注释:“鼓励使用此实用程序,以支持直接访问 .git 目录下的文件。”
j
jo_

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

[alias]
sha = rev-parse HEAD

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

$ git sha
59fbfdbadb43ad0b6154c982c997041e9e53b600

B
Batty

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

您将看到,这些行遵循您的命令。

commit d25c95d88a5e8b7e15ba6c925a1631a5357095db .. (info about your head)

d25c95d88a5e8b7e15ba6c925a1631a5357095db, is your SHA for last commit.

l
leenremm

主 git repo 和子模块的漂亮打印:

echo "Main GIT repo:"
echo $(git show -s --format=%H) '(main)'
echo "Sub-modules:"
git submodule status | awk '{print $1,$2}'

示例输出:

3a032b0992d7786b00a8822bbcbf192326160cf9 (main)
7de695d58f427c0887b094271ba1ae77a439084f sub-module-1
58f427c0887b01ba1ae77a439084947de695d27f sub-module-2
d58f427c0887de6957b09439084f4271ba1ae77a sub-module-3

i
ignorant

我将如何在 python 中做到这一点(基于@kenorb 的 bash 答案)

def get_git_sha():
    # Which branch are we on?
    branch = open(".git/HEAD", "r").read()

    # Parse output "ref: refs/heads/my_branch" -> my_branch
    branch = branch.strip().split("/")[-1]

    # What's the latest commit in this branch?
    return open(f".git/refs/heads/{branch}").read().strip()

D
Daniel Alder

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

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

M
Marcelo Lazaroni

这是另一种方法:)

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

U
Usman Ali Maan

echo "打印当前分支的最后一次提交 id#:";

 git reflog

https://i.stack.imgur.com/B1t2F.jpg