更新文件时Git更改默认umask

Posted

技术标签:

【中文标题】更新文件时Git更改默认umask【英文标题】:Git change default umask when update file 【发布时间】:2012-07-19 10:19:50 【问题描述】:

我对 Git 有疑问。我在 Google 和 *** 中搜索了解决方案,但没有任何帮助。

问题在于,每次 git 更新工作目录中的某些文件时(当我签出分支或合并分支等时),文件权限都会更改,从而添加“可写入组”标志。 如果文件可写入分组,我的 apache 会显示该文件的“错误 500”。

示例: 我有一个文件 index.php。权限是“-rwxr-xr-x”。当前(活动)分支是主分支。此文件在“开发”分支中更改。 我执行“git checkout develop”并且文件 index.php 获得权限“-rwxrwxr-x”(添加了可写到组)。我的网站停止工作。由于 apache 不允许在 php 文件中使用此标志(我不知道为什么,但我无法更改)。

每次执行“git checkout develop”时,我还需要执行“chmod g-w index.php”。我不喜欢执行两个命令(有时我忘记执行此命令,我的网站无法运行)。

我可以做些什么来解决这个问题? 我认为这与umask有关。我做了一些我在网上找到的技巧,但没有任何效果。

谢谢。

【问题讨论】:

你有什么理由不能适当地设置你的 umask(即设置为 0022 或类似的)? 怎么做?要设置umask?这个系统是改变还是只有 git 改变?如果系统那么我不能改变这个 运行umask 0022。要将其设置为交互式会话,请将此命令放入您的 .bashrc 或 shell 的等效项中。总是设置它,但它在你的.profile 我不想更改任何系统设置。该站点与该用户一起运行。我担心这会影响其他事情。有没有办法只通过更改 git 设置来解决问题?我知道 git 中有更新后的钩子。但我找不到如何使用钩子解决这个问题。 不是git问题,是umask问题;如果站点以该用户身份运行并且仅当该用户创建不可组写入的文件时才有效,那么您肯定想要将此用户的umask更改为0022。(.profile用户 设置,而不是系统设置) 【参考方案1】:

快速回答是将这个 shell 函数放入您的~/.profile。下面是解释。

git()(umask 0022; command git "$@")

umask 是进程的属性。它是从父进程继承的,以后可以从内部更改。更改 umask 的命令通常也被命名为 umask。

Git 没有设置 umask 的配置选项,它在执行后不会更改它的 umask。您必须从外部设置 Git 的 umask,让它从父进程(通常是 shell)继承。

嗯,你似乎不喜欢除了 git 之外的任何东西都改变了 umask 的想法。所以我们只在执行git的时候改一下。

当 shell 执行一行时,它会获取该行的第一个单词并尝试查找该名称的函数。只有在没有时,它才会尝试在PATH 中找到该名称的命令。我上面写的函数被命名为git,因此任何对git 的直接调用现在都会执行它而不是git 命令。

该函数执行一个子shell,更改它的umask并从子shell内部执行git命令。 Git 完成工作后,子 shell 也退出,原来的 shell 实例仍然有原来的 umask。

但是,该函数还显示了如何绕过自身。如果您通过command git 甚至/usr/bin/git 调用git,则不会调用该函数。不过,对于任何体面的用途,这已经足够了。

【讨论】:

【参考方案2】:

允许文件以二进制形式执行有点危险。 无论如何,我用umask解决了这个问题。我的post-receive 脚本看起来像:

!/bin/sh
umask 002
GIT_WORK_TREE=/var/www/site git checkout -f

所以,file permissions 设置为664directory permissions 设置为775,这非常适合我。

附:在git用户的.profile文件中设置umask无效,我不明白为什么,如果你知道为什么会发生这种情况,请注释掉。

【讨论】:

umask 0022 对于常规网络服务器更有意义,因为只有所有者才有写权限:导致file permission 644 和 directory permissions 755【参考方案3】:

在使用向后移植的 Xenial 版本 4.x linux 内核检查通过 NFS 在 Ubuntu 14.04 (Trusty) 上挂载的主目录的 repo 时,我刚刚遇到了这个问题。 将 Git 克隆到本地目录就可以了。更奇怪的是:第二台 Ubuntu 14.04 服务器在同一个挂载目录上没有出现同样的问题。

经过大量探索后,我能够看到使用 strace git 调用 open() 系统调用来创建每个文件,选项为 O_CREAT、O_WRONLY 和 O_EXCL,模式为 0666,但接下来的 syscal 是 fstat () 对文件并告诉我它是模式 0700 。就我而言,该问题仅影响回购中的某些文件。尽管大多数文件的“git ls-index”显示模式为 0644,但其中一些被正确创建,而另一些则没有;尽管在克隆时总是有相同的文件具有错误的权限。

我注意到两个系统的内核版本存在差异,然后发现了以下错误:https://bugs.launchpad.net/ubuntu/+source/linux/+bug/1654288

将内核升级到 4.4.0-98(从 4.4.0-59)为我解决了这个问题。 我检查了一些仍在使用版本 3.x Linux Kernel 的主机,这些主机没有问题。

【讨论】:

【参考方案4】:

在结帐后使用钩子更改文件模式可以在问题发生后解决问题。执行钩子时,文件系统中已经存在错误的文件模式。如果一个请求刚好在 checkout 和 hook 执行之间到达,服务器将响应 500 错误。但无论如何,您可能对此解决方案感兴趣。

您需要一个post-checkout 挂钩,在所有必要的文件上运行chmod g-w。钩子是.git/hooks/post-checkout,应该是可执行的,并获取当前的HEAD 作为第二个参数(shell 中的$2)。钩子可能如下所示:

#!/bin/bash
git ls-files -z --with-tree="$2" | xargs -0 chmod g-w --

由于钩子没有得到检出的文件列表,这可能是最好的实现。它改变了当前HEAD中所有文件的模式。

【讨论】:

以上是关于更新文件时Git更改默认umask的主要内容,如果未能解决你的问题,请参考以下文章

umask-创建文件或目录的默认权限

【umask】关于umask值及其对应的文件权限

文件的默认权限:umask

在Linux中设置UMASK值

vs2019更改git存储库默认本地路径

linux那个umask值是啥?