不用再反复 stash:用 Git Worktree 同时开发多个分支
很多开发者都遇到过这样的场景你正在一个功能分支上写代码修改了十几个文件程序暂时还跑不起来也不适合提交。就在这时同事突然告诉你线上出现了一个紧急问题需要马上从main分支拉出一个 Hotfix。按照传统做法你可能会先执行gitstashgitswitch maingitpullgitswitch-chotfix/xxx修复完成以后再回到原来的分支gitswitch feature/xxxgitstash pop如果只是偶尔操作一次这种方式倒也能用。但当你同时维护多个 PR、审查别人代码、修复线上问题或者需要在不同版本之间反复测试时频繁执行stash和switch很容易让工作现场变得混乱。Git 其实提供了一个非常适合这种场景的功能Git Worktree。内容结构概览本文将介绍Git Worktree 是什么它与git switch、git stash和重新clone有什么区别如何创建、查看和删除 Worktree如何在开发新功能的同时处理紧急 Bug多个 PR、代码审查和版本测试中的使用方法常见问题与容易踩到的坑。一、Git Worktree 是什么Git Worktree 可以让一个 Git 仓库同时拥有多个工作目录每个目录分别检出不同的分支。普通情况下一个仓库只有一个代码目录my-project/这个目录某一时刻只能显示一个分支。你从main切到feature/login后目录中的代码也会随之变化。使用 Worktree 后可以变成这样code/ ├── my-project/ # main ├── my-project-feature-login/ # feature/login └── my-project-hotfix/ # hotfix/payment-timeout三个目录属于同一个 Git 仓库但分别检出了三个不同分支。你可以在第一个目录运行稳定版代码在第二个目录继续开发新功能同时在第三个目录修复线上问题。它们彼此独立不需要来回切换分支也不需要把未完成的代码临时藏进stash。Git 官方把最初通过git clone或git init创建的工作目录称为main worktree后来通过git worktree add创建的目录称为linked worktree。一个普通仓库可以拥有一个主工作区以及零个或多个附加工作区。(Git)二、Worktree 到底共享什么Worktree 并不是重新复制出一份完整的 Git 仓库。多个 Worktree 会共享Git 提交历史对象数据库分支和标签引用远程仓库信息大部分 Git 配置。但每个 Worktree 都拥有自己的工作目录当前检出的分支HEAD暂存区也就是 index未提交修改未跟踪文件。可以把它理解为所有工作区共用一个仓库档案室但每个工作区都有自己的桌面。共享的 Git 仓库 commits / objects / refs │ ┌──────────────┼──────────────┐ │ │ │ Worktree 1 Worktree 2 Worktree 3 main feature hotfix 独立文件 独立文件 独立文件 独立 HEAD 独立 HEAD 独立 HEAD 独立 index 独立 index 独立 indexGit 官方文档也说明不同 Worktree 的HEAD等状态彼此独立而普通分支引用通常由各个 Worktree 共享。(Git)三、为什么不直接重新 clone 一份当然可以重新 clonegitclone gitgithub.com:example/project.git project-maingitclone gitgithub.com:example/project.git project-featuregitclone gitgithub.com:example/project.git project-hotfix但这样会得到三套独立仓库project-main/.git/ project-feature/.git/ project-hotfix/.git/对于大型仓库这意味着Git 对象可能被重复存储每个仓库都要单独执行fetchRemote、Hook 和部分配置可能不一致本地仓库数量越来越多很难管理创建新环境的速度比 Worktree 慢。Worktree 复用的是同一套 Git 仓库数据因此创建速度通常很快也更加节省空间。不过要注意Worktree 只共享 Git 数据并不会共享所有构建产物。例如下面这些目录通常仍然是各自独立的node_modules/ target/ dist/ vendor/ .venv/因此两个大型 Rust Worktree 仍可能分别生成自己的target目录占用较多磁盘空间。四、查看当前已有的 Worktree进入任意一个工作区执行gitworktree list可能得到/Users/mac/code/my-project a1b2c3d [main] /Users/mac/code/my-project-login d4e5f6g [feature/login] /Users/mac/code/my-project-hotfix h7i8j9k [hotfix/payment-timeout]每一行分别表示工作目录路径 当前提交 当前分支查看更详细的信息gitworktree list--verbose需要在 Shell 脚本中处理输出时可以使用gitworktree list--porcelain五、为已有分支创建 Worktree假设仓库中已经存在feature/login当前主仓库位于~/code/my-project可以执行cd~/code/my-projectgitworktreeadd\../my-project-feature-login\feature/loginGit 会创建新目录~/code/my-project-feature-login并在里面检出feature/login。现在可以直接进入新目录cd../my-project-feature-logingitstatus输出会显示On branch feature/login此时主目录仍然保持原来的分支和所有未提交修改完全不会受到影响。六、创建新分支时同时创建 Worktree这是最常用的方式。假设要从最新的origin/main创建一个 Hotfixgitfetch origingitworktreeadd\-bhotfix/payment-timeout\../my-project-payment-timeout\origin/main这条命令同时完成三件事基于origin/main创建hotfix/payment-timeout创建目录../my-project-payment-timeout在新目录中检出该分支。它的通用格式是gitworktreeadd-b新分支名新目录起始提交起始提交可以是main origin/main release/v2 v2.1.0 某个 commit hash例如gitworktreeadd\-bfix/readme-typo\../my-project-fix-readme\origin/main我通常建议明确写出origin/main而不是省略起点。这样可以避免本地main很久没有更新导致新分支建立在旧提交上。七、实战开发未完成时紧急修复 Bug假设你正在ethereumjs-monorepo中开发一个功能当前分支有不少未提交修改gitstatus输出类似On branch feature/trie-refactor Changes not staged for commit: modified: packages/trie/src/trie.ts modified: packages/trie/test/trie.spec.ts现在你需要基于上游最新代码修复一个 README typo。不需要stash直接执行cd~/code/ethereumjs-monorepogitfetch upstreamgitworktreeadd\-bfix-util-readme-typo\../ethereumjs-fix-util-readme-typo\upstream/master如果项目默认分支是main则改成gitworktreeadd\-bfix-util-readme-typo\../ethereumjs-fix-util-readme-typo\upstream/main进入新的工作区cd../ethereumjs-fix-util-readme-typo完成修改gitaddpackages/util/README.mdgitcommit-mdocs(util): fix README typogitpush-uorigin fix-util-readme-typo此时目录结构可能是~/code/ ├── ethereumjs-monorepo/ │ └── feature/trie-refactor保留未提交修改 │ └── ethereumjs-fix-util-readme-typo/ └── fix-util-readme-typo准备提交 PR两个工作区互不干扰。修复完成后你可以在浏览器里提交 PR也可以使用 GitHub CLIghprcreate然后回到原来的目录继续开发cd../ethereumjs-monorepo不需要执行gitstashgitswitchgitstash pop也不需要重新启动或恢复原来分支的工作状态。八、PR 合并后如何清理先确认工作区中没有需要保留的修改cd../ethereumjs-fix-util-readme-typogitstatus然后回到主仓库或者任意其他 Worktreecd../ethereumjs-monorepo删除附加工作区gitworktree remove../ethereumjs-fix-util-readme-typo注意git worktree remove会删除对应的工作目录但不会自动删除分支。如果本地分支已经合并可以继续执行gitbranch-dfix-util-readme-typo清理远程已经删除的跟踪引用gitfetch--pruneorigin完整清理流程如下gitworktree remove../ethereumjs-fix-util-readme-typogitbranch-dfix-util-readme-typogitfetch--pruneoriginGit 官方建议使用git worktree remove删除附加 Worktree而不是直接删除目录。(Git)九、为什么不能直接执行 rm -rf下面这种操作并不推荐rm-rf../my-project-hotfix因为目录虽然被删除了但主仓库内部可能仍然保留该 Worktree 的管理信息。这时执行gitworktree list可能仍会看到已经不存在的工作区。可以使用gitworktree prune清理失效记录。正式删除时最好始终使用gitworktree remove工作区路径如果目录已经被手动删除再执行gitworktree prune查看哪些记录将被清理但暂时不执行gitworktree prune --dry-run--verbose十、工作区中有未提交代码时怎么办假设某个 Worktree 中仍然存在修改gitstatus显示Changes not staged for commit此时执行gitworktree remove../my-project-hotfixGit 通常会拒绝删除因为这会导致未提交内容丢失。正确做法是先决定如何处理这些代码方案一提交代码gitadd.gitcommit-mwip: preserve current work方案二暂存修改gitstash push-u方案三确认不再需要强制删除gitworktree remove--force../my-project-hotfix--force可能造成代码永久丢失使用前应确认该目录中没有任何需要保留的文件。十一、一个分支不能同时在两个 Worktree 中检出假设main已经在主工作区中使用gitworktree list输出/Users/mac/code/my-project a1b2c3d [main]此时再执行gitworktreeadd../my-project-main-copy mainGit 通常会拒绝并提示fatal: main is already checked out这是为了防止两个工作目录同时修改同一个分支指针。假设你只是想基于main做实验应该创建一个新分支gitworktreeadd\-bexperiment/new-parser\../my-project-new-parser\main或者创建一个 detached HEAD 工作区gitworktreeadd\--detach\../my-project-main-test\main默认情况下Git 会阻止同一个分支同时出现在多个 Worktree 中。(Git)十二、用 Worktree 审查别人的 PRWorktree 不仅适合开发也非常适合代码审查。假设要审查 GitHub PR#1234可以先拉取 PR 分支gitfetch origin pull/1234/head:review/pr-1234然后创建 Worktreegitworktreeadd\../my-project-review-1234\review/pr-1234进入该目录cd../my-project-review-1234在不影响当前开发环境的情况下运行gotest./...或者cargotest审查结束后cd../my-projectgitworktree remove../my-project-review-1234gitbranch-Dreview/pr-1234这样每个 PR 都可以拥有独立的测试环境不需要频繁切换当前仓库的分支。十三、同时维护多个 PR对于经常给开源项目提交贡献的人Worktree 非常实用。假设正在处理三个 PRfix/readme-typo fix/parser-comment test/new-analyzer可以分别创建gitfetch upstreamgitworktreeadd\-bfix/readme-typo\../project-fix-readme\upstream/maingitworktreeadd\-bfix/parser-comment\../project-fix-parser-comment\upstream/maingitworktreeadd\-btest/new-analyzer\../project-new-analyzer\upstream/main目录结构变成code/ ├── project/ ├── project-fix-readme/ ├── project-fix-parser-comment/ └── project-new-analyzer/每个目录可以分别打开一个终端或 IDE 窗口。等待第一个 PR 的 CI 时可以直接进入第二个目录继续工作cd../project-fix-parser-comment这种方式比不断switch分支更加自然也不容易把不同 PR 的文件混在一起。不过同时提交多个 PR 时仍应注意项目维护者的体验。相关的小修改最好合并处理不要为了增加提交数量而拆成大量价值很低的 PR。十四、测试旧版本或历史提交Worktree 也很适合临时查看某个版本。例如需要测试v1.5.0gitworktreeadd\--detach\../my-project-v1.5.0\v1.5.0进入该目录cd../my-project-v1.5.0完成编译或测试后删除cd../my-projectgitworktree remove../my-project-v1.5.0因为使用了--detach这个工作区没有绑定普通分支适合复现旧版本 Bug比较两个版本的性能编译某个 Tag检查历史提交执行临时实验。十五、移动 Worktree不要优先使用普通的mv命令移动工作区。推荐执行gitworktree move\../my-project-hotfix\../worktrees/my-project-hotfix如果已经使用 Finder 或mv手动移动了目录导致 Git 的路径记录失效可以尝试gitworktree repair也可以指定路径gitworktree repair../worktrees/my-project-hotfix当前 Git Worktree 命令提供了move和repair分别用于移动工作区和修复工作区关联。(Git)十六、外置硬盘上的 Worktree有时 Worktree 放在移动硬盘、网络磁盘或者临时挂载目录中。磁盘没有挂载时Git 可能认为该工作区已经失效并在后续清理中删除管理记录。可以锁定该 Worktreegitworktree lock\--reasonStored on external SSD\/Volumes/SSD/my-project-release解除锁定gitworktree unlock\/Volumes/SSD/my-project-release日常放在本机固定目录中的 Worktree 通常不需要执行lock。这个功能主要用于路径可能暂时不可访问的工作区。Git 官方命令集中也包含lock和unlock。(Git)十七、推荐的目录组织方式不建议把 Worktree 建在主仓库内部my-project/ └── worktrees/ └── feature-login/这样可能导致IDE 重复索引大量文件搜索结果出现多个版本文件监听器监控额外目录构建工具误扫描另一个工作区主仓库出现复杂的未跟踪目录。更推荐使用并列目录~/code/ ├── ethereumjs-monorepo/ ├── ethereumjs-fix-readme/ └── ethereumjs-trie-refactor/或者统一放在专门目录~/code/ ├── ethereumjs-monorepo/ └── worktrees/ └── ethereumjs/ ├── fix-readme/ ├── trie-refactor/ └── review-pr-1234/对应命令gitworktreeadd\-bfix/readme\~/code/worktrees/ethereumjs/fix-readme\upstream/main目录名称不必与分支名完全相同但保持一致会更容易管理。十八、Worktree、stash 和重新 clone 怎么选三种方式分别适合不同场景。场景推荐方式临时离开当前分支几分钟git stash两个任务需要并行开发Worktree同时运行新旧两个版本Worktree审查多个 PRWorktree复现某个历史版本问题Worktree需要完全不同的 Remote 和 Git 配置重新 clone要破坏性修改.git数据重新 clone多个 AI Agent 同时处理不同任务Worktree简单来说stash是临时把桌面收起来Worktree 是再准备一张桌子重新 clone 则是再租一个办公室。十九、常用命令速查查看全部 Worktreegitworktree list为已有分支创建 Worktreegitworktreeadd目录已有分支创建新分支并创建 Worktreegitworktreeadd-b新分支目录起点创建 detached HEAD 工作区gitworktreeadd--detach目录提交或标签删除 Worktreegitworktree remove目录强制删除gitworktree remove--force目录移动 Worktreegitworktree move旧路径新路径清理失效记录gitworktree prune修复关联gitworktree repair锁定外置工作区gitworktree lock目录解除锁定gitworktree unlock目录二十、总结Git Worktree 解决的问题并不复杂它允许同一个 Git 仓库同时在多个目录中检出不同分支。过去我们常常需要在一个目录中不断执行gitstashgitswitchgitstash pop使用 Worktree 后很多时候只需要切换目录cd../project-featurecd../project-hotfix每个任务都有自己的目录、分支、暂存区和未提交修改。正在运行的开发服务器、IDE 窗口以及测试环境也可以继续保持不需要因为切换分支而反复重启。它尤其适合同时维护多个 PR开发新功能时紧急修复 Bug审查其他人的代码对比多个版本同时运行多个测试环境让多个自动化工具或 AI Agent 并行工作。掌握 Worktree 后Git 分支不再只是需要不断切换的状态而可以变成多个真正并行存在的工作空间。对于经常参与大型开源项目、同时维护多个分支的开发者来说这可能是 Git 中最值得养成使用习惯的功能之一。参考资料Git 官方git-worktree文档对 Worktree 的创建、查看、删除、移动、清理、锁定和修复等行为给出了完整定义。(Git)

