【问题标题】:Allowing 'delete branch' without allowing 'rewrite history' in Azure DevOps在 Azure DevOps 中允许“删除分支”而不允许“重写历史”
【发布时间】:2023-02-08 02:36:07
【问题描述】:

根据显示的错误消息,如果我尝试从 Azure DevOps GIT 存储库中删除分支,则需要 Force Push 权限:

然而,允许“强制推送”也允许重写历史。甚至在配置这些权限的地方也明确说明了这一点。

在我对 Git 的理解中,分支无非是书签/更改的快捷方式。在某种程度上,它们是一种特殊的标签。如果这些在合并期间被丢弃,则不需要强制推送权限。

我想授权人们能够删除分支而不给他们混淆历史的权利。他们不应该能够编辑/删除实际的更改集,但他们可以对这些特殊类型的标签做所有想做的事情。我该如何配置?

还是我误解了允许强制推送可以重写的历史数量?我只想保留由谁签入的代码更改。允许强制推送可以打破这个历史吗?

【问题讨论】:

  • 什么会阻止他们删除分支并推出它的新版本(因此......如果他们愿意的话可以完全重写它的历史)?
  • 所以我在一个分支中做了一些提交,而其他人决定扔掉我的分支并进行新的提交?在那种情况下,所有提交都是由另一个人完成的。在极少数情况下,我仍然可以在存储库中找到我的(孤立的)提交。但同样 - “重写历史”表明其他人可以修改或更改我的提交。这可能是我这边的误会。
  • git commit -m "Haha I'll destroy this app" --author="realbart"(我的意思是,git 本身没有身份验证功能,人们可以提交由您“创作”并推送它们。)
  • @RomainValeri 好点:你确实可以在没有强制推送的情况下伪造凭据/欺骗其他用户,除非你使用签名提交,但据我所知,没有办法阻止这些。那么推荐的处理方法是什么?只保留曾经被推过的每一个分支吗?

标签: git azure-devops version-control git-push


【解决方案1】:

我想授权人们能够删除分支而不给他们混淆历史的权利。

根据可用的权限选项,您无法完全实现您的要求,但是,事实证明可能有更好的方法。如果tl;博士适用然后跳到底部部分:“您可能想要着陆的地方”。

背景、问答风格:

问题:什么是“强推”?

我们常说“强推改写历史”。在这个问题的上下文中可能更有用的另一种思考方式是:每当您希望从分支的可达历史记录中删除一个或多个提交时,都需要“强制推送”。如果您不这样做,并且您推送的新提示提交可以访问远程分支的提示,那么定期推送就足够了。

问题:为什么将“强制推送”和“删除分支”混为一谈,成为同一个权限?

考虑一个达到 3 次提交的分支:A-B-C

添加一个提交:A-B-C-D = 常规推送。

删除一项提交:A-B = 强制推送。

完全替换一个提交(即删除一个并添加一个提交):A-B-X = 强制推送。

稍微修改一个提交(即删除一个并添加一个提交):A-B-C' = 强制推送。

消除全部提交(即删除分支)=强制推送。

如果我们将“强制推送”定义为“从一个分支中删除一个或多个提交”,那么删除一个分支在概念上是它的一个子集(删除所有提交),并且有一个用于删除分支的特殊语法:git push -d origin my-branchgit push origin :my-branch

现在假设我们按照您的要求做了:我们可以将“强制推送”定义为“删除一个或多个提交,但不全部commits”,然后分离权限,启用“删除分支”但不允许“强制推送”。正如Romain Valeri's comment 中指出的,没有什么可以阻止某人删除分支,然后重新使用它分支名称以推出新的提交 - 无论如何都有效地实现了“强制推送”。话虽这么说,如果您为“创建新分支”添加了第三个权限,那么您的愿望也许会奏效。但是,允许人们删除一个分支但不创建分支可能会导致比在大多数工作流程中解决的问题更多的痛苦。(但这并不意味着没有人会发现它的价值......)

问题:什么时候可以使用“强制推送”?

这在很大程度上取决于您的情况和偏好。有些人认为答案是“从不”,尽管这种严格的教条可能是少数人的观点。多数立场是不允许强推共享分支机构,并允许以其他方式推动力。一般来说,特别是在私人回购中,人们拥有自己的个人分支机构是很常见的,因此鼓励定期将这些分支机构重新设置为共享目标,因此强制推送个人分支机构将被视为正常且频繁发生。因此,在私有 AzDO 存储库中,允许删除和强制推送分支是有意义的,只要它是个人的分支。

