visitor@wangyvdi.top:~$ cat posts/notes/02_git_worktree.md

git worktree 略记

#git #linux #笔记 2 min

posts/notes/ 下的第二篇。和上一篇共享两个标签(linux、笔记),用来验证标签重复时列表、搜索、上一篇/下一篇都不会串。

它解决什么问题

一个仓库同一时间只能 checkout 一个分支。想一边看 master、一边改特性分支,传统办法是 clone 第二份,代价是两份对象库、两份远端配置、两份忘了同步的缓存。

git worktree 让同一个 .git 下挂多个工作目录,每个目录一个分支。

基本用法

# 在仓库里加一个工作目录,检出已有分支
git worktree add ../ssh-blog-hotfix hotfix/login

# 顺手新建分支并检出
git worktree add -b feat/add-404-page ../ssh-blog-404 master

# 看有哪些
git worktree list

# 用完了
git worktree remove ../ssh-blog-404

和"复制一份"的区别

复制目录 worktree
对象库 各一份 共用一份
分支占用 两边可以检出同一分支,容易互相踩 同一个分支同时只能在一个 worktree 里
体积 随仓库增长 只有工作文件
删除 手动 rm -rf git worktree remove,顺带清理元数据

第二行是最有价值的一条:分支被"占用"这件事,恰好防止了你在两个目录里同时改同一个分支。

几个坑

  • 别忘了它存在。git worktree list 里躺着一堆临时目录,删了目录却没 remove,git worktree prune 才能清干净。
  • 子模块。每个 worktree 都要单独 git submodule update --init,不会共享初始化状态。
  • IDE 缓存。两个目录会各自建立索引,项目大的时候机器会热。
  • 部署脚本。deploy.sh 用 git ls-files 出清单,在哪个 worktree 里跑就按哪个分支的文件发,这倒是符合直觉。

本项目里怎么用

给这个博客加功能时,一个舒服的用法是:主目录留在 master 上跑着 go run . 看效果,另一个 worktree 检出特性分支随便改、随便删,改完再合回来。

不过要注意端口:两个 worktree 同时 go run . 会抢 :2222 和 :8080,第二个得自己改参数。

go run . -addr :2223 -http :8081

这篇想测什么

  • 子目录里的文章能正常出现在列表页,路径带着 notes/
  • 两篇共享标签时,#linux 在两篇上都显示,搜索也不会重复计数
  • 上一篇/下一篇跨目录也接得上:从这篇往下翻应该翻到 01_ssh_端口转发.md
  • tree posts/ 能看到两层结构,cd notes 之后 ls 只有这两篇

在终端里读这篇:ssh -p 2022 wangyvdi.top cat posts/notes/02_git_worktree.md (原文 是同样的纯文本)