比较了Git中四种切换分支方式的优缺点。任何大量使用Git的人都会使用某种形式的上下文切换。有时这只会给您的工作流程增加少量的开销,但有时,这可能是一种痛苦的经历。让我们用下面的例子来讨论一些常见的上下文切换策略的优缺点:假设你在一个名为feature-X的分支中工作。你刚刚发现你需要解决一个不相关的问题。这不能在feature-X分支中完成。你需要在一个新的分支feature-Y中完成这项工作。场景1:暂存+分支解决此问题的最常见工作流程可能如下所示:停止分支上的工作feature-Xgitstashgitcheckout-bfeature-Yorigin/mainTinkeraroundandfixfeature-Ygitcheckoutfeature-X或gitswitch-gitstashpop继续使用feature-X优点:这种方法的优点在于它是一个相当简单的工作流程,可以进行简单的更改。它可以很好地工作,特别是对于小型存储库。缺点:使用此工作流程时,一次只能有一个工作区。此外,根据存储库的状态,使用暂存可能很麻烦。解决方案2:WIPCommit+Branch这种解决方案与上一个非常相似,但它使用WIP(WorkinProgress)提交而不是暂存。当您准备好切换回来时,gitresetHEAD~1不会弹出暂存区,而是扩展WIP提交,您可以自由地继续,就像之前的方案一样,但不会触及暂存区。Stopworkingonbranchfeature-Xgitadd-u(只添加修改和删除的文件)gitcommit-m"WIP"gitcheckout-bfeature-Yorigin/masterTinkeraroundtosolvetheproblemoffeature-Ygitcheckoutfeature-X或gitswitch-gitresetHEAD~1优点:对于简单的更改,这是一个简单的工作流程,也适用于小型存储库。您不需要使用暂存。缺点:任何时候只能有一个工作空间。此外,如果您或您的代码审阅者不够小心,WIP提交可能会合并到最终产品中。使用此工作流程时,您永远不应该考虑将--hard添加到gitreset。如果你不小心这样做了,你应该能够使用gitreflog恢复提交,但你最好完全避免这种情况发生,否则你会听到心碎的声音。场景3:克隆新存储库在该解决方案中,不是创建新分支,而是为每个新功能分支创建存储库的新克隆。优点:您可以同时在多个工作区工作。您不需要gitstash或WIP提交。缺点:需要考虑回购大小,因为这会占用大量磁盘空间(浅克隆可以帮助解决这种情况,但它们可能并不总是合适的。)此外,您的回购克隆将相互不可知。由于它们不相互跟踪,您必须手动跟踪克隆的源存储库。如果你需要githooks,你需要为每个新克隆设置它们。场景4:gitworktree要使用此解决方案,您可能需要了解gitaddworktree。如果您不熟悉Git中的工作树,请不要难过。许多人多年来一直不知道这个概念。什么是工作树?将工作树视为存储库中属于项目的文件。本质上,这是一个工作区。您可能没有意识到您已经在使用工作树。当你开始使用Git时,你会自动得到你的第一棵工作树。$mkdir/tmp/foo&&cd/tmp/foo$gitinit$gitworktreelist/tmp0000000[master]正如您在上面的代码中看到的,您甚至在第一次提交之前就有了一个工作树。继续尝试向您的项目添加另一个工作树。添加工作树要添加新的工作树,您需要提供:磁盘上的位置要添加的分支的分支名称$gitclonehttps://github.com/oalders/http-browserdetect.git$cdhttp-browserdetect/$gitworktreelist/Users/olaf/http-browserdetect90772ae[master]$gitworktreeadd~/trees/oalders/feature-X-boalders/feature-Xorigin/master$gitworktreeadd~/trees/oalders/feature-Y-boalders/feature-Ye9df3c555e96b3f1$gitworktreelist/Users/olaf/http-browserdetect90772ae[master]/Users/olaf/trees/oalders/feature-X90772ae[oalders/feature-X]/Users/olaf/trees/oalders/feature-Ye9df3c5[oalders/feature-Y]与大多数其他Git命令一样,您需要在存储库路径下使用此命令。一旦创建了工作树,就会有一个隔离的工作环境。Git存储库跟踪工作树在磁盘上的位置。如果Git挂钩已在父存储库中设置,则它们在工作树中也可用。请注意,每个工作树仅使用父存储库磁盘空间的一小部分。在这种情况下,工作树只需要原始磁盘空间的三分之一左右。这非常适合缩放。如果您的存储库达到千兆字节级别,您将非常感谢工作树节省的硬盘空间。$du-sh/Users/olaf/http-browserdetect2.9M$du-sh/Users/olaf/trees/oalders/feature-X1.0M优点:您可以同时在多个工作区中工作。您不需要使用暂存。Git跟踪所有工作树。您不需要设置Git挂钩。这也比gitclone更快,并且可以节省网络流量,因为您可以在飞行模式下执行此操作。您还可以更有效地使用磁盘空间,而无需求助于浅克隆。缺点:这是需要学习和记忆的新事物,但如果您能养成使用此功能的习惯,将会获得丰厚的回报。ExtraTips清除工作树的方法有很多种,最流行的方法是使用Git删除工作树:gitworktreeremove/Users/olaf/trees/oalders/feature-X如果你喜欢RM大法,你也可以使用rm-rf删除工作树。rm-rf/Users/olaf/trees/oalders/feature-X然而,如果你这样做,你可能需要使用gitworktreeprune来清理任何剩余的文件。或者你可以暂时跳过清理,这将在将来的某个时候由gitgc自己完成。要记住的事情如果您打算尝试gitworktree,请记住以下几点:删除工作树不会删除分支。可以在工作树中切换分支。您不能同时在多个工作树中签出相同的分支。与其他命令一样,gitworktree需要从存储库中运行。您可以同时拥有许多工作树。要创建从同一个本地存储库检出的工作树,否则它们将相互不可知。关于gitrev-parse的最后一点注意事项:使用gitworktree时,存储库根所在的位置可能取决于上下文。幸运的是,gitrevparse可以让你区分这两者。找到父仓库的根目录:gitrev-parse--git-common-dir找到你当前所在仓库的根目录,执行:gitrev-parse--show-toplevel根据你的需要选择最好的方法就像很多事情一样,TIMTOWDI(条条大路通罗马,有不止一种方法可以做到)。找到适合您需求的工作流程很重要。您的需求可能因手头的问题而异。也许您偶尔会发现自己使用gitworktree作为版本控制工具箱中的一个方便工具。