相关新闻

函数指针、指针函数与结构体的基础知识与应用

函数指针、指针函数与结构体的基础知识与应用

一、指针函数 1.概念 本质是指针&#xff0c;返回值是指针 2.定义格式 数据类型 *函数名(参数列表) { 函数体&#xff1b; return 地址&#xff1b; } 3.应用实例 #include<stdio.h> #include<stdlib.h> #include<string.h> char *fun() {// char p[…

2026/7/22 5:07:53 阅读更多 →
嵌入式AI部署---基于RK3588运行yolov5(2)

嵌入式AI部署---基于RK3588运行yolov5(2)

前言&#xff1a;在上篇博客中撰写了关于yolov5在RK3588上运行的流程&#xff0c; 在学习的过程中发现后处理很难&#xff0c;我一直不理解输出结果是如何存储的&#xff0c;它比较抽象&#xff0c;对于我来讲很难理解&#xff0c;经过一段时间的学习&#xff0c;有了一个比较好…

2026/7/20 20:27:11 阅读更多 →
Netflix-4K-DDplus字幕优化技巧:如何调整字幕样式和关闭imsc字幕

Netflix-4K-DDplus字幕优化技巧:如何调整字幕样式和关闭imsc字幕

Netflix-4K-DDplus字幕优化技巧&#xff1a;如何调整字幕样式和关闭imsc字幕 【免费下载链接】netflix-4K-DDplus MicrosoftEdge(Chromium core) extension to play Netflix in 4K&#xff08;Restricted&#xff09;and DDplus audio 项目地址: https://gitcode.com/gh_mirr…

