git push: refs/heads/my/subbranch exists, cannot create
Asked Answered
T

13

172

Is this not possible to create somme sub-sub-folder in a repo on a server?

if i do:

git push origin dev/master 

everything work find

but if i do

git push origin dev/sub/master

i got this:

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

i checked with git branch -r and directly with ssh, there isn't dev/sub folder already created.

what's wrong?

Tonnie answered 25/3, 2014 at 9:33 Comment(2)
What does git ls-remote origin return?Gerge
just add a dash like so: dev/master dev/master-/subWynellwynn
L
281

It's not a folder that exists, it's a branch. (Well, there may be a folder/directory involved somewhere—or maybe not, as references get "packed" and stop existing as files within directories.)

  • If branch b exists, no branch named b/anything can be created.
  • Likewise, if branch dev/b exists, dev/b/c cannot be created.

This is a git internal limitation. In this particular case, remote origin has a branch named dev/sub (regardless of whether you have it or not, the important thing is whether the remote has it). In order to create, on origin, a branch named dev/sub/master, you must first delete the branch named dev/sub on origin:

git push origin :dev/sub

(Of course, deleting this branch may delete something important over there, so be sure you know what you are doing. Generally, you might want to git fetch origin first, capturing their dev/sub as your origin/dev/sub. You can then make a local branch named dev/renamed-sub pointing to the same commit, create dev/renamed-sub on the remote, delete the remote dev/sub, and then create dev/sub/master on the remote.)


If you can log in on the remote (the system that origin is hosted on), you can go into the repository over there and simply rename the local dev/sub branch. (Based on comments below, I suspect that there's a broken auto-deploy script over there as well, which probably should be fixed to only deploy "deployable" branches, rather than everything that gets pushed. But I am just guessing here.)

Loux answered 25/3, 2014 at 9:44 Comment(20)
but why localy i can do it ? git branch give me : master dev/master dev/sub/master dev/sub/branch2 etcTonnie
@user3458953: Because you locally don't have a refs/heads/dev/sub. You probably have refs/remotes/origin/dev/sub, the tracking ref for the branch at origin, but that is a different name, so it does not conflict. See, the namespaces for branches on different repositories are independent.Easterner
Furthermore, after deleting all branch on origin (exept master), i still can't create dev/sub/masterTonnie
@user3458953: How did you delete the branches on origin?Easterner
Note that git branch -r only lists your local copies of remote branches. git fetch --prune origin will update your local copies, so that git branch -r should show you the state of the remote. Or, use git ls-remote to see the state of the remote, including all its branches. (Git's terminology gets in the way here big time: there's a really big difference between a "remote branch" and a "branch on the remote", even though it sure sounds like those should be the same!)Loux
ooookay thank! but now, this: git push origin :dev/sub give me this error: By default, deleting the current branch is denied, because the next remote: error: 'git clone' won't result in any file checked out, causing confusion. (i don't know what i do with this branch x))Tonnie
Ah, in that case you're kind of stuck, unless you can log in on the system that origin is on. The problem is that the HEAD reference in the git repo over there points to the same commit as the dev/sub branch, most likely because HEAD is a symbolic ref pointing to dev/sub. This suggests there's an auto-deploy script on the remote, possibly a poorly-written one. In one such case pushing a commit (even a dummy one) to master will make the auto-deploy script switch the remote repo to branch master, but it's really in need of fixing over there.Loux
mh, there isn't auto-deploy script, but i create my remote repo with a git clone --bare, before a scp, when i only had the master branch. As i experienced git remote, i looked in one time and maybe touch accidentaly something that i will not have to touch xD. I gonna delete and recreate the repo. thank for all explanations!Tonnie
You can of course delete and re-create it, but you don't have to: you can use regular git branch commands on a bare repo, and do things like git symbolic-ref HEAD refs/heads/master to re-point HEAD.Loux
Note that this isn't necessarily an internal git limitation, but more of a file system limitation. If only packed refs would be used for example, this wouldn't be a problem.Gerge
@Ikke: but that would be changing the internals to remove the limitation, which means it's an internal limitation, no? :-) Also git could keep using unpacked refs: for instance, turn each ref name into a sha1, then store the original name and target of the ref in .git/sharefs/cafeb0b... (requires opening all unpacked refs to find their string forms, hence more expensive than current dir traversal). Basically any internal change that would allow it, would allow it...Loux
The limitation is on how they are stored, not how git internally processes them. I don't say it's a limitation at all that wouldn't require a change to overcome it. It's more of a concrete implementation limitation than a abstract conceptual limitation.Gerge
I guess we're just fussing over terminology here. By "internal limitation" I mean it's something git could overcome without changing how anyone uses git. An unqualified limitation would be something much more fundamental, such as, if someone breaks SHA1: while even this could be overcome (e.g., move to SHA256), the details of 40-character SHA-1s are exposed in, e.g., most hooks, so this limitation leaks into externals.Loux
That's a weirdly irritating limitation, given you might want to have release/1.1 and release/1.2 with release/1.1/hofix/prevent-upload-bork & release/1.1/hotfix/assure-user-of-competence, etc. And the error message leads one here (thank you), rather than stating the limitation! But thank you for simple and clear explanation.Discard
"This is a git internal limitation." -- OK, but why? Was some logic easier to implement this way? Or some tree-traversal? Or what?Nucleoplasm
@D.Kovács: by forbidding that case, Git can simply write reference hashes into files whose name is produced by treating the reference as a path name. If Git allowed both refs/tags/foo and refs/tags/foo/2, for instance, it would not be able to do this: it would need to implement its own key-value store. I think Git is going to be forced to implement its own key-value store anyway, but I do not know if they will remove the limitation then.Loux
@Loux can you give me an official link about this. I think it's really annoying. I read a post about git name convention. I have 1 branch a and many submodule a/b, a/c, a/d will merge into a daily. How can i archive that while keeping a branch.Saiga
@ĐinhAnhHuy: I don't know of any formal documentation describing this limitation. Submodules, however, are in a completely separate name-space: submodule names and branch names should not collide in the same way that branch names and file names don't collide (i.e., they do, but you add a disambiguator: git checkout -- master means check out the file named master, rather than the branch name).Loux
"If branch b exists, no branch named b/anything can be created." You save my life, thank you :DJacobine
"Likewise, if branch dev/b exists, dev/b/c cannot be created." True. But this can be misinterpreted. Instead, if branch dev/b exists and branch dev does not exist, then dev/c can be created.Suu
B
101

