更新文件时Git更改默认umask

时间:2012-07-20 06:53:30

标签: git permissions umask

我遇到Git问题。我在Google和StackOverflow中搜索了一个解决方案,但没有任何帮助。

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

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

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

我该怎么做才能解决这个问题? 我认为这与umask有关。我在网上找到了一些技巧,但没有任何效果。

感谢。

4 个答案:

答案 0 :(得分:9)

允许将文件作为二进制文件执行是危险的。 无论如何,我用umask解决了这个问题。我的post-receive脚本如下:

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

因此,file permission设置为664directory permissions设置为775,这完全适合我。

P.S。在.profile git用户的{{1}}文件中设置umask无效,我不明白为什么,如果你知道为什么会这样,请注释掉。

答案 1 :(得分:8)

快速回答是这个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。

但是,该功能还显示了如何绕过自身。如果您通过gitcommand git致电/usr/bin/git,则系统不会调用此功能。但是,对于任何体面的使用来说,这已经足够了。

答案 2 :(得分:4)

我在Ubuntu 14.04(Trusty)上使用backported Xenial版本4.x linux内核检查通过NFS挂载的主目录的回购时遇到了这个问题。 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内核的主机,这些没有问题。

答案 3 :(得分:1)

结帐后使用挂钩更改文件模式是在问题已经出现后修复问题。执行挂钩时,文件系统中已经存在错误的文件模式。如果请求在结账和挂钩执行之间到达,服务器将响应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中所有文件的模式。