With git-1.7, I regularly get this when pushing to a non-bare repo: remote: error: failed to lock refs/remotes/origin/master ... ! [remote rejected] origin/master -> origin/master (failed to lock) error: failed to push some refs to 'ssh://remote/repo' I see this pushing from a Mac, to either a Mac or to Cygwin. I have seen it on various versions of the 1.7 series and possibly before. In the instance above: local git version 1.7.0.3.436.g2b878 remote git version 1.7.0.3 In addition, the ref is (apparently) updated just fine. If I push a second time, no update occurs. The problem is reproducible. Any idea where I should start debugging it? j. --
Ah, this is the problem: $ git push mirror Total 0 (delta 0), reused 0 (delta 0) error: Ref refs/remotes/origin/master is at 81358fbe72926d74bdeda85669d655e144572c48 but expected 3c0a87afc2e9248890dd6de40b5039bcb48c8516 remote: error: failed to lock refs/remotes/origin/master To ssh://mirror/repo 3c0a87a..81358fb origin/HEAD -> origin/HEAD ! [remote rejected] origin/master -> origin/master (failed to lock) error: failed to push some refs to 'ssh://mirror/repo' The origin/HEAD symref and --mirror do not get along together. Hmm. j. --
Proposal: receive-pack should look through the list of heads it has received and check whether each is locally a symref. If so, and if the destination of the symref is also among the list of heads, it should ignore the symref update. In the example above, receive-pack would determine that refs/remotes/origin/HEAD locally is a symref to refs/remotes/origin/master. Since refs/remotes/origin/master is in the list of heads, it would ignore the update for refs/remotes/origin/HEAD. If that sounds reasonable, I can work on a patch. In case you're wondering how I got into this situation: server$ git clone --bare /shared/project.git ~/backup/project.git client$ git clone server:/shared/project.git client$ cd project client$ git remote add --mirror backup server:~/backup/project.git client$ work, commit, work, commit client$ git push backup j. --
I would rather think that "git push" should notice that */HEAD is a symref and refrain from pushing it. Stated more precisely, - It is perfectly fine to do this: $ git push there HEAD:somebranch - But it does not make sense to push a symref via [remote "there"] push = refs/*:refs/* to a bare repository that is used as a back-up mirror by including refs/HEAD:refs/HEAD in the result of wildcard expansion. --
But nothing prevents the destination repo from having arbitrary symrefs. And there is no way for the source to know which destination refs may be symrefs and which are not. So it seems safer to me that the destination should ignore duplicates in the received list. No? j. --
We probably need it on both ends. On the receiving end, it probably is a better idea to make verify_lock() succeed if the ref has already been updated to the value we are going to update with, as I suspect that the issue is not limited to receive-pack. It needs some restructuring of lock/verify/commit primitives, though. --
