GIT结帐明确无误

时间:2018-03-02 14:35:46

标签: bash git git-bash

我有一个名为test的分支和标记。 如果我有一个明确的引用,如heads/testrefs/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

::为了清晰而编辑::

3 个答案:

答案 0 :(得分:2)

来自文档:

  

分支结帐;如果它引用了一个分支(即,当" 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方法更接近......

答案 1 :(得分:2)

修改: 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只能 是对分支名称的符号引用,而不是标记名称。

  • 大多数Git命令的行为与the gitrevisions documentation中描述的一样,因为[{1}}只能将test解析为指向的提交,而不是refs/tags/test 。但是,refs/heads/test命令的行为有所不同:git checkout更喜欢分支。

因此,如果git checkout test成功,则您的简短引用适合传递给git symbolic-ref。如果失败,则需要运行git checkout以将哈希ID传递给后来的git rev-parse HEAD

答案 2 :(得分:1)

我希望有一个能够处理来自合格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