I was in a state when I couldn't even fetch because my repo had info about non-existing remote branches I didn't even had checked out. I solved it by running combination (thanks @torek) of:

  • git branch -r list local copies of remote branches
  • git ls-remote list remote branches
  • git fetch --prune origin update local copies of remote branches (this actually didn't help me)
  • git remote prune origin remove info about removed remote branches (this did)
Bijou answered 25/6, 2015 at 10:45 Comment(2)
git remote prune origin was the single command I ran in order to resolve this error state. Misleading message indeed - in my case I was trying to push a "release/2.6.0" and I had removed the whole 'refs/remotes/origin/release*' dir - yet git kept complaining 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' whenever I tried push/pull/fetchAdlay
More explanation to walk through such a situation here: stackoverflow.com/a/76012255Manslaughter
A
64

For me -->

Error =

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

Solution =

$~ git update-ref -d refs/heads/release/wl
$~ git checkout release/wl/2.3
Athome answered 26/7, 2018 at 9:46 Comment(5)
git update-ref -d refs/remotes... solved my problem to 'refs/remotes/origin/hotfix' exists; cannot create 'refs/remotes/origin/hotfix/ISSUE...Schug
It also fixed my problem.Rockie
I also got error: 'refs/heads/develop' exists; cannot create 'refs/heads/develop/sort-rows-of-common-tables' while trying to rename my local branch from bugfix/sort-rows-of-common-tables to develop/sort-rows-of-common-tables by running git branch -m develop/sort-rows-of-common-tables, having branch develop already existing. Solved by running git update-ref -d refs/heads/develop and then git branch -m develop/sort-rows-of-common-tables, thanks sir!Suu
However, now II cannot push that branch to remote because on remote it is giving me the same error it was giving me on local. See stackoverflow.com/questions/69257792/…Suu
Fixed the problem, especially for a person that doesn't want to do "git remote prune origin" in a company repo.Slyviasm
T
21

The currently accepted answer didn't help me because I didn't have a ref on the remote repo to delete - it was purely on my local! So if you're in that situation, here's what to do:

This is the issue I was facing:

$ 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)

