2955

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?

2
  • 57
    This is helpful when working with git on Windows + Bash on Ubuntu on Windows Commented Jan 5, 2017 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 answer here. Commented May 31, 2018 at 14:19

12 Answers 12

4902

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 repositories or just for one Git repository:

# This will set your the flag for your user for all Git repositories (modifies `$HOME/.gitconfig`) # WARNING: this will be overridden by the local configuration, and the fileMode value is automatically selected with the latest version of Git. # This means that if Git detects your current filesystem is compatible, it will set the local core.fileMode to true when you clone or init a repository. # A 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 the global setting. git config --global core.fileMode false # This will set the flag for one Git repository (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 repository configuration 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 environments.

Sign up to request clarification or add additional context in comments.

41 Comments

If you do git config --global core.filemode false you'll only need to do this once for all repos.
this didn't work for me until I've fixed the case it should be fileMode instead of filemode
@tishma: Git configuration section and variable names are case insensitive according to the documentation, see the CONFIGURATION FILE section, so if the above didn't work for you then it was for a different reason.
@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).
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.)
|
329

Undo a mode change in the 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 

13 Comments

On OS X Lion, omit the -d'\n' part from xargs as this is an illegal argument (and not needed).
You can ignore any errors about "chmod: missing operand after `+x'"
is this up to date? I get 'chmod: too few arguments' in mingw
@Pascal @pimlottc The -d specifies the delimiter to be newline instead of any whitespace. BSD xargs doesn't have that option, but instead you can pipe the output through tr '\n' '\0' and then use the -0 arg to xargs to use NUL as the delimiter.
Cool, the tr thing worked! Here's the full command for OSX: git diff --summary | grep --color 'mode change 100644 => 100755' | cut -d' ' -f7-|tr '\n' '\0'|xargs -0 chmod -x
|
171

If you want to set this option for all of your repositories, 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 repository, you'll get

error: could not lock config file .git/config: No such file or directory

3 Comments

Looks like later GIT uses --add, as in git config --add --global core.filemode false
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
PLEASE: Update this answer with syedrakib's warning! Everything felt insane before I found it, and made perfect sense after.
121

If

git config --global core.filemode false 

does not work for you, do it manually:

cd into yourLovelyProject folder 

cd into the .git folder:

cd .git 

Edit the configuration file:

nano config 

Change "true" to "false":

[core] repositoryformatversion = 0 filemode = true 

->

[core] repositoryformatversion = 0 filemode = false 

Save, exit, and go to the upper folder:

cd .. 

Reinit the Git instance:

git init 

You are done!

5 Comments

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.
-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 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)
Once this has run git init should we set filemode back to true?
git init returns filemode back to TRUE!
59

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

You can use the --chmod=(-|+)x option of git update-index (a 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").

3 Comments

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: 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 I think you have enough reputation now :) What would this command look like for an example file?
57

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

2 Comments

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)
Removing local configuration is why global didn't work for me. Thanks!
28

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

new mode: 755

old mode: 644

Set the old mode of all files using the below command:

sudo chmod 644 . 

Now set core.fileMode to false in the configuration file, either using a command or manually.

git config core.fileMode false 

Then apply the 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 at false always.

7 Comments

Are you saying that an entire project (in development, staging, and production) should be 755?
@Daniel Feb: No. change the mode of necessary files only.
For best practises don't Keep core.fileMode false always what do you mean, you should explain that.
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
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.
|
22

By defining the following alias (in file ~/.gitconfig), you can easily temporarily disable the fileMode per the 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 

1 Comment

Why not just a pre-commit hook instead of a forgettable parameter?
14

If you want to set filemode to false in configuration files recursively (including submodules):

find -name config | xargs sed -i -e 's/filemode = true/filemode = false/' 

1 Comment

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
8

A simple solution:

Hit this simple command in the project folder (it won't remove your original changes); it will only remove changes that had been done while you changed the project folder permissions.

The command is below:

git config core.fileMode false 

Why this all unnecessary file get modified: because you have changed the project folder permissions with command

sudo chmod -R 777 ./yourProjectFolder 

When will you check changes what not you did? You found like the below while using git diff filename:

old mode 100644 new mode 100755 

1 Comment

This answer duplicates Greg Hewgill's answer from 10 years before.
4

You don't need to change the configuration file.

Just run:

git diff -G. 

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

1 Comment

Even though I changed config, that didn't work. But your solution works
3

This works for me:

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

Or the reverse, depending on your operating system:

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

2 Comments

This would change the permissions of the file, but not make git ignore the file permissions of the file.
Well, you are right, that does not resolve git ignore thing.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.