2026/7/20 20:27:11 阅读更多 →

最新新闻

Unity Android项目性能优化全攻略

Unity Android项目性能优化全攻略

1. 为什么Unity Android项目需要专门优化&#xff1f;移动端与PC平台存在本质差异&#xff0c;Android设备更是性能表现参差不齐。我在2018年接手过一个跑在千元机上的AR项目&#xff0c;默认Quality Settings下帧率直接跌破10FPS。通过系统优化后&#xff0c;中端设备也能稳定…

2026/7/22 6:09:06 阅读更多 →
LuaDec51反编译实战:从字节码还原逻辑的完整指南

LuaDec51反编译实战:从字节码还原逻辑的完整指南

1. 项目概述&#xff1a;为什么我们需要Lua反编译&#xff1f;在游戏开发、嵌入式系统、甚至是一些服务端应用中&#xff0c;Lua脚本的身影无处不在。它轻量、高效、易于嵌入&#xff0c;是许多开发者实现热更新和逻辑分离的首选。然而&#xff0c;当你拿到一个只有编译后的.lu…

2026/7/22 6:09:06 阅读更多 →
PPA框架:大语言模型推理增强的系统化方法与实践

PPA框架:大语言模型推理增强的系统化方法与实践

这次我们来看一个在大语言模型推理中提升效果和稳定性的方法——Partition, Prompt, Aggregate&#xff08;PPA&#xff09;框架。这个框架的核心思路不是训练新模型&#xff0c;而是通过巧妙的提示工程和结果聚合&#xff0c;让现有模型发挥更好性能。如果你经常遇到大模型回答…

