私有化研发协同系统并行期:旧 Jira 与新 Git 并存 6 条数据规则

并行期最容易出的事故,不是代码推不上去,而是同一个需求在两套系统里有两个状态。Jira 里还停在"测试中",新 Git 的合并请求已经进了主干;复盘时,产品经理看 Jira,开发看 Git,测试看流水线,三边都能给出"最新状态"。

私有化研发协同系统并行期,旧 Jira 与新 Git 并存,难点不在装好两套系统,而在把数据主权、关联关系和切换时间定成规则。下面 6 条规则按"先定边界、再定写入、再定退出"的顺序展开,适合 DevOps 负责人、研发主管和平台工程师直接改成本团队的迁移检查表。

并行期最怕的不是两套工具,而是三类"脑裂"

工具并存本身不是问题。问题是同一条业务事实被两套系统分别解释,最后没有统一口径。并行期常见的脑裂有三类。

  • 身份脑裂:Jira 用账号 ID,Git 用提交邮箱,目录服务里还有工号。同一个人在三处可能是三个标识。表现是提交记录归不到人,权限复核对不上。
  • 写入脑裂:Jira 的自动化、Git 的 webhook、人工操作都能改状态。表现是同一个缺陷先被关闭又被打开,或者 Jira 显示"已解决",新系统仍显示"处理中"。
  • 时间脑裂:旧任务没关,新任务已开;旧分支还在提交,新仓库已经冻结。表现是发布清单里出现两套版本号,回滚时找不到对应的代码。

三类问题指向同一件事:并行期缺的不是更多同步,而是一份字段级的数据契约。只发通知、拉群、开会,解决不了"谁能写"的问题。

先把数据主权划清:Jira、Git 与新协作层各管什么

数据主权不是"谁更重要",而是"这个字段允许谁写"。并行期最容易犯的错,是让两套系统都保存全量数据,再做双向同步。同步一多,冲突就不是异常,而是日常。

数据对象 唯一写主库 另一侧保留什么 关联键
需求、任务、缺陷的标题、描述、状态、评论 Jira(切换前) 只读镜像或链接 legacy_id
代码、分支、提交、合并请求、评审记录 新 Git 链接与摘要 commit SHA / MR ID
用户身份 企业目录(LDAP/AD/HR) 各系统本地账号 工号或目录 ID
构建、制品、发布记录 新 Git 或发布系统 Jira 只存版本引用 build ID / artifact ID
审计日志 各系统各自留存 不互相覆盖 event_id + 时间戳

如果新平台同时带来新的项目协作模块,不要把 Jira 的全部字段搬过去再双写。切换前,Jira 仍是问题主库;新协作层只承接新项目,或者做只读镜像。切换后再反过来,旧 Jira 只读。

图 1:数据主权矩阵。Jira 保留历史问题与流程记录,新 Git 持有代码、评审和构建证据,映射层只负责关联,不复制业务字段。

这张矩阵的用法很直接:任何新字段上线前,先填"唯一写主库"一列。填不出来,就不要接同步。以 GitFox 这类私有化 Git 平台为例,代码库、分支、合并请求、流水线、制品库的元数据应由 Git 侧持有;需求与缺陷仍由协作侧持有。两边通过 ID 关联,而不是互相复制整张表。

规则一:一个字段只能有一个写主库

这条规则听起来像废话,落地时却最容易被"先同步起来再说"打破。字段级的主库要写进接口权限,不是写在文档里。

  • 写接口只开给主库 :Jira 的 status、assignee、sprint、fixVersion 等字段,只允许 Jira 或其授权自动化写;新 Git 只能读,或者提交变更请求事件,由 Jira 侧裁决。
  • 读副本可以多,写入口只能一个:报表、看板、搜索索引都可以复制;复制失败不影响主库。反过来,任何"为了看板方便"直接写副本的做法都要禁止。
  • 跨系统只追加三类东西:引用链接、同步事件、审计备注。不要新增"另一个状态字段"来表达同一件事。
  • 例外进队列,不要进数据库:冲突、缺失映射、权限不足,统一进人工复核队列;不要让脚本"猜一个值"写回去。

判断是否双写,有一个简单测试:把新 Git 的写接口关掉 24 小时,业务是否还能正常流转?如果答案是否定的,说明你把主库放错了位置,或者把不该由 Git 承担的字段搬了过去。

规则二:用不可变 ID 建映射,别把项目键当主键

Jira 的 issue key 很好用,但它不是数据库主键。Atlassian 的文档把 issue key 定义为"项目键 + 问题序号"的可读标识;项目键在迁移、改名或重组时可能调整,迁移文档也提醒,改键后要同步配置、过滤器和看板。拿它当跨系统主键,后面会不断修关联。

  • 三层 ID 分开存 :legacy_id(Jira 内部 ID,用于稳定关联)、legacy_key(人看的 issue key,如 PROJ-123)、new_id(新系统 ID)。关联以 legacy_id 为准,legacy_key 只用于搜索和展示。
  • 自定义字段按 ID 映射,不按名称:Atlassian 明确建议使用自定义字段 ID,因为名称可以改。字段名"故事点"明天可能叫"工作量",按名称映射会断。
  • 用户按目录 ID 映射,不按显示名:同名、改名、离职再入职都会让显示名不可靠。最少保留工号或目录 ID、邮箱、Git 提交邮箱三列,做归一。
  • 代码按 commit SHA 绑定,不按分支名:分支会移动,发布标签也可能被重写。发布证据要落到 commit SHA;release tag 要开启保护,不要允许随意的强制推送。
  • 不要复用旧编号 :新系统不要从 PROJ-123 继续编号,也不要给新项目分配旧项目键。旧键保留为别名,新键独立生成;否则历史搜索和审计会混在一起。

