ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

Jujutsu (jj) Git 兼容性全解:Git 后端、Colocated 工作区与格式映射机制

2026/9/10 11:08:51 拓冰建站 浏览量
Jujutsu (jj) Git 兼容性全解:Git 后端、Colocated 工作区与格式映射机制 Jujutsu (jj) Git 兼容性全解Git 后端、Colocated 工作区与格式映射机制【免费下载链接】jjA Git-compatible VCS that is both simple and powerful项目地址: https://gitcode.com/GitHub_Trending/jj/jjJujutsujj提供了两种存储提交的后端其中一种直接建立在标准 Git 仓库之上意味着你可以与 Git 用户协作而对方甚至察觉不到你没有使用git命令行。本篇以官方文档 git-compatibility.md 为主体结合当前仓库源码系统讲解 jj 对 Git 各项特性的支持矩阵、三类建仓流程、Colocated同置工作区的工作原理与转换方法以及提交元数据在 Git 对象格式中的映射细节读完之后你能够独立在 jj 与 Git 之间切换协作并理解二者数据互通的底层机制。双后端架构与 jj git 命令族Jujutsu 有两个提交存储后端默认的后端使用 jj 自有的存储格式而 Git 后端则直接复用真实的 Git 仓库作为对象库这正是 Git 兼容性的基础。通过jj git init或jj git clone创建的仓库都采用 Git 后端仓库中会同时存在.jj与.git两个目录。所有 Git 交互都收敛在jj git命令族之下。从 git 命令入口 的GitCommand枚举可以看到完整的子命令清单clone、colocation、export、fetch、import、init、push、remote与root。官方建议通过jj help git查看该命令族的帮助用jj help git push或更简短的jj git push -h查看具体子命令的帮助。支持的 Git 特性清单以下列表描述了 Jujutsu 与各项 Git 特性的兼容程度更细的工作流差异对比见 Git 对比文档Git 特性兼容程度说明配置Configuration部分支持仅读取 Git 的两类配置remote 配置[remote name]在未通过 CLI 显式指定分支时简单的 fetch refspec 会被遵守底层调用git完成远端操作core.excludesFile认证Authentication支持远端操作底层使用git因此凭证机制完全一致分支Branches支持详见 bookmarks 文档 及本文“分支”一节标签Tags部分支持可按名称检出带标注/轻量标签指向的提交可创建轻量标签但不能创建带标注标签.gitignore支持支持.gitignore、.git/info/exclude以及core.excludesFile。由于几乎所有jj命令都会对工作副本做快照新加入忽略规则的文件需要运行jj file untrack才能从工作副本提交中排除建议尽早配置忽略规则。实现是 jj 的原生实现与git行为不一致时应反馈为 bug.gitattributes不支持上游已立项至少支持eol属性Hooks不支持上游有专门跟进 pre-commit 集成的议题合并提交支持包括八爪鱼合并2 个以上父提交游离 HEADDetached HEAD支持jj 天然支持匿名分支这就是自然状态孤儿分支Orphan branch支持jj 有一个虚拟根提交充当 Git 所谓“根提交”的父提交暂存区Staging area忽略暂存区会被忽略例如jj diff展示的是 Git HEAD 到工作副本的 diff无暂存区也能满足相应使用场景见 Git 对比文档的索引一节垃圾回收GC支持在 Git 仓库里运行git gc应该是安全的未做完整测试建议先备份整个工作区jj 自身的数据结构目前还没有垃圾回收与重打包裸仓库Bare repositories支持用jj git init --git-repopath可以创建由裸 Git 仓库支撑的仓库子模块Submodules不支持不会出现在工作副本中但也不会丢失Partial clones不支持—浅克隆Shallow clones部分支持浅克隆的边界提交以虚拟根提交为父加深或完全去浅unshallow尚不支持会造成问题git-worktree不支持jj 有原生的多工作副本支持单仓库多 working copy见jj workspace命令族Sparse checkouts不支持jj 有原生的 sparse checkout 支持见jj sparse命令签名提交Signed commits支持可通过配置自动签名见 config.md 的 commit signing 一节或使用jj sign命令Git LFS不支持上游已立项跟进三种建仓方式创建空仓库jj git init name这会创建一个 colocated 的 Jujutsu 工作区目录下同时生成.jj与.git。由现有 Git 仓库创建jj git init --git-repopath to Git repo name该仓库的行为类似 Git worktree工作副本文件与工作副本提交的记录相互独立但提交在两个仓库中都可以访问。之后需要双向同步jj git import把 Git 仓库中的变更导入 Jujutsu 仓库jj git export把 Jujutsu 仓库中的变更导出回 Git 仓库。克隆远端 Git 仓库jj git clone URL [destination] # 例如 jj git clone https://github.com/octocat/Hello-World默认远端名为origin可通过--remote remote name指定其他名字。Colocated Jujutsu/Git 工作区Colocated 工作区是一种 Jujutsu/Git 混合工作区也是jj git init和jj git clone的默认形态。此时 Git 仓库与 Jujutsu 工作区共享同一个工作副本Jujutsu 会在每一条jj命令执行时自动完成与 Git 仓库的 import/export。这种模式在构建工具等外部工具“假设 Git 仓库必须存在”的场景下非常方便。在 colocated 工作区里可以任意顺序混合使用jj与git命令但更易于掌握节奏的做法是主要用只读git命令观察仓库用jj发起修改。原因是 jj 没有“当前跟踪分支”的概念jj命令通常会把 Git 仓库置于“detached HEAD”状态在执行会修改仓库的 Git 命令前可能需要先用git switch告诉 Git 当前分支应该是什么。混合使用的回退手段jj undo与jj op restore可以撤销修改性git命令的结果在jj op log中git 引起的变更会显示为一条 “import git refs” 操作。关闭 colocation 有两种方式jj git init/jj git clone加--no-colocate参数或设置配置git.colocate false。从 CLI 内置配置默认值 可以看到当前colocate的默认值是true。关闭后仓库数据仍大多存储为 Git 格式但 Git 仓库会隐藏在.jj目录的一个子目录中除非显式执行jj git import和jj git export那个 Git 仓库要么没有任何分支连 main 都没有要么分支与 jj 的 bookmarks 不同步。为什么有时要禁用 colocation官方文档明确列出了 colocated 模式的几个缺点交叉命令引发冲突状态jj与git命令交错执行会增加分支冲突或“冲突即分叉change id”出现的概率——这些状态不会丢数据但会造成困扰。且这种交错可能不知不觉发生例如某些 IDE 会在后台自动定时执行git fetch。大规模 ref 下变慢分支或其他 ref 数量非常多的 colocated 工作区中由于每条命令都会自动执行jj git import命令可能明显变慢。可以不定期运行jj util gc缓解该命令包含对 Git refs 的打包。Git 工具读不懂含冲突文件的提交jj在工作副本中用冲突标记渲染这些文件但仓库内部存储的是不可读形式Git 工具经常看到的是后者。冲突分支在 Git 侧位置不一致当 jj 分支处于冲突状态时Git 仓库中该分支的位置与冲突位置中的某一个不一致其在 git 中的状态会被标记为属于名为 “git” 的远端例如branchgit。忽略 Git 的中间状态Jujutsu 会忽略 Git 的暂存区也不理解 Git 表示的合并冲突、未完成的git rebase状态以及其他较少见的仓库状态。并发鲁棒性较弱若通过 NFS 或 Dropbox 等共享仓库colocated 工作区对并发问题的抗性更差这类用法目前尚未得到充分测试。偶发的指针错位 bugjj与修改性git命令交错时可能仍有 bug通常表现为分支指针落到了错误位置。维护方正在处理已知问题欢迎报告新发现。在 colocated 与非 colocated 之间转换一个由 Git 仓库支撑的 Jujutsu 工作区内部含有完整的 Git 仓库可以用jj git colocation命令组在两种形态间转换。# 查看当前 colocation 状态 jj git colocation status # 转换为 colocated 工作区 jj git colocation enable # 转换为非 colocated 工作区 jj git colocation disable这些子命令的实现见 colocation.rs。从 status 子命令源码 可以看出它会通过is_colocated_git_workspace判断当前形态并打印工作区名字和“Last imported/exported Git HEAD”——即最后一次导入/导出时 Git HEAD 的位置非 colocated 工作区中该值通常缺席但会打印实际状态以便排障随后给出下一步建议若工作区由外部 Git 仓库支撑则提示“无法启用 colocation”。enable 的实现 自动化的就是下面这套手动流程# 让 Git 忽略 .jj 目录 echo /* .jj/.gitignore # 移动 Git 仓库 mv .jj/repo/store/git .git # 告诉 jj 去哪里找它Windows 上不要用这一行见下文 echo -n ../../../.git .jj/repo/store/git_target # 将 Git 仓库设为 non-bare 并设置 HEAD git config --unset core.bare # 促使 jj 更新 .git/HEAD 指向工作副本提交的父提交 jj new jj undoWindows 注意Windows 上echo会追加行尾换行导致jj抱怨git_target的内容。应改用Set-Content -Path .jj/repo/store/git_target -Value ../../../.git -NoNewLine对照 disable 的实现 可以看到反向操作把.git移回.jj/repo/store/git、将其设为 bare、把git_target内容重置为git、删除.jj/.gitignore并移除 git HEAD 引用。源码中maybe_add_gitignore辅助函数git/mod.rs则负责在 colocated 工作区写入内容为/*的.jj/.gitignore防止 Git 跟踪 jj 的仓库数据。相关行为有专门测试覆盖见 test_git_colocation.rs、test_git_init.rs 与 test_git_clone.rs。分支映射原文档中该节尚标注为 TODO。就当前仓库而言jj 的“bookmarks”在功能上对应 Git 的分支概念二者的互操作细节见 bookmarks 文档在 Git 对象层面与远端标签相关的引用存放在refs/jj/remote-tags/命名空间下见 git.rs。格式映射细节这一节描述 jj 数据与 Git 对象格式之间的具体对应关系是理解“Git 工具看到什么”的关键。路径编码路径默认按 UTF-8 处理官方目前不打算支持其他编码的路径。防 GC 保护由jj创建的提交会带一个以refs/jj/开头的 ref 以防被垃圾回收。从 git_backend.rs 源码看该命名空间具体是refs/jj/keep/jj 会在导入/导出时为活跃提交重建这些 ref并清理指向已不可达提交的旧 ref。Git 无法承载的元数据Change ID、冲突信息等无法表示在 Git 提交中的元数据存储在 Git 仓库之外当前位于.jj/store/extra/。冲突提交的表现含冲突的提交无法在 Git 中直接表示。它们在 Git 提交中表现为一组名为.jjconflict-base-*/与.jjconflict-side-*/的“根目录”。注意这种表示的目的仅是防止相关 tree 被 GC权威信息仍在上文所述的 Git 仓库外存储中。只要用jj命令操作就不会察觉这些路径但若用git switch检出其中一个含冲突的提交工作副本里会看到这些目录随后运行jj status生成的快照会包含它们看起来像替换了仓库中所有其他路径——此时通常需要用jj abandon回到未解决冲突的状态。Change ID 提交头Change ID 以反转的十六进制编码存入 git 提交头change-id常量定义见 git_backend.rs。这是一个非标准头并非所有 git 工具都会保留它git commit --amend会保留而 rebase 不会GitHub 等主要托管平台通常会保留。该头自0.30.0版本起由jj在创建提交时默认写入可通过配置git.write-change-id-header关闭从 内置配置默认值 与 配置解析 看其默认值为true。验证头是否存在git show与git log都不打印这个头。用 git 自身验证时可用git cat-file -p commit ref输出中若带有change-id 十六进制一行即表明头存在。该行为的往返正确性在单元测试中有断言见 test_git.rs 中 “change-id header did not roundtrip” 相关用例。小结与适用前提与 Git 用户协作的入口是jj git命令族init空仓库 /--git-repo基于既有仓库、clone远端 URL、fetch/push远端同步、import/export非 colocated 模式下手工同步、remote远端管理、root/colocation仓库位置与形态管理。默认形态是 colocated共享工作副本、每条jj命令自动双向同步适合希望工具链“无感”的场景对分支/冲突敏感或 ref 数量极多的场景可考虑--no-colocate/git.colocate false并用jj git import/jj git export显式同步。Git 侧无法看到 jj 的 Change ID除非提交头被保留与冲突的内部表示跨工具操作含冲突的提交时要格外小心。以上行为均以当前仓库文档与源码为准特性支持矩阵中的“部分支持/不支持”条目如.gitattributes、hooks、LFS、子模块会随版本演进升级后建议以仓库内文档与 CHANGELOG 复核。【免费下载链接】jjA Git-compatible VCS that is both simple and powerful项目地址: https://gitcode.com/GitHub_Trending/jj/jj创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考