2026/7/22 6:09:06 阅读更多 →
电商 Agent 安全场景:自动下单与优惠券被智能薅羊毛

电商 Agent 安全场景:自动下单与优惠券被智能薅羊毛

电商 Agent 安全场景&#xff1a;自动下单与优惠券被智能薅羊毛 一、当 Agent 替你花钱&#xff1a;电商自动化里的对抗新战场 电商 Agent 的卖点&#xff0c;是"你说一句&#xff0c;它帮你下单、凑单、用券"。但这套能力一旦对外开放&#xff0c;就进入了黑产的视野…

2026/7/22 6:09:06 阅读更多 →
安装VMware Workstation Pro;创建xp虚拟机,安装应用

安装VMware Workstation Pro;创建xp虚拟机,安装应用

安装VMware Workstation Pro 下载安装包 迅雷 分享文件&#xff1a;VMware-workstation-full-17.6.4-24832109.exe 链接&#xff1a;https://pan.xunlei.com/s/VOy2ybeOX0yX6imMHhCZRp6VA1?pwdshgj# 官网 地址&#xff1a;https://www.vmware.com/products/desktop-hyper…

2026/7/22 6:09:06 阅读更多 →
“编程第三时代“,测试人该怎么接招

“编程第三时代“,测试人该怎么接招

