git push:refs / heads / my / subbranch存在,无法创建


84

这不可能在服务器上的存储库中创建somme子文件夹吗?

如果我做:

git push origin dev/master 

一切正常

但是如果我这样做

git push origin dev/sub/master

我懂了:

error: 'refs/heads/dev/sub' exists; cannot create 'refs/heads/dev/sub/master'

我用“ git branch -r”检查并直接用ssh检查,还没有创建dev / sub文件夹。

怎么了?


1
git ls-remote origin返回什么?
Ikke 2014年

Answers:


152

它不是一个存在的文件夹,而是一个分支。(好吧,某个地方可能包含一个文件夹/目录,或者可能没有,因为引用被“打包”并不再以目录中的文件形式存在。)

  • 如果b存在分支,b/anything则不能创建名为的分支。
  • 同样,如果dev/b存在分支,dev/b/c则无法创建。

这是一个git内部限制。在这种特殊情况下,遥控器origin具有一个名为的分支dev/sub(无论您是否拥有它,重要的是遥控器是否具有它)。为了在on上创建origin一个分支dev/sub/master,您必须首先删除dev/subon上的分支origin

git push origin :dev/sub

(当然,删除该分支可能会删除那边的重要内容,因此请确保您知道自己在做什么。通常,您可能git fetch origin首先需要将其捕获dev/sub为您的origin/dev/sub。然后可以创建一个本地分支dev/renamed-sub,该分支指向同一提交,dev/renamed-sub在远程上创建,删除远程dev/sub,然后dev/sub/master在远程上创建。)


如果您可以登录到远程origin主机(托管在其上的系统),则可以进入那里的存储库,然后简单地重命名本地dev/sub分支。(基于下面的评论,我怀疑那里还有一个损坏的自动部署脚本,应该将其修复为仅部署“可部署”分支,而不是部署所有推送的分支。但是我只是在这里猜测。)


1
我想我们只是在这里忙于术语。所谓“内部限制”,是指git可以克服的某些问题而无需更改任何人使用git的方式。不合格的限制将是更为根本的限制,例如,如果有人破坏了SHA1:即使可以克服(例如,移至SHA256),但40个字符的SHA-1的详细信息都暴露在例如大多数钩子中,因此此限制会泄漏到外部。
torek

2
这是一个古怪的刺激性的限制,给了你可能希望有release/1.1release/1.2release/1.1/hofix/prevent-upload-borkrelease/1.1/hotfix/assure-user-of-competence等,以及错误信息,导致人在这里(谢谢),而不是说明的限制!但是,谢谢您的简单明了的解释。
约翰

2
“这是一个git内部限制。” -好吧,为什么呢?以这种方式更容易实现一些逻辑吗?还是一些树遍历?要不然是啥?
D.Kovács17年

2
@D.Kovács:通过禁止这种情况,Git可以简单地将引用哈希写入文件中,这些文件的名称是通过将引用视为路径名来生成的。例如,如果Git同时允许refs/tags/foorefs/tags/foo/2,它将无法执行此操作:它将需要实现自己的键值存储。我认为Git无论如何都会被迫实现自己的键值存储,但是我不知道他们是否会取消限制。
torek '17

1
@ĐinhAnhHuy:我不知道任何描述此限制的正式文档。但是,子模块位于完全独立的名称空间中:子模块名称和分支名称的冲突方式不应与分支名称和文件名称不冲突的方式相同(即,它们会冲突,但是您要添加歧义词:git checkout -- master意味着签出)名为的文件master,而不是分支名称)。
torek '18

60

