我有一个名为test
的分支和标签。如果我有一个明确的引用,如heads/test
或refs/heads/test
,我如何在不进入分离状态的情况下结账?
git checkout heads/test
我想保存当前的HEAD状态,然后返回它:
# Exit if dirty
# Save HEAD
ref=$(git symbolic-ref -q --short HEAD)
if [ -z "$ref" ] ; then # Detached
ref=$(git rev-parse HEAD)
fi
echo $ref
# Do Stuff that changes HEAD
git checkout master
# Restore HEAD
git checkout $ref
::为清晰而编辑::
编辑:Adamarla notes,git symbolic-ref --short -q HEAD
在这种模棱两可的参考情况下行为不端。例如:
$ mkdir t
$ cd t
$ git init
Initialized empty Git repository in ...
$ echo test symref > README
$ git add README
$ git commit -m initial
[master (root-commit) ee3448a] initial
1 file changed, 1 insertion(+)
create mode 100644 README
$ git branch test
$ git tag test
$ git checkout test
warning: refname 'test' is ambiguous.
Switched to branch 'test'
$ git symbolic-ref -q --short HEAD
heads/test
所以我在下面的原始答案有一个重要的错误。我会在OP的替代品上使用一个轻微的变体:
if headRef=$(git symbolic-ref -q HEAD); then
headRef=${headRef#refs/heads/}
else
headRef=$(git rev-parse HEAD)
fi
注意:
git symbolic-ref
不是符号引用时,HEAD
错误(返回失败状态,以及不打印符号引用):
if ! ref=$(git symbolic-ref -q --short HEAD); then
... HEAD is detached ...
(换句话说,您不需要单独的零长度字符串测试。)HEAD
只能是对分支名称的符号引用,而不是标记名称。test
将解析为refs/tags/test
指向的提交而不是refs/heads/test
。然而,git checkout
命令的行为有所不同:git checkout test
将更喜欢分支。因此,如果git symbolic-ref
成功,你的简短参考适合传递给git checkout
。如果失败,您需要运行git rev-parse HEAD
以获取散列ID以传递给更高版本的git checkout
。
来自文档:
分店结帐;如果它引用了一个分支(即一个名称,当它以“refs / heads /”为前缀时,是一个有效的引用),则检查该分支。否则,如果它引用了有效的提交,则您的HEAD将变为“已分离”,并且您不再处于任何分支上(有关详细信息,请参阅下文)。
所以:如果同时存在一个名为test
的分支和标签,那么git checkout test
将检查分支而不分离。确实,git会发出警告,但它仍然会以这种方式表现出来。
但另一方面,如果你给它除了上面定义的“分支名称”之外的任何东西 - 其中包括明确限定分支,如heads/test
- 然后它分离。
因此,如果你有heads/test
并且想要在没有拆卸的情况下结账,那么(瓷器)程序就是剥离heads/
而只是checkout test
。
如果你真的不想这样做......好吧,我不知道一个更好的“安全”选择。
你可以使用git symbolic-ref
git symbolic-ref -m "Checkout test" HEAD refs/heads/test
git reset HEAD -- .
git checkout -- .
但请注意,在这种情况下你必须完全符合参考资格 - 所以你仍然不能只使用heads/test
。此外,如果你没有在-m
论证中手动提供“原因”,你将搞砸reflog。然后,您必须更新索引和工作树。我猜你可以写一个脚本或别名来做所有这些。
或者你可以直接操纵.git/HEAD
文件,但是如果你搞砸了git将不再识别回购,直到你修复它。
另外,你说:
签出标签/测试工作正常。
不知道这意味着什么,因为(a)你的问题是如何检查heads/test
而不进入分离头,但(b)检查标签总是进入分离头。和:
我得到的答案是:
git symbolic-ref -q --short HEAD
在什么情况下这将返回tags/test
?也许我误解了,因为你把它放在你正在谈论签出标签的同一行...你的意思是git symbolic-ref -q --short HEAD
正在返回heads/test
,你是存储它然后试图检查它?
在这种情况下,见上文;但在这种情况下,你可以省略--short
,至少这将使symbolic-ref
方法更接近工作......
我希望有一个管道检查命令,可以处理来自合格ref的分支机构检查,但是已经提出了这个解决方法:
# Save Checkout
refBranch=$(git symbolic-ref -q HEAD)
refDetach=$(git rev-parse HEAD)
echo "refBranch [$refBranch]"
echo "refDetach [$refDetach]"
# Do Stuff
git checkout master --quiet
echo "Now on [$(git symbolic-ref -q --short HEAD)]"
# Restore Checkout
if [[ ${refBranch:0:11} == "refs/heads/" ]] ; then
echo "Checkout Branch [${refBranch:11}]"
git checkout ${refBranch:11} --quiet
else # Detached
echo "Checkout Detach [$refDetach]"
git checkout $refDetach --quiet
fi
或者,如果我们保证始终获得refs/heads/
前缀:
# Save Checkout
if headRef=$(git symbolic-ref -q HEAD); then
headRef=${headRef:11}
else
headRef=$(git rev-parse HEAD)
fi
echo "headRef [${headRef}]"
# Do Stuff
git checkout master --quiet
echo "Now on [$(git symbolic-ref -q --short HEAD)]"
# Restore Checkout
git checkout $headRef --quiet