Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@

## [Unreleased]

### Added

- **Branches 视图按 `/` 前缀分组为文件夹树**:Local / Remote / Tags 三段支持在**平铺**与**按 `/` 前缀分组的可折叠文件夹树**间切换——共享前缀的分支收拢到以前缀命名的文件夹下、叶子仅显示末段后缀(如 `bak/2025`、`bak/master-2025-07` → 📁`bak` → `2025` / `master-2025-07`;远程整体收拢为 `origin` 文件夹并内嵌 `feature`)。新增纯逻辑引擎 [`buildRefTree`](./src/engine/ref/ref-tree.ts)(复用「变更文件目录树」`buildFileTree` 的 trie 构建 + compact 折叠范式;叶子携完整 `RawRef`、命令定位不受影响;分支感知排序:当前 HEAD → 收藏 → 同档文件夹优先、名称数字感知升序),并**隐藏 `origin/HEAD` 符号引用**(对齐主流 Git UI,消除 `origin` 叶子与 `origin` 文件夹同名冲突)。工具栏提供「平铺 ⇄ 树」切换(`hyperGit.branchesGroupByPrefix` / `hyperGit.branchesFlatten`,context key 驱动按钮互斥),偏好按仓库持久化于 `workspaceState`(默认树形),文件夹默认展开、展开态跨刷新稳定。文件夹节点用独立 `contextValue` 且不登记任何右键命令,checkout / delete / rename / merge / rebase / compare / favorite 与多选批量均零改动、零破坏。完整叙述见 [分支前缀分组树](./docs/features/branch-tree-group-by-prefix.md)。

## [0.0.14] - 2026-07-06 — 修复 GRAPH 视图提交记录时间倒序

修复 GRAPH 视图「All」范围下提交记录未按时间倒序排列的问题——取数参数由 `--topo-order` 改为 `--author-date-order`,令跨分支提交按作者日期正确交错、消除「日期回跳」。纯取数排序修复,不改数据协议、布局算法与任何视图交互。完整用户视角叙述见 [Release Note v0.0.14](./docs/releases/v0.0.14.md)。
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
- **Multi-Changelist Changes view**: group edits into named lists, mark one as the active commit target, create / rename / delete / move lists, persisted in `workspaceState` (restored across restarts); status colors reuse the `gitDecoration.*` theme tokens.
- **Commit panel**: a hand-built commit view with real-time Conventional Commits validation, Amend / Sign-off / skip hooks, and Commit / Commit & Push; the checkbox selection is the authoritative commit scope, and recent messages are reusable.
- **Log commit graph (hand-rendered DAG)**: colored swimlanes, branch/merge edges, HEAD/branch/tag badges, virtualized incremental loading; 7 composable filters (author / path / grep / regex / merge-mode / date / clear); per-commit actions (Reset, new branch·tag, Cherry-Pick, Revert, list containing branches).
- **Branches management**: favorites / local / remote / tags grouped into four sections with ahead·behind·upstream tracking; create / checkout / delete / rename / merge / rebase / compare / favorite; **multi-select batch** delete, copy ref, and favorite (with an honest merged/unmerged split confirmation).
- **Branches management**: favorites / local / remote / tags grouped into four sections with ahead·behind·upstream tracking; **prefix folder grouping** (flat ⇄ tree toggle) that collapses `/`-shared branches under their common prefix, showing only the suffix; create / checkout / delete / rename / merge / rebase / compare / favorite; **multi-select batch** delete, copy ref, and favorite (with an honest merged/unmerged split confirmation).
- **Stash & Shelf**: full stash operations (including keep-index / clear / create branch from stash); a standalone **Shelf** (patch-based, independent of stash, with 3-way merge Unshelve).
- **Worktrees**: full-lifecycle management — create (new branch / checkout / detached), open in a new window, lock / unlock, move, remove, and prune stale entries.
- **Line-level & hunk commits**: in-editor "Commit this Hunk" CodeLens, partial stage / unstage, stage at cursor, and hunk-to-changelist attribution.
Expand Down
1 change: 1 addition & 0 deletions docs/.agents/knowledge-map.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
- [Log 视图 CI 状态](../docs/features/log-ci-status.md) — 按提交显示 GitHub CI 最终状态(绿勾/红叉 + Tooltip 明细):认证、限流、懒加载、边界与配置。
- [Commit 视图整合](../docs/features/commit-view-consolidation.md) — 移除 CHANGES 视图,其文件操作/changelist 管理/Git 工具栏/未提交角标零回归平移入 Commit 视图。
- [变更文件目录树](../docs/features/file-list-group-by-directory.md) — Commit / Log 文件列表「平铺 ⇄ 按目录分组」切换:host 侧 `buildFileTree` 构树下发、compact 折叠、目录三态。
- [分支前缀分组树](../docs/features/branch-tree-group-by-prefix.md) — Branches 视图 Local/Remote/Tags「平铺 ⇄ 按 `/` 前缀分组」切换:`buildRefTree` 构树、分支感知排序、compact 折叠、隐藏 `origin/HEAD`、按仓库持久化。
- [Log 提交悬浮详情](../docs/features/log-commit-tooltip.md) — 悬停提交行浮层展示 分支/标签/HEAD/完整消息/作者·提交者/时间/SHA;复用 CI 浮层范式、与其互斥。
- [实施状态总览](../docs/milestones/implementation-status.md) — M0-M5 交付记录 + API 限制 + M5 AI 设计 + 验证/发布(**实施看板**)。
- [工程实施方案](../docs/architecture/engineering-plan.md) — 路径 B 架构 + M0-M5 里程碑(**开发蓝图**)。
Expand Down
73 changes: 73 additions & 0 deletions docs/features/branch-tree-group-by-prefix.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
# 分支前缀分组树(Group Branches by Prefix)

