我正在开发一种流程,它将允许人们访问一个公共环境。我的想法是要有一个只能放入的存储库,而不是一个裸露的存储库,因为我希望人们能够阅读它。我们称之为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钩子中,我执行了一个存储操作,以保存本地修改并中止提交,因此“鲁ck的sudoer”无法提交其更改,但可以稍后选择其修改。在此挂钩中,git stash
的执行效果与预期相同。
我想这个问题与接收前/接收后挂钩是服务器端挂钩这一事实有关,通常只应用于裸仓库。
我终于找到了困扰我的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