【问题标题】:How to retrieve the hash for the current commit in Git?如何在 Git 中检索当前提交的哈希值?
【发布时间】:2010-10-31 06:18:29
【问题描述】:

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

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

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

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

【问题讨论】:

    标签: git git-hash


    【解决方案1】:

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

    【讨论】:

    • git-rev-list 是关于生成提交对象列表的;将对象名称(例如 HEAD)转换为 SHA-1 是 git-rev-parse
    【解决方案2】:

    要将任意扩展对象引用转换为 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,从hash中得到一个特定的位数。
    • @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) 突出显示蓝色提交所必需的十六进制数
    【解决方案3】:

    也总是有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 标记和当前 HEAD 处全局 SHA-1 的前 10 个摘要之后的 447 次提交“65bf4ef2d4”。这对于版本字符串非常有用。使用 --long 它总是会添加计数 (-0-) 和哈希,即使标签恰好匹配。
    • 如果不存在标签,则git describe --always 将“将唯一缩写的提交对象显示为备用”
    • 我使用git describe --tags --first-parent --abbrev=11 --long --dirty --always--always 选项意味着即使没有标签,它也会提供结果(哈希)。 --first-parent 意味着它不会被合并提交弄糊涂,并且只关注当前分支上的项目。另请注意,如果当前分支有未提交的更改,--dirty 会将-dirty 附加到结果中。
    【解决方案4】:

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

    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,但不知道它指的是厕所!瓷器就是马桶,它比水管“更接近使用者”(形象地坐在这个马桶上),而水管更下层,离使用者更远——即:在“瓷器”之下!大吃一惊。
    【解决方案5】:

    另一个,使用 git log:

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

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

    【讨论】:

    • 而且结果不是单引号。
    • 这是正确的答案,因为即使您签出特定的提交而不是 HEAD,它仍然有效。
    • @Parsa:签出特定提交时,HEAD 指向此提交,而不是称为 detached head 的命名分支。
    • 从命令行,避免寻呼机:git --no-pager log -1 --format="%H"
    【解决方案6】:

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

    last_commit=$(git rev-parse HEAD);
    

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

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

    【讨论】:

      【解决方案7】:

      为了完整起见,因为还没有人提出建议。 .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 中)
      【解决方案8】:

      我知道的最简洁的方式:

      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中找到详细信息
      【解决方案9】:
      git show-ref --head --hash head
      

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

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

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

      【讨论】:

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

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

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

      【讨论】:

        【解决方案11】:

        如果你想要超级 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
        

        【讨论】:

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

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

        [alias]
        sha = rev-parse HEAD
        

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

        $ git sha
        59fbfdbadb43ad0b6154c982c997041e9e53b600
        

        【讨论】:

          【解决方案13】:

          要获得完整的 SHA:

          $ git rev-parse HEAD
          cbf1b9a1be984a9f61b79a05f23b19f66d533537
          

          要获得缩短版:

          $ git rev-parse --short HEAD
          cbf1b9a
          

          【讨论】:

          • 如果需要两个 git commit 哈希,例如一个来自您当前正在使用的 branch 和一个 master branch,您也可以使用 git rev-parse FETCH_HEAD 如果您需要将 merged 的 master commit 的哈希值转换为当前的 branch。例如如果你有 branches masterfeature/new-feature 对于给定的回购。而在 feature/new-feature 你可以使用 git fetch origin master &amp;&amp; git merge FETCH_HEAD 然后 git rev-parse --short FETCH_HEAD 如果你需要来自 mastercommit 哈希你只需 merged 输入您可能拥有的任何脚本。
          【解决方案14】:

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

          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
          

          【讨论】:

            【解决方案15】:

            这是另一种方法:)

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

            【讨论】:

              【解决方案16】:

              提交哈希

              git show -s --format=%H
              

              缩写提交哈希

              git show -s --format=%h
              

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

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

              【讨论】:

                【解决方案17】:

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

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

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

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

                如果不行,在.git/refs/heads文件夹中检查你有什么样的头像。

                【讨论】:

                  【解决方案18】:

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

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

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

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

                  【讨论】:

                  • 谢谢,只是被它绊了一跤,它让我免去一个或其他的回声:)
                  • 没有--match "NOT A TAG" 对我有用。在 git 2.18.0 和 2.7.4 中测试。有什么情况需要这个参数?
                  • @Thomas 如果您在当前提交的历史记录中的任何地方都有带注释的标签,它将不起作用。 fake标签确保describe命令不使用标签来描述提交,
                  【解决方案19】:

                  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
                  

                  【讨论】:

                    【解决方案20】:

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

                    你会看到,这些行跟随你的命令。

                    commit d25c95d88a5e8b7e15ba6c925a1631a5357095db .. (info about your head)
                    
                    d25c95d88a5e8b7e15ba6c925a1631a5357095db, is your SHA for last commit.
                    

                    【讨论】:

                      猜你喜欢
                      • 2011-03-27
                      • 2017-06-21
                      • 2014-10-29
                      • 2013-04-28
                      • 2021-02-04
                      • 2018-06-21
                      • 2023-03-16
                      • 1970-01-01
                      相关资源
                      最近更新 更多