972

For some reason, when I initially did a pull from the repository for a git project of mine, I got a ton of files in my working copy that have no discernible changes made to them, but keep showing up in my unstaged changes area.

I'm using Git Gui on Windows xp, and when I go to look at the file to see what has changed. All I see is:

old mode 100755  
new mode 100644  

Does anyone know what this means?

How can I get these files out of my list of unstaged changes? (Very annoying to have to go through 100's of files, just to pick out files I've recently edited and want to commit).

Lemmings19
  • 1,383
  • 3
  • 21
  • 34
concept47
  • 30,257
  • 12
  • 52
  • 74
  • For the full, gory details on what `core.filemode` is all about, see [my answer here](https://stackoverflow.com/a/69341082/1256452). Note that every Git repository is supposed to have its own `core.filemode` setting, set by Git at the time Git created that repository; that setting is *supposed* to be the right one for that one repository. If it's wrong for some reason, you can change it. – torek Sep 29 '21 at 16:48

17 Answers17

1696

That looks like unix file permissions modes to me (755=rwxr-xr-x, 644=rw-r--r--) - the old mode included the +x (executable) flag, the new mode doesn't.

This msysgit issue's replies suggests setting core.filemode to false in order to get rid of the issue:

git config core.filemode false
Lynn
  • 10,425
  • 43
  • 75
Amber
  • 507,862
  • 82
  • 626
  • 550
  • 173
    +1. This means that git thinks that it can correctly set the executable bit on checked out files, but when it attempts to do so it doesn't work (or at least not in a way that it can read). When it then reads back the status of those files it looks like the executable bit has been deliberately unset. Setting core.filemode to false tells git to ignore any executable bit changes on the filesystem so it won't view this as a change. If you do need to stage an executable bit change it does mean that you have to manually do `git update-index --chmod=(+|-)x `. – CB Bailey Aug 11 '09 at 06:49
  • 10
    If, like me, the mode changes are important, you can set core.filemode to false, commit your actual code changes, and then set core.filemode to true and git will preserve the file changes. – Michael T. Smith Sep 26 '09 at 18:48
  • 9
    I have the same problem, but it was due to using the same git repro via SSH git cmd line, and through Git Extensions on a mapped drive in Windows! . . Solution was the same, added into "config" [core] filemode = false – Ian Vaughan Mar 18 '10 at 09:07
  • 2
    That was a life saver, thank you sir! This happened to me on OSX, after I shared a cloned repository on the public folder and changed permissions for the files. – Thiago Ganzarolli Dec 01 '11 at 22:34
  • I ran `chmod -R 777 .` on a project directory without thinking it through. (I wanted some sloppy file access...) This resulted in Git picking up the file changes. Oops! I ended up running the command in this answer, pushing my changes, deleting the local branch, and then pulling the remote branch back down. Then I reversed the command in this answer. This alleviated the issue I had created in which everything was now set to `777`. – Lemmings19 Nov 01 '13 at 22:38
  • 1
    Newbie question: I have to do this in each repo instance? Or can it be saved somehow so when you do `git clone` this setting is already set? – robsch Mar 02 '15 at 13:14
  • 9
    @robsch You can use `git config --global ...` to set the option in your global config file. – Amber Mar 03 '15 at 02:38
  • 1
    @Amber Thanks. Actually I thought it could be part of a repository, so the setting gets considered with any clone and on any machine. Otherwise I have to document that this and that folder/file needs this and that file modifiers and anyone who clones has to set the modifiers manually. Which is cumbersome and error prone. – robsch Mar 03 '15 at 07:17
  • @robsch It doesn't really make sense to be part of a repository since it's a setting that has different implications on different platforms. – Amber Mar 03 '15 at 23:32
  • @Amber That's true. So setting the file permissions has to be done in a different way (manually, by script, ...). – robsch Mar 04 '15 at 07:15
  • 1
    Easily happens when you clone a repo that is primarily Linux-maintained into a Windows system (another issue is same file name with different case). Anyway I ran `git config --local -e` and modified (under `[core]`) `filemode = true` to `filemode = false`. Save and exit the text editor, and Git immediately stopped marking them as "modified". – ADTC Jan 13 '16 at 11:05
  • This was a great bit of advice, just a heads up for future users. This will work retroactively, as in, if you have this issue currently then it will be fixed after running the above command. My biggest concern was that after setting this config option, I would have to manually fix the existing issue with the files. Not the case, it was fixed immediately. – KoldBane May 23 '16 at 17:57
  • This saved my life. But I think that the answer should be updated to also advice about local configuration on the repo, which may overrid the global one. – Danielo515 Jun 02 '16 at 10:42
  • +1 thanks but I have a worry this may be affecting other people who pull the repo and have different local file permissions. Does anyone know if simply changing the file permission to what it was before helps remove the git change message? Is there an easy way to see what it is without the GUI? – aug Sep 26 '16 at 18:01
  • 1
    So the 644 and 755 are unix permission, but what does the `100` mean? – Robert Vanden Eynde Sep 21 '18 at 10:23
  • I have face the same issue. And this save my life: https://gist.github.com/jtdp/5443498 `git diff -p -R --no-color | grep -E "^(diff|(old|new) mode)" --color=never | git apply` – bkm Jan 24 '19 at 15:00
  • 4
    You can use `git config -l --show-origin` to see where each setting is coming from. – Khouri Giordano Nov 12 '19 at 18:32
  • this fix solve the issue, however if you want to restore the file mode, you can follow https://stackoverflow.com/questions/2517339/how-to-restore-the-permissions-of-files-and-directories-within-git-if-they-have/4408378#4408378 even it can be used in combination to resolve it, i.e.: if you have changes apart the of the file-mode changes, then you can set it to false, resolve your changes (or maybe stash it), and then apply the solution commented on the other thread, and at the end enable core.filemode to leave as before – Juan Antonio Aguilar May 16 '21 at 16:54
  • setting this config, before checking out -- all the affected files, doesn't change the `git status` output. – andreagalle May 11 '22 at 10:02
122

Setting core.filemode to false does work, but make sure the settings in ~/.gitconfig aren't being overridden by those in .git/config.

Honest Abe
  • 8,430
  • 4
  • 49
  • 64
NovelX
  • 1,321
  • 1
  • 8
  • 4
  • 3
    Been there, done that. Sadly I found your comment only after having solved the problem myself. Still, +1! – David Schmitt Feb 16 '11 at 15:23
  • 1
    If other users are cloning this project are on Windows, it might be best to actually just apply the change to the `~/.gitconfig` file! – Ian Vaughan Dec 13 '11 at 09:16
  • If you want to check on Windows Powershell. `git config --list --show-origin | sls filemode` or on Linux `git config --list --show-origin | grep filemode`. This will show you where you need to make the adjustments. – Frank Fu Feb 19 '19 at 06:31
  • The `core.filemode` setting is *supposed* to be set in *every* `.git/config`. It is created automatically whenever Git creates a new repository, during `git clone` or `git init`, based on how your OS and file system work. It's not supposed to be wrong, but if it is, that's where to fix the setting: in the one specific repository. – torek Sep 29 '21 at 16:44
79

This usually happens when the repo is cloned between Windows and Linux/Unix machines.

Just tell git to ignore filemode change. Here are several ways to do so:

  1. Config ONLY for current repo:

     git config core.filemode false
    
  2. Config globally:

     git config --global core.filemode false
    
  3. Add in ~/.gitconfig:

     [core]
          filemode = false
    

Just select one of them.

auspicious99
  • 3,902
  • 1
  • 44
  • 58
K. Symbol
  • 3,330
  • 1
  • 21
  • 22
53

I've encountered this problem when copying a git repo with working files from an old hard drive a couple times. The problem stems from the fact that the owner and permissions changed from the old drive/machine to the new one. The long and short of it is, run the following commands to straighten things out (thanks to this superuser answer):

sudo chmod -R -x . # remove the executable bit from all files

The former command will actually resolve the differences that git diff reported, but will revoke your ability to list the directories, so ls ./ fails with ls: .: Permission denied. To fix that:

sudo chmod -R +X . # add the executable bit only for directories

The bad news is that if you do have any files you want to keep executable, such as .sh scripts, you'll need to revert those. You can do that with the following command for each file:

chmod +x ./build.sh # where build.sh is the file you want to make executable again
Scott Willeke
  • 8,884
  • 1
  • 40
  • 52
  • 3
    Thanks, helped me a lot! One should also check that `git config core.filemode` is set to `true`, otherwise permission changes won't be detected. I also needed to refresh the git index after every change to pick it up. – pat-s Jan 19 '18 at 14:56
  • The reason for me having this issue is exactly as described here: I've transferred all my projects to another harddrive when switching to my new computer. Thanks. – philburns Jan 20 '22 at 10:16
16

I have faced the same issue. And this save my life:

This will revert all the permissions to what the diff is so you are left with nothing, but the changes you made to the files.

https://gist.github.com/jtdp/5443498

git diff -p -R --no-color \
| grep -E "^(diff|(old|new) mode)" --color=never  \
| git apply

More details in https://stackoverflow.com/a/4408378/450383

muhqu
  • 12,329
  • 6
  • 28
  • 30
bkm
  • 259
  • 3
  • 8
13

This worked for me:

git ls-files -m | xargs -L 1 chmod 644
eballo
  • 769
  • 1
  • 11
  • 20
8

The accepted answer to set git config core.filemode false, works, but with consequences. Setting core.filemode to false tells git to ignore any executable bit changes on the filesystem so it won't view this as a change. If you do need to stage an executable bit change for this repository anytime in the future, you would have to do it manually, or set core.filemode back to true.

A less consequential alternative, if all the modified files should have mode 100755, is to do something like

chmod 100755 $(git ls-files --modified)

which just does exactly the change in mode, no more, no less, without additional implications.

(in my case, it was due to a OneDrive sync with my filesystem on MacOS; by not changing core.filemode, I'm leaving the possibility open that the mode change might happen again in the future; in my case, I'd like to know if it happens again, and changing core.filemode will hide it from me, which I don't want)

auspicious99
  • 3,902
  • 1
  • 44
  • 58
5

This solution will change the git file permissions from 100755 to 100644 and push changes back to the bitbucket remote repo.

  1. Take a look at your repo's file permissions: git ls-files --stage

  2. If 100755 and you want 100644

    Then run this command: git ls-files --stage | sed 's/\t/ /g' | cut -d' ' -f4 | xargs git update-index --chmod=-x

  3. Now check your repo's file permissions again: git ls-files --stage

  4. Now commit your changes:

    git status
    git commit -m "restored proper file permissions"
    git push
    
ggorlen
  • 44,755
  • 7
  • 76
  • 106
3

It seems you have changed some permissions of the directory. I did the following steps to restore it.

$  git diff > backup-diff.txt                ### in case you have some other code changes 

$  git checkout .
SuperNova
  • 25,512
  • 7
  • 93
  • 64
3

This happens when you pull and all files were executable in the remote repository. Making them executable again will set everything back to normal again.

chmod +x <yourfile> //For one file
chmod +x folder/* // For files in a folder

You might need to do:

chmod -x <file> // Removes execute bit

instead, for files that was not set as executable and that was changed because of the above operation. There is a better way to do this but this is just a very quick and dirty fix.

IskandarG
  • 323
  • 1
  • 3
  • 9
1

You could try git reset --hard HEAD to reset the repo to the expected default state.

Doppelganger
  • 20,114
  • 8
  • 31
  • 29
  • 9
    If git wasn't able to set the executable bit correctly/consistently after a pull, it's not going to fair any better after a reset. – CB Bailey Aug 11 '09 at 06:34
  • This way works great for a copied repository where the copy has flipped the flag. – AndrewCr Nov 08 '10 at 22:05
  • I ended up here because that didn't work. As a matter of fact, I came here because I tried to do a hard reset of a branch, and I ended up with lots of diffs like this one. Amber's answer fixed that for me. – toon81 Dec 06 '13 at 13:30
  • 3
    I moved some projects to an usb drive (fat32) and back again to my ubuntu machine (ext4) and ended up with a bunch of changed files, well, the attributes. `git reset --hard HEAD` worked perfectly for me. thanks – cirovladimir Oct 06 '14 at 03:15
  • 9
    -1. OP states "just to pick out files I've recently edited and want to commit". This would remove those edits too. – whitfin Oct 06 '14 at 22:08
  • 12
    -1 Suggesting this command in git is similar to saying "you can just rm -rf ./, I'm sure it won't have any unintended consequences". – Kzqai Jun 24 '15 at 20:18
  • 2
    No, this doesn't help and this is the problem. You reset and clean and still git status is showing the mode changes. This is a serious problem with windows git and I think it should be fixed, not just worked around by ignoring the file mode. – vezenkov Aug 31 '15 at 12:54
  • A better approach might be `git checkout .` Of course that is not an answer to the original question, but it makes it very clear you are trying to get back to the state of the last commit and will lose any changes. It could help if you copied the project from another drive and you know there are not supposed to be any staged or unstaged changes. – still_dreaming_1 Nov 14 '15 at 15:22
  • 1
    I had the same problem as @cirovladimir, this solved it. – juliangonzalez Feb 01 '17 at 21:29
  • What about the actual code changes! – deepdive Nov 17 '21 at 01:15
1

You can use the following command to change your file mode back. git add --chmod=+x -- filename Then commit to the branch.

Wae
  • 106
  • 7
1

This is like what bkm found, but it also takes into account any deleted files and only gives a warning while still applying the changes.

This works well to revert file mode settings from previous commit.

git diff -p --no-ext-diff --no-color --diff-filter=d | grep -E "^(diff|old mode|new mode)" | sed -e "s/^old/NEW/;s/^new/old/;s/^NEW/new/" | git apply
Goddard
  • 2,863
  • 31
  • 37
1

A number of the solutions above will break if there are any deleted files.

This will list files that are only modified, and not deleted, and change them all to 755

git diff-files --name-only --diff-filter=d | xargs -L 1 chmod 755
riley
  • 2,387
  • 1
  • 25
  • 31
0

I had just the one troublesome file with the changed permissions. To roll it back individually, I just deleted it manually with rm <file> and then did a checkout to pull a fresh copy.

Luckily I had not staged it yet.

If I had I could have run git reset -- <file> before running git checkout -- <file>

kEnobus
  • 66
  • 5
0

I just ran into this issue when diffing my branch with master. Git returned one 'mode' error when I expected my branch to be identical to master. I fixed by deleting the file and then merging master in again.

First I ran the diff:

git checkout my-branch
git diff master

This returned:

diff --git a/bin/script.sh b/bin/script.sh
old mode 100755
new mode 100644

I then ran the following to fix:

rm bin/script.sh
git merge -X theirs master

After this, git diff returned no differences between my-branch and master.

Collin Krawll
  • 2,210
  • 17
  • 15
  • what is `theirs`? – KansaiRobot Jul 05 '21 at 11:25
  • `theirs` tells the merge to use the version in the other branch (not the current branch, which is referred to as `ours`). More info on `ours` vs `theirs` [here](https://stackoverflow.com/questions/31817210/git-confusion-over-terminology-theirs-vs-mine). – Collin Krawll Jul 08 '21 at 15:19
0

Run git from WSL2 for full Linux compatibility then there is no need for workarounds like flipping core.filemode before and after a commit.

Dave M
  • 1