跳至主要内容 跳至导航 跳至页脚
限时:设计合作伙伴计划,BUSINESS 套餐永久免费

rdc repo diff

显示两个写时复制(copy-on-write)分支仓库之间的类Git风格的文件级差异,通过在块级别比较其加密镜像,无需解密。

rdc repo diff

rdc repo diff 报告两个相关仓库之间哪些文件发生了变更:一个分支与其父仓库,或任何共享写时复制祖先的两个仓库。传递 --name <fork> 以针对本地配置记录的分支父仓库进行差异比较,或添加 --base <repo> 以针对任意相关仓库进行差异比较,其中 --base 是基础(旧)端, --name 是目标(新)端。此命令只读,永不解密镜像。它在远程机器上的块级别比较它们,因此成本由改变的块数量决定,而不是仓库的大小:一个1GB的仓库和一个100GB的仓库,如果进行相同的编辑,耗时相同。如果整个仓库发生变更,块数量会随大小而扩展,成本也会随之增加。

何时使用

总之:在推广分支之前,使用 repo diff 命令。一个AI代理在生产环境的分支副本中失控,你想在合并更改前准确看到它修改了哪些文件: repo diff --name <fork> -m <machine> 在几秒内为你提供文件列表。几秒钟。灾难恢复还原后,将已还原的分支与其应该复制的快照进行差异比较,以确认预期的文件集已返回且没有其他内容漂移。对于与父仓库并行运行数周的长期分支,差异比较显示累积的发散(配置编辑、日志增加、模式迁移),无需手动挂载和遍历两棵树。

不要跨不相关的仓库使用它。两端必须共享一个写时复制祖先,因为比较在共享的块历史上工作。这也不是一个二进制差异工具: --content 仅为文本文件产生行级输出,二进制文件报告 Binary files differ

命令参考

概览

rdc repo diff --name <fork> -m <machine>            # diff a fork against its parent
rdc repo diff --name <fork> --base <repo> -m <machine>   # diff against an arbitrary related repo

选项

选项说明默认值
--name <name>要检查的仓库(目标,新端)。必需。必需
--base <name>要进行差异比较的仓库(基础,旧端)。默认为 --name 的父仓库,从本地配置解析。--name 的父仓库
(无格式标志)名称状态输出:每个更改文件显示彩色的 A / M / D / R 字母加一行摘要。启用
--name-only每行一个更改路径,无状态字母。便于管道。禁用
--stat每个文件的更改幅度(字节和块增量)及总计页脚。禁用
--content <path>单个文件的统一文本差异。仅文本;二进制文件报告 Binary files differ禁用
--json用于代理和脚本的结构化输出。禁用
--fast跳过内容哈希确认步骤,信任块筛选器。更快,但可能将文件过度报告为已修改。禁用
-m, --machine <name>目标机器。必需。必需
--debugstderr上的详细诊断。禁用
--skip-router-restart跳过路由器重启步骤。禁用

示例

默认名称状态与父仓库比较

仅使用 --name 时,分支与本地配置中记录的父仓库进行差异比较。此处分支 test-1gb:fork1 有一个已修改的文件:

$ rdc repo diff --name test-1gb:fork1 -m hostinger
M  hello.txt

1 file changed: 0 added, 1 modified, 0 deleted, 0 renamed

与显式基础比较

传递 --base 以针对任意相关仓库进行差异比较。 --base 是基础(旧)端, --name 是目标(新)端:

$ rdc repo diff --name test-1gb:fork1 --base test-1gb:latest -m hostinger
M  hello.txt

1 file changed: 0 added, 1 modified, 0 deleted, 0 renamed

使用 --stat 显示更改幅度

--stat 添加每个文件的字节和块增量及总计页脚:

$ rdc repo diff --name test-1gb:fork1 --stat -m hostinger
 hello.txt | +8 bytes, 1 block

1 file changed, 4096 bytes touched

仅路径,用管道输入工具

--name-only 每行打印一个路径,无状态字母,准备好输入到另一条命令:

$ rdc repo diff --name test-1gb:fork1 --name-only -m hostinger | xargs -I{} echo "review: {}"
review: hello.txt

单个文件的行级差异

--content 生成单个文本文件的统一差异:

$ rdc repo diff --name test-1gb:fork1 --content hello.txt -m hostinger
--- a/hello.txt
+++ b/hello.txt
@@ -1 +1 @@
-the original line of text in the parent
+the original line of text in the parent, now edited

使用 jq 筛选JSON

--json 在stdout上发出结构化信封,因此它可以干净地输入到 jq :

