在 CLI 中优雅地显示分离的头部

Display detached heads elegantly in CLI

我希望我的命令行(PS1 变量)能够更优雅地显示分离的头像,即使它有点模棱两可。我想这样做的原因是因为虽然我从不在分离分支上工作,但由于我们的项目设置,我经常遇到它们,并且想知道它们来自哪个分支(或者至少 a 他们所在的分支)。

首先,我相信我对两者之间的区别有一个很好的理解:

这就是这两个命令的区别:

git checkout master   # Checkout the master branch
git checkout master~0 # Checkout the commit from the head of the master branch

现在进入正题。目前,我的 PS1 末尾包含 $(__git_ps1),结果命令行显示为:

# git checkout master~1
addison:~/project ((111abcdef1...))$ 

# git checkout master~0
addison:~/project ((000abcdef0...))$ 

# git checkout master
addison:~/project (master)$ 

我想要发生的事情是,如果我在一个独立的头脑中,能够找到一个具有匹配提交哈希的分支(首选 master),并显示分支名称,以及如何远远落后于 HEAD 提交是这样的:

# git checkout master~1
addison:~/project (Detached(master~1))$ 

# git checkout master~0
addison:~/project (Detached(master))$ 

# git checkout master
addison:~/project (master)$ 

我知道可能还没有一个实用程序可以执行此操作,我准备好接受这一点 - 如果是这样,我想知道如何找到一个分支名称提交哈希,以及它落后于分支 HEAD 提交的程度。 我知道可能有多个分支的提交具有相同的哈希 - 我只想要一个 'best effort' 解决方案。这可能意味着只选择最近的,或者最接近 HEAD 等

使用这些信息,我可以制作自己的脚本并将其嵌入到我的 $PS1 变量中,并按照我的需要对其进行格式设置。


更新

我发现有一个可以用 $(__git_ps1) 设置的选项,它可以将输出格式更改为我想要的格式:

GIT_PS1_DESCRIBE_STYLE=contains # git describe --contains HEAD
GIT_PS1_DESCRIBE_STYLE=branch   # git describe --contains --all HEAD
GIT_PS1_DESCRIBE_STYLE=tag      # git describe --tags HEAD
GIT_PS1_DESCRIBE_STYLE=describe # git describe HEAD
GIT_PS1_DESCRIBE_STYLE=default  # git describe --tags --exact-match HEAD

如果我将选项设置为 branch,那么输出的可读性会更高。

如您所知,没有完美的解决方案。 Git 本身使用两种方法。一个例子是 git status:当你在某个分支上时,HEAD 包含分支名称,当你分离时,HEAD 包含一个哈希 ID,但是 reflog for HEAD 仍然有分支名称,Git 可以扫描它并挑选出最近的分支,看看你是在那个提交还是它的其中一个后代并说 在 <em>name</em> 分离或 detached from <em>name</em> .1

但是,在您的情况下,您可能想要更像 git describe 所做的事情,只是顺序不是 git describe 的默认顺序。在这种情况下,您想要的更像是 git describe --contains 所做的。 --contains 选项意味着 --tags 选项,它 git describe 查看所有标签,但 查看任何 分支 名字。幸运的是,您可以添加 --all:

git describe --contains --all

查看标签 分支名称——以及其他参考资料,包括 refs/stash,这可能不是很好——并选择其中一个来描述当前提交。所以这可能是 Git 内置的最接近您想要的内容。


1Git 的某些非常旧的版本中没有此功能。我不确定它是什么时候第一次出现的,发行说明只在描述对 Git 2.4.0 的修复时提到了它。在 2.4.0 之前,git branchgit status 在他们说 "detached at" 和 "detached from" 的时间和方式上存在分歧。所以它在 2.4 及更高版本中,但早期版本不太擅长,并且在某些时候,"detached at/from" 东西根本不存在。