4

Help! When I try to do a git push origin master now, I get:

fatal: Unable to create '/home/ubuntu/workspace/.git/refs/remotes/origin/master.lock': File exists.
If no other git process is currently running, this probably means a
git process crashed in this repository earlier. Make sure no other git
process is running and remove the file manually to continue.

Of course, I've found other similar questions (e.g. here), but the upvoted answers in there merely suggest deleting the offending file... but the file does not exist!

I fear that this is happening after I recently tried to clear some space using the following:

$ sudo git reflog expire --all --expire=now
$ sudo git gc --prune=now --aggressive

Could that be the cause? Any suggestions for a fix?

Mouloud85
  • 3,826
  • 5
  • 22
  • 42
drmrbrewer
  • 11,491
  • 21
  • 85
  • 181
  • If the file really does not exist, something bizarre is happening in error handling, as the error message should read `No such file or directory` (i.e., `ENOENT`, not `EEXIST`). The most likely problem after using `sudo`, though, is that you have part of your repository owned by you, and part owned by the super-user, and since you are not the super-user, you no longer have permission to touch your repository. Of course in this case the error should be `EPERM`, `Permission denied`...! – torek May 07 '16 at 18:34
  • @torek, oh dear! Any fix for this? – drmrbrewer May 07 '16 at 18:35
  • Well, first, the question is whether this really is the problem. You could use `ls -lR` (recursive `ls -l`) to see if ownership is mixed-up. If so, since you obviously have sudo, you can `sudo chown -R .` to put all the ownership back to yourself. – torek May 07 '16 at 18:36
  • @torek where should I do that, in the .git folder? – drmrbrewer May 07 '16 at 18:37
  • Given the two commands you ran should only touch things in `.git`, yes (though if it were me I'd run `find . -user root` or `find . ! -user ` as a shortcut for the `ls`, just to see if I'd done something else equally silly elsewhere, doing the `find` as high up as necessary for comfort...). – torek May 07 '16 at 18:40
  • @torek I see mostly 'ubuntu'... but a few are 'root', including the `.git/refs/remotes/origin` folder... – drmrbrewer May 07 '16 at 18:46
  • Presumably you are logged in as `ubuntu` then (or the files are supposed to be owned by `ubuntu` at least), so that would be the `` part to fill in, and you could run it on all of `.git` or just on `.git/refs/remotes`. The expires should not have created any new objects, just modified reflogs and refs. – torek May 07 '16 at 18:48
  • I'm using Cloud9 so assume you're right... I'm logged in as `ubuntu` so I'll try that. – drmrbrewer May 07 '16 at 18:50
  • @torek you are a lifesaver! Worked like a charm! In the `.git` folder I did `sudo chown ubuntu:ubuntu . -R`, then back in the repo folder `git push origin master` is working fine again! Please can you add an Answer so that I can credit you? Also, should I have just done the `git reflog` and `git gc` without `sudo`? There is nothing intrinsically bad about doing `gc` and `reflog`, just that I shouldn't have used `sudo`? – drmrbrewer May 07 '16 at 19:00

1 Answers1

5

The problem appears to have stemmed from running the expiration code as the super-user (sudo ...). When Git adjusted the remote-tracking branch files, they became owned by (and hence only adjustable by) the super-user.

The fix is to put those files back to the correct owner (in this case ubuntu). One can use a blanket ownership-change, e.g., sudo chown -R ubuntu .git, or a selective one (change only mis-owned files), e.g., as root (or with sudo again, this one is a bit more annoying because of the pipeline) find .git -user root -print0 | xargs -0 chown ubuntu. The only difference, if any, between these would be that chown -R might update more files' ctime (inode-change time) fields (by actually running chown system calls on files already properly owned), which can in turn affect backup systems.

The more general rule is "don't arbitrarily prefix stuff with sudo"—in this case, there was no reason to put sudo in front of the git reflog expire and git gc commands.

torek
  • 448,244
  • 59
  • 642
  • 775