$ rdc repo diff --name test-1gb:fork1 --json -m hostinger | jq '.data.entries[] | select(.status=="M")'
{
  "status": "M",
  "path": "/hello.txt",
  "type": "file",
  "old_size": 53,
  "size": 61,
  "bytes_changed": 4096,
  "blocks_changed": 1,
  "inode": 13,
  "content_changed": true,
  "mode_changed": false,
  "uid_changed": false,
  "gid_changed": false
}

输出格式

名称状态(默认)

每个更改文件获得一个状态字母和其路径。 A 表示已添加, M 表示已修改, D 表示已删除, R 表示已重命名(显示旧路径)。后面是总结行,显示每个类别的计数。

--name-only

每行一个路径,无状态字母,无总结。当下游命令需要干净的文件列表时使用。

--stat

每行显示文件的字节增量和块增量。页脚报告总文件数和总修改字节数。这显示了变更的重点在哪里,而不仅仅是哪些文件移动。

--content <path>

单个文本文件的标准统一差异( --- / +++ 头部, @@ 块)。二进制文件报告 Binary files differ 并产生无块。

--json

完整的结构化结果。数据输出到stdout;进度和诊断输出到stderr,因此JSON可以干净地输入到 jq 或另一个解析器,即使进度正在打印。

JSON模式

CLI将renet结果包装在标准信封中( successcommanddataerrorswarningsmetrics )。差异结果位于 data 中,使用snake_case字段:

{
  "success": true,
  "command": "repo diff",
  "data": {
    "base": "<base-guid>",
    "target": "<target-guid>",
    "added": 0,
    "modified": 1,
    "deleted": 0,
    "renamed": 0,
    "strategy": "shared",
    "fast": false,
    "degraded": false,
    "block_size": 4096,
    "total_bytes_changed": 4096,
    "entries": [
      {
        "status": "M",
        "path": "/hello.txt",
        "type": "file",
        "old_size": 53,
        "size": 61,
        "bytes_changed": 4096,
        "blocks_changed": 1,
        "inode": 13,
        "content_changed": true,
        "mode_changed": false,
        "uid_changed": false,
        "gid_changed": false
      }
    ]
  }
}

entries[] 中的每个对象描述一个更改路径:

字段类型说明
statusA | M | D | R已添加、已修改、已删除或已重命名。
pathstring目标端上的路径(或删除的基础端路径)。
old_pathstring之前的路径。仅在重命名时存在。
typefile | dir | symlink | other条目类型。
old_sizenumber基础端的大小(字节)。
sizenumber目标端的大小(字节)。
bytes_changednumber不同的字节数,向上舍入到整数块。
blocks_changednumber已更改块的数量。
inodenumberinode数字,用于重命名检测。
content_changedboolean文件内容(而不仅仅是元数据)是否已更改。
mode_changedboolean文件模式是否已更改。当为真时存在 old_mode / new_mode
uid_changedboolean所有者是否已更改。当为真时存在 old_uid / new_uid
gid_changedboolean组是否已更改。当为真时存在 old_gid / new_gid
old_target / new_targetstring符号链接目标。对于更改的符号链接存在。

有关信封字段和在非TTY环境中发出JSON的自动检测规则,请参阅 JSON输出参考

工作原理

仓库是btrfs池上的LUKS2镜像文件,分支是该镜像的常数时间reflink副本。 repo diff 通过FIEMAP在块级别比较两个加密镜像,仅读取文件系统元数据,永不解密任何内容。它通过LUKS数据偏移移动更改的密文偏移,以获得ext4设备偏移,然后通过每个文件的ext4extent映射将这些偏移映射回文件名。两个挂载的最终inode身份遍历将结果协调为已添加、已修改、已删除和已重命名条目。因为工作受已更改块数量的限制,所以差异与仓库大小无关,因为它在适当位置重用实时挂载,所以它永不扰乱运行中的仓库。完整机制在 Git diff for encrypted disk images 中描述。

限制

  • 仅相关分支。 两端必须共享写时复制祖先。不相关仓库之间没有有意义的块级比较。
  • 重命名检测基于inode。 当相同inode出现在新路径上时,文件被报告为已重命名。删除后重新创建(新inode)显示为已删除加已添加条目,而不是重命名。
  • --content 仅文本。 它为文本文件产生行级块。二进制文件报告 Binary files differ
  • --fast 可能过度报告已修改。 它信任块筛选器并跳过内容哈希确认,因此块移动但内容未更改的文件可能显示为已修改。
  • Extent遍历时间随碎片化扩展,而非大小。 高度碎片化的文件系统有更多extent要映射,即使更改的字节量很小,也会延长遍历时间。

另请参阅