首页 > 解决方案 > 在 Windows 中克隆存储库时如何保持执行权限?

问题描述

我有一个 gitlab 存储库,其中包含几个 shell 文件以及我认为的可执行文件。(我知道构建的可执行文件最好不要包含在 repos 中,但我没有构建 repo)(哦,还有一个 mk 文件)

当我从 linux 机器上 git 克隆 repo 时,我会这样做

ls the/path/I/am/interested -l

我可以看到 sh 文件和可执行文件都具有 x 权限。(还有 mk 文件!虽然我不知道 mk 文件是否应该)

但是,当我从 Windows bash shell git clone 存储库时(为了克隆它,我做了

git clone -c core.symlinks=true  -c core.filemode=false therepo.git

我做同样的事情

我希望所有文件都保留其 X 权限。我能做些什么?

作为参考,我的 git 配置有

core.autocrlf=input
core.fscache=true
core.symlinks=true
core.editor=nano.exe

core.autocrlf=input
core.symlinks=true
core.filemode=false
core.repositoryformatversion=0
core.filemode=false
core.bare=false
core.logallrefupdates=true
core.ignorecase=true
core.symlinks=true
core.filemode=false

PS 有没有办法检查 Gitlab 存储库本身的权限?

标签: gitfile-permissionsgit-bash

解决方案


我希望所有文件都保留其 X 权限。我能做些什么?

可能不多,除了可能要安装和使用WSL(或Cygwin,但请注意它与其他 NTFS 用户不能很好地配合)。请务必使用 NFTS,而不是 FAT。(或者,只是安装和使用 Linux,也许在 VM 中。)继续阅读以了解使用这些东西的更痛苦的方法。

PS 有没有办法检查 Gitlab 存储库本身的权限?

有一种方法可以检查每次提交中每个文件的权限并更新它们,即使您没有使用 WSL。虽然有点痛。

要了解它是如何工作的,让我们从 Unix/Linux 权限本身如何在真正的 Linux/Unix 文件系统上真正工作开始。三个“模式位”分为三组:read、write 和 e xecute 是模式位,user、group 和or 是分组。

  • 三元组rwx意味着无论谁得到这个,都拥有底层文件的所有三个权限:他们可以读取、写入和执行文件。

    三元组---意味着获得此权限的人根本没有权限。

  • 通常,权限要么属于用户,rw-要么rwx属于用户:文件可读可写但不可执行,或者具有完全权限。

  • 通常,对于大多数其他人来说,权限要么是要么r--r-x可读,但既不可写也不可执行;或只读。

  • 在这两者之间,“组”的成员——每个文件由一个用户 ID 和一个组 ID 拥有——可能是r--or r-x,这意味着该组被视为每个人而不是用户;或rw-rwx,表示该组被视为所有者。这种组 ID 的用处有限:大多数现代系统都使用ACL。但这解释了 Git 模式,所以值得一提。

这三组三个权限按顺序呈现:user(文件的所有者)、group 和or。(注意:oforowner在这里更有意义,但o已经习惯了 for other,所以这变成u了 for user。)因此文件最典型地是rw-r--r--,意味着用户读/写,但其他人只读,或者rwxr-xr-x,意味着读/写/为用户执行,但对其他所有人只读和执行。

现在,这是一个棘手的位:三组位以八进制或 base-8 表示法表示,位 2(值 4)表示r位,位 1(值 2)表示w位,位 0(值1) 表示x位。所以对于user 权限为 的文件rwx,值为 7 (4+2+1);对于user 权限为 的rw-,值为 6 (4+2)。对于g组权限为 的文件r-x,值为 5 (4+1);对于r--,它是 4。对于o权限为 的文件r-x,该值又是 5,对于r--它又是 4`。

当我们按照这个顺序把这些放在一起时,我们得到:

755 (rwxr-xr-x)
644 (rw-r--r--)

这些是系统调用结果中最常见的两个数字,在 Linux/Unix 样式的文件系统上,用于权限位。1 但任何组合在技术上都是可能的:用户可以设置他们的文件,以便只有其他人可以读取和写入它们,例如 (或)。这不是很明智,但这是允许的。lstat---rw-rw-066


1注意,对于一个目录,读权限是指可以列出目录中的名称,而执行权限是指可以使用lstat目录中的名称,例如对文件进行尝试open。因此,缺少执行权限的目录令人沮丧:您可以看到其中的名称,但永远不要打开任何这些文件,无论它们的权限如何!这种特殊的怪癖在某些安全模型中具有奇怪且有时有用的效果,但挂载点允许用户绕过怪癖,因此在尝试使用此模型时必须非常小心。


那么这一切与 Git 有什么关系呢?

当 Linus Torvalds最初编写Git 时,他决定为Git 提交中的每个文件的权限完全支持这种模型。因此,Git 的索引为每个文件存储一个mode,作为几个可能的数字之一,通常以八进制表示。该模式有一些额外的高阶位,用于区分常规文件 (mode 100xxx) 和符号链接 (mode 120xxx),他也直接从内部 Unix/Linux 模型中复制了这些位。

这使您可以存储在签出时无法由您自己使用的文件,只能由其他人(mode 100066例如)使用,因为 Git 会使用该确切模式创建文件:066---rw-rw-. 如前所述,这在文件系统中基本上是无用的;它在 Git 中也被证明是无用和有害的,所以在我认为最初的 1.0 版本之前——当然是在 Git 1.5 之前——对 Git 进行了修改,以禁止这样做。现在常规文件允许的唯一模式是100644, or rw-r--r--, and 100755, or rwx-r-xr-x。但奇怪的编号仍然出现。

例如,如果您运行git ls-tree -r HEAD以查看HEAD提交中的文件是如何存储的,您将看到这些完全相同的数字。以下是 Git 存储库中提交中的一些文件:

...
100644 blob 311841f9bed577151a81f87174ccdd6939aa3eee    .gitignore
100644 blob cbeebdab7a5e2c6afec338c3534930f569c90f63    .gitmodules
...
100755 blob 9c125f298aea6863a9370c16a0f70b7cccc73b2d    GIT-VERSION-GEN
100644 blob 66389ce05915d776e5c8ff49aea40e20bc40eb62    INSTALL
100644 blob d38b1b92bdb2893eb4505667375563f2d6d4086b    LGPL-2.1
100644 blob c3565fc0f8f7df81232deca663bf55e14737ae97    Makefile

注意100755中间的:这是一个可执行文件。剩下的文件都是100644,即不可执行的。这些模式字符串实际上是 Git 存储X权限的方式,您可以在任何现有的提交中直接看到它们,使用git ls-tree(记住使用-r和提交哈希 ID;有关更多信息,请参阅文档)。

现在,这仅显示了commits中存储的文件的模式。尚未提交的文件的模式存储在 Git 的索引(又名暂存区,又名缓存)中。要查看这些条目,请使用带有or选项git ls-files命令(同一事物的两个拼写)。这也打印出 mode:或.--stage-s100644100755

暂存条目中的模式条目决定了下一次提交中的内容。 您自己的文件系统中文件的实际模式不相关。但是,该git add命令可以更改暂存区中存储的模式。

如何git add影响暂存模式

当你运行, or , or , 或其他任何东西时,Git 将更新每个文件的索引副本以匹配该文件的工作树副本。这有点复杂:git add filegit add -ugit add .

  • 首先,假设文件从文件系统中删除。在这种情况下,git add也会从索引中删除文件。其他一切都变得无关紧要。但如果没有,我们可能会继续更新文件的模式。

  • 假设core.filemode(或core.fileMode)是true。然后 Git查看lstat系统调用报告的模式。如果该模式x设置了任何位,Git 会将索引的模式设置为100755. 否则,Git 会将索引的模式设置为100644.

这依赖于您的lstat系统调用正确报告可执行权限。如果您的lstat系统调用没有正确报告,您应该core.filemode设置为false. Git 现在忽略lstat模式结果:索引中条目的模式保持不变。不管git ls-files --stage之前说什么,这仍然是模式。

当您的文件系统不合作时手动更新模式

如果您希望更改模式,您有两个选择:

  • git add --chmod=...将从您的工作树副本更新索引设置您指定的模式。这会覆盖lstat结果,也会覆盖core.filemode.

  • git update-index会让你覆盖模式。有很多方法可以做到这一点git update-index;仅覆盖模式的git update-index --chmod=....

命令选项的参数--chmod应该是+x-x+xoption 表示将模式设置为100755,option-x表示将模式设置为100644

最后一点关于core.filemode

每当您创建新存储库时,Git 都会探测文件系统以查看其行为方式。Git 执行此操作的确切方式有点特殊,但本质上,它会尝试查看chmod在文件系统文件上设置和删除可执行性的 s 是否会“粘住”,即被稍后的lstat系统调用反映回来。如果他们愿意,Gitcore.filemodetrue为您设置。如果他们不这样做,Gitcore.filemodefalse为你准备。 这可确保 Git 行为正确。

如果您覆盖此core.filemode设置,Git 可能会开始出现异常行为。如果您确实更改了此设置,请确保您了解上述所有内容。


推荐阅读