我处于无法获取的状态,因为我的回购包含有关我什至没有签出的不存在的远程分支的信息。我通过运行以下内容的组合(感谢@torek)解决了该问题:

  • git branch -r 列出远程分支的本地副本
  • git ls-remote 列出远程分支
  • git fetch --prune origin更新远程分支的本地副本(这实际上对我没有帮助
  • git remote prune origin删除有关已删除的远程分支的信息(这样做

8
git remote prune origin是我为了解决此错误状态而运行的单个命令。确实存在误导性消息-就我而言,我正尝试推送“ release / 2.6.0”,并且删除了整个“ refs / remotes / origin / release *”目录-但是,error: update_ref failed for ref 'refs/remotes/origin/release/2.6.0': cannot lock ref 'refs/remotes/origin/release/2.6.0': 'refs/remotes/origin/release' exists; cannot create 'refs/remotes/origin/release/2.6.0'当我尝试push / pull / fetch时,git一直在抱怨
康尼

30

对我来说->

错误=

fatal: cannot lock ref 'refs/heads/release/wl/2.3': 'refs/heads/release/wl' 
exists; cannot create 'refs/heads/release/wl/2.3'

解决方案=

$~ git update-ref -d refs/heads/release/wl
$~ git checkout release/wl/2.3

1
git update-ref -d refs / remotes ...解决了我的问题,以'refs / remotes / origin / hotfix'存在;无法创建'refs / remotes / origin / hotfix / ISSUE ...-
Eduardo

这也解决了我的问题。
米哈伊尔·莫尔菲科夫

16

目前接受的答案没有帮助我,因为我没有在远程回购一个裁判删除-这纯粹是我的地方!因此,如果遇到这种情况,请执行以下操作:

这是我面临的问题:

$ git fetch origin
error: cannot lock ref 'refs/remotes/origin/fix/sub-branch': 
'refs/remotes/origin/fix' exists; cannot create 
'refs/remotes/origin/fix/sub-branch'
From <repo URL>
 ! [new branch]      fix/sub-branch          -> origin/fix/sub-branch
 (unable to update local ref)

我尝试了接受的答案的建议,但得到了:

$ git push origin :fix
error: unable to delete 'fix': remote ref does not exist
error: failed to push some refs to <repo URL>

所以ref甚至不存在origin-显然它只是挂在我本地存储区的某个地方。所以我跑了$ git remote show me,产生了:

Remote branches:
...
refs/remotes/origin/fix             stale (use 'git remote prune' to remove)
...

然后使解决方案变得清晰:

$ git remote prune origin
Pruning origin
URL: <redacted>
 * [pruned] origin/fix

这样,问题就消失了:

$ git fetch origin
remote: Counting objects: 5, done.
remote: Total 5 (delta 2), reused 2 (delta 2), pack-reused 3
Unpacking objects: 100% (5/5), done.
From <repo URL>
 * [new branch]      fix/sub-branch          -> origin/fix/sub-branch

3
是的,遇到和git remote prune origin修复该问题相同。谢谢!
ToddH '18

3

尝试使用以下命令对其进行修复:

git gc

在当前存储库中运行许多内部管理任务并删除无法访问的对象(通过调用git prunegit fsck --unreachable)。

阅读更多:git help gcgit help prune


2

如果所有其他方法均失败,请检查您的回购系统是否没有分支名称的限制。就我而言,您只能创建以开头的分支SD-<number>。其他任何命名都只会给您一个通用名称:

remote: error: cannot lock ref 'refs/heads/mybranch': 'refs/heads/mybranch/environment-variables' exists; cannot create 'refs/heads/mybranch'
To git.example.com:project/repository.git
 ! [remote rejected] mybranch -> mybranch (failed to update ref)
error: failed to push some refs to 'git@git.example.com:project/repository.git'

1
#!/usr/bin/env bash
echo "update-ref delete refs/tags"
log="git-update-ref-errors.log"
script="./git-update-ref-exist-tags-delete.sh"
git_command="git update-ref -d refs/tags"

echo "log errors from ${git_command} to ${log}"
${git_command} 2>&1 | > ${log}
echo "show errors to ${log}"
cat ${log}
echo create ${script}
touch ${script}
echo "add execute (+x) permissions to ${script}"
chmod +x ${script}
echo "generate ${script} from errors log ${log}"
${git_command} 2>&1 | grep 'exists' | sed -n "s:.*\: 'refs/tags/\(.*\)' exists;.*:git tag -d '\1':p" >> ${script}
echo "execute ${script}"
${script}

echo fetch
log="git-fetch-errors.log"
script="./git-fetch-exist-tags-delete.sh"
git_command="git fetch"
echo "log errors from ${git_command} to ${log}"
${git_command} 2>&1 | > ${log}
echo "show errors from ${log}"
cat ${log}
echo create ${script}
touch ${script}
echo "add execute (+x) permissions to ${script}"
chmod +x ${script}
echo "generate ${script} from errors log ${log}"
${git_command} 2>&1 | grep 'exists' | sed -n "s:.*\: 'refs/tags/\(.*\)' exists;.*:git tag -d '\1':p" >> ${script}
echo "execute ${script}"
${script}
git fetch

echo pull
log="git-pull-errors.log"
script="./git-pull-exist-tags-delete.sh"
git_command="git pull"
echo "log errors from ${git_command} to ${log}"
${git_command} 2>&1 | > ${log}
echo "show errors from ${log}"
cat ${log}
echo create ${script}
touch ${script}
echo "add execute (+x) permissions to ${script}"
chmod +x ${script}
echo "generate ${script} from errors log ${log}"
${git_command} 2>&1 | grep 'exists' | sed -n "s:.*\: 'refs/tags/\(.*\)' exists;.*:git tag -d '\1':p" >> ${script}
echo "execute ${script}"
${script}
git pull

echo push
log="git-push-errors.log"
script="./git-push-exist-tags-delete.sh"
git_command="git push"
echo "log errors from ${git_command} to ${log}"
${git_command} 2>&1 | > ${log}
echo "show errors from ${log}"
cat ${log}
echo create ${script}
touch ${script}
echo "add execute (+x) permissions to ${script}"
chmod +x ${script}
echo "generate ${script} from errors log ${log}"
${git_command} 2>&1 | grep 'exists' | sed -n "s:.*\: 'refs/tags/\(.*\)' exists;.*:git tag -d '\1':p" >> ${script}
echo "execute ${script}"
${script}
git push

上面的脚本会将错误记录到XXX-errors.log中,并通过使用以下命令从XXX-errors.log中自动生成并运行XXX-exist-tags-delete.sh来修复错误:

  1. git update-ref -d参考/标签
  2. git获取
  3. git pull
  4. git推


1

作为Windows用户,到目前为止,没有一种解决方案可以为我解决问题。我看到此错误的原因是因为(使用OP的分支名称)我试图创建一个分支,dev/sub但是其他人创建了一个名为的分支Dev,众所周知,Windows具有不区分大小写的文件系统。

因此,当Windows尝试将其下拉时,dev/sub它首先尝试创建文件夹dev,但由于Dev已经存在而无法创建文件夹。

解决方法是使用删除Dev本地和远程分支git branch -d Dev && git push origin :Dev。一个git pull运行良好。

继续向前的另一课,分支名称应始终为小写,以避免此类陷阱。


1

我知道这个问题已经得到解决,但对我没有用。我不关心本地更改,因为它已经被推高了,但是问题又拉回去了。在我的情况下,我们在以“ hotfix”作为分支到以父文件夹为“ hotfix”的文件夹系统之间进行了更改。

-修补程序---- hotfix / 1234_bug ---- hotfix / 3456_bug

所以我得到以下错误:

Fetching from origin Error: cannot lock ref 'refs/remotes/origin/hotfix/1234_bug': 'refs/remotes/origin/hotfix' exists; cannot create 'refs/remotes/origin/hotfix'

搜索类似的错误后,我终于在这里的讨论线程中找到了解决方案。

git remote prune origin

0
git checkout -b hotfix/my-new-branch

ga
gm "my commit"

gp --set-upstream origin hotfix/subscribers-function

0

重命名dev/subdev/sub/something,则可以创建分支dev/sub/master

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.