前言2026年6月&#xff0c;Cursor CEO Michael Truell在一次访谈中抛出一个判断&#xff1a;AI编程正在进入“第三时代”——云端智能体不再只是补全代码的助手&#xff0c;而是具备自主规划、编码、调试乃至交付能力的“数字工程师”。与此同时&#xff0c;《2026春季Cursor开…

2026/7/22 6:08:06 阅读更多 →

日新闻

TI DSP系统配置模块SYSCFG详解:中断机制与主设备优先级配置实战

TI DSP系统配置模块SYSCFG详解:中断机制与主设备优先级配置实战

1. 项目概述与SYSCFG模块的核心价值在嵌入式系统&#xff0c;尤其是像TI C6000系列这样的高性能DSP开发中&#xff0c;我们常常会与芯片手册里那些密密麻麻的寄存器打交道。很多开发者可能更关注算法实现、内存优化或者外设驱动&#xff0c;但对于一个稳定、高效的系统而言&…

2026/7/22 0:00:26 阅读更多 →
微信Server酱:高到达率的应急通知方案实践

微信Server酱:高到达率的应急通知方案实践

1. 为什么我们需要"最次"的通知方案&#xff1f; 在数字化协作环境中&#xff0c;消息通知系统的重要性不言而喻明。但现实情况是&#xff0c;企业级通知方案往往需要复杂的API对接&#xff08;如企业微信、钉钉、飞书&#xff09;&#xff0c;个人开发者的小项目又经…

