我想用后台作业镜像一些 git 存储库。git clone --mirror
并且git remote update
不会保留通过强制推送未引用的对象,但我也想保留这些对象以防万一。是否有任何工具可以执行安全的 git 镜像?
6 回答
尽管缺少 shell 脚本会很乏味,但如果您可以访问远程存储库,那么您可以执行:
git fsck --lost-found
这将列出未引用的提交,然后您可以为每个提交创建一个分支:
git branch <branch-for-commit> <commit>
在这一点上,没有任何东西是未引用的,并且克隆不会 gc/丢失任何东西。之后,如果您选择,您可以像删除分支一样删除分支
像这样:
git fsck --lost-found | \
grep dangling | \
awk '{ system ("git branch" " br-" $3 " " $3); }'
保留悬空提交和 blob。然后,在克隆之后,
git branch -a | grep "br-" | xargs git branch -D
在重新阅读问题和提供的答案后,我确定我误解了海报的意图。
现在我认为需要在目标存储库中启用reflogcore.logAllRefUpdates
,方法是将其中的 设置为true
,并可能调整控制 reflog 过期策略的相关参数(grep 世界“reflog”的git-config
手册页)。这将记录所有允许回滚强制推送等的“剧烈”参考重新定位。
请注意,仍然唯一真正防止(比如说您说)“黑客攻击”或任何其他类型的损失是拥有安全的异地备份,所以我认为我在第一个答案中提出的建议仍然有效。
这几乎是一个安全问题。如果您不小心推送了密码或其他内容,则可以修改您的提交并强制推送新的提交。之后 git 将不允许对第一次提交进行任何访问。
如果你真的需要这些提交,你需要访问文件系统并使用类似的东西rsync
来获取所有内容。- 但请注意,git 有时会进行一些垃圾收集,因此旧的未引用提交实际上会丢失。
我认为您可以采用两阶段备份:
git fetch <remote> +refs/*:refs/*
更新裸镜像存储库。git gc
可能“规范化”其内容。rdiff-backup
结果到另一个目录,该目录将包含最后备份的版本以及可用于重建任何先前备份的二进制差异文件的集合。
通过这种方式,您可以获得备份快照的版本化历史记录。由于rdiff-backups
允许丢弃旧快照,因此您可以只记录您认为合适的快照数量。
缺点是浪费磁盘空间:
rdiff-backup
将制作源目录的真实副本;不会共享任何文件。- AFAIK,处理包文件的 Git 内部不支持程序的
--rsyncable
命令行选项之类的东西gzip
,因此生成的增量rdiff-backup
可能很大。另一方面,在典型的 Git 存储库中,任何包文件都应该只被附加,而不是重写,所以我可能在这里找错了树。
如果您要获取您控制的存储库,则有一些gc
配置项可以控制删除内容和时间的各个方面;git remote update
(以及其他所有内容)只要您愿意,就会保留未引用的对象。任何具有管理权限的人都可以通过标记未引用的对象来发布它们。
因此,为了安全地镜像存储库,如果您对其具有管理控制权,只需设置一个挂钩来将传入的推送转发到永不过期的备份存储库。否则,关闭提交通知的接收将确保您记住您曾经见过的所有内容。
我认为其中一位评论者说得对:rsync 或等效项是您唯一的朋友,尽管它不是 Github 等的选项。
看到这个(诚然旧的)线程:
http://kerneltrap.org/mailarchive/git/2007/8/28/256180/thread
引用其中一条消息:
它与 Linux 开发实践无关。我们不获取钩子的根本原因是:
它们不是存储库的一部分;只需查看 .gitattributes-in-the-index-but-not-worktree 问题即可了解原因,
它是私有数据,就像配置一样。客户无权阅读它们,更不用说获取它们,
如果你在不同的机器上有钩子,很可能你需要一种机制来更新钩子……这自然建议把钩子放到他们自己的分支中。
可能有更多的理由不允许诸如获取钩子之类的事情。
所以......如果你想将钩子部署在多个位置,将钩子放在他们自己的仓库中是一个很好的解决方案,但除此之外,你无能为力,因为我知道仓库中的各种对象...
(该链接的学分转到:https ://stackoverflow.com/a/6154010/417194 )
特别是对于 github,可能有 github-services 或 web hooks 的变通方法。