Git can’t add files, sees changes

gitosx-snow-leopard

I have an existing project, deployed to heroku and under git control. I've been regularly adding and committing code.

I recently rebuilt the computer I'm working on (OSX, 10.6) and now when I invoke

git status

I see my changes, but when I try to add the changed files for committing, I get

Dans-iMac-335:[app-name-obscured] apple$ git add public/javascripts/*
fatal: Unable to write new index file

I've cloned the project from the heroku git repository, and I can add there. The ownership of the files in the two projects is the same. What could be causing this? My option is to add each of the changed files to the newly cloned version and reconstruct it that way, but there are a lot of changes, and it seems likely there's a fix here.

Anyone experienced this, and any ideas where to start?


Chris : thanks for the exhaustive reply.

I can run git using sudo. It seems in that sense to be a permissions issue, although the directory is 755, and owned by me, and the enclosed files 644, again owned by me (same user as owns the project files). There's lots of disk space, and the suggestion that directory is writable is a good one, but I was running git from inside the directory that contains the project – would it still need to create the path then?

I don't find ktrace on my system, and I'm not a real expert on terminal manipulations, but I tried running dtruss. That showed no problems, but it occurred to me that because I had to use sudo to run dtruss, it meant that the process dtruss was monitoring was also running as superuser. In any case, at that point it was able to add the items to git, and also using sudo I was able to commit them just now. The problem is when adding a new item, as opposed to a modified one. If I had done something like

sudo dtruss su <my_username> git add some/file/name/*

would I have been able to run git as my regular name? I thought of this after I hacked my way to getting the desired result.

I can live with using sudo for operations where items are added and committed for now. What I want to do is get my heroku repo inline with the current work: then I figure I can clone that, and see if the problem goes away. Otherwise, I'll be back…

Best Answer

The index is usually stored at the top level of the .git directory of the repository. Its location can be overridden by using the GIT_INDEX_FILE environment variable (it might be worth checking that: printf '%s\n' "$GIT_INDEX_FILE").

If the index file’s directory was not writable you would get an earlier error message:

fatal: Unable to create '/path/to/.git/index.lock': Permission denied

We can be fairly sure that the containing directory is writable since you did not get this error message.

The error message you reported is issued near the very end of the activity for git add. Unfortunately the errno is not reported by git add; if it had been reported, we might be able to make a guess about the problem based on the reported error.

git add shows the error you reported if it has any problem writing out the contents of the new index (the contents is written into the .lock file) or when it tries to commit the lock-file (rename the .lock file to take the place of the existing index file; this is ‘committing’ the lock-file transaction, not what git commit does).

Disk Space Issue?

How is the free space on the volume that holds your index file? Maybe it is nearly full. I have been able to reproduce the error message when the index is on a volume that just enough free space to create the .lock file but not enough to hold the entire contents.

“Flag” Issue?

Are there any flags set on the index file? On my system having either uchg (“user-level immutable”) or uappnd (“user-level append-only”) set on the index file will cause git add to give the same error message you are getting. Check the flags with ls -lO on your index file (the flags are displayed after the group-owner and before the size; it will show - if there are no flags set). If you see flags, use the chflags command to remove them. You might want to investigate how the flags got there and whether any other files have them (perhaps with ls -lOR).

Use ktrace

If neither of the above suggestions prompts a solution, then you might break out ktrace and kdump to find out what system call is failing immediately before the error message is printed.

ktrace git add whatever
kdump | less
: Go to the bottom. Search for the error message.
: What CALL is RETurning -1? What is the reported errno?

When the volume is full, I see this:

 4728 git      CALL  write(0x9,0x116d24,0x18b0)
 4728 git      RET   write -1 errno 28 No space left on device
 4728 git      CALL  write(0x2,0xbfffcd00,0x26)
 4728 git      GIO   fd 2 wrote 38 bytes
      "fatal: Unable to write new index file
      "

When I have an incompatible flag set, I see this:

 4742 git      CALL  rename(0x105bdd,0xbfffdfa8)
 4742 git      NAMI  ".git/index.lock"
 4742 git      NAMI  ".git/index"
 4742 git      RET   rename -1 errno 1 Operation not permitted
 4742 git      CALL  write(0x2,0xbfffcd40,0x26)
 4742 git      GIO   fd 2 wrote 38 bytes
      "fatal: Unable to write new index file
      "
Related Question