拓冰建站拓冰建站
首页 / 资讯中心 / 正文

hg-git无损双向同步的秘密:git-mapfile映射表与--HG--元数据机制详解

hg-git无损双向同步的秘密git-mapfile映射表与--HG--元数据机制详解【免费下载链接】hg-gitmercurial to git bridge, pushed to directly from the hg-git plugin in Hg项目地址: https://gitcode.com/gh_mirrors/hg/hg-githg-git 是一个在 MercurialHg与 Git 之间实现无损双向同步的桥接插件你用hg gpush推送对端 Git 用户完全无感知你用hg gfetch拉取Git 提交会被完整还原成 Hg 变更集。本文带你拆解它背后的两大核心机制——git-mapfile 映射表与--HG--元数据块理解为什么删掉整个 Git 缓存目录也能无损重建。什么是 hg-git先搞清它的定位Mercurial 和 Git 是两套完全不同的数据模型Hg 用分支 书签组织历史Git 用分支引用 提交图。把提交从一个系统搬进另一个系统最怕的是信息丢失——尤其是分支名、文件重命名记录、committer 等 Git 有而 Hg 没有或反过来的字段。hg-git 的设计目标写得很直白见项目设计文档 DESIGN.txt所有数据以Hg 原生格式为主存储Git 目录只是一个可随时清空的缓存每个 Git 提交在任何机器上都能还原成确定性的 Hg 变更集反之亦然且 SHA 不变Git 侧协作者几乎察觉不到你用的是 Hg唯一的破绽是提交信息末尾多了一段--HG--。想本地体验一下可以克隆仓库git clone https://gitcode.com/gh_mirrors/hg/hg-git下面进入无损的秘密。机制一git-mapfile 映射表——两个世界的翻译字典它长什么样每次 Hg 与 Git 提交相互转换时hg-git 都会把一对孪生 ID记录下来文件位于仓库的.hg/git-mapfile。每行格式极其简单40位Git SHA 40位Hg SHA例如一行就是a1b2c3... 4d5e6f...前面是 Git 提交 ID后面是对应的 Hg 变更集 ID。解析逻辑在 hggit/git_handler.py 的load_map方法中逐行读取严格要求行长为 82 个字符40 1 空格 40 换行任何不合规都会直接报corrupt mapfile错误防止脏数据破坏同步。双向索引查找 O(1)加载时 hg-git 会构建两份内存字典_map_gitGit SHA → Hg SHA_map_hgHg SHA → Git SHA拉取时用它判断这个 Git 提交我导入过没有去重推送时用它把 Hg 变更集的父提交翻译成 Git 父提交 ID。整个导入过程中映射表随进度增量保存可通过hggit.mapsavefrequency配置保存频率中途中断也不会丢已建立的映射。 小结论mapfile 就是双向同步的账本。有了它任何一条历史都能精确地在两个体系间往返对账。机制二--HG-- 元数据——把 Git 装不下的东西塞进提交信息Hg 和 Git 的提交元数据并不等价。比如 Hg 的分支名在普通 Git 提交里不存在Hg 的文件重命名记录在 Git 里只是被推断出来的。如果不把这些信息藏起来round-trip推过去再拉回来之后信息就丢了。hg-git 的解法是把额外信息编码进提交本身。--HG-- 块里装了什么当 Hg 变更集导出为 Git 提交时如果存在额外元数据提交信息末尾会被追加一段见 hggit/hg2git.py你的正常提交说明 --HG-- branch : my-branch rename : old/path.c new/path.c extra : some-key : some-value三类内容各有用途branch分支名不是default时必写保证 Hg 分支在 Git 侧隐形保存rename旧路径 新路径保住 Hg 显式记录的重命名信息extra其余 Hg 扩展字段的键值对URL 编码避免特殊字符破坏格式。新旧两种格式兼容老版本早期版本把元数据全部写进--HG--文本块新版本则优先使用 Git 提交对象原生的extra 字段形如HG:branch、HG:rename、HG:extra把信息放在提交对象元数据里而不是篡改信息正文更原生也更干净。拉取方向的解析统一在 hggit/git2hg.py 的extract_hg_metadata函数中完成先用\n--HG--\n拆分信息兼容旧格式文本块再遍历HG:前缀的 extra 字段解析新格式。解析结果里还有一个精妙的细节——判断这个提交到底来自 Hg 还是 Git来自 Hg 的提交会携带 hg-git 字段导入时保留其重命名信息、禁用 Git 侧的重命名推断来自 Git 的提交则标记hg-git-rename-source: git允许推断。这一个标记就是双向都不猜、都不丢的关键。为什么敢叫无损Git 目录只是缓存设计文档里有一句话最能体现架构自信你可以随时运行hg gclear抹掉整个 Git 目录一切都能从现有 Hg 数据无损重建——它只是缓存。这意味着主存储永远是 Hg 原生格式Git 对象库可随时删除重建重建依据是 mapfile --HG--元数据 Hg 变更集本身三者信息完整自洽分支映射规则明确见 DESIGN.txt 的 Branch Translation Policy启用书签时书签当 Git 分支推送未启用时tip映射到远端master。换句话说无损不是靠魔法而是靠信息守恒两边系统各自缺失的字段都被编码进了对方能承载的载体里且解析规则确定。怎么验证同步真的无损用 hg gverify光说无损不够项目自带校验工具 hggit/verify.py它从 mapfile 查出某 Hg 修订对应的 Git 提交逐文件比对文件内容、权限标志、文件清单任何差异都会列出具体文件和原因比如file found in git but not hg。对应的失败场景测试见 tests/test-verify-fail.t里面演示了篡改 mapfile 后校验如何报错——反向印证了映射表在完整性检查中的核心地位。日常使用建议批量导入后抽查几个关键修订的gverify结果不要手工编辑.hg/git-mapfile行格式有严格长度校验若 Hg 侧strip删除了已映射的变更集先跑hg git-cleanup清理避免拉取时找不到父提交报错hggit/git_handler.py 中对此有明确检查。总结机制文件位置作用git-mapfile.hg/git-mapfileGit SHA ↔ Hg SHA 双向翻译字典去重与对账的账本--HG--元数据提交信息尾部 /HG:extra 字段保全分支、重命名、扩展字段防止 round-trip 丢信息Git 缓存目录.hg/git/或内嵌.git/可随时hg gclear删除并重建的纯缓存verify 校验hggit/verify.py逐文件比对两侧内容验证无损理解了映射表管身份、元数据管内容、Git 目录管速度这三层分工你就掌握了 hg-git 无损双向同步的完整图景——这正是它能让 Hg 用户和 Git 用户在同一个仓库里协作多年而互不察觉的秘密。【免费下载链接】hg-gitmercurial to git bridge, pushed to directly from the hg-git plugin in Hg项目地址: https://gitcode.com/gh_mirrors/hg/hg-git创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
分享:

看完干货,该让你的企业上线了

免费需求沟通 · 48 小时内出具建站方案 · 河南本地可上门