fix(mailmap): 归并目标改为 GitHub noreply,消除幽灵贡献者

★ 根因是我把归并目标写成了 `JianFeeeee@users.noreply.gitcode.com`
  —— 那是**GitCode 的 noreply 域,GitHub 不认**。
  而 459 个提交(早期历史的大头)用的正是它,GitHub 无法把它们关联到
  任何本地账号,只能用启发式挂上一个**不相干的账号**当贡献者
  (实测出现过 linu223xprob1e)。

  ⇒ mailmap 把提交「归并到」某邮箱,等于告诉 GitHub「这些提交属于这个身份」;
    归并到一个它不认识的域,反而**制造**幽灵贡献者。
  ★ 教训:目标必须是**目标平台认的**标识,不是「看起来像匿名邮箱就行」。

归并目标改为标准格式 109188060+JianFeeeee@users.noreply.github.com
(id + 登录名,从 GitHub API 实测得来,非猜测)。

本地实测(origin/main 全历史 765 提交):
  归并前:459 gitcode noreply / 135 root@qq / 51 JianFeeeee@root@qq / 33 jianf…
  归并后:745 JianFeeeee <109188060+JianFeeeee@users.noreply.github.com>
          19 HomeAgent Agent(刻意不归并,区分自动化提交)
           1 pi(自动化 agent)
           1 jianf <â^@2198972886@qq.com>  ← 坏字节,mailmap 治不了

最后 1 条需改写历史(邮箱前缀带 3 个坏字节,文本文件无法表达),
另开一次操作处理。
This commit is contained in:
pi
2026-10-05 11:51:13 +08:00
parent 7901651946
commit 5250ca35ea

View File

