I have a git checkout. All the file permissions are different than what git thinks they should be therefore they all show up as modified.
Without touching the content of the files (just want to modify the permissions) how do I set all the files permissions to what git thinks they should be?
This question is related to
git
file
file-permissions
i know this is old, but i came from google and i didn't find an answer
i have a simple solution if you have no change you want to keep :
git config core.fileMode true
git reset --hard HEAD
git diff -p
used in muhqu's answer may not show all discrepancies.
core.filemode
is false
(which is the default for MSysGit)This code reads the metadata directly instead:
(set -o errexit pipefail nounset;
git ls-tree HEAD -z | while read -r -d $'\0' mask type blob path
do
if [ "$type" != "blob" ]; then continue; fi;
case "$mask" in
#do not touch other bits
100644) chmod a-x "$path";;
100755) chmod a+x "$path";;
*) echo "invalid: $mask $type $blob\t$path" >&2; false;;
esac
done)
A non-production-grade one-liner (replaces masks entirely):
git ls-tree HEAD | perl -ne '/^10(0\d{3}) blob \S+\t(.+)$/ && { system "chmod",$1,$2 || die }'
(Credit for "$'\0'" goes to http://transnum.blogspot.ru/2008/11/bashs-read-built-in-supports-0-as.html)
Try git config core.fileMode false
From the git config
man page:
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).
The default is true, except git-clone(1) or git-init(1) will probe and set core.fileMode false if appropriate when the repository is created.
You could also try a pre/post checkout hook might do the trick.
Git doesn't store file permissions other than executable scripts. Consider using something like git-cache-meta to save file ownership and permissions.
Git can only store two types of modes: 755 (executable) and 644 (not executable). If your file was 444 git would store it has 644.
I use git from cygwin on Windows, the git apply
solution doesn't work for me. Here is my solution, run chmod
on every file to reset its permissions.
#!/bin/bash
IFS=$'\n'
for c in `git diff -p |sed -n '/diff --git/{N;s/diff --git//g;s/\n/ /g;s# a/.* b/##g;s/old mode //g;s/\(.*\) 100\(.*\)/chmod \2 \1/g;p}'`
do
eval $c
done
unset IFS
Thanks @muhqu for his great answer. In my case not all changes files had permissions changed which prevented the command to work.
$ git diff -p -R --no-ext-diff --no-color | grep -E "^(diff|(old|new) mode)" --color=never
diff --git b/file1 a/file1
diff --git b/file2 a/file2
old mode 100755
new mode 100644
$ git diff -p -R --no-ext-diff --no-color | grep -E "^(diff|(old|new) mode)" --color=never | git apply
warning: file1 has type 100644, expected 100755
The patch would then stop and files would be left untouched.
In case some people have similar problem I solved this by tweaking the command to grep only files with permission changed:
grep -E "^old mode (100644|100755)" -B1 -A1
or for the git alias
git config --global --add alias.permission-reset '!git diff -p -R --no-ext-diff --no-color | grep -E "^old mode (100644|100755)" -B1 -A1 --color=never | git apply'
git diff -p \
| grep -E '^(diff|old mode|new mode)' \
| sed -e 's/^old/NEW/;s/^new/old/;s/^NEW/new/' \
| git apply
will work in most cases but if you have external diff tools like meld installed you have to add --no-ext-diff
git diff --no-ext-diff -p \
| grep -E '^(diff|old mode|new mode)' \
| sed -e 's/^old/NEW/;s/^new/old/;s/^NEW/new/' \
| git apply
was needed in my situation
The etckeeper
tool can handle permissions and with:
etckeeper init -d /mydir
You can use it for other dirs than /etc
.
Install by using your package manager or get sources from above link.
The easiest thing to do is to just change the permissions back. As @kroger noted git only tracks executable bits. So you probably just need to run chmod -x filename
to fix it (or +x
if that's what's needed.
Source: Stackoverflow.com