为什么Git允许在已添加的工作树中向签出的分支推送?我应该如何恢复?

3

通常情况下,Git会拒绝向普通非--bare仓库的当前检出分支推送:

$ git push upstream master
Counting objects: 1, done.
Writing objects: 100% (1/1), 188 bytes | 0 bytes/s, done.
Total 1 (delta 0), reused 0 (delta 0)
remote: error: refusing to update checked out branch: refs/heads/master
remote: error: By default, updating the current branch in a non-bare repository
remote: error: is denied, because ...
这是正确的行为。请参见Git推送错误“[remote rejected] master -> master(分支当前被检出)”。但是,在同一上游中,我有一个添加的工作树,其中检出了不同的分支。就在上述错误演示之前,我运行了:
$ git push upstream pytest

它成功了,明显不应该成功,原因与此处的master失败相同。 特别地,receive.denyCurrentBranch 确实被设置为拒绝当前分支。

在上游系统上,git worktree list显示:

$ git worktree list
<path1>     9febb4c [master]
<path2>     406bef8 [pytest]

这表明 Git 部分 知道当前检出的状态,但它仍然允许 push,这引发了两个问题:

  1. 这是一个 bug 吗?

  2. 既然我已经陷入了这种情况,该如何恢复呢?

(另外注意:此 bug 已在 Git 2.26 中得到修复,该版本于 2020 年 3 月发布。)

1个回答

4
  1. Yes, it is (obviously) a bug: Git's "is this a current branch" test, in the receive pack code, is using the pre-multiple-work-trees test, which is just to check the main work-tree's HEAD. It needs to be modified to check all work-trees the same way git worktree list does.

    (I'm working on two systems connected via VPN where only one of them has a server running at the moment, so I'm using an asymmetric fetch/push model here.)

  2. Fortunately, I had no uncommitted work, so recovery was trivial: in the secondary work-tree (on branch pytest), just run:

    git reset --hard HEAD
    

    which cleans up both the index and work-tree.

    If I were not, however, the easiest trick would be to force a new branch to exist at the previous value of the branch, then check out that branch. This can be done in one step:

    git checkout -b tempbranch pytest@{1}
    

    The work-tree would now be on a different (pre-push) branch, where temporary work can now be committed or stashed or rebased or whatever, and dealt with in the usual way.


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接