Git rebase可以完全删除远程历史记录吗?

11

在考虑从SVN转移到git时,一位同事提出了一个担忧:恶意或不小心的开发人员可以使用git rebase从我们共享的代码库中删除远程历史。

编辑:正如答案中指出的那样,也可以使用git push origin :branch-name从远程代码库中删除整个分支。

这是一个现实的问题吗?如果是,我们应该采取什么措施来防止它发生?


@sehe 这并没有解决人为错误的问题,使得Git的采用成为组织问题和技术问题。 - Matthew Gilliard
你是在表达什么观点吗?采用版本控制系统工作流程是一个组织上的挑战。而且,你之前已经接受了一个相同的答案,并提议使用Gerrit来管理推送访问权限,现在却这样说,我感到很有趣...在8月8日。 - sehe
我要表达的观点是,“你必须信任每个开发者,或者有门卫,而且没有人永远不会犯错”并不是一个令人满意的答案来回答我的(同事的)问题。我当时接受了一个大致说出这个答案的回答,就假设它是唯一的解决方案,但几周后有了不同的方法建议。我将尝试配置参数的方法,如果成功,那将是我首选的答案。 - Matthew Gilliard
3个回答

7
我倾向于同意你的同事,因为这里存在问题,原因如下:
  • 无论你对提交者有多么信任,人为错误总是有可能的。
  • 更繁琐的审查流程(例如Gerrit)并不总是合适的。
  • 从备份中恢复可能会很慢且麻烦。

你考虑过receive.denyNonFastForwardsreceive.denyDeletes配置参数吗?据我所知,这些参数在Git 1.6及以上版本中可用。

来自《Pro Git》:

如果你重新整理已经推送的提交,然后再次尝试推送,或者以其他方式尝试将提交推送到不包含当前指向远程分支的提交的远程分支,你将被拒绝。这通常是一个很好的策略;但在重新整理的情况下,您可能会确定自己知道自己在做什么,并可以使用-f标志强制更新远程分支到您的推送命令。

要禁用强制更新远程分支到非快进引用的功能,请设置receive.denyNonFastForwards

另一种方法是通过服务器端接收挂钩来实现,稍后在Pro Git中进行介绍。该方法允许您执行更复杂的操作,例如拒绝某个用户组的非快进引用。正如作者所提到的,这条规则也可以通过接收挂钩来强制执行(在Pro Git中稍后描述)。

这些技术应该可以防止您的共享存储库中发生意外(或恶意)的历史记录丢失。

这对我们来说可能是一个不错的解决方案,但我还是有些紧张,不确定它是否完整。考虑到Git可以有很多不同的使用方式,可能仍然存在漏洞,允许删除代码。 - Matthew Gilliard
1
好的,我们已经实现了 denyNonFastForwards 功能,并且它运行良好 :) - Matthew Gilliard

3
使用rebase会混淆历史记录,但通常远程仓库不会接受修改历史记录的更改(除非使用git push --force)。此外,具有推送权限的开发人员可以完全删除分支(git push origin :branch-name)。因此,简单的规则是:
  • 不要将推送权限授予您不信任的开发人员。

  • 当仓库共享时,不要混淆历史记录,如果需要从不同的分支添加内容,请使用合并或挑选而不是rebase。在这种情况下,历史记录不会受到影响。

  • 您可以保持不在共享仓库上使用'push -f'的策略,在这种情况下,开发人员将知道如果推送被拒绝,则出现了问题(很可能是本地分支与远程分支不一致),应该在本地解决问题,而不是强制推送。

关于如何防止使用Gerrit修订系统的问题,它就像是在开发人员本地代码库和主代码库之间进行提交的中间步骤,并提供了一个良好的网络界面进行修订。您可以授权任何人将更改推送到修订代码库,但是在验证和批准后,更改将合并到您的主分支中(这需要一些通常授予核心开发人员的权限)。您可以在Mahara项目上查看其外观:https://reviews.mahara.org 在这种特殊情况下,只允许gerrit bot将更改推送到主分支(即here),其他人不行。


1

企业级 Git 服务器(如 Gerrit)有一些扩展功能,可以检测历史重写和分支删除,并将它们备份到特殊的引用下,以便在需要时进行恢复,并且不会被垃圾回收清除。如果出于法律原因需要,Gerrit 管理员仍然可以选择性地删除提交记录。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接