Using Team City to check out from a Git Repo. (Gitlabs if it matters)
Start with Empty build directory. Get this error:
fatal: could not set \'core.filemode
Traderhunt Games traced this to some antivirus software, which makes sense. The reason has to do with the process Git uses to update a configuration entry.
When git config
runs and is told to change one or more configuration key = value
field(s), such as changing core.filemode
to false
, the way it implements this is to use a three-step process:
Create a new, empty file (.git/config.lock
), using the OS service call that creates a file, or fails if the file already exists. If this step fails, that indicates that another git config
(or equivalent) command is already running and we must wait for it to finish before we do our own git config
.
Read the existing configuration file, one key = value
entry at a time. If the key is the one that we care about, write the new key = value
value, otherwise copy the existing key = value
.
There's some fanciness here with keys that are allowed to repeat, vs keys that should only occur once; see the --replace-all
and --unset-all
options to git config
for details. Note that git config
itself knows little to nothing about most key and value pairs, and you can invent your own key/value pairs as long as you pick keys that Git is not using today and won't be using in the future. (How you figure out what Git will and won't use in, say, the year 2043, I have no idea. :-) ) The main exceptions are some of the core.*
values, which git config
does understand, and several other Git commands may set on their own.
(Note that --unset
is handled much the same as replacing. Like a non-all
replace, it only unsets the first matching key = value
pair. Unsetting is implemented by simply not writing the given key, instead of writing a replacement key = value
. Since git config
is simply working through the file line-by-line, that's easy to do. Also, if your key = value
is totally new, Git handles this by reading through all the lines, noticing that it did not replace any existing key
, and hence adding a new key = value
line. This is complicated a bit by the fact that the keys are listed section-by-section, but the logic itself is simple enough.)
Finally, having read through the entire existing configuration and completely written out the new one (using fflush
and fsync
and fclose
and so on as needed), git config
invokes the OS service to rename a file, in order to rename .git/config.lock
to .git/config
. This is where the process is failing in this particular case.
The rename, if it succeeds, has the effect of putting the new configuration into effect and removing the lock file, all as one atomic operation: any other Git command sees either the complete old configuration, from the original .git/config
file, or the complete new configuration, from the new .git/config
file that was known during construction as .git/config.lock
.
Another StackOverflow question asks: Will we ever be able to delete an open file in Windows? The accepted answer includes this statement: An anti virus product that does not open files with full sharing (including deletion) enabled is buggy. If that's the case—that is, if this particular AV software fails to open with the "allow delete" flag, and if such software is buggy, then this particular AV software is the problem and is buggy.
In my case using "sudo" worked for me. For example:
asif@asif-vm:/mnt/prog/protobuf_tut$ git clone https://github.com/protocolbuffers/protobuf.git
Cloning into 'protobuf'...
error: chmod on /mnt/prog/protobuf_tut/protobuf/.git/config.lock failed: Operation not permitted
fatal: could not set 'core.filemode' to 'false'
After doing a "sudo" I could get it working:
asif@asif-vm:/mnt/prog/protobuf_tut$ sudo git clone https://github.com/protocolbuffers/protobuf.git
Cloning into 'protobuf'...
remote: Enumerating objects: 5, done.
remote: Counting objects: 100% (5/5), done.
remote: Compressing objects: 100% (5/5), done.
remote: Total 66782 (delta 0), reused 0 (delta 0), pack-reused 66777
Receiving objects: 100% (66782/66782), 55.83 MiB | 2.04 MiB/s, done.
Resolving deltas: 100% (45472/45472), done.
Checking out files: 100% (2221/2221), done.