映射表最少要有这些列:legacy_system、legacy_id、legacy_key、new_id、object_type、migrated_at、mapping_status、checksum。mapping_status 至少区分 mapped、missing、conflict、ignored。没有这四态,迁移报告只会告诉你"大概迁完了"。

Atlassian 的迁移故障排查文档还提到,空必填字段会导致迁移失败,历史记录引用缺失时该条历史不会迁移。这说明迁移不是把页面复制过去,先把数据清洗和引用补齐,比切工具更重要。

规则三:提交、分支和评审只走一条关联链

很多团队在并行期会同时保留两套关联:Jira 的提交信息解析,和新 Git 的自动关联。两边都能识别单号,两边都能改状态,最后同一件事被写两次。

Atlassian 的 Bamboo 文档说明,提交信息里出现默认格式的 issue key 时,构建会自动建立关联。提交信息本身就是一条数据入口;入口越多,重复写入的概率越高。

  • 提交信息用固定结构 :feat(scope): 摘要 [WORK-123]。如果需要兼容旧 Jira,再加一行 Legacy-Key: PROJ-123。新系统只解析 WORK-123 或 legacy_id,旧键只做展示。
  • 分支名和合并请求标题带工作项 ID :分支用 feature/WORK-123-short-name,hotfix 同样。合并请求标题带 ID,正文写影响范围;不要用"最终版""再改一版"这类无法解析的名字。
  • 只保留一个解析器:要么 Jira 侧解析旧提交,要么新 Git 侧解析新提交;不要让两边同时消费同一批 webhook。谁负责写状态,就在谁那里配置规则。
  • 发布标签保护:release tag 绑定 commit SHA,开启保护,禁止普通开发者移动或删除。回滚时按 tag 找 SHA,再找构建和制品,不要按"最新分支"找。

规则四:同步用事件流,别做双向全量覆盖

并行期需要同步,但不需要"两边一样"。同步的目标是让新系统能解释旧系统的事实,而不是把旧系统的每个字段复制一遍。

  • 事件而不是轮询全表 :主库发生变更时发事件,事件带 event_id、object_type、object_id、version、occurred_at、source。消费端按 event_id 幂等,重复消费不产生第二条记录。
  • 版本号解决乱序:网络重试和并发会让事件乱序。消费端只接受高于本地版本的事件;低版本进日志,不覆盖。
  • 失败进死信队列:重试三次仍失败的事件集中存放,附原始 payload 和错误码;不要静默丢弃,也不要用"下次全量同步"掩盖。
  • 全量对账只在低峰做:每天或每周一次对账,比对数量、校验和、抽样字段;全量对账是兜底,不是实时同步的主路径。
  • 冲突按字段类型处理:状态、负责人、权限这类字段以主库为准;描述、备注这类只追加的内容可保留双方;无法判断的进人工队列。不要把所有字段都交给"最后写入获胜"。

图 2:一条可追溯链路。工作项 ID 只负责定位,commit SHA 负责代码证据,构建和制品负责交付证据,审计记录负责把证据串起来。

私有化环境还要多一层:如果系统在隔离内网,公网 webhook 进不来,就要在内网或隔离区搭一个轻量 relay;事件签名、时间戳、重放窗口都要校验。服务器接同一套 NTP,时间偏差会让签名失效,也会让事件顺序失真。

规则五:用冻结窗口切时间,不用通知切时间

并行期最危险的不是同步失败,而是切换当天还有人往旧系统写。通知只能提醒,冻结才能阻断。

时间点 动作 通过条件 失败时
T-14 天 完成字段、用户、仓库映射,做一次全量演练 映射覆盖率、抽样一致率达到约定值 延期,不带问题切换
T-1 天 公告冻结范围,导出备份,关闭旧系统写权限 备份可恢复,关键人确认 回滚到旧系统
T0 冻结 Jira 写入;迁移在途问题;新 Git 只接新提交 旧系统写请求为 0,新系统可建单 暂停切换,保留双读
T+1 天 新工作只在新系统创建;旧 Jira 只读 新单量、构建量正常 开例外通道,限期关闭
T+7 天 复核关联、权限、审计 关联完整率达标,孤儿引用有 owner 补映射,不删记录
T+30 天 退出并行期或延长 退出条件全部满足 延长并复盘

图 3:并行期切换时间轴。准备、冻结、只读三个阶段单向推进,每个阶段都有明确的通过条件。

冻结范围要写清楚:哪些项目、哪些字段、哪些自动化、哪些 API。只冻结页面不够,脚本和 webhook 也要停。

