如果已修改git中的文件和目录的权限,如何还原它们?


Answers:


572

当使用来创建补丁时,Git会跟踪文件权限并公开权限更改git diff -p。因此,我们需要做的是:

  1. 创建一个反向补丁
  2. 仅包括权限更改
  3. 将补丁应用到我们的工作副本

作为单线:

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您运行的最后一个命令代替。

感谢@Mixologic指出,只需使用-Ron git diffsed就不再需要繁琐的命令。


3
我在OS X中,这不起作用。我已经确定问题出在git apply中。它不应用文件权限更改。
pepper_chico 2012年

15
哦,行得通,我试图从不同于存储库根目录的目录中应用。git apply仅适用于此。
pepper_chico 2012年

6
是否有某些原因您不愿意执行“ git diff -p -R”而不是执行sed来使其反转?
Mixologic 2013年

6
使用muhqu的命令时@RobQuist我的本地更改未删除
名言

17
我得到fatal: unrecognized input
Tieme,2015年

120

尝试 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。


谢谢,这就是我最后要做的。非常习惯于cvs不跟踪权限,因此可以正常工作。
Dale Forester 2010年

3
@shovas:很高兴这有所帮助。在Linux和Windows之间共享存储库时,我遇到了类似的问题。顺便说一句:如果这回答了您的问题,请把回答标记为正确。
蒂姆·海尼根2010年

是否可以git checkout origin/master将提交给服务器的文件权限设置为我的本地工作副本?因为每当我为ArangoDB构建V8时,文件许可权都会更改,以便拒绝对整个构建文件夹的访问(即使具有提升的权限;也就是Windows 7+)。我需要先修复所有本地文件权限,然后才能继续构建过程。可以core.filemode false解决这个问题吗?我怀疑git在Windows计算机上设置Linux权限。构建脚本可能只是保留它们,并将相同的权限应用于新创建的文件...
CodeManX 2015年

我想知道是否有任何缺点设置filemodefalse
kevoroid

11

Git除了可执行脚本之外,不存储文件权限。考虑使用类似 git-cache-meta之来保存文件所有权和权限。

Git只能存储两种类型的模式:755(可执行)和644(非可执行)。如果您的文件是444,那么git将存储644。


14
对不起,但这是不正确的。实际上,Git确实会跟踪权限。
2013年

4
大致准确,请参见git.wiki.kernel.org/index.php/ContentLimitations。设置的确切权限似乎基于服务器(可能还有客户端umask)以及配置设置,请参阅stackoverflow.com/a/12735291/125150
Motti Strom,2014年

12
@不会,不会。不敢相信您的评论获得了如此多的赞誉。
eis

@Will,这是大致正确的。根据文档 ...a mode of 100644, which means it’s a normal file. Other options are 100755, which means it’s an executable file; and 120000, which specifies a symbolic link. The mode is taken from normal UNIX modes but is much less flexible — these three modes are the only ones that are valid for files (blobs) in Git (although other modes are used for directories and submodules).
esmail

9
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

在我的情况下是需要的



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


-1

git diff -pmuhqu的答案中使用的词语可能不会显示所有差异。

  • 在Cygwin中看到了我不拥有的文件
  • 如果core.filemodefalse,则模式更改将被完全忽略(这是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


-2

最简单的方法是只更改权限。正如@kroger所指出的,git仅跟踪可执行位。因此,您可能只需要运行chmod -x filename即可对其进行修复(或者+x是否需要这样做)。


下面是一个例子git show:DIFF --git一个/ OpenWatch / SRC /组织/ ALE / openwatch / FB / FBUtils.java B / OpenWatch / SRC /组织/ ALE / openwatch / FB / FBUtils.java索引cd6fa6a..e5b0935 100644 即粗体位表示具有文件权限。
康拉多

对我来说,这似乎也是最简单的。不幸的是,我遇到了与Conrado相同的问题-我无法将许可从更改100644100755。我认为你不应该被否决。Git应该被否决。它在许多不同的层面上以多种方式被破坏了……
jww

-2

etckeeper工具可以处理权限并具有:

etckeeper init -d /mydir

您可以将其用于其他目录 /etc

使用软件包管理器进行安装,或从上述链接中获取资源。


4
它将权限设置为什么?如果它不读取Git元数据或调用Git,则不会执行OP要求的操作。
ivan_pozdeev
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.