Git Worktree:优雅解决多分支开发痛点的终极利器

594 阅读8分钟

引言

很久没写一些日常开发技巧类的教程了,今天来简单介绍一个笔者认为比较实用的临时分支管理指令——git work tree,希望对你的日常开发有所帮助。

我是 SharkChili ,Java 开发者,Java Guide 开源项目维护者。欢迎关注我的公众号:写代码的SharkChili,也欢迎您了解我的开源项目 mini-redis:github.com/shark-ctrl/…

为方便与读者交流,现已创建读者群。关注上方公众号获取我的联系方式,添加时备注加群即可加入。

传统的临时修复管理策略

一般情况下,我们在日常的版本迭代时都会在feature分支下进行新功能开发,临时遇到线上生产问题需要修复时,对应的解决策略是:

  1. 通过git stash暂存当前更改
  2. 切换到release分支并基于该分支checkout出hotfix版本
  3. 修复问题提交代码
  4. 切回原有分支,通过git stash pop还原继续完成开发

这种做法也是不错的选择,但存在一个笔者认为不是很优雅的缺点,即通过git stash策略完成版本修复回归后,尽管我们可以还原之前的开发工作,但编译构建工作却需要从头开始,这对于那些编译型的编程语言,例如:C、Go或者java都不是很友好。

详解git worktree

Git worktree是Git提供的一个强大功能,允许你从单个仓库创建多个工作目录,每个目录可以检出不同的分支。在Git中,我们把通过git initgit clone创建的原始工作目录称为主工作树,而通过git worktree add命令创建的额外工作目录称为链接工作树。所有工作树共享同一个仓库数据(对象、引用等),但拥有各自独立的working directory、index和HEAD。

主要命令包括:

  • git worktree add <path> [<branch>] - 创建新的工作树
  • git worktree list - 列出所有工作树
  • git worktree remove <path> - 删除工作树
  • git worktree move <old-path> <new-path> - 移动工作树
  • git worktree lock/unlock <path> - 锁定/解锁工作树
  • git worktree prune - 清理残留的元数据

git work tree使用思路

相较于git stash,worktree的理念会显得更加优雅,我们还是以之前的例子,当我们在进行开发过程中遇到线上故障需要切换代码打补丁进行修复时,以work tree的使用方式,对应的策略为:

  1. 通过git worktree指令为release分支创建一个临时文件夹
  2. 通过ide工具打开对应文件夹下的release版本工程
  3. checkout出hotfix分支并进行修改
  4. 删除worktree文件夹,打开原有的idea继续feature的工作

可以看到,worktree给人一种用后即焚,一种更贴近于"回到手头的活儿"的感觉:

git worktree操作演示

我们现在就来实际操作演示一下,假设我们现在有一个release分支记录着我们发布的开发代码,对应代码如下比较简单,遍历数组让这些数值作为除数,因为从0开始遍历,所以潜藏着一个异常:

public static void main(String[] args) {
        SpringApplication.run(IdeaGitApplication.class, args);

        for (int i = 0; i < 10; i++) {
            System.out.println("num:"+(10/i));
        }
    }

又假设笔者现在正在feature分支开发,此时正在编写一个插入排序的工具类,对应的分支情况如下图,可以看到:

  1. target目录存在已编译好的字节码
  2. 新增了一个未提交的工具类SortUtils

此时,对应release版本在生产上出现问题需要紧急修复,我们就可以通过worktree指令进行切换修复,对应执行如下指令,即在/tmp文件夹下创建一个hotfix-release处理release分支的问题:

git worktree add /tmp/hotfix-release release

对应的我们就可以在tmp文件夹下看到这个release版本的工程了:

➜  /tmp ls |grep hotfix      
hotfix-release

同时我们进入hotfix-release这个工程,通过git branch就可以看到,当前的工程的版本确实是release版本:

随后我们就可以打开tmp文件夹下的工程checkout出hotfix进行修改并提交进行线上验证:

通过idea也可以看到,通过该工程修改后的hotfix版本确实已经成功提交到远程仓库了:

