# lnq-git **Repository Path**: lv_nanqing/lnq-git ## Basic Information - **Project Name**: lnq-git - **Description**: No description available - **Primary Language**: Unknown - **License**: MulanPSL-2.0 - **Default Branch**: main - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 1 - **Forks**: 0 - **Created**: 2026-07-27 - **Last Updated**: 2026-07-29 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # LnqGit 一个 macOS 上的 Git 可视化工具。目标是补上 SourceTree 缺失、而 IDE(IntelliJ / VS Code)做得很好的那些能力。 ## 安装 到 [发行版](https://gitee.com/lv_nanqing/lnq-git/releases) 下载 `.dmg`,拖进「应用程序」即可。 目前只提供 **Apple Silicon(arm64)** 版本。 ### 首次打开提示「已损坏」怎么办 这个包**没有 Apple 开发者签名与公证**(那需要每年 99 美元的开发者账号), macOS 的 Gatekeeper 会拦下所有未公证的应用,并给出一个具有误导性的 "已损坏,无法打开"提示 —— 应用本身是完好的。 绕过方式,任选一种: ```bash # 方式一:移除隔离属性(推荐,一次即可) xattr -cr /Applications/LnqGit.app ``` 方式二:在「访达」里**右键点击** LnqGit.app → 打开 → 在弹窗里再点「打开」。 (必须右键,双击不会给你这个选项。) 方式三:系统设置 → 隐私与安全性 → 在"已阻止使用"处点「仍要打开」。 介意的话可以自己从源码构建,见下方。 ## 从源码构建 ```bash # 开发模式(热重载) npm install npm run app # 打包 npm run app:build # 产物:src-tauri/target/release/bundle/ # macos/LnqGit.app # dmg/LnqGit_1.0.0_aarch64.dmg ``` 依赖:Node 18+、Rust 1.77+、Xcode Command Line Tools、Git。 ## 快捷键 | 键 | 作用 | |---|---| | `⌘K` | 命令面板(低频功能都在这里) | | `⌘O` | 打开仓库 | | `⌘1` | 显示/隐藏侧边栏 | | `⌘2` / `⌘3` | 提交历史 / 本地改动 | | `⌘\`` | 命令记录面板 | | `⌘⇧K` | 推送 | ## 四条设计原则 这些原则来自对 JetBrains IDE、VS Code + GitLens 等工具的功能调研,贯穿全部功能设计。 ### P1 · 不做黑箱 所有操作调用系统 `git` 二进制,不用 libgit2。每条命令连同完整输出都进「命令记录」面板,可复制、可复现。 用户的 `.gitconfig`、hooks、credential helper、别名全部自然生效;行为与命令行完全一致。这也顺带避开了 SourceTree 因 libgit2 进程内运行导致的卡死问题——git 是独立进程,可设超时、可终止、可流式读输出。 ### P2 · 危险操作三段式暴露 以强制推送为例: 1. **显式开关** —— 设置里打开「允许强制推送」,入口才出现 2. **默认安全变体** —— 默认使用 `--force-with-lease`,远端有他人新提交时会拒绝 3. **二次确认 + 受保护分支拦截** —— `main`、`release/*` 等名单内分支直接禁止强推 强推前还会列出**将被覆盖的远端提交**,让用户看清代价。拦截在 Rust 侧也做了一遍——安全检查不能只依赖界面。 ### P3 · 一切可搜索、键盘可达 分支模糊搜索(`fbl` → `feature/big-login`)、提交多维过滤器叠加、`⌘K` 命令面板。低频功能藏进命令面板,不占界面——这也是「界面保持简洁」的实现手段。 ### P4 · 不可逆操作有后悔药 - **自动快照**:重置、变基、丢弃改动前,用 `git stash create` 把现场存进 `refs/lnqgit/snapshots/`,不污染 stash 栈也不动工作区 - **时光机**:可视化 reflog + 快照列表,任意时点一键回去 - **删除分支后可撤销**:通知里带「撤销」按钮 - 丢弃未跟踪文件走系统废纸篓,不直接删除 ## 主要功能 ### 分支 模糊搜索 · 最近使用置顶 · 收藏星标 · 按 `/` 层级折叠 · `↓N ↑M` 收发徽标 · **Smart Checkout**(有未提交改动时自动 stash → 切换 → 恢复,而不是像 SourceTree 那样报错让你自己处理)· 分支对比 · 跨分支取文件 ### 提交历史 Canvas 绘制的 DAG 提交图(泳道布局在 Rust 侧计算)· 虚拟化列表 · **多维过滤器可自由叠加**(作者 + 路径 + 时间 + 消息 + 内容,SourceTree 只有单一搜索框)· 按改动内容搜索(`-S` / `-G`) ### 本地改动 文件 / hunk / **行级暂存**(拖选即选中,所见即所选)· 词级 diff 高亮 · 提交消息历史复用 · **跳过 hooks 复选框**(命令行要记 `--no-verify`,多数 GUI 根本不给这个选项) ### 同步 **推送前预览每一个提交及其 diff** · 对话框内直接改目标分支 · 强推三段式(见 P2) ### 变基与冲突 图形化交互式 rebase(拖拽重排、行内选动作、reword 就地改消息)· **编排阶段不执行任何 git 命令,可无限反悔** · 三方合并编辑器(结果栏可自由编辑、自动解决简单冲突、冲突计数递减) ### 逐行追溯(blame) 热力图着色(越新越亮,按文件内相对时间归一化)· 同一提交的连续行只显示一次作者,不刷屏 · 悬停高亮同提交的所有行 · **往前追(Annotate Previous Revision)**:带面包屑的追溯栈,一路跳过格式化提交这类噪音,追到真正写这行的人 ### 选区历史 选中若干行 → 看这几行的完整演进史(`git log -L`)。定位「这行为什么这么写」的最快路径,SourceTree 完全没有。 ### 工作树 列表 / 新建 / 删除 / 锁定 / 清理失效记录。让你在不同分支上并行工作,无需反复贮藏和切换 —— 2025+ 的新兴刚需,老牌 GUI 普遍缺失。 ### 补丁 导出(工作区 / 暂存区 / 指定提交,支持反向)· 应用前预检(能否干净应用、涉及哪些文件)· 从剪贴板应用时**自动提取提交消息与作者** · 三方合并模式产生冲突时明确提示并直送冲突编辑器,不会假报成功 ### 提交右键菜单 拣选 · 回退 · 改写消息 · 导出补丁 · **重置(四种模式各自解释后果)**。仓库处于变基/合并等中间态时,危险项自动禁用。 ### 进行中操作 rebase / merge / cherry-pick 中断时,顶部有一条**持续可见**的状态条,显示进度并提供继续 / 跳过 / 中止——不靠用户记忆自己处在中间态。 ## 项目结构 ``` src-tauri/src/ ├── git/ │ ├── exec.rs git 进程封装:超时、流式读、命令广播、错误翻译成中文 │ ├── repo.rs 仓库状态、进行中操作检测 │ ├── log.rs 提交历史 + DAG 泳道布局计算 │ ├── branch.rs 分支 CRUD、模糊匹配评分、Smart Checkout │ ├── diff.rs diff 解析 + 行级 patch 重组(行级暂存的核心) │ ├── status.rs 工作区状态 │ ├── remote.rs fetch/pull/push、force-with-lease、受保护分支 │ ├── rebase.rs 交互式变基(GIT_SEQUENCE_EDITOR 注入 todo) │ ├── merge.rs 冲突标记解析、三方版本提取、自动解决 │ ├── snapshot.rs 自动快照 + reflog │ ├── stash.rs 贮藏 │ ├── blame.rs 逐行追溯 + 热力图 + git log -L │ └── worktree.rs 工作树 ├── commands.rs Tauri 命令层(薄转发) ├── state.rs 应用状态与设置 └── watcher.rs 文件监听 → 增量刷新 src/ ├── panels/ BranchPanel / HistoryPanel / ChangesPanel / CommitDetail / ConsolePanel ├── components/ CommitGraph / DiffViewer / StatusBar / OperationBanner / Toast ├── dialogs/ CommandPalette / PushDialog / ReflogDialog / RebaseEditor / MergeEditor ├── store/ zustand 全局状态 └── api/ Tauri 命令封装 + 类型定义 ``` ## 性能 面向大仓库设计。实测基准是一个 **1332 个分支**的真实仓库,其中单个文件的 diff 可达 **1.3 万行**、单个提交可达 **22 万行**。 | 场景 | 处理方式 | |---|---| | 22 万行的 diff | 虚拟化,只渲染视口内 **58 行**(DOM 节点 110 万 → 290) | | 词级高亮 | 只算视口内涉及的 hunk,按 hunk 缓存;否则 22 万行要同步跑 917ms | | 提交图滚动 | 绘制/尺寸/取色三个 effect 分离,滚动只触发绘制;rAF 合并帧 | | 1332 个分支 | 树结构与展开态分离缓存,展开某个目录不重建整棵树 | | 分支搜索 | 后端限 200 条,前端超 300 行启用虚拟化 | 行高不统一(普通行 18px、hunk 头 24px)所以虚拟化用前缀和偏移表 + 二分查找, `scripts/bench-diff.mjs` 会验证「任意滚动位置的可见区间都完整覆盖视口」。 ### 文件监听的范围 只监听 `.git` 顶层(HEAD / index)、`.git/refs`,以及工作区中排除 `node_modules` / `target` / `build` 等目录之后的部分。 早期版本递归监听整个仓库,在一个 14801 个目录、`.git` 达 2GB 的真实仓库上, 应用**空闲时也持续占用 6-7% CPU** —— macOS 要为每个目录维护 FSEvents 监视, 而 `.git` 内部在后台一直有写入。改成选择性监听后空闲占用降到 0%。 ## 测试 ```bash # Rust 单元测试(覆盖 diff patch 重组、模糊匹配、冲突标记解析、 # blame porcelain 解析、DAG 布局、受保护分支通配等纯逻辑) cd src-tauri && cargo test --lib # 前端类型检查 npx tsc --noEmit # React Hook 顺序检查 —— tsc 查不出「hook 写在提前 return 之后」, # 但它会让整棵组件树被卸载(界面空白、点击无反应)。已构建期强制执行。 node scripts/check-hooks.mjs # 虚拟化正确性与收益 node scripts/bench-diff.mjs ```