把「有没有 commit 没推」「现在在哪个 worktree」变成不用问就能看见的信息。
下面每一块都用 web-terminal 此刻的真实状态渲染 —— 包括那个正在说谎的 ↓0。
替换现在标题行里那个孤零零的圆点。四个格子回答四个问题:我在哪个分支、有多少要推、有多少要拉、这两个数字还能不能信。
「存疑」标记是这块最重要的设计。ahead/behind 比的是本地缓存的
@{u},不 fetch 就永远不会变 —— 没有这个标记,面板会自信地告诉你已经同步,而这正是它此刻在做的事。
规则:FETCH_HEAD 的 mtime 超过阈值(建议 1 小时)就给 ↓ 挂上存疑,并把 Fetch 按钮点亮。
Fetch 是只读的,不 pull、不 merge —— 符合写侧一贯的克制。
你要的不是「有 9 个没推」这个数字,而是哪 9 个。复用现有的 commit 列表,给未推送的加左侧竖线和 ↑,在边界上画出 upstream 的位置 —— 一眼看完,零点击。
分界线不是装饰 —— 它是 origin/develop 在时间轴上的真实位置。分支没有 upstream 时不画线,改在顶部显示「无 upstream」(见 ④)。
现在这块叫 BRANCH、只有一行。按「每个 session 一个 worktree」的规矩,它很快会变成 4–5 行,而且每一行要能独立回答:哪个分支、在哪、干净不干净、推没推、里面跑着谁。这是编辑器给不了的视角 —— Cursor 一次只看得见一个 worktree。
「无 upstream」必须显式标出。新建的 worktree 分支天然没有 upstream,ahead/behind 全是
undefined —— 绝不能因为「没有数字」就渲染成绿色的「已同步」。这是这套 UI 最容易犯的错。
同步条的全部形态。做设计稿的意义一半在这里 —— 边界情况不定死,实现时就会各写各的。
只有一个状态配用绿色:↑0 ↓0 且刚 fetch 过。其余一律中性或警示 —— 绿色在这里的含义是「我确认过了,你不用管」,给错了就是骗人。
编号 = 建议实现顺序。01 和 02 共用同一份数据,应该一个 PR 一起做。
| 元素 | 数据来源 | 后端现状 |
|---|---|---|
| 分支名 | .git/HEAD(不 spawn 进程) |
✓ 已有 |
| ↑ ahead / ↓ behind | git rev-list --count --left-right @{u}...HEAD |
助手已有,ProjectDetail 没接 |
| upstream 名字 | git rev-parse --abbrev-ref @{u} |
缺 |
| 未推送的 sha 集合 | git log @{u}..HEAD --format=%H |
缺 |
| 上次 fetch 时间 | .git/FETCH_HEAD 的 mtime(不 spawn) |
缺 |
| Fetch 按钮 | git fetch --no-tags,只读 |
缺(需新路由) |
| 未提交数量 | git status --porcelain 的行数 |
只有布尔 dirty,没有计数 |
| worktree 列表 | git worktree list --porcelain |
✓ 已有 |
| 每个 worktree 的 dirty / ↑↓ | 同上,逐 worktree 跑一次 | 缺 — 成本最高的一项 |
成本控制。只有分支名和 fetch 时间是读文件、免费的;其余每项都要 spawn 一次 git,而这台机器同时在跑 Claude Code 和构建。三条便宜的对策:按仓库去重(N 个 tab 同一个 repo 只查一次)、盯
.git/HEAD / .git/index / .git/refs 的 mtime 变了才查、页面隐藏时暂停。逐 worktree 的 ↑↓ 建议懒加载 —— 展开那一行才算。
范围外。这一页不加 reset、不加切分支 checkout、不加 clean、不加 force-push。
stage / commit / push 已经在 diff.ts 里,维持现状。
这块面板的职责是告诉你发生了什么,不是替代编辑器去处理它。