git Git在更新文件时更改默认umask
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/11574271/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Git change default umask when update file
提问by Roman Gelembjuk
I have a problem with Git. I searched for a solution in Google and in StackOverflow but nothing helps.
我对 Git 有问题。我在 Google 和 StackOverflow 中搜索了解决方案,但没有任何帮助。
The problem is that every time git updates some file in the working directory (when I checkout branches or I merge a branch, etc.) then the file permissions are changed such that the "writable to group" flag is added. And my apache shows "Error 500" for the file if it is writable to group.
问题是每次 git 更新工作目录中的某个文件时(当我检出分支或合并一个分支等时),然后文件权限就会改变,从而添加了“可写到组”标志。如果文件可写入分组,我的 apache 会显示“错误 500”。
Example: I have a file index.php. Permissions are "-rwxr-xr-x". Current (active) branch is master. This file was changed in the branch "develop". I execute "git checkout develop" and the file index.php gets permissions "-rwxrwxr-x" (writable to group is added). And my site stops working. As apache doesn't allow this flag in php files (I don't know why but I can not change this).
示例:我有一个文件 index.php。权限是“-rwxr-xr-x”。当前(活动)分支是 master。该文件在“开发”分支中被更改。我执行“git checkout develop”并且文件index.php获得权限“-rwxrwxr-x”(添加了可写到组)。我的网站停止工作。因为 apache 不允许在 php 文件中使用这个标志(我不知道为什么,但我不能改变这个)。
Every time when I execute "git checkout develop" I need to execute also "chmod g-w index.php". I don't like to execute two commands (and sometimes I forget to execute this and my site doesn't work).
每次执行“git checkout develop”时,我还需要执行“chmod gw index.php”。我不喜欢执行两个命令(有时我忘记执行这个并且我的网站不工作)。
What can I do to solve this problem? I think this is something related to umask. I did some tricks I found on web, but nothing works.
我能做些什么来解决这个问题?我认为这与umask有关。我做了一些我在网上找到的技巧,但没有任何效果。
Thanks.
谢谢。
回答by Palec
Quick answer is this shell function to be put in your ~/.profile
. An explanation follows.
快速回答是这个 shell 函数要放在你的~/.profile
. 解释如下。
git(){(umask 0022; command git "$@")}
A umaskis property of a process. It is inherited from the parent process and can be changed from inside later. The command to change umask is usually named umask too.
一个的umask是一个过程的性质。它是从父进程继承的,以后可以从内部更改。更改 umask 的命令通常也命名为 umask。
Git has no configuration option for setting its umask, it does not change its umask after it is executed. You have to set Git's umask from outside, let it be inherited from parent process (usually a shell).
Git 没有设置其 umask 的配置选项,它在执行后不会更改其 umask。您必须从外部设置 Git 的 umask,让它从父进程(通常是 shell)继承。
Mmm, you seem to dislike the idea that anything except git has changed umask. So let's change it just when executing git
.
嗯,你似乎不喜欢除了 git 之外的任何东西都改变了 umask 的想法。所以让我们在执行时改变它git
。
When a shell executes a line, it takes the first word on the line and tries to find a function of that name. Only if there is none, it tries to locate a command of that name in PATH
. The function I've written above is named git
, therefore any direct invocation of git
now executes it instead of the git
command.
当 shell 执行一行时,它会获取该行的第一个单词并尝试找到具有该名称的函数。只有当没有时,它才会尝试在PATH
. 我上面写的函数名为git
,因此任何直接调用git
now 都会执行它而不是git
命令。
The function executes a subshell, changes its umask and executes the git
command from inside the subshell. After Git finishes its work, the subshell also exits and the original shell instance will still have the original umask.
该函数执行子shell,更改其umask 并git
从子shell 内部执行命令。Git 完成工作后,子shell 也会退出,原始shell 实例仍将具有原始umask。
However, the function also shows how to bypass itself. If you call git
via command git
or even /usr/bin/git
, the function won't be called. For any decent use this is good enough, though.
但是,该函数还显示了如何绕过自身。如果您调用git
viacommand git
或 even /usr/bin/git
,则不会调用该函数。不过,对于任何体面的使用,这已经足够了。
回答by zogby
It is kind of dangerous to allow file execution as a binary.
Anyway I solved the problem with umask. My post-receive
script looks like:
允许以二进制形式执行文件是一种危险。无论如何,我用 umask 解决了这个问题。我的post-receive
脚本看起来像:
!/bin/sh
umask 002
GIT_WORK_TREE=/var/www/site git checkout -f
So, file permission
s set to 664
and directory permissions
set to 775
, which suits me perfectly.
所以,file permission
s set to664
和directory permissions
set to 775
,这非常适合我。
P.S. Setting umask in a .profile
file of git
user has no effect, and I don't understand why, please comment out if you know why this happens.
PS 在用户的.profile
文件中设置 umaskgit
没有效果,我不明白为什么,如果你知道为什么会发生这种情况,请注释掉。
回答by JonathanDIT
I've just been hitting this problem when checking out a repo to a home directory mounted via NFS on Ubuntu 14.04 (Trusty) using the backported Xenial version 4.x linux Kernel. Git clone to a local directory was fine. Even more odd: A second Ubuntu 14.04 server did not exhibit the same problem on the same mounted directory.
在使用向后移植的 Xenial 版本 4.x linux 内核在 Ubuntu 14.04 (Trusty) 上通过 NFS 挂载的主目录检出 repo 时,我刚刚遇到了这个问题。Git 克隆到本地目录很好。更奇怪的是:第二个 Ubuntu 14.04 服务器在同一个挂载目录上没有出现同样的问题。
After a lot of poking around I was able to see using strace that git called the open() system call to create each file with options O_CREAT,O_WRONLY and O_EXCL and a mode of 0666, but then the next syscal was an fstat() against the file and told me it was mode 0700 . In my case the problem only affected certain files in the repo. Despite 'git ls-index' showing mode 0644 for most files, some of them were being created correctly and others not; although it was always the same files which had wrong permissions on clone.
经过大量的探索后,我能够看到使用 strace git 调用 open() 系统调用来创建每个文件,其中包含选项 O_CREAT、O_WRONLY 和 O_EXCL 以及模式 0666,但是接下来的系统卡是一个 fstat() 反对文件并告诉我它是模式 0700 。在我的情况下,问题仅影响 repo 中的某些文件。尽管“git ls-index”显示大多数文件的模式为 0644,但其中一些文件被正确创建,而另一些文件则没有;虽然它总是相同的文件,但对克隆具有错误的权限。
I noticed that there was a difference in Kernel version between the two systems and then discovered the following bug: https://bugs.launchpad.net/ubuntu/+source/linux/+bug/1654288
我注意到两个系统之间的内核版本存在差异,然后发现了以下错误:https: //bugs.launchpad.net/ubuntu/+source/linux/+bug/1654288
Upgrading the kernel to 4.4.0-98 (from 4.4.0-59) fixed this for me. I checked some hosts still using the version 3.x Linux Kernel and these did not have problem.
将内核升级到 4.4.0-98(从 4.4.0-59)为我解决了这个问题。我检查了一些仍在使用 3.x Linux Kernel 的主机,这些都没有问题。
回答by Palec
Using hooks to change file mode after checkout is fixing the problem after it already ocurred. You already have bad file mode in the filesystem when executing the hook. If a request arrives just between the checkout and hook execution, the server will respond with the 500 error. But you may be interested in this solution anyway.
结帐后使用钩子更改文件模式可以解决问题已经发生后的问题。执行钩子时,文件系统中已经存在错误的文件模式。如果请求恰好在结帐和钩子执行之间到达,服务器将响应 500 错误。但无论如何,您可能对此解决方案感兴趣。
You need a post-checkout
hook running chmod g-w
on all the files necessary. The hook is .git/hooks/post-checkout
, should be executable and gets the current HEAD
as second parameter ($2 in shell). The hook could look like this:
您需要在所有必要文件上post-checkout
运行一个钩子chmod g-w
。钩子是.git/hooks/post-checkout
, 应该是可执行的,并获取当前HEAD
作为第二个参数(shell 中的 $2)。钩子可能如下所示:
#!/bin/bash
git ls-files -z --with-tree="" | xargs -0 chmod g-w --
As the hook does not get list of files checked out, this may be the best implementation possible. It changes the mode of all the files in current HEAD
.
由于钩子没有检出文件列表,这可能是最好的实现。它改变了当前HEAD
.