我有一个git checkout。所有文件权限都与git认为应该是的不同,因此它们都显示为已修改。
不触及文件内容(只想修改权限)如何将所有文件权限设置为git认为应该是什么?
答案 0 :(得分:496)
使用git diff -p
创建补丁时,Git会跟踪文件许可并公开权限更改。所以我们需要的是:
作为一个单行:
git diff -p -R --no-color \
| grep -E "^(diff|(old|new) mode)" --color=never \
| git apply
您也可以将它作为别名添加到您的git配置...
git config --global --add alias.permission-reset '!git diff -p -R --no-color | grep -E "^(diff|(old|new) mode)" --color=never | git apply'
...您可以通过以下方式调用它:
git permission-reset
注意,如果你的shell是bash
,请务必在'
周围使用"
而不是!git
引号,否则会被最后{{1}替换你运行的命令。
要求@Mixologic指出,只需在git
上使用-R
,就不再需要繁琐的git diff
命令。
答案 1 :(得分:101)
尝试git config core.fileMode false
注意:core.fileMode
区分大小写!
来自git config
手册页:
core.fileMode
如果为false,则忽略索引和工作副本之间的可执行位差异;对像FAT这样的破碎文件系统很有用。请参阅git-update-index(1)。
默认值为true,但git-clone(1)或git-init(1)将在创建存储库时探测并设置core.fileMode false。
答案 2 :(得分:8)
Git不存储可执行脚本以外的文件权限。请考虑使用git-cache-meta之类的内容来保存文件所有权和权限。
Git只能存储两种模式:755(可执行)和644(不可执行)。如果您的文件是444 git将存储它有644。
答案 3 :(得分:6)
git diff -p \
| grep -E '^(diff|old mode|new mode)' \
| sed -e 's/^old/NEW/;s/^new/old/;s/^NEW/new/' \
| git apply
在大多数情况下都可以使用,但是如果你有像meld这样的外部差异工具,你必须添加--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
在我的情况下需要
答案 4 :(得分:0)
您也可以尝试使用前/后结帐钩子来解决这个问题。
答案 5 :(得分:0)
我在Windows上使用cygwin的git,git apply
解决方案对我不起作用。这是我的解决方案,在每个文件上运行chmod
以重置其权限。
#!/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
答案 6 :(得分:0)
感谢@muhqu出色的answer。就我而言,并非所有更改文件的权限都已更改,这阻止了该命令的工作。
$ 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
然后补丁将停止并且文件将保持不变。
如果有人遇到类似的问题,我可以通过调整命令以仅更改权限已更改的文件来grep来解决此问题:
grep -E "^old mode (100644|100755)" -B1 -A1
或git别名
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'
答案 7 :(得分:0)
我知道这很老,但是我来自Google,却没有找到答案
如果您没有要保留的更改,我有一个简单的解决方案:
git config core.fileMode true
git reset --hard HEAD
答案 8 :(得分:0)
我遇到了类似的问题,有人向服务器上的所有文件添加了可执行标志,但是除了权限损坏的文件之外,我还有本地修改过的文件。然而,由于 git 跟踪的唯一权限是可执行标志,这个管道为我解决了这个问题:
git status | grep 'modified:' | awk '{print $3}' | xargs chmod a-x
基本上该命令运行 git status,过滤报告为修饰符的文件,通过 awk
提取它们的路径,并删除可执行标志。
答案 9 :(得分:-1)
最简单的方法是重新更改权限。正如@kroger所说,git只跟踪可执行位。因此,您可能只需要运行chmod -x filename
来修复它(或+x
,如果需要的话。
答案 10 :(得分:-1)
git diff -p
可能不会显示所有差异。
core.filemode
为false
(这是MSysGit的默认设置),此代码直接读取元数据:
(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)
非生产级单线(完全替换面具):
git ls-tree HEAD | perl -ne '/^10(0\d{3}) blob \S+\t(.+)$/ && { system "chmod",$1,$2 || die }'
(" $' \ 0'"转到http://transnum.blogspot.ru/2008/11/bashs-read-built-in-supports-0-as.html)
答案 11 :(得分:-2)