【问题标题】:How to find the current git branch in detached HEAD state如何找到处于分离 HEAD 状态的当前 git 分支
【发布时间】:2011-08-28 21:30:21
【问题描述】:

我可以通过以下任一方式找到当前的 git 分支名称:

git branch | awk '/^\*/ { print $2 }'
git describe --contains --all HEAD

但是当处于分离的 HEAD 状态时,例如在 Jenkins maven 构建(或 Travis git fetch)的后期构建阶段,这些命令不起作用。

我目前的工作解决方案是这样的:

git show-ref | grep $(git log --pretty=%h -1) | sed 's|.*/\(.*\)|\1|' | sort -u | grep -v HEAD

它显示在其 HEAD 提示上具有最后一次提交的任何分支名称。这很好用,但我觉得 git-fu 更强大的人可能有更漂亮的解决方案?

【问题讨论】:

  • “current git branch [...] in detached HEAD” – Detached HEAD 表示没有当前分支,那么你要查找哪个分支?
  • @poke:OP 的例子很清楚他在寻找什么。
  • @Jefromi:我知道,但是要求一些东西并通过一个已经有效的解决方案来定义它不是一个好主意。不是每个人都能读懂,看看会产生什么样的结果..
  • @poke:我不只是要求一个可行的解决方案,我要求找到匹配分支的 最简单的方式(或“git 方式”?)姓名。

标签: git bash jenkins branch travis-ci


【解决方案1】:

更瓷器的方式:

git log -n 1 --pretty=%d HEAD

# or equivalently:
git show -s --pretty=%d HEAD

引用将以(HEAD, master) 的格式列出 - 如果您打算在脚本中使用它而不是供人类使用,则必须对其进行一些解析。

您也可以自己更简洁地实现它:

git for-each-ref --format='%(objectname) %(refname:short)' refs/heads | awk "/^$(git rev-parse HEAD)/ {print \$2}"

好处是可以在不同的行上获取候选参考,没有额外的字符。

【讨论】:

  • 您可以使用--pretty=%D 来获取HEAD, branchname 而无需周围的括号。在 git v2.11.0 上测试
  • 确保您查看的是 jenkins 上的原始引用,而不是 @epeli 指出的本地引用
  • git show -s --pretty=%D HEAD | tr -s ', ' '\n' | grep -v HEAD | head -n1
  • 更新:git show -s --pretty=%D HEAD | tr -s ',' '\n' | sed 's/^ //' | grep -v -e HEAD -e '^origin/' | head -n1 不幸的是,仅在分离时才有效。
  • $ mkdir test $ cd test $ git init 。 $ touch a.txt $ vi a.txt $ git add a.txt $ git commit -am 'a' $ git status $ git checkout -b test1 $ git status $ git branch master * test1 $ git show -s --pretty =%d HEAD (HEAD -> test1, master) $ vi a.txt $ git commit -am '2' $ git status $ git show -s --pretty=%d HEAD (HEAD -> test1) $ git checkout master $ git show -s --pretty=%d HEAD (HEAD -> master) $ git merge test1 $ git show -s --pretty=%d HEAD (HEAD -> master, test1)
【解决方案2】:

我需要为 Jenkins 提供一些不同的解决方案,因为它没有分支的本地副本。所以当前提交必须与远程分支匹配:

git ls-remote --heads origin | grep $(git rev-parse HEAD) | cut -d / -f 3

或没有网络:

git branch --remote --verbose --no-abbrev --contains | sed -rne 's/^[^\/]*\/([^\ ]+).*$/\1/p'

还值得注意的是,当您在同一提交中有多个分支头时,这可能会返回多个分支名称。

更新:

我刚刚注意到 Jenkins 设置了 GIT_BRANCH 环境变量,其中包含类似 origin/master 的值。这也可以用于在 Jenksin 中获取 git 分支:

echo $GIT_BRANCH | cut -d / -f 2

【讨论】:

  • 我认为 --format=%(refname:lstrip=-2) 为您节省了 sed
  • 我的问题与 OP 与 gilab-runners 相同,“无网络”解决方案是迄今为止最好的解决方案!谢谢!
【解决方案3】:
git branch --contains HEAD

明显丢弃(无分支)。当然,您可能会得到任意数量的分支,这些分支可以描述当前的 HEAD(当然包括没有,这取决于您如何进入无分支),这些分支可能已经快进合并到本地分支中(许多很好的理由之一)为什么你应该总是使用git merge --no-ff)。

【讨论】:

  • @neu242:另一个答案中的哪个命令返回一个有用的分支(例如,不是 HEAD),而这个命令不会(如果它是一个远程分支添加 -a)?在测试期间它工作正常git checkout @{0}
  • @Jefromi 的所有答案,加上我的“当前工作解决方案”以分离的 HEAD 状态返回有用的分支。
【解决方案4】:

sed 解决方案:

git log -1 --pretty=%D HEAD | sed 's/.*origin\///g;s/, .*//g'

这使用log 检查最后一项是否存在于分支上。然后sed 找到origin/ 前面的分支并删除该短语及其之前的所有内容。然后sed 再次删除任何可能的其他列出的分支(逗号及其后面的所有内容)。最后一个log 的原因被用作完整性检查,以确保此分离的 HEAD 不是高于已知分支 HEAD 的提交。

如果这是空的,可以实现故障安全逻辑来标记分支“分离”(或“未定义”?)或确保它是最新的或回滚到已知 HEAD 的尖端。

【讨论】:

  • 效果很好,谢谢! :-) 在 sed 表达式中使用备用分隔符不需要转义 / 并且可能更容易阅读,例如... sed 's|.*origin/||g;s|, .*||g'.
【解决方案5】:

这里是git nthlastcheckout,它会从 reflog 中获取您在最后一次结帐时使用的确切字符串:

git config --global alias.nthlastcheckout '!nthlastcheckout'"() {
        git reflog |
        awk '\$3==\"checkout:\" {++n}
             n=='\${1-1}' {print \$NF; exit}
             END {exit n!='\${1-1}'}'
}; nthlastcheckout \"\$@\""

例子:

$ git nthlastcheckout
master
$ git nthlastcheckout 2
v1.3.0^2

【讨论】:

    【解决方案6】:

    我在 bitbucket 管道上工作的最短时间:

    git show -s --pretty=%D HEAD | awk '{gsub("origin/", ""); print $2}'
    

    【讨论】:

      【解决方案7】:

      我更喜欢用这个:

      git branch --remote --contains | sed "s|[[:space:]]*origin/||"
      

      如果一个分支的头被检出,以及当前的检出是一个分离的头并且它不需要网络访问,它工作正常。

      【讨论】:

        猜你喜欢
        • 2018-04-28
        • 2022-01-19
        • 2014-03-17
        • 2014-06-04
        • 2014-11-14
        • 1970-01-01
        • 1970-01-01
        • 2023-04-09
        • 2016-06-21
        相关资源
        最近更新 更多