在会话侧栏里逐行暂存改动、查看提交图与冲突
29.9/100
综合分
0
GitHub 星标
—
npm 周下载
—/5
用户评分
数据截至 2026/10/28 · 周下载取自 npm 全网(含 CI / 镜像),非本站安装数;综合分由星标、活跃度与兼容性检查合成。
相关生态插件(非 dsh 原生,按其对应运行时安装)
git clone https://github.com/yann9/dsh-git-workbench.git状态速览
判定依据:实装验证 · 静态安装检查 · 自动扫描 · 仓库维护状态信任档位:仅索引
是什么
生态应用
桌面端 / Web 外壳,不以 dsh plugin add 安装
装得上吗
本站尚未做安装检查
安全吗
本站尚未对该插件做风险分级
暂未覆盖,不等同于无风险
还在维护吗
活跃:最近一次提交在 5 天前
档位由哪些信号合成
本站实装验证(真实安装 L4 覆盖全站;L5 为运行时冒烟或实机截图,覆盖范围小于 L4) · 验证所用 dsh 版本 · 静态安装检查 · 风险分级 · 仓库维护状态。 下方各区块是它的证据明细。
社区实装还没有人打卡 · 装过的第一个就是你
安全扫描自动 · 静态分析源码v2.7.0🔵 扫描:含敏感能力尚无人工评估展开查看扫描说明与证据 ↓
安全扫描自动 · 静态分析源码
v2.7.0静态扫描发现插件具备触达本地系统的能力:执行外部命令、读写/删除本地文件、读取剪贴板或密钥类环境变量(至少其一)。这是能力清单,不是危险判定——具体能力项与证据见下方,安装前请自行判断是否需要。
可执行外部命令读写/删除本地文件写入剪贴板(不计风险)发起外部网络请求
查看扫描证据(共 39 处,展示前 38 条)
- 读取本地文件src/git/service.js:783
return await readFile(path.join(root, file), 'utf8') - 写入本地文件src/git/service.js:795
await writeFile(path.join(root, file), applyDecision(segments, region, strategy, resolution), 'utf8') - 写入本地文件src/git/service.js:903
await writeFile(todoFile, `${lines.join('\n')}\n`, 'utf8') - 删除本地文件src/git/service.js:930
await rm(todoFile, { force: true }) - 写入本地文件src/git/service.js:973
await writeFile(todoFile, `${lines.join('\n')}\n`, 'utf8') - 删除本地文件src/git/service.js:998
await rm(todoFile, { force: true }) - 读取本地文件src/git/service.js:1052
text = await readFile(file, 'utf8') - 写入本地文件src/git/service.js:1064
await writeFile(file, `${prefix}${added.join('\n')}\n`, 'utf8') - 写入本地文件src/git/service.js:1151
await copyFile(indexPath, temp).catch((error) => { - 删除本地文件src/git/service.js:1178
await rm(temp, { force: true }).catch(() => {}) - 写入本地文件src/git/service.js:1590
await copyFile(path.join(gitDir, 'index'), indexFile) - 删除本地文件src/git/service.js:1613
if (indexFile) await rm(indexFile, { force: true }) - 读取本地文件src/git/service.js:1685
const folder = await stat(candidate).catch(() => null) - 读取本地文件src/git/repo.js:82
const head = (await readFile(path.join(gitDir, 'HEAD'), 'utf8')).trim() - 读取本地文件src/git/repo.js:86
await stat(path.join(gitDir, ref)) - 读取本地文件src/git/repo.js:90
const packed = await readFile(path.join(gitDir, 'packed-refs'), 'utf8') - 读取本地文件src/git/repo.js:239
await stat(path.join(gitDir, marker)) - 读取本地文件src/git/repo.js:491
if (!rev) return readFile(path.join(root, file), 'utf8') - 读取本地文件src/git/patch.js:110
const original = await readFile(target, 'utf8') - 写入本地文件src/git/patch.js:163
await writeFile(target, `${lines.join('\n')}${endsWithNewline && lines.length > 0 ? '\n' : ''}`, 'utf8') - 执行外部命令固定命令src/git/exec.js:156
child = spawn('git', argv, { - 执行外部命令固定命令src/git/exec.js:302
spawn('taskkill', ['/pid', String(child.pid), '/T', '/F'], { windowsHide: true, stdio: 'ignore' }) - 读取本地文件src/git/revision.js:27
const info = await stat(target) - 读取本地文件src/git/revision.js:42
const info = await stat(dotGit) - 读取本地文件src/git/revision.js:48
const pointer = (await readFile(dotGit, 'utf8')).trim() - 读取本地文件src/git/revision.js:66
const head = (await readFile(path.join(gitDir, 'HEAD'), 'utf8')).trim() - 读取本地文件src/git/revision.js:70
return (await readFile(path.join(gitDir, ref), 'utf8')).trim() - 读取本地文件src/git/revision.js:72
const packed = await readFile(path.join(gitDir, 'packed-refs'), 'utf8') - 读取本地文件src/git/checks.js:31
raw = await readFile(path.join(root, 'package.json'), 'utf8') - 读取本地文件src/git/checks.js:76
await stat(path.join(root, file)) - 执行外部命令来自配置/变量src/git/checks.js:113
child = spawn(file, args, { - 发起网络请求src/client/client.core.js:160
const response = await fetch(`/dsh-git/api${path}?${query}`, { headers: { accept: 'application/json' } }) - 发起网络请求src/client/client.core.js:193
const response = await fetch(`/dsh-git/api${path}?${search}`, { - 写入剪贴板src/client/client.ui.js:467
const written = navigator.clipboard?.writeText(output) - 写入剪贴板src/client/client.ui.js:1367
const written = navigator.clipboard?.writeText(text) - 写入本地文件src/git/rebase-editor.js:6
copyFileSync(process.env.DSH_REBASE_TODO, process.argv[2]) - 写入本地文件src/git/reword-editor.js:6
writeFileSync(process.argv[2], `${process.env.DSH_REWORD_MESSAGE ?? ''}\n`, 'utf8') - 读取本地文件src/git/workspaces.js:65
const parsed = JSON.parse(await readFile(store, 'utf8'))
扫描于 2026/11/2(0 天前) · 范围 入口闭包 + 发布文件清单 · 来源 GitHub 仓库
静态扫描只反映源码中出现的调用,不构成安全背书;人工评估与自动扫描相互独立、互不覆盖。
依赖的 DSH / Cordis 模块
@deepseek-ai/cordis给这个插件打分还没有人投票↓
用户评分
还没有人投票,来当第一个
为 DeepSeek Harness 打造的 JetBrains 风格 Git 工作台插件:支持按代码块或按行暂存、并排对比、提交图谱、三方冲突视图。
README
由 DeepSeek 最新模型翻译生成dsh-git-workbench
JetBrains 式的 Git 工作台,跑在 DeepSeek Harness 里。 Local Changes 树、逐 Hunk / 逐行暂存、并排 Diff、Commit 窗口、提交图、Annotate、交互式变基、储藏、冲突三方视图 —— 全部留在会话旁边,不用切终端。
目标不是"能提交",而是"改哪一行、暂存哪一段、提交进哪个分支"都能像在 IDEA 里一样看得见。
English · · 功能清单 · HTTP API · 架构 · 设计取舍 · 开发与发布
提交页签与变更列表
是什么
DSH 的右侧栏是可拖动的页签区(能拖到别的面板、拆成第二栏、浮动、全屏),正好对应 IDE 的两个工具窗口;diff 则和 IDEA 一样开在编辑器位置、只有一块。
展开完整文档(README 剩余 1 节)
dsh-git-workbench
JetBrains 式的 Git 工作台,跑在 DeepSeek Harness 里。 Local Changes 树、逐 Hunk / 逐行暂存、并排 Diff、Commit 窗口、提交图、Annotate、交互式变基、储藏、冲突三方视图 —— 全部留在会话旁边,不用切终端。
目标不是"能提交",而是"改哪一行、暂存哪一段、提交进哪个分支"都能像在 IDEA 里一样看得见。
English · · 功能清单 · HTTP API · 架构 · 设计取舍 · 开发与发布
提交页签与变更列表
是什么
DSH 的右侧栏是可拖动的页签区(能拖到别的面板、拆成第二栏、浮动、全屏),正好对应 IDE 的两个工具窗口;diff 则和 IDEA 一样开在编辑器位置、只有一块。于是插件就是三个彼此独立的界面:
| JetBrains | 这里 | 内容 |
| Commit 工具窗口 | 页签 提交 | 变更树 + 变更列表 + 冲突 + 提交信息 + AI / 最近信息 / 检查 / Amend |
| Log 工具窗口 | 页签 历史 | 提交图 + 提交详情 + 文件清单,只读 |
| 编辑器里的 diff tab | 主区域 差异视图 | 并排 / 统一 diff、块级与行级暂存、Annotate、冲突三方视图,单例、每次替换 |
提交与历史各有自己的勾选、滚动、过滤和草稿,互不干扰;差异视图由"来源"决定内容与可写性——从「提交」进来是工作区(可写),从「历史」或会话轮次进来是只读快照。
此外它还接进了 DSH 自己的几个 surface:会话头部的分支芯片、新会话空状态的分支选择器、会话卡片的 Git 按钮、右侧「文件」页的 Git 按钮、输入框上方的改动条。仓库绑定会话的 cwd,切换会话就切换仓库。
截图
| 差异视图(并排、行内词级高亮) | 历史页(提交图 + 表头排序) |
| 差异视图 | 历史页 |
| 冲突三方视图 | 储藏(命名 + 部分文件) |
| 冲突视图 | 储藏弹窗 |
深色主题完全跟随宿主,没有自己的主题开关,因此不再单独保留深色截图。同一组界面的英文版截图也在同目录(*-en.png),英文 README 用的是那套。
安装
插件以目录形式安装到 DSH 的 web profile。先在 PATH 上准备好 git、Node ^22.19.0 || >=24.0.0、pnpm(dsh plugin 转发给它)以及 DSH 0.2.1-rc.2 以上。
从 npm 安装
dsh plugin --profile web add @yann9/dsh-git-workbench
或让 DSH 从本地目录安装(file: 复制内容;link: 建符号链接)
dsh plugin --profile web add link:<仓库目录的绝对路径>
bundle 层只在启动时读取,重启后生效
dsh web
打开终端打印的 ?token=... 地址。右侧栏 + 的引导页里能看到并打开「提交」「历史」,会话头部的分支芯片、设置 → 插件 → Git 工作台也直接可用。
file: 安装是复制,改完代码要重新 add;开发期用 link:,改完重启一次即可(代价是要自己维护下面这行 bundle 登记)。
如果 profile 里没有自动登记 bundle(DSH 0.2.1-rc.2 用 link: / file: 安装时偶发),在 ~/.dsh/profiles/web/package.json 里补一行,效果与 plugin add 相同:
"dsh": { "profile": { "bundles": ["@deepseek-ai/dsh-base", "@deepseek-ai/dsh-web-app", "@yann9/dsh-git-workbench"] } }
升级与卸载(同样要重启 dsh web):
dsh plugin --profile web add @yann9/dsh-git-workbench@latest
dsh plugin --profile web remove @yann9/dsh-git-workbench
/dsh-git/ 只提供 JSON API 与 SSE 事件流,没有独立页面;任何别的客户端都可以直接复用它(见 docs/api.md)。
配置
全部配置项都能在 设置 → 插件 → Git 工作台 里改(保存后插件自动重载一次),也可以直接写进 profile 的 cordis.patch.yml 后重启 dsh web:
- insert:
- id: git-workbench
name: '@yann9/dsh-git-workbench'
config:
repoPath: '' # 没有任何会话上下文时的兜底仓库 maxLog: 400 # 提交图/历史最多取多少条(1–5000)
readOnly: false # true = 只读:写接口一律 403,界面不出现写入入口
branchPattern: 'session/{date}-{time}' # 新建分支的默认名,占位符 {date} {time} {datetime} {repo} confirmDirtySwitch: true # 工作区有改动时,切分支先确认
diffFullFile: true # true = 整文件 + 折叠未变区;false = 只看改动前后 3 行 diffWrap: true # true = 长行软换行;false = 裁切 diffFoldThreshold: 8 # 未变区超过多少行折叠(2–500) diffSideBySide: true # 首次打开用并排还是统一视图
listMode: 'last' # 'tree' | 'flat' | 'last'(跟随上次选择)
commitLanguage: 'auto' # 'auto'(跟随界面语言)| 'zh' | 'en' llmProvider: '' # 留空 = DSH 里选中的模型路由 llmModel: '' # 留空 = 该路由选中的模型
未写的键使用上表默认值。readOnly: true 适合把工作台当作只读评审面板:暂存、提交、分支、网络、冲突解决全部禁用,HTTP 写接口返回 403(/config 除外)。
主要能力
完整的 50+ 项对照表在 docs/features.md,这里只列骨架:
- 暂存:整文件 / 逐 Hunk(裁剪 patch → git apply --cached)/ 逐行;反向取消暂存同样精确。提交永远以 index 为准。
- 差异阅读:并排与统一视图、双行号、行内词级高亮、忽略空白(只读保护)、未变区折叠、文件间 ‹ n/m › 与块间 F7。
- 提交:Commit 窗口(Ctrl+Enter)、AI 草稿与最近信息召回(↑)、Amend、变更列表、提交前按仓库 package.json 跑检查(失败默认拦截)。
- 历史:DAG 泳道提交图、表头排序、列宽可拖、列开关、按分支/作者/日期归类、结构化筛选(author: message: hash: tag: branch: date:)、多选后批量拣选 / 还原。
- 改写历史:交互式变基(pick / squash / fixup / drop)、改写提交信息、撤销提交、拣选、还原、软/硬重置,全部二次确认。
- 分支与远程:切换 / 新建 / 重命名、领先落后 ↑N ↓N、设置与取消上游、分支比较、变基到所选分支、fetch / pull / push(首次推送让你选远程)、远程仓库增删改。
- 冲突与序列器:unmerged 独立分组、三方视图逐块选边或手写合并结果、合并 / 拣选 / 变基暂停时的状态条与「继续 / 中止」。
- 储藏:命名 + 勾选文件(部分储藏走临时 index,不带走别的暂存内容)、只读预览、应用 / 弹出 / 删除。
- 可观测:Git 控制台按仓库记录每条真实 argv、退出码、耗时与输出,失败自动展开。
- 空目录:一键 git init,不动现有文件。
- 中英双语:跟随 DSH 的语言偏好(没设置时看浏览器语言),切换即时生效;Git 的英文拒绝会被本地化而不是原样甩给用户。
快捷键
| 操作 | 快捷键 / 手势 |
| 刷新 | F5 |
| 提交 | Ctrl/Cmd + Enter |
| 聚焦提交信息 | Ctrl/Cmd + K |
| AI 生成提交信息 | Ctrl/Cmd + G |
| 上一个 / 下一个文件 | Alt + ↑ / Alt + ↓,或头部 ‹ n/m › |
| 上一个 / 下一个差异块 | Shift + F7 / F7,或工具栏 ↑ 差异 ↓(走到头自动进相邻文件) |
| 还原当前差异块 | Ctrl + Alt + R(工作区来源,先确认) |
| 当前文件集里挑文件 | 点头部 3 / 5 |
| 从差异回到会话 | Esc 或右上角 ✕ |
| 历史页逐条翻提交 | ↑ / ↓、Home / End,Enter 或双击打开差异 |
| 历史页多选提交 | Ctrl/⌘ 点选、Shift 连选、Ctrl+A 选可见项、Esc 清空 |
| 空提交框召回上一条信息 | ↑ / ↓ |
| 暂存选中行 | 点行首 +/− 选中,再点「暂存选中行」 |
文档
| 文档 | 内容 |
| docs/features.md | 与 JetBrains 逐项对照的完整功能表、布局断点、已知限制、路线图 |
| docs/api.md | /dsh-git/api 全部端点、参数、缓存与 CSRF 约定,以及给模型的 8 个工具 |
| docs/architecture.md | host / client 分层、DSH 槽位、状态同步、多语言、安全模型 |
| docs/jetbrains-parity.md | 为什么不照抄 JetBrains、为什么不用 iframe、为什么只读是一种渲染路径 |
| docs/development.md | 开发循环、测试、调试服务器、截图约定、发布到 GitHub / npm 的检查清单 |
| CONTRIBUTING.md | 提 PR 前要跑的检查与代码约定 |
| CHANGELOG.md | 版本变更记录 |
开发
npm test # 104 个单测,使用真实 git 仓库(含 Windows 路径与 CRLF)
只跑 API、不带 UI,方便调试或给别的客户端用
node scripts/dev-server.js <仓库路径> 5178
→ http://127.0.0.1:5178/dsh-git/api/...
host 与 client 都是可直接运行的 ESM,没有构建步骤:link: 指向目录,改代码重启 dsh web 即生效。细节见 docs/development.md。
安全
- 所有 git 调用都是 spawn('git', argv),不经过 shell;用户输入只以白名单校验后的 argv 片段出现。
- 写操作串行化(withWriteLock),路径拒绝 .. 逃逸,commit/ref 只接受合法 revision。
- Origin 与 Host 不匹配的请求一律 403;请求体上限 2 MB;/dsh-git/ 下只映射 API。
- readOnly: true 时除 /config 外的 POST 全部 403。
- 不在浏览器里跑 git、不在页面里收集凭据;网络操作 120 s 超时且 GIT_TERMINAL_PROMPT=0,绝不挂起。
完整说明见 docs/architecture.md#安全模型。
版本
semver,且 package.json 的 version、CHANGELOG.md 的段落标题与 git tag(v0.1.0)三处始终一致。CI 在 Ubuntu 与 Windows 上跑 Node 22 / 24 四组矩阵,合并前必须全绿。
推送 tag 就是发布:.github/workflows/release.yml 先跑同一套矩阵当闸门,再建 GitHub Release(说明按 conventional commit 的类型分组),然后用 npm 的 Trusted Publishing(OIDC,仓库里没有 token)把包发到 npm 并从官方源回读校验包内容。流程细节与 Trusted Publisher 绑定步骤见 docs/development.md。
许可
MIT预览分享卡片长什么样 ↓
分享 · DeepSeek Harness Hub
yann9/dsh-git-workbench
在会话侧栏里逐行暂存改动、查看提交图与冲突
相关插件 · 开发 / 工程
隐私简历生成器reactive-resume/reactive-resume
Reactive Resume 已迁至 GitHub 上的…
★ 45,125已汉化MCP
71.7
AI 架构文档生成器sopaco/deepwiki-rs
🚀 Litho 已进化为 Terrain —— 给你的 AI 智能体一张会呼吸的代码库地图。
★ 3,157已汉化DSH
70.8
长时任务执行闭环AMAP-ML/LongHorizon-Harness
面向 Computer-Use Agent 的 Loop Engineering
★ 1,764已汉化DSH
70.5
AI 编程纪律方法包GanyuanRan/Aegis
让 AI 编程 agent 变得可信:少返工、更安全、说“完成”前先给证据。
★ 1,384已汉化DSH
69.6
多代理编排运行时Enderfga/claw-orchestrator
面向编程智能体的运行时。把 Claude Code、Codex、Antigravity、Grok…
★ 586已汉化MCP
69.4
记忆进化插件csyangwen/dsh-memory-evolve
dsh-memory-evolve 使用场景指南
★ 461已汉化DSH
67.9