# Git 版本管理

在项目工作区打开 Git 页面，可以可视化地管理代码版本。底部有三个标签页：状态、分支、提交。如果当前目录不是 Git 仓库，可一键初始化为空白仓库（默认分支为 `main`），或输入远程地址直接克隆已有仓库（**1.12.0 起**）。

## 多目录识别

Git 页会自动识别当前工作区根目录及其**一层直接子目录**里的 Git 仓库：

- 顶栏标题下方显示当前仓库名，点击可弹出仓库选择列表，在多个仓库间切换。
- 仓库选择列表仅列出识别到的 Git 仓库，当前选中的仓库以主色高亮显示。
- 若工作区根不是 Git 仓库但子目录是，会自动选中子目录仓库，展示其状态、分支、提交。
- 工作区根与子目录都找不到 Git 仓库时，显示「非 Git 仓库」提示，可「初始化新仓库」（在当前工作区根执行 `git init`），也可点「选择已有仓库」。

## 凭据与署名

右上角的钥匙图标进入「凭据与署名」页，内含署名和凭据两个标签页——**首次使用必须先配好署名，否则无法提交**。

凭据页右上角的「+」用于新增 Git 凭据，提供两种方式：

- **手动添加**：填写远程主机、用户名与访问令牌（Token / PAT）。
- **快速登录**（**1.13.0 起**）：用 GitHub 账号授权一键添加，无需自己创建 Token。选中 GitHub 后，应用会显示一个设备码；点击「复制并前往授权」会自动复制设备码并打开 GitHub 验证页，粘贴设备码并授权后，应用会自动完成登录并把 `github.com` 的凭据写入列表。也可以单独点击「复制设备码」后手动在浏览器打开。

  快速登录基于 GitHub App 的细粒度授权：能访问哪些仓库、有哪些权限，由该 App 注册时的配置决定，并在安装时由你勾选，不再需要账号下所有仓库的完全权限。登录完成后，如果还没把 Muse 安装到你的仓库，弹层会提示并给出「去安装」按钮，点它跳到 GitHub 安装页选择要授权的仓库即可。

如果快速登录提示「该应用未启用设备码流」，说明对应的 GitHub App 尚未开启 Device Flow；提示「客户端 ID 无效」则说明应用配置有误。

离开 App 去浏览器授权期间，登录弹层会在后台继续等待（设备码有效期 15 分钟），网络短暂中断会自动重试，回来时通常已经完成。

## 状态

查看当前仓库的工作区状态。

顶部卡片显示当前分支名、相对远程领先或落后多少个提交（上下箭头），以及已暂存、已修改、未跟踪的文件数量。

**提交**是全宽的主按钮，需要先暂存改动并配好署名才能点击，点击后填写提交信息。

次级操作一行四个按钮：

- **暂存全部**：把所有改动加入暂存区。
- **储藏**（**1.12.0 起**）：打开储藏箱，见下文「储藏」小节。
- **拉取 / 推送**：需要已配置远程仓库。当前分支没有上游时，推送会自动建立关联。

分组标题右侧还有：

- **全部取消暂存**：在已暂存分组，执行前会二次确认。此操作只取消暂存，不会删除文件内容。
- **全部回退**（**1.11.0 起**）：在已修改分组，把所有未暂存的改动还原成上次暂存或提交的内容。已暂存的内容不受影响，但丢弃掉的改动无法找回，执行前会二次确认。

文件改动按「已暂存 / 已修改 / 未跟踪」分成三组：

- 已暂存：点行查看暂存区与上次提交的差异，行尾「−」取消暂存。
- 已修改：点行查看工作区与上次提交的差异，行尾「+」暂存该文件。被删除的文件也在这一组，状态徽标是红色的 D。
- 未跟踪：点行查看这个新文件的内容（整份按新增显示），行尾「+」暂存。git 会把新建的目录折叠成一行（如 `feature/`），点它展开里面的文件，再点单个文件即可查看内容。

如果工作区有未提交的改动，点「拉取」会先提示可能产生冲突，确认后才执行。

### 提交弹窗（1.12.0 起增强）

点「提交更改」弹出的窗口里：

- **AI 生成**：点标题栏右侧的按钮，让 AI 读取暂存区与工作区的差异，自动生成一条符合 Conventional Commits 的提交信息。生成期间按钮显示「正在生成…」，生成失败会提示检查模型或网络。
- **快捷类型**：输入框上方一排 Chip（`feat`、`fix`、`refactor`、`chore`、`docs`、`style`、`perf`、`test`），点一下即把对应前缀套到当前信息上。
- **追加到上次提交（--amend）**：底部开关，开启后这次提交会合并进上一次提交，而不是新建一条。

### 合并冲突（1.12.0 起）

