防止或追赶git历史重写的策略

虽然我喜欢git历史重写function,但是如何确保历史不会被重写。

我们不介意程序员在自己的机器上做什么,但是我们需要确保一个版本不会推送到改变历史logging的服务器上。

即我们需要保证过去的某个版本确实是那个版本。 因此,这将包括阻止某人通过并永久删除历史logging中的文件,或在所有历史logging中永久更改文件。

如果你可以运行:

git config --system receive.denyNonFastforwards true 

在服务器上,这应该照顾重写历史案件被推送到所述服务器。
但是,这是所有回购,而不是一个特定的文件或一组文件。

git config

receive.denyNonFastForwards

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

另一种方法是通过服务器端的接收挂钩,我会稍微介绍一下。 这种方法可以让你做更复杂的事情,例如拒绝某些用户的非快速转发。


作为ebneter (谁知道一个连贯的存储库的重要性 – 请参阅SVN到Git迁移的答案[现在删除的问题,只有10K +用户])评论:

您可能还想添加receive.denyDeletes true ,否则,有人可以删除该分支,然后将其重写的分支作为新分支,有效地重写历史logging。

git config

denyNonFastForwards策略的解决方法之一是用户删除分支,然后用新引用将其重新推回。 在较新版本的Git中(从版本1.6.1开始),可以将receive.denyDeletes设置为true:

$ git config --system receive.denyDeletes true

这样一来,就会拒绝分支和标签的删除 – 用户无法做到这一点。 要删除远程分支机构,您必须手动从服务器中删除ref文件。 还有一些更有趣的方法可以通过ACL在每个用户的基础上做到这一点,正如您将在本章最后学到的一样。

如果你没有为receive.denyNonFastForwards使用一个足够新的git,你可以通过服务器上的{pre,post}-receive (除其他之外)钩子来强制执行策略,这允许特定分支的粒度更细一些等等。

一些很好的例子(包括一个禁止历史重写的例子)被GNOME项目用来pipe理所有的仓库:

https://git.gnome.org/browse/sysadmin-bin/tree/git

我特别看在接收前检查政策 。

如果你不能/完全不希望禁用Git历史重写,但希望得到关于这种性质的每一个变化的通知,甚至可以在几年后恢复,那么企业Git服务器的扩展,如Gerrit将检测历史重写和分支删除,将在特殊的参考下支持它们,以便在需要时可以恢复它们,不会被垃圾收集修剪。 如果法律原因需要,Gerritpipe理员仍然可以删除选定的提交。