我有一个git结帐。所有的文件权限都不同于git认为它们应该是什么,因此它们都显示为修改。
没有触及文件的内容(只是想修改权限),我如何设置所有文件的权限,git认为他们应该是什么?
Git不存储除可执行脚本以外的文件权限。考虑使用类似git-cache-meta的东西来保存文件所有权和权限。
Git只能存储两种模式:755(可执行)和644(不可执行)。如果你的文件是444,git会存储它的644。
最简单的方法就是把权限改回来。正如@kroger指出的,git只跟踪可执行位。所以你可能只需要运行chmod -x filename来修复它(如果需要的话,可以运行+x。
chmod -x filename
+x
尝试git config core.fileMode false
git config core.fileMode false
从git config手册页:
git config
core.fileMode 如果为false,则忽略索引和工作副本之间的可执行位差异;对FAT等损坏的文件系统很有用。看到git-update-index (1)。 默认为true,除非git-clone(1)或git-init(1)将探测和设置core。在创建存储库时,fileMode为false(如果合适)。
core.fileMode
如果为false,则忽略索引和工作副本之间的可执行位差异;对FAT等损坏的文件系统很有用。看到git-update-index (1)。
默认为true,除非git-clone(1)或git-init(1)将探测和设置core。在创建存储库时,fileMode为false(如果合适)。
你也可以尝试一个前/后结帐挂钩。
看:定制Git - Git钩子
Git会跟踪文件权限,并在使用git diff -p创建补丁时公开权限更改。所以我们只需要:
git diff -p
一句话:
git diff -p -R --no-ext-diff --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-ext-diff --no-color | grep -E "^(diff|(old|new) mode)" --color=never | git apply'
...你可以通过以下方式调用它:
git permission-reset
注意,如果你的shell是bash,请确保在!git周围使用'而不是"引号,否则它会被你运行的最后一个git命令所取代。
bash
!git
'
"
git
感谢@Mixologic指出,只要在git diff上使用-R,就不再需要繁琐的sed命令了。
git diff
-R
sed
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
在我的情况下需要什么
etckeeper工具可以处理权限和:
etckeeper
etckeeper init -d /mydir
你可以将它用于/etc以外的其他dirs。
/etc
使用你的包管理器安装或从上面的链接获取源代码。
在muhqu的回答中使用的git diff -p可能不能显示所有的差异。
core.filemode
false
这段代码直接读取元数据:
(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 }'
(Credit for "$'\0'" goes to http://transnum.blogspot.ru/2008/11/bashs-read-built-in-supports-0-as.html)子> < /
我在Windows上使用cygwin的git, git apply解决方案不适合我。这是我的解决方案,在每个文件上运行chmod来重置其权限。
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
感谢@muhqu的伟大回答。在我的例子中,并不是所有的更改文件都更改了权限,这阻止了命令的工作。
$ 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 -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'
我知道这很古老,但我来自谷歌,我没有找到答案
我有一个简单的解决办法:
git config core.fileMode true git reset --hard HEAD
我遇到了类似的问题,有人在服务器上的所有文件中添加了可执行标志,但是我也有本地修改的文件,除了那些权限被破坏的文件。然而,由于git唯一跟踪的权限是可执行标志,这个管道为我解决了这个问题:
git status | grep 'modified:' | awk '{print $3}' | xargs chmod a-x
基本上,该命令运行git status,过滤作为modifier报告的文件,通过awk提取它们的路径,并删除可执行标志。
awk