2026/7/22 0:00:26 阅读更多 →
甲方要的“简洁“PPT,到底是简洁还是省事?

甲方要的“简洁“PPT,到底是简洁还是省事?

甲方说"简洁一点"&#xff0c;乙方听到的是"少做几页"。甲方说"不要太复杂"&#xff0c;乙方理解成"别放图表了"。结果交过去&#xff0c;甲方说"我说的简洁不是这个意思"。"简洁"这个词在PPT语境里&#xff0c;是…

2026/7/22 0:00:26 阅读更多 →

周新闻

Go语言静态资源打包方案对比与实践指南

Go语言静态资源打包方案对比与实践指南

1. 项目背景与核心需求在Go语言开发中&#xff0c;我们经常需要处理静态资源文件的打包问题。无论是Web应用的模板文件、前端资源&#xff0c;还是配置文件、证书等&#xff0c;都需要随程序一起分发。传统做法是将这些文件与编译后的二进制文件放在同一目录下&#xff0c;但这…

2026/7/21 8:48:31 阅读更多 →
Go语言实现高性能LDAP认证服务的架构与实践

Go语言实现高性能LDAP认证服务的架构与实践

1. 项目背景与核心价值LDAP&#xff08;轻量级目录访问协议&#xff09;作为企业级身份认证的黄金标准&#xff0c;已经服务了超过80%的财富500强公司。我在金融科技领域实施统一认证体系时&#xff0c;发现传统Java方案存在启动慢、内存占用高等痛点。而Go语言凭借其协程并发模…

2026/7/21 5:34:47 阅读更多 →
【AI面试官实战指南】:用ChatGPT模拟10类高频技术岗面试,3天提升应答精准度92%

【AI面试官实战指南】:用ChatGPT模拟10类高频技术岗面试,3天提升应答精准度92%

更多请点击&#xff1a; https://intelliparadigm.com 第一章&#xff1a;AI面试官实战指南的核心价值与适用场景 AI面试官并非替代人类HR的“黑箱工具”&#xff0c;而是以可解释、可审计、可迭代的方式&#xff0c;赋能招聘全链路的关键基础设施。其核心价值在于将主观经验沉…

2026/7/21 8:25:39 阅读更多 →

月新闻