防止 git 在 git 拉取时覆盖文件所有者
Prevent git from overwriting file owner upon git pull
我在这里看到了一些类似的问题,但是 none 给出的解决方案似乎有效...想知道它们是否已经过时,或者这种情况有所不同...所以我想开一个新话题来谈谈它。
我 运行 遇到了一个令人沮丧的问题,每次我执行 git pull
时,它都会将所有者更改为拉动者的用户。然后发生的是该站点显示以下错误:
Warning: file_get_contents(/var/www/html/wp-content/themes/<my-theme>/resources/views/<changed-file>): failed to open stream: Permission denied in /var/www/html/wp-includes/class-wp-theme.php on line 1207
只能通过 运行ning chown www-data
在更改的文件上修复。
当更多人开始在网站上工作时,或者当重要文件发生更改(默认 template/header/footer..)时,这将成为一个问题,并且网站变为空白,直到 chown 为 运行 .
站点详细信息
Laravel, wordpress, ubuntu 18, 装甲托管
Git repo 存储在自定义主题中
我已经尝试了一些解决方案,但 none 似乎有效,(可能是因为它们实施不正确..)
我试过的解决方案
1: 将 filemode 设置为 false - 我在我的本地计算机和相关服务器上将 filemode 本地和全局设置为 false。我也试过将大小写更改为 "fileMode"。
2: 实现 post-更新挂钩 - 我添加了一个 post 更新挂钩来自动更新文件 permissions/ownership。这是脚本(请注意 git 存储库位于自定义主题中):
#!/bin/sh
# default owner user
OWNER="www-data:www-data"
# changed file permission
PERMISSION="664"
# web repository directory
REPO_DIR="/var/www/html/wp-content/themes/quorum-theme"
# remote repository
REMOTE_REPO="origin"
# public branch of the remote repository
REMOTE_REPO_BRANCH="master"
cd $REPO_DIR || exit
unset GIT_DIR
files="$(git diff-tree -r --name-only --no-commit-id HEAD@{1} HEAD)"
git merge FETCH_HEAD
for file in $files
do
sudo chown $OWNER $file
sudo chmod $PERMISSION $file
done
exec git-update-server-info
让我知道是否还有其他值得尝试的事情,或者如果您发现我的代码有问题...
祝一切顺利,
吉尔
您非常接近正确的解决方案。
您需要启用以下挂钩:
post-merge
,成功后调用git pull
post-checkout
,成功后调用git checkout
如果确定只使用git pull
,post-merge
钩子就够了。
启用这两个挂钩可以确保您始终调用挂钩而不需要额外费用。
钩子的内容应该是这样的:
#!/bin/sh
# default owner user
OWNER="www-data:www-data"
# web repository directory
REPO_DIR="/var/www/html/wp-content/themes/quorum-theme"
echo
echo "---"
echo "--- Resetting ownership to ${OWNER} on ${REPO_DIR}"
sudo chown -R $OWNER $REPO_DIR
echo "--- Done"
echo "---"
该脚本会将 REPO_DIR
内所有文件和目录的所有权重置为 OWNER
。
我已经从你的 post 中复制了这些值,最终将其更改为你的需要。
要启用挂钩,您应该:
- 使用上面的脚本创建一个名为
post-merge
的文件
- 将其移至您的存储库
的目录 .git/hook/
中
- 给它可执行权限
chmod +x post-merge
最后对 post-checkout
钩子重复这些步骤,它需要等于 post-merge
钩子。
如果您的用户不是 root
,请注意执行 sudo git pull
。目标目录中的所有文件和目录都属于www-data
,您需要以超级用户权限执行git pull
命令,否则命令将失败。
从你的问题来看,你似乎正在使用 git pull
在生产中部署。
git
不是部署工具。如果你想部署你的代码,我会邀请你写一个部署脚本。
您的脚本的第一个版本可能是:
# deploy.sh
# cd to the appropriate directory :
cd /var/www/mysite
# change to the correct user before pulling :
sudo -u www-data git pull
更新版本将根据 git pull
停止。
理想情况下:您希望能够识别可以部署到产品中的代码版本,而不是依赖于“git 拉取将在不触发合并冲突的情况下工作”这一事实。
这是您可以遵循的通用工作流程的概要:
何时要部署到生产环境:
生成一些工件,从已识别的提交中打包您的代码:对于 php 代码,这可以是一个简单的 .tar.gz
# set a clearly identifiable tag on target commit
git tag v-x.y.z
# create a tar.gz archive that stores the files :
# look at 'git help archive'
git archive -o ../myapp-x.y.z.tgz v-x.y.z
将工件推送到您的生产服务器
scp myapp-x.y.z.tgz production-server:
运行 您的部署脚本,不再调用 git :
# deploy.sh :
# usage : ./deploy.sh myapp-x.y.z.tgz
archive=""
# extract the archive to a fresh folder :
mkdir /var/www/mysite.new
tar -C /var/www/mysite.new -xzf "$archive"
chown -R www-data: /var/www/mysite.new
# replace old folder with new folder :
mv /var/www/mysite /var/www/mysite.old
mv /var/www/mysite.new /var/www/mysite
您通常希望围绕部署管理的一些额外操作:
- 部署前备份您的数据库
- hanlde 配置参数(复制您的生产配置文件?设置环境?...)
- 应用迁移操作
- 重启apache或nginx
- ...
您可能希望随项目一起对 deploy.sh
脚本进行版本控制。
我的方法适合我。
首先,将名为post-merge
的文件添加到/path/to/your_project/.git/hooks/
cd /path/to/your_project/.git/hooks/
touch post-merge
然后,将其所有权更改为与 文件夹相同(这与 nginx
和 php-fpm
运行ner 相同),在我的例子中,我使用 www:www
sudo chown www:www post-merge
然后把它的文件模式改成775(就可以执行了)
sudo chmod 775 post-merge
然后把下面的片段放到post-merge
。要了解该代码段,请参阅 here(实际上就是我)。
#!/bin/sh
# default owner user
OWNER="www:www"
# changed file permission
PERMISSION="664"
# web repository directory
REPO_DIR="/www/wwwroot/your_project/"
# remote repository
REMOTE_REPO="origin"
# public branch of the remote repository
REMOTE_REPO_BRANCH="master"
cd $REPO_DIR || exit
unset GIT_DIR
files="$(git diff-tree -r --name-only --no-commit-id HEAD@{1} HEAD)"
for file in $files
do
sudo chown $OWNER $file
sudo chmod $PERMISSION $file
done
exec git-update-server-info
一切都完成了,现在,回到your_project文件夹
cd /path/to/your_project/
运行 git pull
在 your_project 文件夹下,记住你必须 运行 作为 root 或 sudo(我记得 sudo)
sudo git pull
现在检查从远程仓库拉取的新文件,看看它的所有权是否已经更改为www:www
(如果符合预期,新拉取文件的所有权应更改为www:www
).
这种方法比sudo chown -R www:www /www/wwwroot/your_project/
好得多,因为它只改变了新文件的所有权,而不是全部!假设我刚刚提取了 2 个新文件,如果更改整个文件夹的所有权,则会花费更多的时间和服务器资源(cpu 使用率、内存使用率...),这是完全没有必要的。
我在这里看到了一些类似的问题,但是 none 给出的解决方案似乎有效...想知道它们是否已经过时,或者这种情况有所不同...所以我想开一个新话题来谈谈它。
我 运行 遇到了一个令人沮丧的问题,每次我执行 git pull
时,它都会将所有者更改为拉动者的用户。然后发生的是该站点显示以下错误:
Warning: file_get_contents(/var/www/html/wp-content/themes/<my-theme>/resources/views/<changed-file>): failed to open stream: Permission denied in /var/www/html/wp-includes/class-wp-theme.php on line 1207
只能通过 运行ning chown www-data
在更改的文件上修复。
当更多人开始在网站上工作时,或者当重要文件发生更改(默认 template/header/footer..)时,这将成为一个问题,并且网站变为空白,直到 chown 为 运行 .
站点详细信息
Laravel, wordpress, ubuntu 18, 装甲托管
Git repo 存储在自定义主题中
我已经尝试了一些解决方案,但 none 似乎有效,(可能是因为它们实施不正确..)
我试过的解决方案
1: 将 filemode 设置为 false - 我在我的本地计算机和相关服务器上将 filemode 本地和全局设置为 false。我也试过将大小写更改为 "fileMode"。
2: 实现 post-更新挂钩 - 我添加了一个 post 更新挂钩来自动更新文件 permissions/ownership。这是脚本(请注意 git 存储库位于自定义主题中):
#!/bin/sh
# default owner user
OWNER="www-data:www-data"
# changed file permission
PERMISSION="664"
# web repository directory
REPO_DIR="/var/www/html/wp-content/themes/quorum-theme"
# remote repository
REMOTE_REPO="origin"
# public branch of the remote repository
REMOTE_REPO_BRANCH="master"
cd $REPO_DIR || exit
unset GIT_DIR
files="$(git diff-tree -r --name-only --no-commit-id HEAD@{1} HEAD)"
git merge FETCH_HEAD
for file in $files
do
sudo chown $OWNER $file
sudo chmod $PERMISSION $file
done
exec git-update-server-info
让我知道是否还有其他值得尝试的事情,或者如果您发现我的代码有问题...
祝一切顺利,
吉尔
您非常接近正确的解决方案。
您需要启用以下挂钩:
post-merge
,成功后调用git pull
post-checkout
,成功后调用git checkout
如果确定只使用git pull
,post-merge
钩子就够了。
启用这两个挂钩可以确保您始终调用挂钩而不需要额外费用。
钩子的内容应该是这样的:
#!/bin/sh
# default owner user
OWNER="www-data:www-data"
# web repository directory
REPO_DIR="/var/www/html/wp-content/themes/quorum-theme"
echo
echo "---"
echo "--- Resetting ownership to ${OWNER} on ${REPO_DIR}"
sudo chown -R $OWNER $REPO_DIR
echo "--- Done"
echo "---"
该脚本会将 REPO_DIR
内所有文件和目录的所有权重置为 OWNER
。
我已经从你的 post 中复制了这些值,最终将其更改为你的需要。
要启用挂钩,您应该:
- 使用上面的脚本创建一个名为
post-merge
的文件 - 将其移至您的存储库 的目录
- 给它可执行权限
chmod +x post-merge
.git/hook/
中
最后对 post-checkout
钩子重复这些步骤,它需要等于 post-merge
钩子。
如果您的用户不是 root
,请注意执行 sudo git pull
。目标目录中的所有文件和目录都属于www-data
,您需要以超级用户权限执行git pull
命令,否则命令将失败。
从你的问题来看,你似乎正在使用 git pull
在生产中部署。
git
不是部署工具。如果你想部署你的代码,我会邀请你写一个部署脚本。
您的脚本的第一个版本可能是:
# deploy.sh
# cd to the appropriate directory :
cd /var/www/mysite
# change to the correct user before pulling :
sudo -u www-data git pull
更新版本将根据 git pull
停止。
理想情况下:您希望能够识别可以部署到产品中的代码版本,而不是依赖于“git 拉取将在不触发合并冲突的情况下工作”这一事实。
这是您可以遵循的通用工作流程的概要:
何时要部署到生产环境:
生成一些工件,从已识别的提交中打包您的代码:对于 php 代码,这可以是一个简单的
.tar.gz
# set a clearly identifiable tag on target commit git tag v-x.y.z # create a tar.gz archive that stores the files : # look at 'git help archive' git archive -o ../myapp-x.y.z.tgz v-x.y.z
将工件推送到您的生产服务器
scp myapp-x.y.z.tgz production-server:
运行 您的部署脚本,不再调用 git :
# deploy.sh : # usage : ./deploy.sh myapp-x.y.z.tgz archive="" # extract the archive to a fresh folder : mkdir /var/www/mysite.new tar -C /var/www/mysite.new -xzf "$archive" chown -R www-data: /var/www/mysite.new # replace old folder with new folder : mv /var/www/mysite /var/www/mysite.old mv /var/www/mysite.new /var/www/mysite
您通常希望围绕部署管理的一些额外操作:
- 部署前备份您的数据库
- hanlde 配置参数(复制您的生产配置文件?设置环境?...)
- 应用迁移操作
- 重启apache或nginx
- ...
您可能希望随项目一起对 deploy.sh
脚本进行版本控制。
我的方法适合我。
首先,将名为post-merge
的文件添加到/path/to/your_project/.git/hooks/
cd /path/to/your_project/.git/hooks/
touch post-merge
然后,将其所有权更改为与 nginx
和 php-fpm
运行ner 相同),在我的例子中,我使用 www:www
sudo chown www:www post-merge
然后把它的文件模式改成775(就可以执行了)
sudo chmod 775 post-merge
然后把下面的片段放到post-merge
。要了解该代码段,请参阅 here(实际上就是我)。
#!/bin/sh
# default owner user
OWNER="www:www"
# changed file permission
PERMISSION="664"
# web repository directory
REPO_DIR="/www/wwwroot/your_project/"
# remote repository
REMOTE_REPO="origin"
# public branch of the remote repository
REMOTE_REPO_BRANCH="master"
cd $REPO_DIR || exit
unset GIT_DIR
files="$(git diff-tree -r --name-only --no-commit-id HEAD@{1} HEAD)"
for file in $files
do
sudo chown $OWNER $file
sudo chmod $PERMISSION $file
done
exec git-update-server-info
一切都完成了,现在,回到your_project文件夹
cd /path/to/your_project/
运行 git pull
在 your_project 文件夹下,记住你必须 运行 作为 root 或 sudo(我记得 sudo)
sudo git pull
现在检查从远程仓库拉取的新文件,看看它的所有权是否已经更改为www:www
(如果符合预期,新拉取文件的所有权应更改为www:www
).
这种方法比sudo chown -R www:www /www/wwwroot/your_project/
好得多,因为它只改变了新文件的所有权,而不是全部!假设我刚刚提取了 2 个新文件,如果更改整个文件夹的所有权,则会花费更多的时间和服务器资源(cpu 使用率、内存使用率...),这是完全没有必要的。