@ -1,49 +1,59 @@
# .mailmap —— 提交身份归并 # .mailmap —— 提交身份归并
# #
# 为什么需要:GitHub 的 Contributors 按**提交邮箱**归并身份,而本项目历史里 # 为什么需要:GitHub 的 Contributors 按**提交邮箱**归并身份,而本项目历史里
# 同一个人的提交来自多个邮箱(本地 root、个人 QQ、gitcode noreply、 # 同一个人的提交来自多个邮箱(本地 root、个人 QQ、GitCode noreply、
# GitHub noreply),于是列表里出现若干「虚拟贡献者」。 # GitHub noreply),于是列表里出现若干「虚拟贡献者」。
# #
# 本文件只影响 **展示层**(git log --use-mailmap / GitHub Contributors), # 本文件只影响**展示层**(git log --use-mailmap / GitHub Contributors),
# 不改写任何提交对象,历史 SHA 全部保持不变。 # 不改写任何提交对象,历史 SHA 全部保持不变。
# #
# 格式:<归并到的姓名> <归并到的邮箱> <历史姓名> <历史邮箱> # ★★★ 归并目标为什么必须是 GitHub 的 noreply(2026-10-05 踩坑)
# #
# ★★ 写法要点(2026-10-05 实测踩坑,附实证): # 原先归并到 `JianFeeeee@users.noreply.gitcode.com` —— 那是**GitCode 的
# noreply 域,GitHub 不认**。而 459 个提交(占大头的早期历史)用的正是
# 它,于是 GitHub 无法把它们关联到任何本地账号,只能用启发式挂上一个
# **不相干的账号**当贡献者(实测出现过linu223xprob1e)。
# #
# ① 右端必须写成「历史姓名 + 历史邮箱」成对形式。 # ⇒ mailmap 把提交「归并到」一个邮箱,等于告诉 GitHub「这些提交属于这个
# 只写邮箱时git 要求提交的 author name **也为空**才匹配, # 身份」;归并到一个它不认识的域,反而制造幽灵贡献者。
# 而历史提交都带名字 ⇒ 映射静默失效,且**不报任何错**。
# (实证:只写邮箱的那版,`jianf` 仍出现在 Contributors 里。)
# #
# ② 注释里**不要写出形如映射的示例行**。 # ★ 教训:mailmap 的目标必须是**目标平台认的**标识,
# git 只认行首 `#` 作为注释起点;缩进注释里若出现 # 不是「看起来像匿名邮箱就行」。
# 「姓名 邮箱」或「若干空格 + 邮箱」,仍会被解析成真实条目。
# 同名目标后者覆盖前者 ⇒ 真正的映射被悄悄顶掉。
# #
# ③ 坏字节邮箱无法在文本文件里表达 —— 那种提交只能改写历史 # ★★ 写法要点(都实测过):
# (git filter-repo --mailmap)。本文件已不含此类条目: #
# 唯一那<E4B880><E982A3><EFBFBD>(58ef728,邮箱前缀多出 3 个坏字节)已于 2026-10-05 改写。 # ① 右端必须写成「历史姓名 + 历史邮箱」成对形式。只写邮箱时 git 要求提交的
# author name **也为空**才匹配,而历史提交都带名字 ⇒ 静默失效且不报错。
#
# ② 注释里**不要写出形如映射的示例行**。git 只认行首 `#` 作为注释起点;
# 缩进注释里若出现「姓名 邮箱」或「若干空格 + 邮箱」,仍会被解析成
# 真实条目,且同名目标**后者覆盖前者** ⇒ 真正的映射被悄悄顶掉。
#
# ③ 坏字节邮箱无法在文本文件里表达(提交 58ef728 的 author 邮箱前缀带
# 3 个坏字节)。mailmap 对它**无效**,只能改写历史。
# #
# 注意:HomeAgent Agent <agent@homeagent.local> **不归并** —— agent 的自动提交 # 注意:HomeAgent Agent <agent@homeagent.local> **不归并** —— agent 的自动提交
# 保留独立身份,便于区分人类提交与自动化提交。 # 保留独立身份,便于区分人类提交与自动化提交。
# ── 主身份(显式写出,避免依赖隐式默认)── # ── 主身份:GitHub noreply(GitHub 认这个;109188060+登录名 是标准格式)──
JianFeeeee <JianFeeeee@users.noreply.gitcode.com> JianFeeeee <JianFeeeee@users.noreply.gitcode.com> JianFeeeee <109188060+JianFeeeee@users.noreply.github.com>
# ── 本地 root(历史署名有 root 与 JianFeeeee 两种)── # ── 历史主身份:GitCode noreply(459 个提交,最大头)──
JianFeeeee <JianFeeeee@users.noreply.gitcode.com> root <root@qq.com> JianFeeeee <109188060+JianFeeeee@users.noreply.github.com> JianFeeeee <JianFeeeee@users.noreply.gitcode.com>
JianFeeeee <JianFeeeee@users.noreply.gitcode.com> JianFeeeee <root@qq.com>
# ── 本地 root ──
JianFeeeee <109188060+JianFeeeee@users.noreply.github.com> root <root@qq.com>
JianFeeeee <109188060+JianFeeeee@users.noreply.github.com> JianFeeeee <root@qq.com>
# ── 个人 QQ 邮箱(历史上配过 jianf 与 JianFeeeee 两个名字)── # ── 个人 QQ 邮箱(历史上配过 jianf 与 JianFeeeee 两个名字)──
JianFeeeee <JianFeeeee@users.noreply.gitcode.com> jianf <2198972886@qq.com> JianFeeeee <109188060+JianFeeeee@users.noreply.github.com> jianf <2198972886@qq.com>
JianFeeeee <JianFeeeee@users.noreply.gitcode.com> JianFeeeee <2198972886@qq.com> JianFeeeee <109188060+JianFeeeee@users.noreply.github.com> JianFeeeee <2198972886@qq.com>
# ── 本地开发身份 ── # ── 本地开发身份 ──
JianFeeeee <JianFeeeee@users.noreply.gitcode.com> JianFeeeee <jianfeeeee@homeagent.local> JianFeeeee <109188060+JianFeeeee@users.noreply.github.com> JianFeeeee <jianfeeeee@homeagent.local>
JianFeeeee <JianFeeeee@users.noreply.gitcode.com> dev <dev@local> JianFeeeee <109188060+JianFeeeee@users.noreply.github.com> dev <dev@local>
JianFeeeee <JianFeeeee@users.noreply.gitcode.com> root <root@minecraft-server> JianFeeeee <109188060+JianFeeeee@users.noreply.github.com> root <root@minecraft-server>
JianFeeeee <JianFeeeee@users.noreply.gitcode.com> JianFeeeee <109188060+JianFeeeee@users.noreply.github.com> JianFeeeee <109188060+JianFeeeee@users.noreply.github.com> JianFeeeee <109188060+JianFeeeee@users.noreply.github.com>
# ── pi(自动化 agent,保留独立身份)── # ── pi(自动化 agent,保留独立身份)──
pi <pi@local> pi <pi@local> pi <pi@local> pi <pi@local>