最后,我们进行用后即焚烧的工作,通过remove指令将该文件夹删除

git worktree remove /private/tmp/hotfix-release 

好的,我们tab切换回原来的工程就可以继续工作了,是不是很方便呢?

git worktree带来的便捷

从上面的演示可以看出,worktree可以非常快速的在指定目录下创建指定版本工程,对当前分支没有任何影响,我们也不用像git stash那样进行繁琐的保存和来回切换,对应编译的代码也不会消失。它是真正的做到了无缝衔接和用后即焚,是一种非常优雅的解决方案。

其他应用场景

除了紧急修复生产问题外,git worktree在日常开发中还有很多其他实用场景:

1. 并行功能开发

当需要同时开发多个功能特性时,可以为每个特性创建独立的工作树,避免频繁切换分支和重新编译:

# 为不同的功能特性创建独立的工作树
git worktree add ../feature-user-auth feature-user-auth
git worktree add ../feature-payment feature-payment

这样可以同时在多个功能上并行工作,每个工作树都有独立的编译环境和IDE配置。

2. 代码审查和测试

在进行代码审查时,可以创建一个专门的工作树来检出和测试他人的PR分支,而不影响当前的开发工作:

# 为审查PR创建专门的工作树
git worktree add ../review-pr-123 pr-123

3. 版本维护和发布

当需要维护多个版本时,可以为不同版本创建工作树,同时进行bug修复和功能开发:

# 为不同版本维护创建工作树
git worktree add ../release-v1.0 release-v1.0
git worktree add ../release-v2.0 release-v2.0

最佳实践

为了更好地使用git worktree,以下是一些推荐的最佳实践:

1. 目录组织和命名

  • 使用清晰的目录命名约定,例如:../hotfix-release../feature-user-auth
  • 将工作树目录放在主仓库目录的同级目录中,便于管理

2. 及时清理不再需要的工作树

定期清理已完成的工作树,避免占用过多磁盘空间:

# 移除工作树后记得清理残留的元数据
git worktree remove ../feature-completed
git worktree prune  # 清理残留的元数据

3. 使用git worktree list管理多个工作树

通过git worktree list命令可以查看所有工作树的状态:

git worktree list
# 输出示例:
# /path/to/main-repo  abc1234 [master]
# /path/to/feature    def5678 [feature-branch]

4. 移动工作树目录

如果需要移动工作树到其他位置,可以使用git worktree move命令:

git worktree move /old/path/to/worktree /new/path/to/worktree

5. 锁定可移动媒体上的工作树

对于存储在USB驱动器或网络共享上的工作树,使用锁定功能防止自动清理:

git worktree lock /path/to/worktree-on-usb
# 完成后解锁
git worktree unlock /path/to/worktree-on-usb

小结

git worktree是一个非常实用的Git功能,它允许我们在同一仓库中管理多个工作目录,每个工作目录可以独立检出不同的分支。相比传统的git stash方式,worktree具有以下优势:

  1. 保持编译状态:切换分支时不会丢失已编译的代码,避免重新编译的时间成本
  2. 并行开发:可以同时在多个分支上工作,提高开发效率
  3. 隔离环境:每个工作树都有独立的目录和状态,互不影响
  4. 灵活管理:支持创建、移动、删除工作树等操作

通过合理使用git worktree,我们可以更高效地处理紧急修复、并行开发、代码审查等多种场景。掌握其核心命令和最佳实践,能够显著提升我们的开发效率和工作体验。

我是 SharkChili ,Java 开发者,Java Guide 开源项目维护者。欢迎关注我的公众号:写代码的SharkChili,也欢迎您了解我的开源项目 mini-redis:github.com/shark-ctrl/…

为方便与读者交流,现已创建读者群。关注上方公众号获取我的联系方式,添加时备注加群即可加入。

参考

git-stash用法小结:www.cnblogs.com/tocy/p/git-…

【双语视界】我错怪了 Git Stash:www.bilibili.com/video/BV1Xv…

本文使用 markdown.com.cn 排版