Tencent / Tencent/teamai-cli

[bug] `teamai push` 无法指定目标分支:Gitee 等泛型 host 上 CLI 不会自动建 PR,新资源会悬空在 teamai/push/* 分支上(过程中还有一次 hard reset)

Open
#663 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
TypeScript
Stars
4.8k
Forks
342
Avg merge
13h 48m
Merged PRs (30d)
211

Description

English summaryteamai push has no way to target the default branch: it always creates
teamai/push/<user>/<timestamp> and relies on the provider's PR automation. There is no Gitee
provider in the bundle
(Gitee appears only inside an unrelated GitCode comment), so Gitee falls
through to the generic provider and PR creation throws
Automatic pull/merge request creation is not supported for generic Git hosts. A push that
contained real new content — 2 new skills, 906 insertions(+), no deletions — then sat unmerged on
a remote branch with no PR and no visible signal. push --help accepts only
--all / --skill / --role / --project: there is no option to push to the default branch.
Separately, a reset --hard HEAD runs during the push sequence (per reflog), which silently
discarded an uncommitted change in my working tree.

Correction (2026-09-19) — an earlier revision of this issue claimed the pushed branch carried
destructive deletions (907 insertions(+), 4618 deletions(-), removing skills/team-wiki-codebase/*).
That claim was wrong and I have removed it. I compared with git diff <default>..<branch>
against a branch that was already an ancestor of the default branch, which reverses the diff
direction and renders everything the default branch gained later as "deletions". The real proposal
is git diff <default>...<branch>, which is empty for that branch. There is no destructive
deletion behaviour to report. Sorry for the noise.

Description

teamai push 的落点是写死的:永远新建一个 teamai/push/<user>/<timestamp> 分支,然后交给 provider 去开 PR/MR。命令本身没有任何指定目标分支的开关

$ teamai push --help
Options:
  --all              Push all without confirmation
  --skill <path>     Push a specific skill by path
  --role <id>        Target role namespace for pushed project skills
  --project <id>     Target a project

而 provider 侧没有 Gitee 实现——在 bundle 里搜 gitee 只有一处命中,还是 GitCode 的注释:

// GitCode's API addresses repos by the plain `owner/repo` path (Gitee-style),
// not a URL-encoded id. Kept for interface parity with other providers.

所以 Gitee 落到泛型 provider,PR 自动化直接抛错:

Automatic pull/merge request creation is not supported for generic Git hosts.
后果:有真实新内容的推送会静静悬空

第二次推送(teamai/push/C/20260919-190031)带着 2 个新 skill,相对默认分支的真实提议是:

$ git diff --stat master...teamai/push/C/20260919-190031
 skills/jira-workflow-transition/SKILL.md          | 607 ++++++++++++++++++++++
 skills/neusoft-localization-delivery/CONTRIBUTORS |   1 +
 skills/neusoft-localization-delivery/SKILL.md     | 297 +++++++++++
 4 files changed, 906 insertions(+)

纯新增、零删除。但 CLI 报完那句错就结束了:

  • 分支推上去了(git ls-remote 能看到),用户会以为 push 成功了;
  • 没有 PR(仓库 PR 列表里只有 #1,且 #1 属于更早的那次推送);
  • 分支就一直挂在远端,直到我手工清理时才发现它从没被合并。

对比很说明问题:更早那次推送的 PR #1(head = teamai/push/C/20260919-173548确实合并了——但那个 PR 是手工在 Gitee 上建的(17:38:38 创建、17:39:10 合并),不是 CLI 建的,因为 CLI 根本没有 Gitee provider。两次推送的差别不是配置,而是"人有没有去手动开 PR"。

换句话说:在 Gitee 上,teamai push 的自动化在"建分支"之后就断了,剩下那一步完全依赖用户自己发现、自己去网页上补。而 CLI 的输出里没有任何东西告诉你"需要你手动去开 PR"。

push 过程中还有一次 hard reset

pushRepoBranch() 里有 reset --hard + clean -fd 的路径:

await git.add(files);
const status = await git.status();
if (status.staged.length === 0) {
  await git.reset(["--hard", "HEAD"]);
  await git.clean("f", ["-d"]);
  ...
}

实际后果(reflog 可查,本机 2026-09-19):

$ git reflog --date=format:'%H:%M:%S' | sed -n '5,9p'
592d5f9 HEAD@{19:00:24}: reset: moving to HEAD          ← hard reset
592d5f9 HEAD@{19:00:32}: checkout: moving from master to teamai/push/C/20260919-190031
6819735 HEAD@{19:00:34}: commit: [teamai] Push 2 resource(s) from C
592d5f9 HEAD@{19:00:40}: checkout: moving from teamai/push/C/20260919-190031 to master

我在 push 之前改好的 env/env.yaml 没有进那次提交——它被这次 hard reset 丢掉了,我事后只能重新改一遍再手动提交。整个过程里 push 没有任何提示说"你有未提交的改动会被丢弃"。附带地,push 后 git status 还出现过一批 D skills/...,需要用 git checkout -- . 恢复干净。

Reproduction

  1. 团队仓库远端指向 Gitee(或任何非 GitHub/TGit 的泛型 host)。
  2. 本地准备一份有新内容的推送目标(例如一个新 skill),teamai push --all
  3. 观察:
    • 分支 teamai/push/<user>/<ts> 出现在远端;
    • CLI 打印 Automatic pull/merge request creation is not supported for generic Git hosts.
    • 没有 PR 被创建,变更不会进默认分支;CLI 也没有提示"请手动开 PR"。
  4. 若此时工作区有未提交改动,对照 reflog 可见一次 reset: moving to HEAD,改动消失。

Environment

  • OS: Windows 11 25H2 (10.0.26200)
  • Node.js: v22.22.2
  • teamai: 0.24.0
  • Provider: Gitee(走泛型 provider)
  • AI tool(s): WorkBuddy / CodeBuddy

Suggested fix

  1. 提供落到默认分支的能力(本 issue 的核心诉求)。 例如 teamai push --direct(直接推默认分支,可要求二次确认),或 teamai push --branch <name> 指定目标分支。当前 push 只接受 --all/--skill/--role/--project,用户完全没有办法让变更进默认分支,只能绕开 CLI 手搓 git——这恰恰是 CLI 想避免的事。
  2. PR 不可用时要"响",并给出下一步。 provider 无法自动创建 PR 时,不要只打一行错误就结束。至少要把推送分支名、以及一条可直接执行的 git push origin HEAD:<default> 或者"请在 上为分支 X 创建 PR"的提示打出来。现在的输出让人以为事情已经办完了。
  3. 不要对用户的工作区做 reset --hard / clean -fd 动手前先检测脏工作区:有未提交改动就中止(或先 stash 并在结束后恢复),至少要有明确警告。这一步是静默且不可逆的。

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start at the mentioned pushRepoBranch() entry point and the push command's option/help definitions; reproduce the generic-host flow with new content and a dirty worktree. Trace the PR failure path and the reset --hard/clean path against the reported behavior. Done means the supported target-branch behavior, actionable generic-host output, and safe handling of uncommitted changes are covered by tests.

Written by the indexing model from the issue text.

Assessment

Tech stack
git, typescript
Domain
cli, developer-experience
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
48/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.