> Branches 视图的 **Local / Remote / Tags** 三段支持在**平铺列表**与**按 `/` 前缀分组的文件夹树**之间切换(对齐 VS Code SCM / GitLens 的分支分组)。共享前缀的分支收拢到以前缀命名的可折叠文件夹下,叶子仅显示末段后缀;工具栏一键切换、按仓库记忆偏好,默认树形。**Favorites 段恒平铺**并显示完整短名。

## 效果:扁平 → 前缀树

```mermaid
flowchart LR
subgraph FLAT["平铺(切换前)"]
direction TB
a1["bak/2025"]
a2["bak/master-2025-07"]
a3["feature/1.0.0"]
a4["2022 / 2023 / 2024"]
end
subgraph TREE["前缀树(切换后)"]
direction TB
b0["📁 bak"] --> b1["2025"]
b0 --> b2["master-2025-07"]
b3["📁 feature"] --> b4["1.0.0"]
b5["2022 / 2023 / 2024"]
end
FLAT -->|Group by Prefix| TREE
style b0 fill:#8957e5,color:#fff
style b3 fill:#8957e5,color:#fff
```

远程段整体收拢为单个 `origin` 文件夹,内部再嵌 `feature`:`origin/feature/1.0.0` → `origin` → `feature` → `1.0.0`。

## 设计:引擎算树、适配层渲染(单一事实源)

分支前缀分组与「变更文件目录树」(见 [file-list-group-by-directory](./file-list-group-by-directory.md))是同构问题,故沿用其成熟范式:纯逻辑引擎构树、上层仅渲染。

```mermaid
flowchart LR
A["RawRef[]<br/>(displayRefs,已滤 origin/HEAD)"] -->|adapter| B["buildRefTree()<br/>engine/ref/ref-tree"]
B -->|"RefTreeNode[]<br/>(folder / leaf)"| C["BranchesTreeProvider<br/>toBranchNodes()"]
C --> D{"grouping?"}
D -->|on| E["文件夹节点 + 后缀叶子"]
D -->|off| F["平铺(既有排序)"]
style B fill:#1f6feb,color:#fff
style E fill:#238636,color:#fff
```

- **纯逻辑 `buildRefTree`**([`engine/ref/ref-tree.ts`](../../src/engine/ref/ref-tree.ts),零 vscode 依赖、Vitest 覆盖):按 `shortName` 的 `/` 分段建 trie;叶子携带完整 `RawRef`(短名不丢,命令仍以 `ref.shortName` 定位)、`label` 取末段后缀。**分支感知排序**——当前 HEAD(第 0 档)→ 收藏(第 1 档)→ 同档内**文件夹在前**、名称数字感知升序、稳定;**compact 折叠**单目录子链(如 `a/b/c` → `a/b`,遇含叶子或多子目录即停,对齐 VS Code `explorer.compactFolders`)。
- **含 `/` 的远程名无需特判**:fork 场景 remote 名可含 `/`(如 `myorg/repo`),compact 折叠会把 `myorg/repo` 单目录子链渲染为单个文件夹,视觉上与「remote 为一层」等价;删除等**正确性敏感**逻辑仍走 [`resolveRemoteBranch`](../../src/engine/ref/remote-ref.ts) 的最长前缀匹配,两者正交不耦合。
- **隐藏 `origin/HEAD`**:远程符号引用 `refs/remotes/<remote>/HEAD`(短名如 `origin`)非真实分支,视图统一过滤(`isRemoteHead`)——既对齐主流 Git UI,也消除「`origin` 叶子」与分组后「`origin` 文件夹」的同名冲突,远程计数随之归为真实分支数。

## 切换 UI:原生 TreeView 双命令 + context key

Branches 为原生 TreeView(非 webview),切换采用 VS Code 惯用范式:两条互斥命令 + `setContext` 驱动工具栏按钮显隐。

| 状态 | 工具栏按钮 | 命令 | 图标 |
|---|---|---|---|
| 平铺 | 显示「分组」 | `hyperGit.branchesGroupByPrefix` | `$(list-tree)` |
| 树形 | 显示「平铺」 | `hyperGit.branchesFlatten` | `$(list-flat)` |

