Git 与 Worktree
Codeg 在工作区中内置了一个完整的 git 客户端,因此审阅智能体写下的内容并将其落地,与提示同属一个闭环——无需跳转到单独的 git 工具。一切都位于你已经打开的面板中:更改标签页管你的工作树,提交标签页管历史与远程,composer 正下方的分支标签管选分支。集成终端始终在那里,供你运行偶尔需要的命令,但你很少会用到它。
每类操作各归其位
这三处界面原本是重叠的——分支标签扛着整个 git 菜单,而两个标签页各自还有自己的工具栏。现在每一处各管一类工作:
| 界面 | 里面有什么 |
|---|---|
| 更改标签页 | 工作树——快速提交、储藏与恢复储藏、全部添加、全部回滚 |
| 提交标签页 | 历史与远程事务——包括管理远程仓库 |
| 分支标签 | 选分支,以及作用于你当前所在那个分支的操作 |
拉取、获取和推送这三样三处都有,因为这三处都是你会顺手想用它们的地方。
审阅你的更改
打开右侧面板中的更改标签页,即可一眼看到你的工作树,它分为已跟踪的更改和未跟踪的文件。每个已跟踪的文件都会显示它的 git 状态(M 已修改、A 已添加、D 已删除、R 已重命名……)以及一个实时的 +/− 行数统计。点击任意文件即可打开它的 diff。
这些 diff 是只读的——并排显示,HEAD 在左侧,你的工作树在右侧,配有上一处/下一处以逐一浏览每处更改。它们用于查看改动了什么,无论改动出自你还是智能体之手;你在提交时决定保留什么,而不是通过编辑 diff 来决定。
右键点击一个文件——或一个文件夹,以便一次性操作多个——即可看到其余操作:
- 查看 Diff / 打开文件——审阅更改,或打开真实文件进行编辑。
- 添加到会话——把文件作为上下文交给智能体。
- 回滚——放弃某个文件的更改,并将其恢复到上一次提交。此操作具有破坏性,会先征询确认。
- 删除——对于未跟踪的文件,将其从磁盘上移除。同样具有破坏性,同样需要确认。
这里没有单独的暂存步骤——Codeg 不会要求你在提交前先 git add。你只需在提交时(见下文)勾选想要的文件即可。新文件起初处于未跟踪状态;如果你想在提交之前就把某个文件纳入 git,添加到 VCS 会开始跟踪它。
还不是仓库?
如果文件夹不在 git 管理之下,更改标签页会予以说明——从分支菜单中选择初始化 Git 仓库即可创建一个。(下面说的那个提交工具栏在仓库之外根本不会渲染。)
提交
更改标签页顶上就是一条工具栏,因此要提交你正盯着的这些改动,不必再打开任何东西:在输入框里写一条消息,按回车。
这种快速提交只取已跟踪的改动——一个没被忽略的 dist/ 或 node_modules/ 绝不会因为一次敲键就搭上车——而且切换到别的文件夹时草稿消息会被丢弃,于是为某个仓库写的消息不会落到下一个仓库里。
旁边那个圆形按钮打开的菜单里是其余的一切:拉取、获取、推送、储藏与恢复储藏,外加全部添加到 VCS 和全部回滚(这两项都走文件选择器,因此谁都不会盲写),以及提交代码——它打开完整的提交窗口。
那个窗口依然用于任何更慎重的场合:勾选要包含的文件(已跟踪的文件默认被选中,未跟踪的则不会),点击任意名称可预览其 diff,写一条消息,然后提交。它的提交按钮同时也是一个菜单——提交记录选中的文件,提交并推送在同一步骤中把它们发送到你的远程仓库。
Codeg 会用你为该远程仓库设置的 git 账户 的作者身份为每次提交盖章,因此你的提交能被正确归属,而无需在每个项目中都设置 user.name 和 user.email。
分支、合并与变基
composer 下方的分支标签——参见工作区——是你的分支切换器。它列出你的本地和远程分支,把 feature/… 这类共同前缀折叠成默认收起的分组,并将当前检出的那个标记为当前;选择一个分支即可看到它的操作——切换到此分支、将它合并到当前分支、把当前分支变基到它上面、将它删除,以及下面这两个根本不需要检出它的操作:
- 拉取代码会把那个分支快进到它的上游,完全不动你的工作树,因此你可以一边待在自己的特性分支上,一边把
main更新到最新。它刻意选择拒绝而不是强推:非快进会被拒绝,被另一个 worktree 占用的分支也会被拒绝。绝不会在你打开着的工作树底下悄悄改写历史。(对于你当前所在的那个分支,它就是普通的拉取,冲突处理照旧。) - 推送会打开针对该分支预选好的推送窗口,让你先审阅即将发出去的提交。已经打开的推送窗口会被重新定向,而不是继续指着它原先针对的那个分支。
新建分支...会从你当前所在的位置创建一个分支并检出它。顶部的一个搜索框会同时过滤分支和操作,因此你可以输入分支名的一部分直达目标。
每个对话各有一个这样的标签,因此当你平铺多个会话时,每一个都会显示并切换它自己的分支。
切换使用的是普通的检出,因此 Codeg 不会替你移动未提交的更改——如果 git 会拒绝,请先提交或储藏。储藏位于更改标签页的菜单里:储藏更改会把你的工作收起来(可选择保留索引中的暂存内容),而恢复储藏会列出你的储藏,供你应用或丢弃。
推送、拉取与远程仓库
- 拉取代码会获取并合并你的上游;如果合并发生冲突,Codeg 会打开冲突工具(见下文),而不是把你留在一个进行了一半的合并上。
- 获取远程分支会从你的远程仓库刷新一切,而不触动你的工作树。
- 推送会打开一个窗口,列出你尚未推送的提交,让你在它们发出去之前确切看到即将发送的内容。在提交标签页中,每次提交都标注了它的推送状态:带对勾的云朵表示已推送到远程,划掉的云朵表示未推送到远程,而当你筛选到某个没有上游的本地分支后,问号表示推送状态未知。
- 管理远程仓库让你添加、编辑或移除仓库所指向的远程仓库。它位于提交标签页的菜单里——那也正是你需要它的时候会待的地方:一个还没有任何引用的仓库,恰恰是最该去添第一个远程的时候。
阅读历史——提交标签页
右侧面板中的提交标签页是项目的完整历史,而不只是最近的一页:它是一条时间线,会随着你滚动不断加载更早的提交。每一行都带有它的推送状态、提交标题、作者、落地时间,以及短哈希。刷新按钮旁边的一个操作菜单里是拉取、获取、推送和管理远程仓库。
顶部的两个胶囊可以缩小你查看的范围,而且 Codeg 会按项目记住这两者,因此重新打开一个仓库时会回到你上次离开的视图:
- 分支——默认同时显示全部分支。打开它即可搜索并选择一个;本地和远程分支会分组,当前检出的那个标记为当前,✕ 可清除该筛选。它们上方还有一项 HEAD,跟随当前分支——这个筛选不会钉住某个名字,而是在每次查询时重新解析,因此历史会跟着你的每一次检出走,处于分离 HEAD 时也照常可用。如果你曾用来筛选的某个分支后来被删除了,该筛选会悄悄退回到全部分支,而不是让你看到一片空白。它只渲染屏幕上的那些行,因此有几百个远程分支的仓库打开时不再有以前那一下卡顿——搜索、前缀分组和键盘导航都照旧可用。
- 作者——你自己的提交一键可达(你的 git 身份排在最前,带 you 徽标),最近的选择会被保留以便复用,输入内容则会搜索仓库中的每一位作者。
点击某个提交将其展开,你无需离开该面板即可看到全貌:完整的哈希和提交信息(两者都可复制,信息很长时会有展开开关)、作者和精确的时间戳、它改动的每个文件及 +/− 计数——点击某个文件可查看它在该提交时的 diff——以及标示包含它的那些分支的小标签。
右键点击某个提交可使用这些操作:
- 查看差异——把整个提交作为一份 diff 在编辑器标签页中打开。
- 新建分支...——从该提交创建分支;Codeg 会创建它并把你切换过去。
- 重置到此处——把当前分支移动到该提交,并选择模式:
--soft、--mixed(默认)、--hard或--keep,每一种都在对话框中有说明。重置针对的始终是你实际所在的那个分支,因此在全部分支视图下、在 HEAD 下、以及按名字查看当前分支时都可用——但在你正看着另一个分支时不行,Codeg 会说明原因。 - 刷新与推送...
登录以推送——git 账户
通过 HTTPS 推送需要凭据,而 Codeg 会以 git 账户的形式为你管理它们,这样你就不必每次推送都重新输入令牌。在设置 → 版本控制下添加一个:
- 一个 GitHub 账户——一个个人访问令牌,附带一个直达 GitHub 令牌页面的链接,并已预选好正确的作用域。
- 一个用于 GitLab、Bitbucket 或自托管服务器的 Git 账户——服务器 URL、用户名和令牌。
账户按远程仓库的主机进行匹配,其中一个被标记为默认以打破平局,而令牌保存在你的系统密钥环中,绝不以明文形式存储。账户一旦设置好:
- 你的推送和拉取会顺畅运作——Codeg 会自动向 git 提供凭据。
- 智能体的也一样。 当智能体在终端中运行自己的
git push时,它会通过同一个账户进行认证——无需单独设置。 - 提交会被归属到该账户的身份。
如果某个 git 操作撞上了认证壁垒,Codeg 会内联提示,验证你输入的内容,并将其保存为一个账户,这样就不会再次询问。SSH 远程仓库继续使用你自己的 SSH 密钥,因此它们在这里不需要账户。
→ 版本控制与 Git 详细介绍了这些设置中的每一个字段。
解决冲突
当合并、变基或拉取遇到冲突时,Codeg 会捕捉到它并给出一个合并冲突提示:中止并退出,或打开合并工具。该工具是一个三栏编辑器——左侧是本地(Ours),右侧是远程(Theirs),中间是一个可编辑的结果。
逐一处理每处冲突:接受某一侧——在该块上点击接受本地或接受远程——或者直接把解决方案输入到结果窗格中;这是 Codeg 中唯一一个你可以编辑的 diff。标题栏按钮可一次性应用整整一侧,或应用所有无冲突的块。当某个文件干净后,点击标记为已解决,Codeg 会暂存它并把你带到下一个。一旦每个文件都解决完毕,完成合并会结束该操作——或者用中止把整件事回退。
使用 worktree 并行工作
git worktree 是同一个仓库的第二份工作副本,在它自己的目录中检出到它自己的分支上。Codeg 围绕它们构建并行开发:不再是一次只有一个智能体在一个分支上工作,你可以让多个智能体同时工作,每个都在自己的 worktree 中、在自己的分支上——不会互相踩到对方的文件,也不会有做了一半的更改在任务之间相互渗漏。
从分支菜单 → 新建 worktree 创建一个。Codeg 会预填一个新的分支名称和一个与你仓库相邻的同级目录(两者都可编辑),运行 git worktree add,并且——精彩之处在于——开启一个以该 worktree 为根的全新对话。在那里开启一项任务,智能体便会完全在其内部工作。
那里的位置输入框,如今在 Codeg 每一处需要你指定目录的地方都是同一个——克隆仓库、创建 worktree、新建项目。主目录和上一级收在输入框的左端内部,文件夹选择器在右端;而选择器的图标会告诉你将打开哪一个:本地文件用你操作系统自己的对话框,指向服务器时用 Codeg 内置的浏览器。选定文件夹只会把路径填进输入框,把确认这一步留给你,而不是直接对这次选择采取行动。
在侧边栏中,一个仓库的 worktree 会分组显示在它下方,因此一个项目的并行分支会聚在一起。切换到某个位于 worktree 中的分支,会把你带到那个 worktree,而不是在你当前的分支之上进行检出。回报是:将几个会话并排平铺,每个都在自己的 worktree 中,看着一支智能体舰队同时构建不同的功能——这是多智能体协作的天然搭档。
另有两项功能依赖同样的机制。自动化可以让每次运行在自己的一次性 worktree 中执行,因此计划任务永远不会与你的工作树发生碰撞。而每一条待办都会自动拿到一个——分支为 task/<id>,默认建在项目旁边的同级目录里,也可以由你指定放到哪儿——正是这一点让多个任务可以同时推进、再一个一个地落地。
用完之后把它删掉
worktree 分支以前是一条死路:删除分支只会得到 git 的拒绝——"cannot delete branch 'x' used by worktree at …"——因为检出必须先走。现在在分支标签里选中它,你会得到两个真正管用的删除操作:
- 删除工作树——移除检出,保留分支及其工作区文件夹,因此之后还可以在那个路径上把 worktree 重建回来。
- 删除工作树及分支——检出、分支和该 worktree 的工作区文件夹一并移除。它里面的会话会移到仓库文件夹下,并标记它们实际运行的位置,因此不会丢失任何历史。
有两种情况会被提前拒绝,理由值得知道:仓库的主工作树不会被提供任何破坏性操作(git 既拒绝移除它的检出,也拒绝删除它的分支);而正在运行或正在合并的待办任务,会挡住它所在那棵树的移除——强行删除等于把一个活着的智能体的目录从它脚下抽走。当一个 worktree 文件夹真的被移除时,每一条引用它的待办都会被解除关联并刷新卡片,而不是留在那里提供一个注定失败的清理操作。
从工作区移除,不等于删除 worktree
文件夹菜单上的从工作区移除只是把它移出 Codeg 并关闭它的标签页——磁盘上的 worktree 及其分支不受影响。当你真的想移除检出本身时,请用上面分支标签里那两项。
待办任务的 worktree 在看板上有它自己的入口,而且通常那才是你该去的地方:当你合并或删除一个任务时,看板会主动提出移除它;而从 0.28 起,任务抽屉里的删除 worktree 按钮可以回收一份遗留的检出——目录连同工作分支——同时不动任务本身,专门用于那些你在合并时选了「不」的情况。以上任何一步失败,它都会告诉你。→ 待办任务