您可能希望登陆 Azure DevOps 的地方:

  1. 对于将对任何 AzDO Git 存储库做出贡献的所有用户,默认情况下,设置:

    允许对于“贡献”和“强制推送”。

    没有设置对于其他一切。

    请注意,这些设置将应用于最多分支机构。

  2. 对于具体受保护分支机构,使用分支机构政策。这将需要一个 Pull Request(具有许多可配置选项)以便合并到受保护的分支中,并且还有效地防止任何人强行推送或删除这些分支。

    对于受保护的分支,如果需要,您可以选择通过关闭继承来添加额外的安全性,然后根据需要设置显式安全性。在那种情况下,您可以为可以在分支中完成 PR 的用户集添加“Contribute”,但这次(可能)不包括“Force Push”1个.其他权限示例可能包括:

    • 您可能有一组特定的自动构建用户,他们被允许“在推送时绕过策略”,这样他们就可以在没有合并请求的情况下推送提交。
    • 如果一群人需要绕过门控签入或使用分支策略不允许的某种合并类型,则可能允许“在完成合并请求时绕过策略”。
    • 一组被授予“管理权限”的管理员,因此在需要强制推送的紧急情况下,他们可以暂时赋予某人“强制推送”和“推送时绕过策略”的能力,然后删除强制推送完成后立即获得这 2 个权限。

    Azure DevOps 试图阻止这种情况,并且几乎成功了:

    我认为重要的是要指出在幕后,AzDO 实际上赋予了意义创造者的一个分支。这个概念在 Git 中实际上并不存在,但是(通过反复试验我已经确认)AzDO 将其定义为:

    分支创建者是最新的经过身份验证的用户,在分支名称不存在时推送该分支名称。

    请注意,这意味着分支创建者可以更改,例如,如果分支被删除,然后其他人推送同名分支 - 最后一个推送它的人在它不存在时成为创建者。此外,要推送的人是在 AzDO 中经过身份验证的人(在客户端或 UI 中);此人与分支上提交的作者无关。

    这里有趣的部分是分支的“创建者”自动获得对该分支的额外权限,包括强制推送权限,这意味着如果你没有像我上面推荐的那样默认为每个人启用强制推送,这个人(或管理员或一组人特别给予强制推送权限)仍然可以删除自己的分支。恕我直言,这是避免给每个人强制推送权限的一个非常好的尝试,但在实践中我发现它不起作用。问题在于,当您选择在完成 PR 后删除分支的选项时,只有当该分支的“创建者”是完成 PR 的人时,它才会起作用。如果其他人完成了 PR,则分支删除将失败。在我的工作流程中,这是一个非常重要的问题,许多人完成其他人的 PR,我们必须默认授予每个人强制推送权限。


    1个请注意,启用分支策略后,为了强制推送,您必须为两个权限设置“允许”:“强制推送”和“推送时绕过策略”。这意味着任何用户都可以拥有一个或另一个,只要他们不拥有两者即可。这就是为什么出于理智的目的,您“可能”想要从受保护分支上的每个人那里删除“强制推送”权限,但实际上可能没有必要这样做。

【讨论】:

  • 问题:孤立的提交没有从回购协议中删除,是吗?如果我仍然知道 ID,那么我仍然可以查看它们,对吗?使用正确的工具,我可以看到它们吗?
  • 这是正确的。 AzDO 不会删除孤立的提交。您仍然可以从推送日志中找到提交 ID,或者在 PR 中(如果当时存在的话)。知道 ID 后,您可以直接导航到它(单击任何提交链接,然后更改 url 中的提交 ID),如果需要,您可以从那里在该提交处创建一个新分支。您还可以使用git fetch origin <full-40-char-hash> 获取任何已知 ID,一旦您在本地拥有它,您就可以用它做任何想做的事。
  • 所以在我看来,“改写历史”这个词选得不好。它导致我们的 IT 部门恐慌并阻止了所有人的这项权利。对我来说,变化就是历史。分支和标签只是书签。
  • @realbart 如果您认为“分支”基本上是指向单个提交的指针,那么当您添加新提交时,您就是在“添加历史记录”到那个分支,但是如果你删除一个提交,你确实是在“重写历史”那个分支的.我认为恐慌是由于没有意识到无论如何都会删除的短期特征分支的“重写历史”根本无关紧要,但绝对应该避免长期共享分支的“重写历史”!
  • @realbart 这并没有真正出现在我的回答中,但你关于标签的观点也是正确的。如果您标记您感兴趣的特定构建,即使重写或删除的分支不再可以访问它们,每个人仍然可以轻松地看到它们以供将来参考。这些提交 ID 由标签保留在前面和中间。
猜你喜欢
  • 1970-01-01
  • 2020-11-01
  • 2021-01-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-03-17
  • 2015-05-13
  • 1970-01-01
相关资源
最近更新 更多