我有一个 Git checkout。所有文件的权限都与 Git 认为应该有的不同,因此它们都被显示为已修改。
在不触及文件内容的情况下(只想修改权限),如何将所有文件的权限设置为 Git 认为应该具备的权限?
我有一个 Git checkout。所有文件的权限都与 Git 认为应该有的不同,因此它们都被显示为已修改。
在不触及文件内容的情况下(只想修改权限),如何将所有文件的权限设置为 Git 认为应该具备的权限?
git diff -p
命令。所以我们只需要:
git diff -p -R --no-ext-diff --no-color --diff-filter=M \
| grep -E "^(diff|(old|new) mode)" --color=never \
| git apply
git config --global --add alias.permission-reset '!git diff -p -R --no-ext-diff --no-color --diff-filter=M | grep -E "^(diff|(old|new) mode)" --color=never | git apply'
git permission-reset
!git
周围使用'
而不是"
引号,否则它会被替换为您最后运行的git
命令。git diff
上简单使用-R
,就不再需要繁琐的sed
命令了。git config core.fileMode false
来自git config
手册:
core.fileMode
如果设置为false,则忽略索引和工作副本之间的可执行位差异;在像FAT这样的损坏文件系统上很有用。请参见git-update-index(1)。
默认值为true,除非在创建存储库时git-clone(1)或git-init(1)会探查并设置core.fileMode为false。
git checkout origin/master
是否可能将提交到服务器的文件权限设置为我的本地工作副本?因为每当我为ArangoDB构建V8时,文件权限都会更改,以便拒绝访问整个构建文件夹(即使具有提升的权限;Windows 7+)。在继续构建过程之前,我需要修复所有本地文件权限。core.filemode false
能否也解决这个问题?我怀疑 git 在我的 Windows 机器上设置了 Linux 权限。构建脚本可能只是保留它们并将相同的权限应用于新创建的文件... - CodeManXfilemode
设置为false
是否有任何不利影响! - kevoroidgit diff -p \
| grep -E '^(diff|old mode|new mode)' \
| sed -e 's/^old/NEW/;s/^new/old/;s/^NEW/new/' \
| git apply
这个命令通常可以工作,但是如果你安装了外部的 diff 工具(比如 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
在我的情况下是必要的。
Git不会存储除可执行脚本之外的文件权限。建议使用类似git-cache-meta的工具来保存文件所有权和权限。
Git只能存储两种类型的模式:755(可执行)和644(不可执行)。如果您的文件是444,Git将把它存储为644。
……一个100644的模式表示它是普通文件。其他选项有100755(表示可执行文件)和120000(指定符号链接)。该模式来自于标准的 UNIX 模式,但不够灵活——这三种模式是 Git 中文件(blob)有效的唯一模式(虽然其他模式用于目录和子模块)。
- esmail感谢 @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 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
awk '/modified/{print $3}'
),尽管这种解决方案无法正确处理文件名中的空格。幸运的是,有一个本地的 git 等效命令可以做到:git ls-files -m -z | xargs -0 chmod a-x
。 - hlovdalgit diff -p
在 muhqu's answer 中使用可能无法显示所有差异。
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 }'
(感谢http://transnum.blogspot.ru/2008/11/bashs-read-built-in-supports-0-as.html提供"$'\0'"的信用)
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