git-annex 8.20210223 配置参数详解
git-annex 8.20210223 三层配置体系实测:git config annex.* 键、.gitattributes annex.largefiles 分流、numcopies 三层来源优先级实测、trust 信任级别与 group/wanted 分组、git-annex 元数据分支账本(numcopies.log/trust.log)与 .git/annex 目录结构。
git-annex 8.20210223 配置参数详解
实测环境:Ubuntu 22.04 LTS 服务器,git-annex 8.20210223(jammy apt 仓库),双机目录仓库(repo-a/repo-b)实测取值。实测日期:2026-10-30。安装过程见 《Ubuntu 22.04 安装 git-annex 8.20210223 指南》。
一、配置体系总览:三层配置源与生效优先级
git-annex 没有"一个主配置文件",它的配置分散在三个位置,按用途分工:
| 层 | 载体 | 管什么 | 随仓库传播 |
|---|---|---|---|
| git config 层 | 仓库内 .git/config(或全局 ~/.gitconfig) | 仓库自身属性:UUID、版本、backend、SSH 行为等 annex.* 键 | 否(.git/config 不被 clone 携带) |
| .gitattributes 层 | 工作区 .gitattributes 文件 | 文件分流规则(哪些文件进 annex/进 git)、按路径的 numcopies | 是(作为普通文件提交) |
| git-annex 分支层 | git-annex 元数据分支内的 log 文件 | 全网络生效的状态:副本数下限(numcopies.log)、信任级别(trust.log)、仓库分组与偏好表达式 | 是(随 sync 双向收敛) |
前两层之外的第四个入口是命令行参数(如 --numcopies=N),优先级最高但一次性生效。
优先级实测(8.20210223,同一仓库同时存在多层配置时的实际生效情况):
先让两层配置同时存在——git config 层设 annex.numcopies=1,再用 git annex numcopies 2 命令写入分支层:
git config annex.numcopies 1
git annex numcopies 2
git show git-annex:numcopies.log
(recording state in git...)
1793341478.291006959s 2
对当前只有 2 份副本的文件执行 drop(drop 后剩 1 份):若 config 层的 1 生效则放行,若分支层的 2 生效则拒绝:
git annex drop big2.bin
drop big2.bin (unsafe)
Could only verify the existence of 1 out of 2 necessary copies
Rather than dropping this file, try using: git annex move
(Use --force to override this check, or adjust numcopies.)
failed
git-annex: drop: 1 failed
拒绝信息中的必要副本数是 2——8.20210223 实测:分支层 numcopies.log 覆盖 git config 层的 annex.numcopies。把 config 层改成 3 再次验证:
git config annex.numcopies 3
git annex drop big2.bin 2>&1 | grep verify
git annex numcopies
Could only verify the existence of 1 out of 2 necessary copies
2
config=3 仍显示 "out of 2",且 git annex numcopies 查询命令读到的也是分支层的 2。只有命令行参数能即时压过它:
git annex drop big2.bin --numcopies=3 2>&1 | grep verify
Could only verify the existence of 1 out of 3 necessary copies
结论(8.20210223 实测顺序):命令行 --numcopies > git-annex 分支 numcopies.log > git config annex.numcopies。因此生产上管理副本下限推荐统一走 git annex numcopies N 命令(写入分支层、随 sync 全网络传播),避免两层并存造成认知负担。
💡 技术拓展:为什么配置要放进 git 分支? numcopies、trust、group 这类状态本质是"全网络共识"——一台机器说了不算,所有仓库必须一致。git-annex 把它们记成
git-annex分支里的 log 文件(时间戳 + 值),靠 git 的 push/pull 实现无中心的一致性收敛,这是把 git 分布式能力复用到配置上的典型设计。同类方案里,etcd/consul 需要独立集群达成共识,而 git-annex 直接"借住" git。
二、git config 层:annex.* 键实查
在已初始化的 repo-a 中实查全部 annex 相关键:
git config -l | grep -i annex
实测回显(该仓库配有一个 node-b remote 的状态):
annex.uuid=da2dfc12-a5d2-4a5b-b7d0-7efc76ae9b07
annex.version=8
annex.numcopies=1
filter.annex.smudge=git-annex smudge -- %f
filter.annex.clean=git-annex smudge --clean -- %f
remote.node-b.annex-uuid=0be16052-5128-42f8-9ae7-1ab9a32dfc83
逐键说明:
- annex.uuid:本仓库在 annex 网络中的全局唯一身份。
git annex init时生成,跨仓库追踪副本全靠它,不可手工改动; - annex.version:仓库格式版本,8.20210223 创建的是 v8 仓库(
git annex version的supported repository versions: 8一致对应); - annex.numcopies:本仓库视角的副本下限(受第一节的优先级实测约束,见 numcopies.log);
- filter.annex.smudge / clean:git clean/smudge 过滤器定义,实现工作区 symlink 与 git 内容的转换。
git annex init自动写入,不要手工编辑; - remote.<name>.annex-uuid:把 remote 名字与对端仓库的 annex UUID 绑定,sync/whereis 用它定位对端。
其他常用可配置键(git annex version 实测的构建特性支持的范围内):
| 键 | 作用 | 实测/说明 |
|---|---|---|
| annex.backends | 仓库默认 backend(内容哈希算法) | 默认 SHA256E;可用 git annex init --backend=SHA256E 或对该键设置 |
| annex.sshcaching | SSH 连接复用 | 默认开启,多机同步减少握手开销 |
| annex.largefiles | 全局兜底的文件分流表达式 | 建议用 .gitattributes 按路径配置(第三节) |
| annex.autocommit | assistant 是否自动 commit | assistant 场景使用 |
| annex.skipunknownremote | sync 跳过不可达 remote | 多机场景容错 |
三、.gitattributes 层:annex.largefiles 分流规则
3.1 问题:默认行为把所有文件都 annex 化
8.20210223 默认 git annex add 把任何文件都转成 symlink(安装篇实测:12 字节的 notes.txt 也进了 annex 对象库)。生产仓库通常希望小文本文件直接进 git(享受 git diff/合并),大文件进 annex——这就是 annex.largefiles 属性的职责。
3.2 配置与分流实测
在 repo-a 配置"大于 1 MB 的文件才进 annex":
echo "* annex.largefiles=(largerthan=1mb)" > .gitattributes
git add .gitattributes
git commit -m "configure annex.largefiles 1mb threshold"
echo "small text" > small.log
dd if=/dev/zero of=big2.bin bs=1M count=2 2>/dev/null
git annex add small.log big2.bin
git annex list
ls -l small.log big2.bin | awk '{print $1, $9}'
实测回显:
add small.log (non-large file; adding content to git repository) ok
add big2.bin
100% 2 MiB 281 MiB/s 0s ok
(recording state in git...)
here
|node-b
||web
|||bittorrent
||||
X___ big2.bin
_X__ bigfile.bin
X___ dataset-2026.tar
____ notes.txt
lrwxrwxrwx big2.bin
-rw-r--r-- small.log
分流一目了然:11 字节的 small.log 被 add 时明确提示 (non-large file; adding content to git repository),落盘为普通文件 -rw-r--r--;2 MB 的 big2.bin 进 annex,落盘为 symlink。此后 addurl 拉取的小文件同样走 git(实测 addurl 下载 robots.txt 时提示 non-large file; adding content to git repository)。
3.3 largefiles 表达式语法
annex.largefiles 的值是一个匹配表达式,常用操作符(均可在实测环境验证):
| 表达式 | 含义 |
|---|---|
| largerthan=1mb / smallerthan=100kb | 按大小分流(单位 b/kb/mb/gb) |
| include=.mp4 / exclude=.c | 按 glob 路径匹配 |
| mimetype(text/) / mimetype(image/) | 按 MIME 类型(需 build flags 含 MagicMime,jammy 包实测含) |
| anything / nothing | 全部/全不 |
多条件可用 and/or 组合,如 *.annex.largefiles=(largerthan=100mb or include=*.iso)(按路径前缀生效不同规则)。注意:该属性只影响此后 add 的文件,已 annex 化的文件要用 git annex migrate 转换 backend 或重新 add。
3.4 .gitattributes 里的 numcopies:按路径副本数
.gitattributes 还支持按路径设置副本下限,与分支层全局 numcopies 叠加生效(取更严格者):
echo "* annex.numcopies=2" >> .gitattributes
git add .gitattributes && git commit -m "require 2 copies for all annexed files"
上面这行让全仓库 annex 文件至少 2 副本;写成 datasets/** annex.numcopies=3 则只对 datasets 目录强制 3 副本。
四、副本管理配置:numcopies 全参数实测
4.1 设置与查询命令
git annex numcopies 2 # 写入分支层 numcopies.log(全网络生效)
git annex numcopies # 查询当前生效值
实测回显:
(recording state in git...)
2
4.2 drop 的副本校验语义(实测)
numcopies=N 的准确语义是:drop 本地副本后,全网络剩余副本数必须 ≥ N。安装篇与第一节实测的拒绝信息反复印证:
- 2 份副本、numcopies=2:
Could only verify the existence of 1 out of 2 necessary copies(除本地外剩 1 份 < 2,拒绝); - 位置记录未同步时:
Could only verify the existence of 0 out of 2 necessary copies——先git annex sync让 location log 收敛再 drop; - numcopies=1、另一仓库有副本:正常放行。
git-annex 还有一个更强的 required content 机制(对特定仓库强制"必须/不得"持有内容表达式,违反时 drop 直接报错),由 git annex required <remote> <expression> 管理。注意 8.x 的 required 命令第一个参数必须是仓库名,实测传数字会报错:
git annex required 1
git-annex: there is no available git remote named "1"
git-annex: Specify a repository.
五、信任级别与仓库分组
5.1 三级信任与特殊 UUID
git annex info 实测展示的信任体系:
trusted repositories: 0
semitrusted repositories: 4
00000000-0000-0000-0000-000000000001 -- web
00000000-0000-0000-0000-000000000002 -- bittorrent
0be16052-5128-42f8-9ae7-1ab9a32dfc83 -- [node-b]
da2dfc12-a5d2-4a5b-b7d0-7efc76ae9b07 -- node-a [here]
untrusted repositories: 0
- trusted:无条件相信其持有声明,副本计数必算;
- semitrusted(默认):副本计数算入,但单独存在不阻止数据被判定"安全";
- untrusted:副本计数忽略(网络盘/不可靠存储适合);
web与bittorrent是两个保留 UUID(全 0 特殊值),代表"从 URL 直接可取"的虚拟 remote。
信任级别变更写入分支层 trust.log,实测内容(semitrusted 记为 ?):
git show git-annex:trust.log
0be16052-5128-42f8-9ae7-1ab9a32dfc83 ? timestamp=1793341363.120228306s
5.2 trust 命令的防呆设计(实测)
把仓库标记为 trusted 需要 --force——8.20210223 明确拒绝轻率信任:
git annex trust node-b
git-annex: Trusting a repository can lead to data loss. If you're sure you know what you're doing, use --force to make this take effect. If you choose to do so, bear in mind that any time you drop content from node-b, you will risk losing data.
failed
git-annex: trust: 1 failed
恢复默认用 git annex semitrust node-b(实测回显 (recording state in git...),info 显示回到 semitrusted);标记不可靠存储用 git annex untrust(实测后 info 显示 trust: untrusted);退役仓库用 git annex dead——实测 dead usbdir 后 whereis 的副本列表立即排除该仓库。
5.3 分组与偏好内容:describe / group / wanted
为 remote 写描述、归组、设偏好内容表达式:
git annex describe node-b "second backup node"
git annex group node-b backup
git annex wanted node-b standard
git annex info node-b
实测回显(info 头部):
uuid: 0be16052-5128-42f8-9ae7-1ab9a32dfc83
description: second backup node [node-b]
trust: semitrusted
remote: node-b
cost: 100.0
type: git
repository location: /work/repo-b
last synced: 2026-10-30 06:20:49 UTC
remote annex keys: 2
remote annex size: 15.73 megabytes
- group 预置语义组:
backup(尽量多拿内容)、client(只留最近用过的)、archive(只进不出)等。git annex wanted <remote> standard启用该组的内置偏好表达式; - cost:remote 传输代价,默认本地 git remote 100,数值越小越优先作为 get 的来源;
- wanted 接受偏好表达式(与 largefiles 语法同源),如
git annex wanted node-b "include=datasets/**"让 node-b 只收数据集。
批量交互编辑这些配置用 git annex vicfg(按 tab 分列列出 group/wanted/trust,保存即写入分支层)。
六、git-annex 元数据分支:仓库的"账本"
git-annex 分支是 git-annex 的全部状态账本,普通 git 命令即可审阅:
git log git-annex --oneline
实测回显:
ada9d52 update
bd0db40 update
268b843 update
67e58ef update
53839b2 update
每次 annex 操作产生一个 update 提交。分支内的关键 log 文件(均实测可 git show git-annex:<文件> 查看):
| 文件 | 内容 | 实测样例 |
|---|---|---|
| numcopies.log | 全局副本下限(时间戳 + 值) | 1793341478.291006959s 2 |
| trust.log | 仓库信任级别(T/S/?/U/D) | 0be16052-... ? timestamp=1793341363.120228306s |
| uuid.log | UUID → 描述映射 | describe/group/wanted 写入处 |
| log(location log) | key → 持有仓库(时间戳 + UUID + # Present) | whereis/list 的数据源 |
运维要点:账本即 git 历史,任何状态变更可审计、可回滚(git checkout 到旧提交对照);两仓库只要 git 能互通,账本就能收敛——这就是"无中心、无数据库"的配置体系。
七、数据目录结构:.git/annex/ 实查
repo-a 的 annex 数据目录实测结构:
ls .git/annex/
gitqueue.lck
index
index.lck
journal
journal.lck
keysdb
keysdb.cache
keysdb.lck
mergedrefs
move.lck
move.log
objects
othertmp.lck
sentinal
sentinal.cache
smudge.lck
tmp
transfer
| 目录/文件 | 用途 |
|---|---|
| objects/ | 内容对象库:两级哈希分桶(实测 objects/G8/4G/<key>/<key> 形态),同名 key 内容唯一 |
| journal/ | 未提交到 git-annex 分支的状态变更日志(崩溃恢复依据) |
| transfer/ | 进行中的内容传输暂存(assistant/copy 断点) |
| tmp/ | 下载中对象的临时文件 |
| keysdb/ | SQLite 的 key 数据库缓存(加速 find/whereis) |
| *.lck | 并发锁文件(多命令并发安全) |
| index | git-annex 分支的工作索引 |
目录级 remote(如 directory 型 usbdir)的落盘形态同样是分桶:实测 /work/annex-dir/ 下直接是 7de/、tmp/ 等目录。
八、特殊 remote 配置:initremote / enableremote
除 git remote 外,git-annex 用 initremote 创建带独立配置的特殊仓库(云存储、目录、rsync 等),配置保存在分支层 uuid.log:
git annex initremote usbdir type=directory directory=/data/annex-dir encryption=none
实测回显:
initremote usbdir ok
(recording state in git...)
随后可对其 copy/get(实测 copy --to usbdir 后 whereis 显示 3 copies:node-b + usbdir + here)。两个实测踩坑点:
- 目标目录必须先存在,否则报错
git-annex: Directory does not exist: /data/annex-dir且 initremote 整体 failed; - 仓库退役不要直接删 remote,用
git annex dead <name>标记死亡(whereis 立即排除其副本),确认无副本依赖后再清理存储。
启用已存在但未激活的 remote 用 git annex enableremote <name>(如换机器后重新指向 S3 bucket)。加密场景 encryption=none 换成 encryption=shared(对称密钥)或 encryption=<keyid>(gpg 公钥),密钥配置同样落在 uuid.log。
九、配置自查命令速查
| 目的 | 命令 |
|---|---|
| 看仓库身份/版本 | git config annex.uuid、git config annex.version |
| 看当前副本下限 | git annex numcopies |
| 看某 remote 全量属性 | git annex info <remote> |
| 看分流规则 | cat .gitattributes |
| 看信任/分组账本 | git show git-annex:trust.log、git show git-annex:uuid.log |
| 交互式改配置 | git annex vicfg |
| 全仓库健康检查 | git annex fsck(逐 key 校验哈希,实测 3 个 key 全 ok) |
命令族的完整用法(get/drop/move/copy/sync 等的参数与回显)见 《git-annex 8.20210223 常用 CLI 命令详解》。