2815

I have a project in which I have to change the mode of files with chmod to 777 while developing, but which should not change in the main repo.

Git picks up on chmod -R 777 . and marks all files as changed. Is there a way to make Git ignore mode changes that have been made to files?

VonC
  • 1,262,500
  • 529
  • 4,410
  • 5,250
Ro Marcus Westin
  • 28,490
  • 4
  • 18
  • 11
  • 48
    This is helpful when working with git on Windows + Bash on Ubuntu on Windows – Elazar Jan 05 '17 at 19:50
  • 10
    For anyone who just wants to ignore permission changes for a specific invocation of `git diff`, and who therefore does not want to alter their Git configuration files: you can use `git diff -G.` per [Zed's](https://stackoverflow.com/users/19202/zed) answer [here](https://stackoverflow.com/a/22389011/82216). –  May 31 '18 at 14:19

14 Answers14

4677

Try:

git config core.fileMode false

From git-config(1):

core.fileMode
    Tells Git if the executable bit of files in the working tree
    is to be honored.

    Some filesystems lose the executable bit when a file that is
    marked as executable is checked out, or checks out a
    non-executable file with executable bit on. git-clone(1)
    or git-init(1) probe the filesystem to see if it handles the 
    executable bit correctly and this variable is automatically
    set as necessary.

    A repository, however, may be on a filesystem that handles
    the filemode correctly, and this variable is set to true when
    created, but later may be made accessible from another
    environment that loses the filemode (e.g. exporting ext4
    via CIFS mount, visiting a Cygwin created repository with Git
    for Windows or Eclipse). In such a case it may be necessary
    to set this variable to false. See git-update-index(1).

    The default is true (when core.filemode is not specified
    in the config file).

The -c flag can be used to set this option for one-off commands:

git -c core.fileMode=false diff

Typing the -c core.fileMode=false can be bothersome and so you can set this flag for all git repos or just for one git repo:

# this will set your the flag for your user for all git repos (modifies `$HOME/.gitconfig`)
# WARNING: this will be override by local config, fileMode value is automatically selected with latest version of git.
# This mean that if git detect your current filesystem is compatible it will set local core.fileMode to true when you clone or init a repository.
# Tool like cygwin emulation will be detected as compatible and so your local setting WILL BE SET to true no matter what you set in global setting.
git config --global core.fileMode false

# this will set the flag for one git repo (modifies `$current_git_repo/.git/config`)
git config core.fileMode false

Additionally, git clone and git init explicitly set core.fileMode to true in the repo config as discussed in Git global core.fileMode false overridden locally on clone

Warning

core.fileMode is not the best practice and should be used carefully. This setting only covers the executable bit of mode and never the read/write bits. In many cases you think you need this setting because you did something like chmod -R 777, making all your files executable. But in most projects most files don't need and should not be executable for security reasons.

The proper way to solve this kind of situation is to handle folder and file permission separately, with something like:

find . -type d -exec chmod a+rwx {} \; # Make folders traversable and read/write
find . -type f -exec chmod a+rw {} \;  # Make files read/write

If you do that, you'll never need to use core.fileMode, except in very rare environment.

Stargateur
  • 24,473
  • 8
  • 65
  • 91
Greg Hewgill
  • 951,095
  • 183
  • 1,149
  • 1,285
  • 235
    If you do `git config --global core.filemode false` you'll only need to do this once for all repos. – Greg Oct 21 '12 at 20:05
  • 22
    this didn't work for me until I've fixed the case it should be fileMode instead of filemode – tishma Oct 31 '12 at 10:02
  • 11
    @tishma: Git configuration section and variable names are [case insensitive according to the documentation, see the CONFIGURATION FILE section](https://www.kernel.org/pub/software/scm/git/docs/git-config.html), so if the above didn't work for you then it was for a different reason. – Greg Hewgill Oct 31 '12 at 18:24
  • 2
    If you get into the situation where you have to change file permission and commit the in git from a windows machine: http://blog.lesc.se/2011/11/how-to-change-file-premissions-in-git.html – fooMonster May 17 '13 at 19:19
  • This is not working for me :(, however solution given by @Sinan Eldom worked for me. But that is per project basis. What is the global solution to it. – shairya Aug 12 '13 at 07:26
  • This is all nice, but which config file does this go to? – donquixote Nov 27 '13 at 02:34
  • 14
    @donquixote: The `git config` command writes the setting to the correct config file (`.git/config` for just the current repository, or `~/.gitconfig` if used with `--global`). – Greg Hewgill Nov 27 '13 at 21:15
  • Thanks. Maybe would be useful to add that to the answer for completeness? – donquixote Nov 28 '13 at 00:56
  • 2
    @GregHewgill: Does this ignore mode changes on commit? It seems as though samba sets files to +x when saving from windows. Will setting fileMode to false do an update-index if I'm committing it anyway? Or will it just commit the text changes but not the chmod changes? Thanks! – Jordan Dec 17 '13 at 19:42
  • 3
    If it is not working try this: `git filter-branch -f --tree-filter 'find * -type f | xargs chmod 644 ' -- --all` – WonderLand Feb 07 '14 at 11:17
  • 4
    I had to `git init` for this config to take effect. – Gra Aug 18 '14 at 13:14
  • 2
    After recovering from a corrupted git repository my files had the wrong permissions. It was better to actually re-set them instead of making git ignore them: find . -type d | xargs chmod 0755 find . -type f | xargs chmod 0644 (http://stackoverflow.com/questions/14892289/is-this-correct-to-re-set-up-permissions-for-rails-app) – Yo Ludke Oct 09 '14 at 12:50
  • 2
    `filemode` or `fileMode` exactly? – zx1986 May 23 '15 at 06:48
  • 11
    @zx1986: It doesn't matter. From [git config](https://git-scm.com/docs/git-config): "The variable names are case-insensitive, ..." – Greg Hewgill May 23 '15 at 07:03
  • 8
    @greg even after doing a global edit, it will not work if the local config already had filemode=True. The local value will override the global setting... i had to go to every repo in my machine and change the local config value of filemode to false for each of the local repos – Rakib Jul 09 '15 at 19:22
  • @greg i tried and failed with your suggestion... Hence, i reached you out. – Rakib Jul 09 '15 at 19:38
  • @syedrakib Oh wow, a 2012 flashback... It was the right Greg after all. – Greg Jul 09 '15 at 19:40
  • @greg yeah... Posts on the internet don't have an expiry date – Rakib Jul 09 '15 at 19:43
  • @GregHewgill you should have created a secondary account and upvoted your post to thank yourself. – naneri Oct 13 '15 at 07:17
  • 1
    I tryed git config core.fileMode false and worked for me, thanks for sharing. For those interested, it seems that this setting is not inherited and should be reapplied if the repo is included as submodule. – Gianluca Casati Nov 27 '15 at 19:34
  • 1
    Whenever I initialize a new repository (git init), the setting is back to "true" for the new repo.. (after doing git config --global core.filemode false) – donquixote Jan 03 '16 at 05:06
  • 8
    To get the file/directory permissions to work on OSX and ubuntu (I was getting an `find: unknown predicate '-t'` error), I had to change it to this: `find . -type d -exec chmod 755 {} \;` and `find . -type f -exec chmod 644 {} \;` – SammyK Feb 21 '16 at 18:41
  • 11
    PLEASE add a second warning to this answer, stating that the global setting won't be applied to existing repos! For each repo you need to run the local command (or it seems "git init" has the same effect). This will affect pretty much everyone and can be extremely confusing (esp. when you first interact with a second repo and have no idea why the global setting isn't working when it worked on the first repo, where you ran both the global and local versions of the setting change.) – jerclarke Mar 01 '16 at 20:42
  • @GregHewgill If I use git config core.sharedRepository true then would I need to change fileMode? – Duc Tran Jul 28 '16 at 22:59
  • with chmod you can use +/-X tu change the executable bit for folders only, for example, `chmod +X somefile` is a noop, while `chmod +X somedir` will set the execute bit on that dir – Geoffrey Bachelet Aug 03 '16 at 19:50
  • 2
    The description has been changed and reflects the problem more correctly now `core.fileMode ... Some filesystems lose the executable bit when a file that is marked as executable is checked out, or checks out an non-executable file with executable bit on. git-clone[1] or git-init[1] probe the filesystem to see if it handles the executable bit correctly and this variable is automatically set as necessary.` – phuclv Mar 20 '17 at 04:18
  • FAT is not "broken" in this sense because obviously it's not designed for Unix, so can't store those permissions. The same problem can occur in NTFS, exFAT or when mounting via NFS... `A repository, however, may be on a filesystem that handles the filemode correctly, and this variable is set to true when created, but later may be made accessible from another environment that loses the filemode (e.g. exporting ext4 via CIFS mount, visiting a Cygwin created repository with Git for Windows or Eclipse). In such a case it may be necessary to set this variable to false. See git-update-index[1].` – phuclv Mar 20 '17 at 04:20
  • 3
    --global will only take effect with newly cloned repositories. – jgmjgm Nov 22 '17 at 15:47
  • very rare environment = vagrant on ubuntu with ubuntu? :( – Menasheh Feb 08 '18 at 23:51
  • 4
    I don't know whether the behaviour has changed, but `core.fileMode` is now set explicitly in the per-repo git config on clone. So `git config --global core.filemode false` as suggested in the top comment will have no effect, as it's overridden by the local setting. – mtripp100 Nov 16 '18 at 17:26
  • @mtripp100 Like all other git settings, the local setting only overrides the global if it is present. If not present, the global setting is used. See `man git-config`. – Greg Hewgill Nov 17 '18 at 18:01
  • 5
    @GregHewgill sure, I just wanted to highlight that unlike most other settings (such as `autocrlf`), the git binary will set `core.filemode` locally for each repo on clone: [git-clone or git-init probe the filesystem to see if it handles the executable bit correctly and this variable is automatically set as necessary.](https://git-scm.com/docs/git-config#git-config-corefileMode) – mtripp100 Nov 18 '18 at 14:34
  • 2
    I may have came back to this line around 9876 times, easier to find this than to remember :) – vknyvz Jan 24 '19 at 20:17
  • In our production environment for a client, the index.php file needs to be 655. IN dev and staging, 755. So I set the index.php to 655, deployed to prod and dev. Set file perms to false on dev, and there changed the permissions on dev to 755. One reconciled git repo with different permissions! – dustbuster Feb 27 '19 at 17:50
  • 3
    Note that `git init` and `git clone` will ignore the `--global` setting and explicitly set `core.filemode` to `true`. See https://stackoverflow.com/questions/30392318/git-global-core-filemode-false-overridden-locally-on-clone for workaround ideas. – here Sep 17 '19 at 22:26
  • I needed to add sudo for it to work. So the full command was: `sudo git config core.fileMode false` – Jules Colle Apr 17 '21 at 10:54
  • It seems that Changes of the global AND system (`--system`) setting won't be applied to existing repositories. – Timo Jun 10 '21 at 19:34
  • You've visited this page many times. Last visit: 8/5/21 Indeed. – Blazinator Aug 05 '21 at 17:41
  • 2
    This is the 50th time I came here to remember the command. – John Jiang Mar 23 '22 at 03:30
  • I needed this when I had mounted a remote directory with sshfs and ran git pull. Got the "fatal detected dubious ownership in repository"; not sure but suspecting it was because the files and folders on the remote machine mismatched user and group uids (and none of those uids existed on my local machine). – Arno Teigseth Jul 29 '22 at 01:03
325

undo mode change in working tree:

git diff --summary | grep --color 'mode change 100755 => 100644' | cut -d' ' -f7- | xargs -d'\n' chmod +x
git diff --summary | grep --color 'mode change 100644 => 100755' | cut -d' ' -f7- | xargs -d'\n' chmod -x

Or in mingw-git

git diff --summary | grep  'mode change 100755 => 100644' | cut -d' ' -f7- | xargs -e'\n' chmod +x
git diff --summary | grep  'mode change 100644 => 100755' | cut -d' ' -f7- | xargs -e'\n' chmod -x

Or in BSD/macOS

git diff --summary | grep --color 'mode change 100644 => 100755' | cut -d' ' -f7- | tr '\n' '\0' | xargs -0 chmod -x
git diff --summary | grep --color 'mode change 100755 => 100644' | cut -d' ' -f7- | tr '\n' '\0' | xargs -0 chmod -x
Afriza N. Arief
  • 7,696
  • 5
  • 47
  • 74
yoda
  • 4,859
  • 3
  • 19
  • 9
158

If you want to set this option for all of your repos, use the --global option.

git config --global core.filemode false

If this does not work you are probably using a newer version of git so try the --add option.

git config --add --global core.filemode false

If you run it without the --global option and your working directory is not a repo, you'll get

error: could not lock config file .git/config: No such file or directory
Arslan Ali
  • 17,418
  • 8
  • 58
  • 76
adrien
  • 1,713
  • 1
  • 10
  • 2
  • 7
    Looks like later GIT uses `--add`, as in `git config --add --global core.filemode false` – mgaert Apr 04 '13 at 10:56
  • 20
    If the repo's local config already has filemode=true then changing the global config won't help as the local config will override the global config. Will have to change local config of each repo of the machine once – Rakib Jul 09 '15 at 19:40
  • 5
    PLEASE: Update this answer with syedrakib's warning! Everything felt insane before I found it, and made perfect sense after. – jerclarke Mar 01 '16 at 20:43
116

If

git config --global core.filemode false

does not work for you, do it manually:

cd into yourLovelyProject folder

cd into .git folder:

cd .git

edit the config file:

nano config

change true to false

[core]
        repositoryformatversion = 0
        filemode = true

->

[core]
        repositoryformatversion = 0
        filemode = false

save, exit, go to upper folder:

cd ..

reinit the git

git init

you are done!

Sinan Eldem
  • 5,564
  • 3
  • 36
  • 37
  • 16
    Instead of editing `.git/config`, a simple `git config core.fileMode false` in the root of your project is enough. If you edit the config file, you're better of removing the directive entirely, so that the global one is picked up. – Felix Jan 13 '14 at 12:50
  • 9
    -1 if git config --global doesn't work it means you don't have the permissions to do it at the system level, removing `global` option does exactly the same thing as manually editing .git/config – CharlesB Apr 10 '14 at 07:57
  • 1
    @CharlesB incorrect - the answered provided a workaround by putting the option directly in the project, making it project-specific. This will not work with other git projects that you make/checkout in the future, but does work for the project you're working on. (let's make sure we disambiguate `~/.gitconfig`, and `~/project/.git/config`) – ddavison Aug 04 '17 at 19:54
  • 2
    Once this has run `git init` should we set filemode back to true? – Jordan Nov 20 '17 at 20:53
  • 2
    `git init` returns filemode back to TRUE! – Geka P Feb 28 '21 at 10:24
58

Adding to Greg Hewgill answer (of using core.fileMode config variable):

You can use --chmod=(-|+)x option of git update-index (low-level version of "git add") to change execute permissions in the index, from where it would be picked up if you use "git commit" (and not "git commit -a").

Community
  • 1
  • 1
Jakub Narębski
  • 309,089
  • 65
  • 217
  • 230
  • 2
    This should have been edited into Greg Hewgill's answer rather than added as a separate answer, thus creating one supreme answer with a single unambiguous representation. – Greg Jun 13 '12 at 12:37
  • 6
    @Greg: One needs to have enough points to edit not own answer; I think I didn't have enough for editing permissions at that time. – Jakub Narębski Jun 15 '12 at 16:34
  • 1
    @Jakub I think you have enough reputation now :) What would this command look like for an example file? – Alex Hall May 03 '18 at 20:09
50

You can configure it globally:

git config --global core.filemode false

If the above doesn't work for you, the reason might be your local configuration overrides the global configuration.

Remove your local configuration to make the global configuration take effect:

git config --unset core.filemode

Alternatively, you could change your local configuration to the right value:

git config core.filemode false

Tyler Liu
  • 19,552
  • 11
  • 100
  • 84
  • 5
    If the main answer doesn't help you - try this one. If you want to check your local config without modifying it, check `git config -l` (list current config - both local and global) – Krzysztof Bociurko Dec 14 '15 at 19:41
  • Removing local configuration is why global didn't work for me. Thanks! – Greadimar Mar 11 '21 at 14:14
26

If you have used chmod command already then check the difference of file, It shows previous file mode and current file mode such as:

new mode : 755

old mode : 644

set old mode of all files using below command

sudo chmod 644 .

now set core.fileMode to false in config file either using command or manually.

git config core.fileMode false

then apply chmod command to change the permissions of all files such as

sudo chmod 755 .

and again set core.fileMode to true.

git config core.fileMode true

For best practises don't Keep core.fileMode false always.

Kishor Vitekar
  • 537
  • 5
  • 12
  • Are you saying that an entire project (in development, staging, and production) should be 755? – Daniel Feb 01 '16 at 22:48
  • @Daniel Feb: No. change the mode of necessary files only. – Kishor Vitekar Feb 10 '16 at 05:09
  • `For best practises don't Keep core.fileMode false always` what do you mean, you should explain that. – bg17aw Jun 22 '16 at 12:43
  • 1
    `For best practises don't Keep core.fileMode false always.` Some filesystems (FAT for example) don't support file permissions, so the OS will report a default value (766 on my system anyway). In this case, `core.filemode` is absolutely necessary in the local config, unless you want to bloat the commit history with unnecessary and unintentional permission changes – KevinOrr Oct 19 '16 at 17:39
  • Also, why do you bother changing the perms back at all? If you set `core.filemode=false` then git will ignore execute bit changes, no need to change local permissions. Unless you've already added permission changes to the index, in which case you're missing the step where you would need to `git add` after you turn off `core.filemode`. – KevinOrr Oct 19 '16 at 17:47
  • I was wondering what happens if I have this situation (with modified permissions) and then I use `git config core.fileMode false`. while after setting this some files will not be seen as modified (the ones that will have only permissions changes) but others that had other changes beyond permissions e.g valid code modifications etc will still be seen as modified due to code changes. If I commit these files will the mod change also be committed as part of it? – Raja Ehtesham Oct 21 '16 at 11:15
  • @RajaEhtesham No, though you probably already figured that out. The only things that are commited are what you stage for commit (i.e. the files that you `git add`, and the changes you see when you run`git status`) – KevinOrr Nov 03 '16 at 13:09
22

By definining the following alias (in ~/.gitconfig) you can easily temporarily disable the fileMode per git command:

[alias]
nfm = "!f(){ git -c core.fileMode=false $@; };f"

When this alias is prefixed to the git command, the file mode changes won't show up with commands that would otherwise show them. For example:

git nfm status
Tomasz Gandor
  • 8,235
  • 2
  • 60
  • 55
Ville
  • 4,088
  • 2
  • 37
  • 38
14

If you want to set filemode to false in config files recursively (including submodules) : find -name config | xargs sed -i -e 's/filemode = true/filemode = false/'

Rey0bs
  • 1,192
  • 12
  • 19
  • 6
    This won't work if that line is not in the config file. If you want to change it for submodules, try this: `git submodule foreach git config core.fileMode false` – courtlandj Nov 14 '14 at 19:39
6

Simple solution:

Hit this Simple command in project Folder(it won't remove your original changes) ...it will only remove changes that had been done while you changed project folder permission

command is below:

git config core.fileMode false

Why this all unnecessary file get modified: because you have changed the project folder permissions with commend sudo chmod -R 777 ./yourProjectFolder

when will you check changes what not you did? you found like below while using git diff filename

old mode 100644
new mode 100755
0xC0000022L
  • 20,597
  • 9
  • 86
  • 152
Shashwat Gupta
  • 5,071
  • 41
  • 33
3

This works for me:

find . -type f -exec chmod a-x {} \;

or reverse, depending on your operating system

find . -type f -exec chmod a+x {} \;
Martin Volek
  • 315
  • 2
  • 13
2

This may work: git config core.fileMode false

  • 6
    How would that be any different from the [top answer](https://stackoverflow.com/a/1580644/6309)? – VonC Dec 28 '21 at 18:28
2

if you set : sudo chmod 777 -R

you can run : git config core.fileMode false

you can sée : https://www.w3docs.com/snippets/git/how-to-make-git-ignore-file-mode-changes.html

1

You don't need to change the config file.

Just run:

git diff -G.

Note that the trailing dot is not end of sentence, but regex expression that matches everything, and must be included.

Daniel Reis
  • 12,944
  • 6
  • 43
  • 71