我正在开发一种流程,该流程将允许人们访问公共环境。
我的想法是要有一个只能放入的存储库,而不是一个裸露的存储库,因为我希望人们能够阅读它。我们称之为 COMMON
这是因为我不希望人们必须克隆存储库才能访问数据。
要做到这一点,我具有以下结构:
COMMON存储库不应有任何直接修改。但是,由于有多个用户在使用sudoers,所以我不能100%确保有人不会直接对其进行修改。
或者,相应地,对于Murphy,我100%确信有人有一天会在COMMON资源库中本地修改某些内容...
为了确保当有人正确地将其推入远程目录并因此推入COMMON存储库时没有冲突,我考虑了以下用于COMMON的钩子:
#!/bin/bash
#Stash local modifications if there are ones to avoid conflicts
echo "## Local modifications on the Product-Line are stashed with the tag: 'local modifications @ $(date)' "
git stash push -m "local modifications @ $(date)"
exit 0
#!/bin/bash
#Checks out the the branch that contains the last commit
git checkout $( git log --branches -1 --pretty=format:'%D' | sed -e 's/.*-> //g' -e 's/.*, //g' )
#Forces synchronization with the last commit
git stash
git stash drop stash@{0}
exit 0
但是,隐藏命令似乎无法按预期运行。在本地存储库中进行推送时返回的日志如下:
$> echo toto >> stash_test ; git commit -am "test" ; git push
[tbranch f6e8fbb] test
1 file changed, 1 insertion(+)
Enumerating objects: 5, done.
Counting objects: 100% (5/5), done.
Delta compression using up to 48 threads
Compressing objects: 100% (3/3), done.
Writing objects: 100% (3/3), 351 bytes | 351.00 KiB/s, done.
Total 3 (delta 1), reused 0 (delta 0)
remote: remote: ## Local modifications on the Product-Line are stashed with the tag: 'local modifications @ Mon Dec 23 17:44:59 CET 2019'
remote: remote: No local changes to save
remote: remote: Already on 'tbranch'
remote: remote: M stash_test
remote: remote: Saved working directory and index state WIP on tbranch: f6e8fbb test
remote: remote: stash@{0}: WIP on tbranch: f6e8fbb test
remote: remote: Dropped stash@{0} (b29b76ceb2b2dfd2fcf6d0577c7200e517641328)
remote: To ../pl
remote: f75b5d1..f6e8fbb tbranch -> tbranch
To /home/usr/TEMP/remote
f75b5d1..f6e8fbb tbranch -> tbranch
这里有两个问题:
git stash push -m "msg"
时,它将返回No local changes to save
git stash
加git stash drop stash@{0}
应该模拟对当前分支的最后一次提交的更新。在日志中,似乎该操作有效,但是,如果我在COMMON信息库中获得了状态,则可以获得:On branch tbranch
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git checkout -- <file>..." to discard changes in working directory)
modified: stash_test
modified: test
stash_test
是上次提交修改的文件test
是在本地修改以测试所有过程的文件双龙效应:
1. git stash list
为空,其中应包含test
的修改。但是,该日志与其保持一致,因为它没有将test
隐藏在预接收钩子中
2. stash_test
未更新为最后一次提交...这里很奇怪,因为日志表明一切正常...
我迷路的地方是我尝试手动执行这些步骤,并且...按预期工作。
但是我在git管理方面还很陌生,所以我可能会错过一些东西...
git stash
命令在钩子中是否表现出令人讨厌的行为,使我无法做我想做的事情?执行挂钩时,它位于我的COMMON目录的.git目录中。
因此,git stash
无法检测到修改。
如果在预接收挂钩中执行git status --porcelain
,则会得到:
?? HEAD
?? ORIG_HEAD
?? config
?? description
?? gitk.cache
?? hooks/applypatch-msg.sample
?? hooks/commit-msg.sample
?? hooks/fsmonitor-watchman.sample
?? hooks/post-receive
?? hooks/post-update.sample
?? hooks/pre-applypatch.sample
?? hooks/pre-commit
?? hooks/pre-commit.sample
?? hooks/pre-push.sample
?? hooks/pre-rebase.sample
?? hooks/pre-receive
?? hooks/pre-receive.sample
...
这是预期的,因为.git dir的内容不受版本控制。
实际上,即使@knittl建议使用git reset --hard
也不起作用,因为它不是在common的“ work”目录中完成的。
我想到的简单解决方法是使用以下命令将操作封装在钩子中:
pwd # returns COMMON/.git
pushd .. > /dev/null
pwd # returns COMMON
#hook operations
popd > /dev/null
在钩子中使用pwd
命令进行检查我终于在正确的目录中执行存储/重置了。
但是,执行此操作时,远程消息将返回我:
remote: remote: fatal: not a git repository: '.'
所以现在我有点困惑,因为我实际上是我的COMMON的根,所以应该将其视为git存储库...
即使按照@knittl和@torek的建议,这也不是部署某些东西的黄金方式,我还是想了解为什么存在这些限制以及是否存在覆盖它们的方法。
在pre-commit钩子中,我执行了一个存储操作以保存本地修改并中止提交,因此“鲁udo的sudoer”无法提交其更改,但可以稍后选择其修改。
在此钩子中,git stash
的执行预期。
我想这个问题与以下事实有关:接收前/接收后挂钩是服务器端挂钩,通常只应用于裸仓库。
答案 0 :(得分:0)
我终于发现piece of documentation困扰着我:
在Git调用一个钩子之前,它将其工作目录更改为裸存储库中的$ GIT_DIR或非裸存储库中工作树的根。推送(预接收,更新,接收后,更新,推送到签出)期间触发的钩子是例外,它们总是在$ GIT_DIR中执行。
因此,GIT_DIR
环境变量使我的钩子在COMMON / .git中运行。
因此,为了覆盖,我终于将当前工作目录更改为COMMON并设置了GIT_DIR=$(pwd -P)/.git
如果未以这种方式设置GIT_DIR
,则git不会将COMMON视为git目录(因为默认情况下,GIT_DIR='.'
且git会在较高级别中查找.git目录)
作为参考,我的接收后钩子最终看起来像:
#!/bin/bash
# Make sure that we are on the branch containing the last commit
git checkout -f $( git log --branches -1 --pretty=format:'%D' | sed -e 's/.*-> //g' -e 's/.*, //g' )
# Forces synchronization with the last commit by discarding the local modifications. A bit trickerish but it works...
cd ..
export GIT_DIR=$(\pwd -P)/.git
git reset --hard
exit 0