在途问题要有归属:已经打开的需求和缺陷,要么迁到新系统,要么在旧系统关闭并写迁移备注;不要留下"半开半关"的记录。

旧系统不删除:切只读、保留查询和审计,设置跳转链接;删除旧库会让历史证据消失。

回滚路径要演练:至少验证一次"旧系统恢复写入、新系统停止接收"的路径;没有回滚演练,冻结窗口就不算准备完成。

规则六:退出并行期要靠可复核的证据

并行期什么时候结束?不是大家口头说"都用新系统了",也不是旧 Jira 到期。退出要有可复核的证据,最好能写成查询。

  • 写入证据:连续 14 天旧 Jira 没有新增问题、评论、状态变更;如果有例外,逐条有审批和关闭日期。
  • 映射证据:在途问题、附件、评论、关联链接的映射覆盖情况;未映射项有 owner 和原因。
  • 关联证据:随机抽样提交或合并请求,能从工作项追到 commit SHA、构建、制品;反向也能追回工作项。孤儿引用(找不到对应工作项的提交、合并请求或制品)要逐条可解释。
  • 重复证据:同一业务对象没有两条有效记录;重复事件被幂等吞掉,不靠人工删数据。
  • 权限证据:离职、转岗、外包账号已回收;旧系统只读权限和新系统最小权限一致。
  • 审计证据:关键操作日志可导出,时间戳一致,保留周期满足公司或行业要求。

把这些检查做成一张退出看板:红、黄、绿三档。红色项不清零,不退出;黄色项要有 owner 和截止日期。退出条件不是"新系统功能齐全",而是"旧系统不再产生新事实,历史事实仍可追溯"。

14 天零写入、关键对象映射无遗漏、孤儿引用逐条解释,可以作为起点,再按团队的风险和监管要求调整。不要用"大家都登录新系统了"代替验收,登录量只能说明入口换了,不能说明数据已经收口。

私有化部署额外要补的三道检查

公有云上的集成经验,搬到私有化环境经常会失效。网络、身份、日志这三件事,必须在切换前单独验收。

网络与时间

内网 DNS、证书、代理和防火墙要先配置好。隔离环境里公网 webhook 进不来,就在内网或隔离区搭一个 relay,事件签名、时间戳和重放窗口都要校验。所有节点接同一套 NTP;时间偏差会让签名失效,也会让事件顺序失真。

身份与权限

Jira、Git、目录服务各有一套账号体系。并行期要先定身份源:LDAP、AD 还是 HR 系统,工号是否唯一,离职和转岗多久回收权限。空间、仓库、分支、目录四级权限要逐项复核;外包账号只给必要范围,不要用"先给管理员,后面再收"这种临时方案。

以 GitFox 为例,私有化部署下可以把空间、仓库、分支、目录权限和操作日志放在同一套管控里;具体配置以当前版本为准。能力是现成的,规则仍要写清楚:谁能在哪个空间建仓库、谁能合并主干、谁能改保护分支。

日志与备份

应用日志、审计日志、流水线日志分开保留,时间统一到同一时区或明确标注 UTC。备份清单不要只写数据库,代码仓库、附件、制品、配置和密钥都要覆盖;至少做一次恢复演练,确认备份不是"看起来有"。

结语:并行期不是长期架构

旧 Jira 与新 Git 并存,可以是几周,也可以是几个月,但不应该变成常态。并行期越长,双写、孤儿关联和权限漂移越多,最后不是迁不完,而是没人敢关旧系统。

把 6 条规则落成三样东西:一张字段级数据主权表、一张 ID 映射表、一张退出验收看板。每周复核一次,红色项不清零就不扩大范围。新 Git 平台负责代码事实,Jira 负责历史问题事实,映射层负责让两边可解释;三者各守边界,并行期才有终点。

如果新 Git 采用 GitFox 这类私有化平台,代码、评审、流水线、制品和审计记录可以落在同一套底座上,但迁移规则仍要自己定。工具能提供能力,不能替团队决定哪条数据算数。

本文事实核验参考了 Atlassian 的 Automation smart values - issues、Linking JIRA issues to a build 和 Jira Cloud Migration Assistant 故障排查文档。

相关推荐
Madison-No72 小时前
Git版本控制工具(二)
git
Brookty5 小时前
Git 与 GitHub|第一阶段:仓库、版本历史与 Git 对象模型(上篇)
git·github
Kimnol18 小时前
我的第一次 Git 贡献:从 fork 到合并 PR #3130
git
鬼手点金1 天前
消息的四种角色
java·前端·人工智能·git·深度学习
齐 飞2 天前
idea中git误操作撤回git reset --hard ‘HEAD@{1}‘
java·git·intellij-idea
长成一棵参天树2 天前
React15 vs React16 核心区别
git·vscode
驭渊的小故事2 天前
Git 基础操作与对象观察
git
Hvitur2 天前
Gitea 版本控制服务端【Red Hat 离线安装】
git
flytalei2 天前
逐浪笔记 GitOps 实战:Jenkins 构建、Argo CD 同步与 Git 回滚
笔记·git·jenkins