git push failing for certain branch names

萝らか妹 提交于 2019-12-11 13:09:32

问题


In our company, it is not uncommon to branch features out using our names. So if we are on master and want to branch a new feature, we would create john/feature-test or bob/feature-test2. This has worked great until recently one of our teammates lost the ability to push anything onto our origin.

She can create other branches just fine, but if the branch starts with mira/... then it fails like this:

$ git push -f
Counting objects: 2, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (2/2), done.
Writing objects: 100% (2/2), 243 bytes | 0 bytes/s, done.
Total 2 (delta 1), reused 0 (delta 0)
remote: error: Cannot update the ref 'refs/heads/mira/testing': unable to create directory for logs/refs/heads/mira/testing: No such file or directory
To git@bitbucket.org:<team>/<repo>.git
 ! [remote rejected] mira/testing -> mira/testing (failed to update ref)
error: failed to push some refs to 'git@bitbucket.org:<team>/<repo>.git'

I get the same thing when I try this on my machine. So the problem appears to be with the remote git server on Bitbucket. We have tried deleting all branches that start with mira/... and that didn't help. I have pruned the remote and local, ran a git gc, etc.. nothing seems to work.

Whats interesting is we can go into Bitbucket, create a branch called mira/testbranch, run git fetch, run git checkout mira/testbranch, make a change, commit, then push... but the push will still fail with the same problem.

Does anyone have any idea how this could occur and what we can do to fix it?


回答1:


The problem is on the server and must be fixed there (perhaps by action on a client; see below).

The server is giving as much information to the client as it reasonably can (but see below):

remote: error: Cannot update the ref 'refs/heads/mira/testing': unable to create directory for logs/refs/heads/mira/testing: No such file or directory

from which we can conclude:

  • the server config has core.logAllRefUpdates set (see below)
  • file logs/refs/heads/mira/testing does not currently exist (see below)
  • some directory/directories in logs/refs/heads/mira also does/do not exist
  • the process doing the push is also failing to create that directory because some predecessor directory does not exist (this is the mysterious part, since git will create every directory in the path as needed).

Further investigation should probably happen on the server, but the most likely problem is that logs/refs/heads/mira already exists as a plain file rather than a directory, and git is clobbering the EEXIST error for the file path with an ENOENT error during the make-directories sequence. (This would be a minor bug in git: either way it must fail, but it could say "unable to create logs/refs/heads/mira/testing because logs/refs/heads/mira is a regular file", for instance. Moreover, if there is an un-deleted branch in the way—see below—it should give a much clearer error message; this would be a bigger bug in git.)

How that file got left behind is a mystery, assuming my guess (that there is such a file) is correct in the first place. Probably there was a branch named mira, which necessitated creating a reflog file named logs/refs/heads/mira, but when it was deleted—which it must have been at some point in order to create a branch named mira/testing; you cannot have a branch X/Y if there is already a branch X—that should have deleted the reflog as well. But if this is the problem, the fix is to move the file out of the way if you want its contents back, or just remove it entirely if not. If there is an un-deleted branch in the way (with the reflog problem showing up before the branch problem), you can simply delete the branch, which will also delete the reflog file.

You can also disable core.logAllRefUpdates. Normally it would be disabled anyway since this should be a --bare repository.

About core.logAllRefUpdates

This is described reasonably well in the git config documentation:

core.logAllRefUpdates

Enable the reflog. Updates to a ref <ref> is logged to the file "$GIT_DIR/logs/<ref>", by appending the new and old SHA-1, the date/time and the reason of the update, but only when the file exists. If this configuration variable is set to true, missing "$GIT_DIR/logs/<ref>" file is automatically created for branch heads (i.e. under refs/heads/), remote refs (i.e. under refs/remotes/), note refs (i.e. under refs/notes/), and the symbolic ref HEAD.

This information can be used to determine what commit was the tip of a branch "2 days ago".

This value is true by default in a repository that has a working directory associated with it, and false by default in a bare repository.



来源:https://stackoverflow.com/questions/36853142/git-push-failing-for-certain-branch-names

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!