git push fails unless I do a gc on the remote repo first
I am using git on my Windows 7 machine, pushing to a shared folder on a Server 2008 machine. This has been working perfectly for the past 6 months. However, as of yesterday, I can no longer push to the remote repo. Every time I try, I get the following:
$ git push Counting objects: 39, done. Delta compression using up to 8 threads. Compressing objects: 100% (23/23), done. Writing objects: 100% (23/23), 8.42 KiB, done. Total 23 (delta 15), reused 0 (delta 0) Unpacking objects: 100% (23/23), done. error: Couldn't set refs/heads/my-branch To //my-server/Code/my-project.git ! [remote rejected] my-branch -> my-branch (failed to write) error: failed to push some refs to '//my-server/Code/my-project.git
Googling for the 'failed to push some refs' error gives various results about not having pulled first (I am completely up to date), and not having the right permissions (I have full access to everything, and can create/delete/edit files in the remote repo via explorer).
I then stumbled across this blog post http://henke.ws/post.cfm/error-failed-to-push-some-refs which mentions that you might have to run some cleanup commands on the remote repository. So I ran git gc on the remote repository:
$ git gc Counting objects: 3960, done. Compressing objects: 100% (948/948), done. Writing objects: 100% (3960/3960), done. Total 3960 (delta 2971), reused 3942 (delta 2964)
And lo and behold, I can push again!
$ git push Counting objects: 39, done. Delta compression using up to 8 threads. Compressing objects: 100% (23/23), done. Writing objects: 100% (23/23), 8.42 KiB, done. Total 23 (delta 15), reused 0 (delta 0) Unpacking objects: 100% (23/23), done. To //my-server/Code/my-project.git 8153afd..1385d28 my-branch -> my-branch
The problem, though, is that I now have to run a gc on the remote repository every time I want to do a push. If I don't, I get the 'failed to push some refs' error again.
So, why is my repo so busted? How can I permanently fix the problem?
It appears that you are pushing over a windows network share, as opposed to using ssh or git protocols. This would mean your local computer has to write the files onto the network share and so could be thwarted by any locked files or permission issues relating to that server.
When pushing a branch, after writing the objects git will update the ref for the branch by writing to the file .git/refs/heads/my-branch. It appears that file is not currently writable from your client.
When you do a gc, refs are collected from being loose files in the refs dir and put into a text file .git/packed-refs, and the individual ref files are then deleted.
My theory is your push is failing when the ref exists as a loose file on the server, because you do not have permissions to overwrite an existing file, whilst you do have permissions to create new files. After packing the refs with a gc, the ref file no longer exists and thus you are able to push again, once.
My suggested fixes are:
- Verify whether you can overwrite existing files from you client and if not fix permissions or file locking problems
- Switch to using the git protocol, this blog seems like a good overview of options for windows http://freshbrewedcode.com/derekgreer/2012/02/19/hosting-a-git-repository-in-windows/
As a last resort, if you find yourself stuck with the gc option, you could try running 'git pack-refs -all' instead. It will be faster than fixing the problem with a gc each time.