预防或捕获Git历史重写的策略

44
尽管我喜欢git历史重写功能,但如何确保历史记录不被重写呢?
我们不介意程序员在自己的机器上做什么,但我们必须确保不会将更改历史记录的版本推送到服务器。
即我们需要确保过去的某个特定版本真的是那个版本。因此,这将包括防止有人在历史记录中永久删除文件或在整个历史记录中永久更改文件。
3个回答

42

如果您可以运行:

 git config --system receive.denyNonFastforwards true

在服务器上,应该处理重写历史记录的情况,当被推送到该服务器时。
但是这仅适用于整个仓库,而不是特定文件或文件组。

git config:

receive.denyNonFastForwards

如果您重新设置已经推送的提交,然后尝试再次推送,或者尝试将提交推送到不包含远程分支当前指向的提交的远程分支中,您将被拒绝。这通常是很好的策略;但是对于rebase,您可能确定自己知道自己在做什么,并且可以使用-f标志强制更新远程分支以进行推送。

您还可以通过服务器端接收钩子(稍后我将介绍)来执行此操作。该方法允许您执行更复杂的操作,例如拒绝某些用户的非快进。


正如ebneter(他知道一致性存储库的重要性--请参见关于从Subversion到Git的迁移的答案[问题现已删除,仅适用于10K+用户])所评论的:

您可能还需要添加receive.denyDeletes true,否则,某人可以只需删除分支,然后将其重写的分支作为新的分支推送,从而有效地重写历史记录。

git config:

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

$ git config --system receive.denyDeletes true

这样就禁止了跨越板块的分支和标签删除--没有用户可以这样做。要删除远程分支,必须手动从服务器中删除ref文件。还有更有趣的方法可通过ACL以每个用户为基础来执行此操作,您将在本章末尾学习它们。


3
如果您的git版本不够新,无法使用receive.denyNonFastForwards,您可以通过服务器上的{pre,post}-receive(等等)钩子来强制执行该策略,这允许对特定分支进行更细粒度的控制等。
GNOME项目使用一些很好的示例(包括禁止历史重写)来管理所有存储库:https://git.gnome.org/browse/sysadmin-bin/tree/git。我建议特别查看pre-receive-check-policy

0

如果您不能/不想完全禁用Git历史重写,但希望在每次此类更改时得到通知并能够在多年后进行恢复,那么企业Git服务器(如Gerrit)有扩展功能可以检测历史重写和分支删除,并将它们备份到特殊的引用下,以便在需要时进行恢复,并且不会被垃圾回收清除。 Gerrit管理员仍然可以出于法律原因删除选定的提交。


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