CANN 社区任务提交 PR 踩坑与修复全记录(GitCode 平台)
实战总结:一次 huber_loss / SageAttention2 设计文档提交,被维护者 @ 提醒"目录不对、PR 混任务",最终通过"关旧开新 + 对象层面建分支"修复。本文把全部经验整理成可复用的工作流。
一、背景
CANN 开源社区(cann/cann-ops-competitions)的 8 月社区任务,要求参赛者在自己的 fork 中提交算子设计文档(design.md),通过 Pull Request(MR)合入上游仓库。提交规范为:
04_tasks/01_community-task-2026/tasklist/<任务目录>/<用户名>/docs/design.md
本次踩坑涉及两个任务:
- huber_loss → 上游目录
08-5-huber_loss - SageAttention2 → 上游目录
08-11-sageAttention2
二、踩坑 1:任务目录名必须与上游一致
这是被 @ 提醒的头号原因。
| 对比项 | 错误写法(被拒) | 正确写法 |
|---|---|---|
| huber_loss | 08-1-HuberLoss/zhangfeng1133/docs/design.md |
08-5-huber_loss/zhangfeng1133/docs/design.md |
| SageAttention2 | 08-17-SageAttention2/zhangfeng1133/docs/design.md |
08-11-sageAttention2/zhangfeng1133/docs/design.md |
- 上游
08-1是 ELU 任务,HuberLoss 实际编号是 08-5(大小写、下划线都要照抄上游)。 - SageAttention2 编号是 08-11,不是 08-17。
- 我自己的 fork 里那个目录名是自己臆造的,上游根本没有。
教训:不要凭任务清单编号猜目录名 ,提交前先拉最新上游,
git ls-tree upstream/master --name-only <tasklist目录>对照真实命名。
三、踩坑 2:一个 PR 只装一个任务
旧 PR 的源分支用了 fork 的 master,而 master 上攒了两个任务的提交(huber_loss + SageAttention2),导致一个 PR 的 diff 里出现两个任务的文件。维护者看到必然打回。
- 社区要求一个 PR 对应一个设计/一个任务。
- fork 的
master只用来同步上游,永远不直接往 master 上提交任务代码。
教训:一任务 = 一分支 = 一 PR。分支名随意,但内容必须单一。
四、踩坑 3:GitCode 平台限制------PR 不能改源分支、不能删除
这是本次最核心的平台认知:
- PR 创建后无法修改源分支 :
PATCH /pulls/{number}支持的字段只有title / description / target_branch / state_event / labels等,没有 head/source_branch。 - PR 无法删除,只能关闭(closed)。
- 因此,当源分支本身选错(混任务、目录错)时,唯一修复路径是 关旧开新 :
- 用正确分支新建 PR(
POST /pulls) - 确认新 PR 内容无误后,
PATCH {"state":"closed"}关闭旧 PR - 保证任意时刻每个设计只有一个 open 的 PR
- 用正确分支新建 PR(
关键澄清:关旧开新 ≠ 重复提交。closed 的 PR 等于作废撤回,不进评审队列;重复提交指同一内容同时挂两个 open PR。只要"先开新、再关旧",任何时刻都不会出现两个 open 的同任务 PR,合规。
五、踩坑 4:提交邮箱必须与账号邮箱一致
GitCode(GitLab 系)会校验提交作者邮箱:
bash
git config user.name zhangfeng1133 # 账号用户名
git config user.email yanggg1133@163.com # 必须与账号邮箱一致
- 若邮箱不匹配(如
noreply.gitcode.com),提交者会显示为"未知用户",维护者会提醒。 - 已提交的历史提交如需修正:
git commit --amend或重置后重新提交,再 force push。
六、踩坑 5(环境):Windows 无法 checkout 上游仓库
上游 master 存在含 :: 的非法路径(如 pto::tile_fma/),Windows NTFS 不允许 : 出现在文件名中,导致:
error: invalid path '01_official/.../pto::tile_fma/op_kernel/scale.cpp'
git checkout / git reset / git read-tree 全部报错,用户 fork 因此落后上游 130 个提交无法同步。
解法:git 对象层面操作,不落地文件系统
bash
# 1. 取旧分支中 design.md 的 blob
BLOB=$(git rev-parse "旧分支:旧路径")
# 2. 用临时索引载入最新上游树(核心:必须 -c core.protectNTFS=false + 临时索引)
rm -f /tmp/fix_idx
git -c core.protectNTFS=false read-tree --index-output=/tmp/fix_idx upstream/master
GIT_INDEX_FILE=/tmp/fix_idx git -c core.protectNTFS=false update-index --add --cacheinfo "100644,$BLOB,新路径"
# 3. 生成树与提交(commit-tree 没有 --author,用环境变量)
TREE=$(GIT_INDEX_FILE=/tmp/fix_idx git -c core.protectNTFS=false write-tree)
export GIT_AUTHOR_NAME="zhangfeng1133" GIT_AUTHOR_EMAIL="yanggg1133@163.com"
export GIT_COMMITTER_NAME="zhangfeng1133" GIT_COMMITTER_EMAIL="yanggg1133@163.com"
COMMIT=$(GIT_INDEX_FILE=/tmp/fix_idx git -c core.protectNTFS=false commit-tree $TREE -p upstream/master -m "提交说明")
# 4. 创建分支并推送
git update-ref refs/heads/<新分支> $COMMIT
git push origin <新分支>
⚠️ 三个坑必须注意:
read-tree若不指定GIT_INDEX_FILE会污染主索引 (git status瞬间全乱),务必用临时索引,事后git reset --hard HEAD可恢复。commit-tree不支持--author参数,必须用GIT_AUTHOR_*环境变量。- 拉新分支前先验证:
git diff --stat upstream/master <新分支>应只剩预期文件。
七、GitCode API 速查(亲测有效)
bash
# 端点:GitHub 风格 /pulls,不是 /merge_requests!
BASE="https://gitcode.com/api/v5/repos/cann/cann-ops-competitions"
# 创建 PR(head 必须带 fork 前缀)
curl -X POST "$BASE/pulls" \
-H "PRIVATE-TOKEN: YOUR_GITCODE_TOKEN" -H "Content-Type: application/json" \
-d '{"head":"zhangfeng1133:huber-loss-design","base":"master","title":"标题","body":"说明"}'
# 查询单个 PR(含 head.sha / state / mergeable_state)
curl -H "PRIVATE-TOKEN: YOUR_GITCODE_TOKEN" "$BASE/pulls/1137"
# 关闭 PR({"state_event":"close"} 单独传会报 400,用 {"state":"closed"} 实测有效)
curl -X PATCH "$BASE/pulls/1037" -H "PRIVATE-TOKEN: YOUR_GITCODE_TOKEN" \
-H "Content-Type: application/json" -d '{"state":"closed"}'
# 筛选"我发起的 PR":creator 参数不生效,须按 head.repo.namespace 或 user.login 过滤
curl -H "PRIVATE-TOKEN: YOUR_GITCODE_TOKEN" "$BASE/pulls?state=all&per_page=50&page=1"
补充限制(都亲测过):
- 给已关闭 PR 加评论:
/pulls/{n}/comments返回 405、/notes404、/issues/{n}/comments404 ------ API 不支持,只能网页手动留言。 - 鉴权必须用
PRIVATE-TOKEN请求头(Authorization: token会 401)。
八、标准工作流(以后照做)
bash
# 1. 接新任务:从最新上游拉分支(不用 fork master!)
git fetch upstream
git checkout -b <任务名>-design upstream/master # Windows 撞非法路径时用上面的对象层面方法
# 2. 开发:多次提交都在这个分支
# 改文件 → git add → git commit(邮箱已配好)
# 3. 推送 + 开 PR
git push origin <任务名>-design
# 网页开 PR:head = fork 的新分支,base = master,标题写明任务名
# 4. 维护者提意见 → 继续在同一个分支改 → push → PR 自动更新(永远不重建 PR)
# 5. 提交前自查清单:
# □ 目录名与最新上游一致(git ls-tree 对照)
# □ PR diff 只含本任务文件(git diff --name-only upstream/master...<分支>)
# □ 提交邮箱 = 账号邮箱
# □ 每个设计全局只有 1 个 open PR
九、FAQ
Q:一个设计开过旧 PR 又开新 PR,算重复提交吗?
A:不算。旧 PR closed = 作废;只要任何时刻每个设计只有 1 个 open PR 即可。GitCode 不支持改源分支/删 PR,关旧开新是平台唯一路径,社区广泛接受。
Q:能不能在旧 PR 上继续修改?
A:可以,前提是源分支没选错。源分支正确时,"同一个 PR 上修改" = 本地同分支改 → push → PR 自动更新(GitCode 帮助文档"版本"篇即是此模型)。源分支选错(混任务/目录错)时无解,只能关旧开新。
Q:Windows 上怎么完整 checkout 这个仓库?
A:上游含 :: 非法路径,Windows 无法完整 checkout。要么用 WSL/Linux,要么只做对象层面操作(见第六节);git fetch 不受影响。
本文为实战经验总结,命令均已在 GitCode 平台验证。欢迎交流讨论。