gpt4 book ai didi

git - 强制整个团队 merge

转载 作者:太空狗 更新时间:2023-10-29 13:42:52 25 4
gpt4 key购买 nike

所以在工作中,我们正在实现一个新的,不错的git分支策略-太棒了!
为了保留存储库的新结构(而且很好),我们希望所有合并都使用--no-ff标志(以及--no-commit标志,以便更好地合并提交消息)。然而,仅仅要求每个人记住它,似乎有点不可靠。有没有办法强制每个开发人员都必须与上述标志合并?
据我所知,这是不可能用钩子检查的(因为git不可靠地存储任何关于快进的信息)。我知道可以在每台开发人员机器上设置配置(通过运行git config --global merge.ff no)。如果这是解决方案,我如何确保每个开发人员都有这个配置集?

最佳答案

我相信您可以在服务器上的pre-receive hook中检查到这一点,但是很难定义什么是允许的,而且这可能会使推送对执行推送的人来说更加困难。而且,它只会给那些做错事的人一个错误:由他们来修复,这对一些用户来说可能有点复杂。
此外,您(和开发人员)可能不希望在某些合并上强制执行--no-ff:特别是,如果您在branchX上没有提交,并且获取了新的origin/X提交,那么您可能希望将X快速转发到origin/X。(另一方面,在这种情况下,您/他们总是可以使用git rebase。)
也就是说,让我们看看是否可以定义正确的行为。
首先,我们可能会注意到“快进”实际上是标签移动的属性,而不是合并的属性。当标签的前一个提交是其新提交的祖先时,标签会以快速前进的方式移动。(因此,git使用术语“快进合并”来指代事实上根本不是合并的内容。)git用于任何分支推送更新的默认测试是,除非设置了force标志,否则标签更新必须是快进操作。
我们不想拒绝标签快速转发,因为这是扩展分支的正常情况,无论是否合并:

...--o--o--n--n--n   <-- br1

在这个图中,我们表示一个建议的更新(如在预接收钩子中看到的),它将现有的提交写为“cc>”,并且新的写为“cc>”。标签 o(更准确地说, n)用于指向尖端most br1,现在将指向尖端most refs/heads/br1
在预接收钩子中,实际发生的情况是存储库已经用新的提交(合并与否)进行了更新,git只是以 o元组的形式将每个引用更新请求交给您。换言之,考虑到上面的压缩 n更新图,我们可以使用大写和小写(唉,我不能用颜色)重写它,大写代表传入的 <old-hash, new-hash, name>br1值,给出:
...--o--O--n--n--N   <-- br1

如果您拒绝推送,git将收集新提交的垃圾,因为您告诉git不允许任何引用更新(包括分支名称),所以 old-hash仍会指向commit new-hash
现在,合并通常在您的系统中是可以的,但是您需要的是确保当 br1获取稍后将在 O上的合并提交时,branch br1不会移动到直接包含该合并提交。也就是说,这没关系:
...--o--O--n--n--N   <-- br1
... /
...---o--O--n--N <-- br2

即使这样也没问题(也许我们可以假设您在以后的推送中会得到一个 br2更新,然后我们会检查该部分;我们还不能这样做,因为我们还没有得到 br2更新):
...--o--O--n--n--N   <-- br1
... /
... n--n
... /
...----o--o <-- br2 (you get no update since br2 did not move)

但这是要被拒绝的:
...--o--O--n--n--N   <-- br1, br2
... /
...---o--O--n--n

这也是:
...--o--O--n--n--N     <-- br1
... / \
...---o--O--n--n N <-- br2

另一方面,这是可以的(尽管我们可能希望在 br2上限制允许它通过哪个父节点;在这些图中,指向左边的直线都是 br2链接):
...--o--O--n--n--N     <-- br1
... / \
...---o--O--n--n---N <-- br2

此外,可以在合并后获取其他非合并提交:
...--o--O--n--n--n--N   <-- br1
... / \
...---o--O--n--n---N <-- br2

(同样在 br2上)。但是,我们必须检查每个合并,因为这不正常:
...--o--O--n--n--n--n--n---N   <-- br1
... / \ \ /
...---o--O--n--n n--n--N <-- br2

(这里有人在 --first-parent时执行 br2,然后在 git merge br2时执行 br1快速前进,然后在 git merge br1上执行两次提交;他们也在 br2上执行两次提交;然后他们再次将 br2合并到 br1中,然后将 br1合并到 br2中作为 br2合并;然后在一个 br1中同时推 --no-ffbr1)。
那么:确切地说,我们应该执行什么规则?我认为,我们可以在遍历合并提交时强制执行有关 br2的规则,从而使这项工作变得更容易和更好。特别是,我们想要的是:
给定分支更新(不是创建或删除)
按图形顺序遍历
要求结果列表中最早的提交具有作为其第一父级的旧哈希。
有很多方法可以编写这个,尝试使用 git push是很有诱惑力的,但是这并不能正常工作,因为为合并显示的边界提交包括其所有父级,即使使用 --first-parent。所以让我们直截了当地说:
# Operation must be a fast-forward.  This ensures that
# $oldsha is an ancestor of (and thus related to) $newsha,
# and thus we are not discarding any commits.
if ! git merge-base --is-ancestor $oldsha $newsha; then
... reject as non-fast-forward
fi
edge=$(git rev-list --topo-order --first-parent $oldsha..$newsha | tail -1)
# If the rev-list is empty then $oldsha is not related to $newsha.
# However, we checked that first. (The only other case where this
# can occur is if $oldsha equals $newsha, which is not an update,
# so we won't be running this code at all.)
#
# The listed edge commit may, however, be a root commit (have
# no parent). We must reject this case as well as "parent is
# not $oldsha". Fortunately that happens automatically since
# the empty string does not match a valid hash; we just need
# to be sure to quote "$parent".
parent=$(git rev-parse -q --verify $edge^)
if [ "$parent" = $oldsha ]; then
... update is OK
else
... reject as containing a bogus merge
fi

注意,这也会拒绝 "foxtrot merges",因为第一个父 --first-parent不会返回到原始散列。
(我没有测试过这些。)

关于git - 强制整个团队 merge ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36172424/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com