一、 为什么当前会报错(Why)
- Azure DevOps REST API 的严格约束:Azure DevOps 在提交变更 (
pushesAPI) 时,每个文件变更必须严格显式声明changeType为'add'(新增)或'edit'(覆盖修改)。如果文件在目标分支已存在,却以'add'类型提交,API 会直接抛出硬错误拒绝推送。 - 当前逻辑痛点:目前推送是在点击后静默进行一次性探测,缺乏提交前的预检(Pre-flight)与用户交互决策界面;且一旦路径探测返回异常,默认降级为
'add'便直接引发阻断。
二、 完整解决方案与落地机制(How)
要实现“同名对比、让用户选择覆盖或忽略”,整体流程分为三个阶段:
1. 预检嗅探(Pre-flight Check)
在弹窗加载完成或用户选定目标仓库/分支后,提前对待同步的文件清单进行一次远程探测:
- Azure DevOps:调用
GET items?path={path}&versionDescriptor.version={branch}获取文件元数据; - GitHub:调用
GET /repos/{owner}/{repo}/contents/{path}?ref={branch}获取远程 SHA 与内容。
2. 前端交互界面(UI Decision Layer)
在“待同步文章”列表中,给每个文件增加状态徽标与用户操作切换器:
- 🟢 新增 (New):远程不存在,以
'add'提交。 - 🟡 同名存在 (Conflict):
- 默认提供单选/切换开关:覆盖 (Overwrite) vs 忽略 (Skip)。
- 顶部增加一键快捷操作:“全部覆盖” 与 “跳过同名”。
- (可选进阶)点击文件名可弹出轻量 Diff 预览,查看本地与远程文章的内容差异。
- ⚪ 内容无变更 (Identical):若本地内容与远程内容比对无差异,自动标记“已是最新,跳过”。
3. 提交载荷精准映射(Payload Mapping)
用户点击“一键直通发布”后,根据用户的选择构建最终的 Push Payload:
- 选择覆盖的文件:
changeType: 'edit'; - 选择新增的文件:
changeType: 'add'; - 选择忽略的文件:从当前提交的
changes列表中直接剔除,不发送给远程。
三、 总结
该机制不仅可以彻底杜绝 already exists 导致的发布失败,还能保障文章不会被无意冲掉。
