简体   繁体   English

如何在分离的 HEAD state 中找到当前的 git 分支

[英]How to find the current git branch in detached HEAD state

I can find the current git branch name by doing either of these:通过执行以下任一操作,我可以找到当前的 git 分支名称:

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

But when in a detached HEAD state, such as in the post build phase in a Jenkins maven build (or in a Travis git fetch), these commands doesn't work. But when in a detached HEAD state, such as in the post build phase in a Jenkins maven build (or in a Travis git fetch), these commands doesn't work.

My current working solution is this:我目前的工作解决方案是这样的:

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

It displays any branch name that has the last commit on its HEAD tip.它显示在其 HEAD 提示上具有最后一次提交的任何分支名称。 This works fine, but I feel that someone with stronger git-fu might have a prettier solution?这很好用,但我觉得 git-fu 更强大的人可能有更漂亮的解决方案?

A more porcelain way:更瓷器的方式:

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

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

The refs will be listed in the format (HEAD, master) - you'll have to parse it a little bit if you intend to use this in scripts rather than for human consumption. refs 将以(HEAD, master)格式列出 - 如果您打算在脚本中使用它而不是供人类消费,则必须对其进行一些解析。

You could also implement it yourself a little more cleanly:你也可以自己更干净地实现它:

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

with the benefit of getting the candidate refs on separate lines, with no extra characters.好处是可以在单独的行上获取候选参考,没有额外的字符。

I needed a bit different solution for Jenkins because it does not have local copies of the branches.我需要为 Jenkins 提供一些不同的解决方案,因为它没有分支的本地副本。 So the current commit must be matched against the remote branches:所以当前提交必须与远程分支匹配:

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

or without network:或没有网络:

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

It's also worth noting that this might return multiple branch names when you have multiple branch heads at the same commit.还值得注意的是,当您在同一提交中有多个分支负责人时,这可能会返回多个分支名称。

UPDATE:更新:

I just noticed that Jenkins sets GIT_BRANCH environment variable which contains a value like origin/master .我刚刚注意到 Jenkins 设置了GIT_BRANCH环境变量,其中包含一个类似origin/master的值。 This can be used to get git branch in Jenksin too:这也可用于在 Jenksin 中获取 git 分支:

echo $GIT_BRANCH | cut -d / -f 2
git branch --contains HEAD

Obviously discarding (no branch).明显丢弃(无分支)。 Of course, you may get an arbitrary number of branches which could describe the current HEAD (including of course none depending on how you got onto no-branch) which might have be fast-forward merged into the local branch (one of many good reasons why you should always use git merge --no-ff ).当然,您可能会得到任意数量的分支,这些分支可以描述当前的 HEAD(当然包括没有分支,这取决于您如何进入无分支),这些分支可能已快速合并到本地分支中(许多很好的原因之一)为什么你应该总是使用git merge --no-ff )。

A sed solution:一个sed解决方案:

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

This uses log to check the last item for its presence on a branch.这使用log来检查最后一项是否存在于分支上。 Then sed finds the branch preceded by origin/ and removes the phrase and everything before it.然后sed找到以origin/ sed的分支并删除该短语及其之前的所有内容。 Then sed does another removal of any possible additional listed branches (comma and everything after it).然后sed再次删除任何可能的附加列出的分支(逗号及其后的所有内容)。 The reason last log was used as a sanity check to ensure this detached HEAD is not a commit above known branch HEADs.最后一个log被用作健全性检查的原因是为了确保这个分离的 HEAD 不是已知分支 HEAD 之上的提交。

If this is empty, failsafe logic can be implemented to label the branch "detached" (or "undefined"?) or to ensure it's up-to-date or rolled back to the tip of a known HEAD.如果这是空的,可以实现故障安全逻辑来标记分支“分离”(或“未定义”?)或确保它是最新的或回滚到已知 HEAD 的尖端。

如果您在分支上,则git symbolic-ref HEAD返回refs/heads/branchname否则返回错误。

Here's git nthlastcheckout , it gets the exact string you used for your nth last checkout from the reflog:这是git nthlastcheckout ,它从引用日志中获取您用于第 n 次最后一次结帐的确切字符串:

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

Examples:例子:

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

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

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

I prefer to use this one:我更喜欢使用这个:

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

It works fine if the head of a branch is checked out as well as when the current checkout is a detached head and it requires no network access.如果分支的头部被签出以及当前签出是一个分离的头部并且不需要网络访问时,它工作正常。

This is what I am using in one of my projects:这是我在我的一个项目中使用的:

const { execSync } = require('child_process');

const getBranchName = () => {
  let branch = execSync('git rev-parse --abbrev-ref HEAD').toString().trim();
  if (branch === 'HEAD') branch = execSync(`git branch -a --contains HEAD | sed -n 2p | awk '{ printf $1 }'`).toString().trim();
  return branch;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM