Git chmod problem: Checkout screws exec bit

10

4

Under Ubuntu and Debian the last committed files are getting the execution bit set, when I try a checkout afterwards. It's quite strange and driving me nuts:

$ ls -l file
-rw-r--r-- ... file

# on branch master:
$ git commit -m 'mode is 644' file
[master 0123456] mode is 644
 1 files changed, 1 insertions(+), 1 deletions(-)
# All ok

$ git checkout dev-branch
Switched to branch 'dev-branch'
# Seemingly all ok, but file now has the exec bit set

$ git merge master
Updating 6543210..0123456
error: Your local changes to 'file' would be overwritten by merge.  Aborting.
Please, commit your changes or stash them before you can merge.
# Oops...

$ ls -l file
-rwxr-xr-x ... file

Has anyone an idea, when and why the execution bit slips in? core.filemode is set to true.

I have the file open in vim during the branch switching, if that's important somehow.

Addendum 1: It's the checkout, where the permissions are screwed up. I can play the game on and on:

$ git br
* master
  dev-branch

$ git diff
diff --git a/file b/file
old mode 100644
new mode 100755

$ chmod 644 file

$ git diff

$ git checkout dev-branch

$ git diff
diff --git a/file b/file
old mode 100644
new mode 100755

$ chmod 644 file

$ git diff

$ git checkout master

$ git diff
diff --git a/file b/file
old mode 100644
new mode 100755

# ...and so on ad inf.

Addendum 2: This happens, by the way, for every file in this repository, that I commit. After the successful commit I can't switch branches without the permission screw-up.

Boldewyn

Posted 2010-10-29T12:04:20.397

Reputation: 3 835

Have you checked the permissions at the #seemingly all ok step... – RobotHumans – 2010-11-05T06:29:32.487

I agree here. On dev-branch, 'git-log master...HEAD -- file' and see if anything has changed between the branch and now on that file. – yuriismaster – 2010-11-05T08:50:29.913

@aking1012: Yes, at that point the file modes already changed. I'll update the question. – Boldewyn – 2010-11-05T09:49:30.680

@yuriismaster: git-log shows no output at all, for neither combination of master, dev-branch or HEAD (which is strange, isn't it? Shouldn't the command print the last commit message from master?) – Boldewyn – 2010-11-05T09:52:53.983

@Boldewyn that is quite odd... it looks like the file is always being set back to executable on checkout. Unless something is scripted-ly setting the ex flag, it maybe be an oddity in the index. Is there something in gitignore? I don't know if playing around with git-update-index will help (see ref at http://justaddwater.dk/2009/12/07/how-to-make-git-ignore-files-that-already-exist-in-your-project/ )

– yuriismaster – 2010-11-06T04:16:46.267

@yuriismaster: Yes, there is content in my .gitignore, but it is different from where the above problem occurs (in all branches). I didn't use update-index on this repository yet (I did it with anotzer on the same machines with --assume-unchanged, but that repository doesn't show this behaviour). – Boldewyn – 2010-11-06T13:05:45.233

2What filesystem are you on? – bitmask – 2010-11-07T22:20:04.223

@bitmask I have the same issue, also on Ubuntu. My filesystem is "cifs" with flags "rw". – dolmen – 2012-08-10T08:10:13.597

Answers

12

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.

harrymc

Posted 2010-10-29T12:04:20.397

Reputation: 306 093

1Actually, I try hard to commit the files with the correct permissions. I even re-committed all files after chmod'ing them. Since I work on Windows from time to time (not with this repo, though), I know about core.fileMode, but I hoped to be able to leave it true. – Boldewyn – 2010-11-05T09:13:24.220

It might even be a bug in git when working on what they call "broken filesystems". There are no broken filesystems, only broken software. – harrymc – 2010-11-05T09:42:45.573

As I said, the repos never have touched FAT or NTFS. They live happily on an cifs (mounted via samba) and an ext4. (OK, the cifs might come near a "broken FS", but I never had issues before.) – Boldewyn – 2010-11-05T09:56:20.080

I was just remarking on the negative attitude of the Git developers sweeping problems under the carpet. The permission mask might be another such problem. I suggest to use the above info to correct the permission mask of this file in the repo, and if this happens again (under controlled conditions), to disable core.filemode and launch a bug report. – harrymc – 2010-11-05T10:11:18.720

4i have to agree with the git developers that fat is broken – RobotHumans – 2010-11-05T13:44:17.297

true my bad on the flamebait – RobotHumans – 2010-11-05T14:19:07.573

@Boldewyn: After your Addendum 2, this looks more and more like a Git bug. If you have managed to narrow it down to such a simple and reproducible scenario, then I still think that the only solution is disabling core.filemode and launching a query on the Git community. – harrymc – 2010-11-06T16:37:29.690

3OK, it was the file system. I couldn't reproduce it on another machine, where the directory is mounted via NFS. On the main machine it is, as I said, CIFS. When I asked on the git mailing list, I got the answer, that CIFS is broken concerning execution bits. Darn! – Boldewyn – 2010-11-09T21:36:37.290

@Boldewyn: please add a link to your post in the mailing list archive. – dolmen – 2012-08-10T08:13:25.607

2

@dolmen: http://comments.gmane.org/gmane.comp.version-control.git/160861 :-)

– Boldewyn – 2012-08-10T10:21:22.077

3

Did you check whether there is a custom hook that is executed during commit or checkout? There might be some custom hooks tampering with your files. Checkout the githooks manpage.

Hooks are basically little programs called by git at certain events (commit, checkout etc.).

bandi

Posted 2010-10-29T12:04:20.397

Reputation: 654

Good try, but my .git/hooks directory is untouched. – Boldewyn – 2010-11-06T13:02:09.837

1

have you tried git commit -m 'mode is 644' file on branch dev-branch

to me it looks like what is happening is you are changing permissions on main then pulling down the dev branch that has the wrong permission, clobbering your local permission. then trying to commit again. either clone, change, commit, merge; or try changing the file individually with a single file commit into dev then merge

RobotHumans

Posted 2010-10-29T12:04:20.397

Reputation: 5 758

Actually, I never touch permissions in the original scenario. All permission changing is done by git in the 'checkout' step. – Boldewyn – 2010-11-06T13:00:00.980

...that is, I did some chmoding once on the files, but I can't unfortunately remember, if the problem started to occur right afterwards. I think, it did not. – Boldewyn – 2010-11-06T13:08:44.387

i tried to replicate you problem and i can't – RobotHumans – 2010-11-08T20:56:18.747

That's because you don't work on a mounted CIFS ;-). I forgot the +1 for the try, thanks! – Boldewyn – 2010-11-11T12:18:12.687

1

There are good answers at these links.

https://stackoverflow.com/questions/9027584/how-to-change-the-file-mode-on-github

and

https://stackoverflow.com/questions/1611211/how-do-i-make-git-accept-mode-changes-without-accepting-all-text-changes

Essentially you need to git update-index --chmod=(+|-)x <file> and this will add a change that you then need to commit and push to have the permissions added/removed.

dragon788

Posted 2010-10-29T12:04:20.397

Reputation: 634