I tried the accepted answer's suggestion but got this:

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

So the ref didn't even exist on origin - it was clearly just hanging around somewhere on my local repo. So I ran $ git remote show me, which produced:

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

Which then made the solution clear:

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

With this, the problem disappeared:

$ 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
Tapping answered 29/1, 2018 at 3:55 Comment(1)
Yep, same issue as you ran into and git remote prune origin fixed it. Thanks!Fatwitted
M
7

I understand this is already answered, but it did not worked for me. I did not cared for local changes as it was already pushed up but having issues pulling back. In my case, we changed halfway between having "hotfix" as branch to folder system having parent folder as "hotfix".

-- hotfix ----hotfix/1234_bug ----hotfix/3456_bug

So I was getting following error:

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

After searching for similar errors finally I found solution on a discussion thread here.

git remote prune origin
Melainemelamed answered 8/11, 2019 at 13:45 Comment(0)
S
5

Try this command to fix it:

git gc

to run a number of housekeeping tasks within the current repository and remove unreachable objects (by invoking git prune and git fsck --unreachable).

Read more: git help gc (docs) and git help prune (docs).

git-gc - Cleanup unnecessary files and optimize the local repository

git-prune - Prune all unreachable objects from the object database

Selfpossessed answered 15/3, 2016 at 10:6 Comment(0)
Q
3

Rename dev/sub to dev/sub/something, then you can create branch dev/sub/master.

Queen answered 18/8, 2020 at 17:22 Comment(1)
This is great! Thanks!Gastro
C
2

As a windows user, none of the solutions thus far solved the problem for me. The reason I was seeing this error was because (using the OP's branch names) I was trying to create a branch dev/sub but someone else had created a branch called Dev and as we all know, windows has a case insensitive file system.

So when windows tried to pull down dev/sub it was first trying to create the folder dev, but it couldn't because Dev already existed.

The solution was to delete the Dev branch locally and remotely with git branch -d Dev && git push origin :Dev. A git pull after this ran fine.

Another lesson going forward, branch names should always be lowercase to avoid this kind of gotcha's.

Convergence answered 5/9, 2018 at 3:44 Comment(0)
P
2

If all else fails, check that your repo system does not have limitations for branch names. In my case, you could only create branches that start with SD-<number>. Any other naming would give you just a generic:

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 '[email protected]:project/repository.git'
Pacifism answered 5/4, 2019 at 10:45 Comment(0)
P
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

The script above will log errors to XXX-errors.log and fix them by generating and running a XXX-exist-tags-delete.sh automatically from the XXX-errors.log using the following commands:

  1. git update-ref -d refs/tags
  2. git fetch
  3. git pull
  4. git push
Padlock answered 5/12, 2017 at 10:13 Comment(0)
S
1

First I removed the branches that weren't present in remote but were affecting me locally:

git remote prune origin

Then I proceeded on to delete any references that were affecting me from creating my develop branch (In my case I had two such references, so I ran it twice):

git update-ref -d refs/heads/develop/dummy

Lastly, set the correct tracking reference:

git checkout --track origin/develop
Sanmicheli answered 11/9, 2023 at 7:9 Comment(0)
A
0

git remote prune origin fixed the issue for me

Alikee answered 6/3, 2018 at 10:24 Comment(0)
P
-2
git checkout -b hotfix/my-new-branch

ga
gm "my commit"

gp --set-upstream origin hotfix/subscribers-function
Pique answered 13/7, 2020 at 10:49 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.