- context key `hyperGit.branchesGrouping` 由 [`extension.ts`](../../src/extension.ts) 在 `activate` 时按 provider 持久化初值设定,命令翻转时同步更新;`package.json` 的 `view/title` `when` 子句据此互斥显示两按钮。
- 偏好按仓库持久化于 `workspaceState`(键 `hyperGit.branchesGrouping:${repoRoot}`,仿 [`BranchFavorites`](../../src/adapter/branch-favorites.ts)),重启后恢复;文件夹默认展开、点击即折叠/展开,展开态经 `TreeItem.id`(`folder:${group}:${path}`)跨刷新稳定。

## 兼容性(命令零破坏)

文件夹节点使用独立 `contextValue` `hyperGit.branchFolder`,不匹配任何 `view/item/context` 命令 → 无右键菜单;多选批量经 [`selectedBranchRefs`](../../src/adapter/branch-selection.ts) 只保留 `kind === 'branch'`,文件夹节点天然被忽略。checkout / delete / rename / merge / rebase / compare / favorite 等命令均无需改动。

## 实现

- 引擎:[`engine/ref/ref-tree.ts`](../../src/engine/ref/ref-tree.ts)(+ [`tests/unit/ref-tree.test.ts`](../../tests/unit/ref-tree.test.ts),12 用例)。
- 适配层:[`adapter/tree/branches-tree.ts`](../../src/adapter/tree/branches-tree.ts)(`BranchFolderNode`、`grouping` 状态与持久化、`isRemoteHead` 过滤、`sectionNodes`/`toBranchNodes`、folder 的 `getTreeItem`)。
- 装配 / 贡献点:[`extension.ts`](../../src/extension.ts)(context key + 命令)、[`package.json`](../../package.json)(两命令 + `view/title` 互斥菜单)。

## 验证

`pnpm run test:unit`(含 `ref-tree.test.ts`)全绿;Extension Development Host(F5):Local/Remote/Tags 在平铺 ⇄ 树间即时切换、刷新后保持;共享前缀收拢为文件夹、叶子仅显示后缀;`origin/HEAD` 不再单列、远程计数为真实分支数;文件夹可折叠、compact 生效;分支右键命令与多选批量均正常,文件夹节点无菜单、被多选忽略。
2 changes: 1 addition & 1 deletion docs/i18n/zh-CN/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
- **多 Changelist Changes 视图**:将改动分组到命名列表,设活动列表为提交目标,新建/重命名/删除/移动,`workspaceState` 持久化(重启恢复);状态色复用 `gitDecoration.*` 主题色。
- **Commit 提交窗口**:自绘提交面板 + Conventional Commits 实时校验 + Amend / Sign-off / 跳过 Hook + 提交 / 提交并推送;勾选集即提交权威范围;最近消息复用。
- **Log 提交图(自绘 DAG)**:彩色泳道、分叉·合并连线、HEAD/分支/标签徽标,虚拟滚动增量加载;7 个可组合过滤器(作者/路径/grep/正则/合并模式/日期/清除);per-commit 操作(Reset、新建分支·标签、Cherry-Pick、Revert、查看包含分支)。
- **Branches 分支管理**:收藏/本地/远程/标签四段分组 + ahead·behind·upstream 跟踪;新建/检出/删除/重命名/合并/变基/比较/收藏;**多选批量**删除、复制引用、收藏(已合并/未合并诚实分栏确认)。
- **Branches 分支管理**:收藏/本地/远程/标签四段分组 + ahead·behind·upstream 跟踪;**前缀文件夹分组**(平铺 ⇄ 树切换)将共享 `/` 前缀的分支收拢到共同前缀下、仅显示后缀;新建/检出/删除/重命名/合并/变基/比较/收藏;**多选批量**删除、复制引用、收藏(已合并/未合并诚实分栏确认)。
- **Stash & Shelf**:Stash 全操作(含 keep-index / clear / 从 Stash 建分支);独立 **Shelf**(基于 patch、独立于 stash,含 3-way 合并 Unshelve)。
- **Worktrees**:全生命周期管理——新建(新分支/检出/detached)、在新窗口打开、锁定/解锁、移动、删除、清理失效。
- **行级与 Hunk 提交**:编辑器内 CodeLens「Commit this Hunk」、部分暂存/取消暂存、光标处暂存、Hunk 归属 Changelist。
Expand Down
22 changes: 22 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,18 @@
"category": "Hyper Git",
"icon": "$(refresh)"
},
{
"command": "hyperGit.branchesGroupByPrefix",
"title": "Group Branches by Prefix",
"category": "Hyper Git",
"icon": "$(list-tree)"
},
{
"command": "hyperGit.branchesFlatten",
"title": "Show Branches as Flat List",
"category": "Hyper Git",
"icon": "$(list-flat)"
},
{
"command": "hyperGit.logFilter",
"title": "Filter Graph…",
Expand Down Expand Up @@ -764,6 +776,16 @@
"when": "view == hyperGit.branches",
"group": "navigation@5"
},
{
"command": "hyperGit.branchesGroupByPrefix",
"when": "view == hyperGit.branches && !hyperGit.branchesGrouping",
"group": "navigation@6"
},
{
"command": "hyperGit.branchesFlatten",
"when": "view == hyperGit.branches && hyperGit.branchesGrouping",
"group": "navigation@6"
},
{
"command": "hyperGit.fetch",
"when": "view == hyperGit.branches",
Expand Down
Loading