我有几个非裸Git存储库。有一个中央Git存储库(或者至少作为中央存储库处理;这可能会改变)但这也是非裸的(因为我想在同一台机器上进行结账)。我的历史主要是线性的,我是唯一一个会对此存储库进行更改的人,因此不太可能发生冲突。 (这是我的文件目录。)
如果我到处使用master
分支,则直接推入另一个非裸存储库不起作用。有receive.denyCurrentBranch
允许这样做,但它并没有真正帮助我,因为(1)它没有更新本地结账和(2)我害怕发生冲突时会发生什么。< / p>
这里有一些相关/类似的问题:
ssh git pull
)。post-update
挂钩(强烈建议避免它)。或者更确切地说,将其推送到某个特定的唯一远程引用,然后让目标稍后处理合并。我想要一个100%安全的解决方案。所以我认为使用post-update
钩子对我来说是没有选择的。
我认为我的用例实际上不常见,所以我想知道是否有一些常见的解决方案。有吗?
我想,我想要的是:
master
推送到某个远程特殊引用(例如merge-request-xy
)(例如git push origin master:merge-request
?)。git merge merge-request && git branch -D merge-request
?)。这样做是安全的还是一种好方法?
答案 0 :(得分:2)
您建议的解决方案是安全的,只要您(1)推送到master
以外的其他分支,如merge-request
和(2)进行合并检查。对于第二部分,如果遥控器上的所有内容都是快速转发,则可以使用像这样的post-update
挂钩:
#!/bin/sh
# check args to see if merge-request was pushed,
# and do nothing if it wasn't
if ! $(echo $@ | grep -q 'merge-request');
then
echo "merge-request not updated"
exit 0
fi
# cancel if master is not checked out
THIS_BRANCH=$(git branch --no-color | sed -e '/^[^*]/d' -e 's/* \(.*\)/\1/')
if [ "$THIS_BRANCH" != "master" ];
then
echo "master not checked out, not merging"
exit 1
fi
# cancel if working dir is dirty
if [ $(git status --porcelain | wc -l) != 0 ];
then
echo "working dir is dirty, not merging"
exit 1
fi
# try to merge, but only do so if the merge is fast-forward
# try to delete, but only do so if the merge succeeded
git merge --ff-only merge-request && git branch -d merge-request
确保chmod +x
您的更新后脚本。当您按下时,此挂钩的输出将显示在以“remote:”
要从远程master
推送到origin/merge-request
,您可以在push
中设置远程配置中的.git/config
var(可让您拨打{ {1}}:
git push origin
或者您可以设置特定于回购的别名:
[remote "origin"]
push = +refs/heads/*:refs/merge-request/*
答案 1 :(得分:0)
使用post-update
挂钩推送到非裸存储库的危险部分是远程工作副本是否不干净和/或您无法快进。如果您要将这些先决条件放在解决方案上,那么您最好使用带有结帐选项的经过更好测试的post-update
挂钩。
如果您无法保证这些先决条件,那么无论如何您都必须解决来自另一端的任何冲突。在这种情况下,您再次使用post-update
挂钩选项,但请确保在没有--force
的情况下进行结帐,因此如果发生冲突,您不会丢失本地更改。
我仍然不明白为什么这么多人似乎不愿意在同一台机器上进行裸露且非裸露的回购。我家里有一个简单的回购,我从家里和工作中推进。当我开始在任何一个位置工作时,我会进入我的非裸存储库。这需要2秒钟,而且我总是处于解决任何潜在冲突的最佳物理位置。