合并分支后如果产生冲突，状态页会单独列出冲突文件（状态徽标为紫红色 U）。在编辑器中解决冲突后，暂存对应文件。

没有未解决的冲突、但合并尚未提交时，页面显示「合并待提交」。此时请确认并暂存需要保留的改动，再点「提交更改」完成合并；这不表示仍有冲突。

如果要放弃本次合并，可点「中止合并」还原到合并前的状态。不要仅为关闭提示而中止合并。

## 储藏（1.12.0 起）

储藏用于临时收起当前改动、让工作区回到干净状态，之后再取回来。点状态页的「储藏」按钮打开储藏箱：

- **储藏改动**：可填一句可选说明，并可勾选「包含未跟踪文件（-u）」把新文件也一并收起。
- **弹出 (Pop)**：取出这条储藏并把它从储藏列表移除。
- **应用 (Apply)**：取出内容但保留这条储藏记录。
- **丢弃 (Drop)**：删除单条储藏，执行前二次确认。
- **清空全部**：删除所有储藏，执行前二次确认。

丢弃与清空都不可撤销。

## 回退与删除（1.11.0 起）

::: tip 版本说明
状态页的长按操作菜单（回退改动、恢复文件、删除未跟踪项）与「全部回退」从 1.11.0 起提供；菜单里的「添加到 .gitignore」从 1.12.0 起提供。
:::

**长按任意文件行**会从底部弹出操作菜单，菜单顶部显示完整路径。可用的操作按文件所在分组不同：

| 分组 | 菜单项 |
| --- | --- |
| 冲突文件 | 查看差异、暂存、复制路径 |
| 已暂存 | 查看差异、回退改动（还原到上次提交，已暂存和未暂存的改动都会丢失）、复制路径 |
| 已修改 | 查看差异、回退改动（还原成上次暂存或提交的内容）、复制路径 |
| 已修改中被删除的文件 | 查看差异、**恢复文件**（从上次提交把文件取回来）、复制路径 |
| 未跟踪文件 | 查看差异、**添加到 .gitignore**（忽略此文件 / 忽略同类型文件）、删除文件、复制路径 |
| 未跟踪目录 | **添加到 .gitignore**（忽略整个目录）、删除目录、复制路径 |

两类操作的后果完全不同，注意区分：

- **回退改动 / 恢复文件**：针对 Git 已经跟踪过的文件。内容存在版本库里，因此无论文件是被你删的、还是被终端命令或 AI 删的，都能取回来。代价是这次没提交的改动会丢失。
- **删除文件 / 删除目录**：只出现在未跟踪项上。这些文件从来没进过版本库，**删除后 Git 无法恢复**。

所有回退和删除操作执行前都会弹确认框，说明将丢失什么。

## 分支

分成 HEAD、本地分支、远程分支、标签四组显示。当前分支卡片会显示分支名和三类引用的数量。本地分支按路径树形展示，当前分支高亮。

**切换分支**：点任意分支或标签，确认后切换。点远程分支会创建一个本地跟踪分支再切过去。切换到标签会进入 detached HEAD 状态（此时的提交不属于任何分支，注意不要在该状态下长期工作）。

**点分支行**弹出操作菜单：

- **切换**：切到该分支。
- **合并分支**（**1.12.0 起**）：把该分支合并到当前分支，确认框里可选「创建合并提交（--no-ff）」。当前分支自身不显示这一项。
- **重命名**：改本地分支名。
- **删除**：本地分支使用安全删除，只能删已合并的分支；未合并的分支会被拒绝并给出原因。远程分支的删除会直接作用到远端，**不可撤销**。当前所在的分支不能删除。

**新建分支**：点本地分支分组标题右侧的 +，填分支名、选基准分支（默认当前分支），「创建并切换」开关默认开启。

**标签**：点标签分组标题右侧的 + 从当前 HEAD 创建轻量标签；点已有标签 → 操作菜单 → 删除可以删本地标签。

### 首次推送 master 分支的命名建议（1.12.0 起）

如果当前本地分支叫 `master` 且还没建立上游，第一次推送时会弹窗建议重命名为 `main`（GitHub、GitLab 的默认主分支）。可以选择「重命名为 main 并推送」，或「保留 master 推送」。

## 提交

显示最近的提交，带彩色的分支拓扑图。每条显示短哈希、作者、相对时间、提交信息，以及所在分支或标签的标记。

**搜索过滤**（**1.12.0 起**）：列表上方有搜索框，输入关键词即可按提交说明、作者或短哈希实时筛选。

点一条提交会弹出底部详情面板：完整提交信息、作者与时间、完整哈希（短哈希和完整哈希都可以复制）、是否是合并提交，以及这次改动的文件清单。点文件可以查看该文件的差异。

详情面板上方还有一排深度操作（**1.12.0 起**）：

