如果修改了git中的文件和目录的权限,如何恢复?

Dal*_*ter 260 git file-permissions file

我有一个git checkout.所有文件权限都不同于git认为应该是的权限,因此它们都显示为已修改.

在不触及文件内容的情况下(只想修改权限)如何将所有文件权限设置为git认为应该是什么?

muh*_*hqu 534

使用时,Git会跟踪文件许可并公开权限更改git diff -p.所以我们需要的是:

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

作为单线:

git diff -p -R --no-color \
    | grep -E "^(diff|(old|new) mode)" --color=never  \
    | git apply
Run Code Online (Sandbox Code Playgroud)

你也可以把它作为你的git配置的别名添加...

git config --global --add alias.permission-reset '!git diff -p -R --no-color | grep -E "^(diff|(old|new) mode)" --color=never | git apply'
Run Code Online (Sandbox Code Playgroud)

...你可以通过以下方式调用它:

git permission-reset
Run Code Online (Sandbox Code Playgroud)

注意,如果你是shell bash,请确保使用'而不是"引号!git,否则它将被git你运行的最后一个命令所取代.

感谢@Mixologic指出,只需使用-Ron git diff,sed就不再需要繁琐的命令了.

  • 哦,它有效,我试图从不同于存储库根目录的目录中应用.git apply只适用于那里. (15认同)
  • 我变得"致命:无法识别的输入" (10认同)
  • @RobQuist使用muhqu命令时,我的本地更改未被删除 (6认同)
  • 有什么理由你不会做"git diff -p -R"而不是做sed使其反转? (5认同)
  • 我在OS X中,这不起作用.我已经确定问题出在git apply中.它不适用文件权限更改. (3认同)
  • 如果你收到 `fatal: unrecognized input`,你可能已经应用了下面建议的 `git config core.fileMode false`。你应该在运行上面的命令之前设置`git config core.fileMode true`! (3认同)
  • 请注意,此次还会恢复文件内部的更改.我需要更新文件(编译的js文件),因此内容更改应该保留,但文件权限搞砸了.蒂姆亨尼根的答案下面修正了我的许可改变,忽略了它们(是的,我被迫使用windows :() (2认同)
  • 关于“致命:无法识别的输入” - 如果您已经暂存更改(您正处于交互式变基过程中,例如准备好继续),请将“--cached”添加到 git diff 命令中 (2认同)

Tim*_*gan 108

尝试 git config core.fileMode false

注:git config区分大小写的!

core.fileMode手册页:

git config core.fileMode false

如果为false,则忽略索引和工作副本之间的可执行位差异; 对像FAT这样的破碎文件系统很有用.请参阅git-update-index(1).

默认值为true,但git-clone(1)或git-init(1)将在创建存储库时探测并设置core.fileMode false.

  • @shovas:很高兴这有所帮助。在Linux和Windows之间共享存储库时,我遇到了类似的问题。顺便说一句:如果这回答了您的问题,请标记为正确的回答。 (3认同)

kro*_*ger 9

Git不存储可执行脚本以外的文件权限.考虑使用git-cache-meta之类的东西来保存文件所有权和权限.

Git只能存储两种模式:755(可执行)和644(不可执行).如果您的文件是444 git将存储它有644.

  • 对不起,但这是不正确的.确实,Git会跟踪权限. (14认同)
  • @Will不,它没有.无法相信你的评论得到了如此多的赞成. (10认同)
  • 它大致准确,请参阅https://git.wiki.kernel.org/index.php/ContentLimitations.设置的确切权限看起来基于服务器和可能的客户端`umask`以及配置设置,请参阅http://stackoverflow.com/a/12735291/125150. (3认同)
  • @Will,这大致是正确的。根据[文档](https://git-scm.com/book/en/v2/Git-Internals-Git-Objects) `...模式为 100644,这意味着它是一个普通文件。其他选项是100755,这意味着它是一个可执行文件;120000,指定符号链接。该模式取自普通的 UNIX 模式,但灵活性要差得多 — 这三种模式是唯一对 Git 中的文件(blob)有效的模式(尽管其他模式用于目录和子模块)。 (2认同)

zai*_*eer 7

git diff -p \
| grep -E '^(diff|old mode|new mode)' \
| sed -e 's/^old/NEW/;s/^new/old/;s/^NEW/new/' \
| git apply
Run Code Online (Sandbox Code Playgroud)

在大多数情况下都可以使用,但是如果您安装了外部差异工具(如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
Run Code Online (Sandbox Code Playgroud)

在我的情况下是需要的