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
"
Not a Git user, but I believe that Git stores the entire file permission mask.
That means that you have once set the file to executable, which Git picked up and replicated in the repository. Therefore you must change the file's permission mask itself before committing.
To make Git ignore such changes, use
git config core.filemode false
From git-config(1) :
core.fileMode
If false, the executable bit differences between the index and the
working copy are ignored; useful on broken filesystems like FAT.
See git-update-index(1). True by default.
Best Answer
Edit:
A solution might be to set
core.fileMode
variable tofalse
in your~/.gitconfig
. This makes git ignore the executable bit.If you are using a FAT filesystem, you might want to set
core.ignorecase
totrue
as well.Old answer
Assuming you commit on the Linux box, you can use a hook, in this case
.git/hooks/pre-commit
:This is somewhat crude in the sense that forces all files and directories to a certain permission. You might want to add
chmod
commands for specific files if they need to have other permissions between thefind
andgit add
. On the other hand it is short and simple.A more complex solution might use
git diff --cached --name-only
to check which files are actually going to be committed and would fix only those. But this would be more complex and wouldn't fix random permission changes.