如何确保队友通过重写历史来搞砸git repo?

时间:2014-11-02 17:55:06

标签: git github version-control

通常的建议似乎不是改变,重置或执行其他历史记录重写"提交后的操作已被推送。

建议在您自己的机器上执行所有这些切片和切割,但是一旦您推动它,就让它成为现实。

这是有道理的。

但是如何执行这项政策呢?对于多个开发人员,我们如何确保没有人这样做?

似乎应该有一种方法让git以编程方式知道它是否正在重写已经被推送的东西的历史记录。

如果没有内置,似乎应该有办法编写一个可以检查此内容的脚本。

理想情况下,人们不会被允许做任何重写历史记录的事情。它会返回错误。

如果这不可能,那么至少会阻止人们推送任何重写历史记录。

这可行吗?

3 个答案:

答案 0 :(得分:1)

一种可能的解决方案是client side hook (pre-rebase)

  

我们可以做的另一件事是确保用户不会推送非快速转发的引用。要获得不是快进的引用,您必须重新调整已经推送的提交或尝试将其他本地分支推送到同一个远程分支。

     

据推测,服务器已经配置了receive.denyDeletesreceive.denyNonFastForwards来强制执行此策略,因此您可以尝试捕获的唯一意外事情是重新定位已经推送的提交。

     

一个示例pre-rebase脚本,用于检查:它获取了您要重写的所有提交的列表,并检查它们是否存在于任何远程引用中。
  如果它看到一个可从某个远程引用访问的内容,则会中止该rebase。

#!/usr/bin/env ruby

base_branch = ARGV[0]
if ARGV[1]
  topic_branch = ARGV[1]
else
  topic_branch = "HEAD"
end

target_shas = `git rev-list #{base_branch}..#{topic_branch}`.split("\n")
remote_refs = `git branch -r`.split("\n").map { |r| r.strip }

target_shas.each do |sha|
  remote_refs.each do |remote_ref|
    shas_pushed = `git rev-list ^#{sha}^@ refs/remotes/#{remote_ref}`
    if shas_pushed.split("\n").include?(sha)
      puts "[POLICY] Commit #{sha} has already been pushed to #{remote_ref}"
      exit 1
    end
  end
end

但这仍然是客户端解决方案,可以绕过,并且必须通过回购部署来部署/激活回购。

在服务器端,这不容易强制执行(在配置receive.denyNonFastForwards旁边)。

但是自从git 1.8.5起,而不是简单的git push --force(在rebase之后),你现在可以做 git push --force-with-lease

  

你假设你在决定改变历史应该是什么时拿到了ref的租约,只有在租约没有被破坏的情况下你才可以撤回。

至少,你知道你的推力是否会引起问题。

但这仍然是用户必须考虑的事情。

答案 1 :(得分:0)

添加到VonC的答案,您实际上可以要求github拒绝快速推送到您的存储库。我做了几次。

只需向他们发送电子邮件并要求他们这样做。

答案 2 :(得分:0)

如果您可以控制您使用的服务器,则可以。如果您有自己的github安装,则可以拒绝来自客户端的强制推送。如果没有,您可以请求github管理在您的存储库中设置它,然后它将被强制执行。