git - 在 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
我做同样的事情
sh 文件保留其 x 权限
可执行文件(和 mk 文件)失去权限。
我希望所有文件都保留其 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 存储库本身的权限?
解决方案
我希望所有文件都保留其 X 权限。我能做些什么?
可能不多,除了可能要安装和使用WSL(或Cygwin,但请注意它与其他 NTFS 用户不能很好地配合)。请务必使用 NFTS,而不是 FAT。(或者,只是安装和使用 Linux,也许在 VM 中。)继续阅读以了解使用这些东西的更痛苦的方法。
PS 有没有办法检查 Gitlab 存储库本身的权限?
有一种方法可以检查每次提交中每个文件的权限并更新它们,即使您没有使用 WSL。虽然有点痛。
要了解它是如何工作的,让我们从 Unix/Linux 权限本身如何在真正的 Linux/Unix 文件系统上真正工作开始。三个“模式位”分为三组:r
ead、w
rite 和 e x
ecute 是模式位,u
ser、g
roup 和o
r 是分组。
三元组
rwx
意味着无论谁得到这个,都拥有底层文件的所有三个权限:他们可以读取、写入和执行文件。三元组
---
意味着获得此权限的人根本没有权限。通常,权限要么属于用户,
rw-
要么rwx
属于用户:文件可读可写但不可执行,或者具有完全权限。通常,对于大多数其他人来说,权限要么是要么
r--
:r-x
可读,但既不可写也不可执行;或只读。在这两者之间,“组”的成员——每个文件由一个用户 ID 和一个组 ID 拥有——可能是
r--
orr-x
,这意味着该组被视为每个人而不是用户;或rw-
或rwx
,表示该组被视为所有者。这种组 ID 的用处有限:大多数现代系统都使用ACL。但这解释了 Git 模式,所以值得一提。
这三组三个权限按顺序呈现:u
ser(文件的所有者)、g
roup 和o
r。(注意:o
forowner
在这里更有意义,但o
已经习惯了 for other
,所以这变成u
了 for user
。)因此文件最典型地是rw-r--r--
,意味着用户读/写,但其他人只读,或者rwxr-xr-x
,意味着读/写/为用户执行,但对其他所有人只读和执行。
现在,这是一个棘手的位:三组位以八进制或 base-8 表示法表示,位 2(值 4)表示r
位,位 1(值 2)表示w
位,位 0(值1) 表示x
位。所以对于u
ser 权限为 的文件rwx
,值为 7 (4+2+1);对于u
ser 权限为 的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
-s
100644
100755
暂存条目中的模式条目决定了下一次提交中的内容。 您自己的文件系统中文件的实际模式不相关。但是,该git add
命令可以更改暂存区中存储的模式。
如何git add
影响暂存模式
当你运行, or , or , 或其他任何东西时,Git 将更新每个文件的索引副本以匹配该文件的工作树副本。这有点复杂:git add file
git add -u
git 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
。+x
option 表示将模式设置为100755
,option-x
表示将模式设置为100644
。
最后一点关于core.filemode
每当您创建新存储库时,Git 都会探测文件系统以查看其行为方式。Git 执行此操作的确切方式有点特殊,但本质上,它会尝试查看chmod
在文件系统文件上设置和删除可执行性的 s 是否会“粘住”,即被稍后的lstat
系统调用反映回来。如果他们愿意,Gitcore.filemode
会true
为您设置。如果他们不这样做,Gitcore.filemode
会false
为你准备。 这可确保 Git 行为正确。
如果您覆盖此core.filemode
设置,Git 可能会开始出现异常行为。如果您确实更改了此设置,请确保您了解上述所有内容。