- **分支**：基于这条提交新建分支并切换过去。
- **标签**：在这条提交上打标签。
- **Reset**：把当前分支重置到这条提交，可选 `Soft`（保留工作区与暂存区）或 `Mixed`（保留工作区，清空暂存区）。

往下滚动接近底部时会自动加载更早的提交，全部加载完会显示「没有更多了」。

## 差异视图

点文件或提交查看差异时进入独立的差异页：

- 差异按带行号的 `+ / −` 彩色显示，顶栏可以**在编辑器中打开**该文件（**1.12.0 起**），直接跳到代码编辑器对应文件。
- 单侧文件超过 2MB 时直接提示「文件过大」，不展示内容（二进制文件同理）。

## 超大输出

为保护手机内存，Git 页面不会将超大内容完整读入：状态、分支、提交列表等读取 git 输出超过上限时，会提示「输出过大，已截断，请缩小范围后重试」，不再尝试加载。

## 常见错误提示

操作失败时 Git 的原始报错会被翻译成中文提示。若某条错误没有对应翻译，会直接展示 Git 原文，方便排查。

| 场景 | 提示 |
| --- | --- |
| 当前目录不是仓库 | 当前目录不是 Git 仓库 |
| 仓库所有者异常 | Git 检测到仓库目录所有者异常（常见于外部存储），无法安全操作 |
| 仓库被占用 / 残留锁文件 | 仓库正被其他 Git 操作占用，请稍后重试 |
| 索引损坏 | Git 索引文件已损坏，请关闭后重新打开仓库 |
| 磁盘写入失败 | 无法写入仓库文件，请检查存储权限或剩余空间 |
| 删除当前所在分支 | 无法删除当前所在分支，请先切换到其他分支 |
| 删除有未合并提交的分支 | 该分支有未合并的提交，无法安全删除 |
| 新建分支重名 | 同名分支已存在 |
| 分支名不合法 | 分支名不合法 |
| 新建标签重名 | 同名标签已存在 |
| 删除不存在的标签 | 标签不存在 |
| 切换到不存在的分支/引用 | 分支、标签或提交不存在 |
| 操作的路径不存在 | 指定的文件或路径不存在 |
| 未跟踪文件会被覆盖 | 存在会被覆盖的未跟踪文件，请先移动或删除后再继续 |
| 切换时本地改动会被覆盖 | 本地有未提交的改动会被覆盖，请先提交或储藏后再切换分支 |
| 处于分离头指针状态 | 当前处于分离头指针状态，无法执行该操作，请先切换到某个分支 |
| 合并冲突 | 合并产生冲突，请前往状态页查看并解决冲突 |
| 存在未解决的冲突 | 存在未解决的冲突，请先解决冲突或中止合并 |
| 无共同历史 | 两个分支没有共同历史，无法合并 |
| 目标无法合并 | 无法合并：目标不是有效的分支或提交 |
| 无法快进 | 无法快进合并，存在分叉的提交，请改用普通合并 |
| 合并时本地有改动 | 本地有未提交的改动，请先提交或储藏（Stash）后再合并 |
| 未配置提交署名 | 尚未配置提交署名，请在设置中填写用户名和邮箱 |
| 无可提交改动 | 没有需要提交的改动 |
| 提交信息为空 | 提交信息不能为空 |
| 冲突未解决时提交 | 合并冲突尚未解决，无法提交 |
| 分支未关联远程 | 当前分支未关联远程分支，无法拉取 |
| 未指定拉取分支 | 未指定要拉取的远程分支 |
| 未配置远程仓库 | 未配置远程仓库，无法推送 |
| 本地无可推送提交 | 本地没有可推送的提交 |
| 本地与远程分叉 | 本地与远程分支已分叉，请先拉取合并或变基后再推送 |
| 推送被拒（远程有更新） | 推送被拒绝，远程有更新的提交，请先拉取 |
| 推送被远程拒绝 | 远程拒绝了本次推送，可能受分支保护或权限限制 |
| 远程分支不存在 | 远程分支不存在 |
| 远程仓库不可用 | 远程仓库不可用或无访问权限 |
| 远程鉴权失败 | 远程鉴权失败，请检查凭据配置（用户名/密码/Token） |
| 远程仓库不存在 | 远程仓库不存在或无访问权限 |
| 域名解析失败 | 无法解析远程主机地址，请检查网络或代理 |
| 连接失败或超时 | 连接远程仓库失败或超时，请检查网络或代理 |
| 连接中断 | 与远程仓库的连接中断 |
| 证书/TLS 失败 | 安全连接建立失败（服务器证书校验或 TLS 握手失败） |
| 克隆目录非空 | 当前工作区目录非空，无法直接克隆到当前目录 |
| 无改动可储藏 | 当前没有需要储藏的改动 |
