我用git-worktree做什么?

我读Github上git-worktree的帖子。他们写道:

假设您正在一个名为feature的分支的Git存储库中工作,这时一个用户报告了master中的一个高度紧急的错误。首先,你创建一个带有新分支的链接工作树,hotfix,相对于master[…]签出。你可以修复错误,推送热修复,并创建一个拉请求。

当我在一个叫做feature的分支上工作时,master中报告了一些非常紧急的bug,我通常会把我正在做的东西藏起来,然后创建一个新的分支。当我完成时,我可以继续工作。这是一个非常简单的模型,我已经做了很多年了。

另一方面,使用git-worktree也有其局限性:

例如,不允许在两个链接的工作树中同时签出同一个分支,因为这将允许在一个工作树中提交的更改导致另一个工作树不同步。

为什么我要为一个已经解决的问题选择一个更复杂的工作流?

有没有关于git-worktree的任何事情是事先不能做的,这证明了这个全新的、复杂的特性是正确的?

102681 次浏览

我能看出这东西的用处。

如果您有一个运行很长时间的测试套件,想象一下,当您启动它时,它会有效地阻塞工作副本,直到测试完成。在这些测试期间切换分支会以一种难以理解的方式破坏它们。

因此,有了git-worktree,我可以为另一个分支启动第二个想法,在那里工作。

另外,当我切换到其他分支做一些快速调查时,我的IDE认为很多文件突然发生了变化,并将索引所有这些更改,只是在我切换回来时必须重新索引它们。

第三个用例是使用除git-diff以外的其他工具在两个目录之间(而不是两个分支)进行文件比较,比如正常的diff

tl;dr:无论什么时候你想同时签出两个工作树,git-worktree都是一种快速且节省空间的方法。

如果你创建另一个工作树,回购的大部分(即.git)将被共享,这意味着如果你在一个工作树中创建一个分支或获取数据,它也可以从你拥有的任何其他工作树中访问。假设你想在分支foo上运行你的测试套件,而不需要把它推到某个地方来克隆它,并且你想避免在本地克隆你的回购的麻烦,使用git-worktree是在一个单独的地方创建一个新的状态签出的好方法,无论是临时的还是永久的。就像克隆一样,当你完成它时,你所需要做的就是删除它,对它的引用将在一段时间后被垃圾收集。

对我来说,git工作树是很长一段时间以来最大的改进。我在企业软件开发部门工作。在那里,你必须维护像3年前发布的那样的旧版本是很常见的。当然,每个版本都有一个分支,这样您就可以轻松地切换到它并修复错误。然而,切换的代价是昂贵的,因为与此同时,您完全重构了存储库并可能构建了系统。如果您切换,您的IDE将会疯狂地尝试适应项目设置。

使用工作树,您可以避免不断的重新配置。使用worktree将这些旧的分支签出到单独的文件夹中。对于每个分支,都有一个独立的IDE项目。

当然,这在过去可以通过多次克隆回购来实现,这一直是我到目前为止的方法。然而,这也意味着浪费硬盘空间,更糟糕的是需要多次从回购中获取相同的更改。

  1. 文件系统中同时需要多个工作树是有原因的。

    • 操作签出文件需要在其他地方进行更改(例如。编译/测试)

    • 通过普通的diff工具区分文件

    • 在合并冲突期间,我经常想通过源代码导航,因为它在源端解决文件中的冲突。

    • 如果您需要经常来回切换,就会浪费签出和重新签出的时间,而您不需要在多个工作树中执行这些操作。

    • 通过git存储在分支之间切换精神上下文的精神成本实际上是无法测量的。有些人发现,通过简单地从不同目录打开文件来存储不存在的东西是有精神成本的。

    • 李< / ul > < / >
    • 有些人会问“为什么不做多个本地克隆”。的确,使用“——local”标志,您不必担心占用额外的磁盘空间。这(或类似的想法)是我到目前为止所做的。与本地克隆相比,链接工作树的功能优势如下:

      1. 对于本地克隆,您的额外工作树(在本地克隆中)根本无法访问原始分支或上游分支。克隆中的“origin”将与第一个克隆中的“origin”不同。

        • 运行git log @{u}..git diff origin/feature/other-feature可能非常有用,但它们要么不再可能,要么更加困难。这些想法在技术上是可以通过各种各样的解决方法在本地克隆上实现的,但是通过链接工作树,你可以做的每个解决方法都更好或更简单。
        • 李< / ul > < / >
        • 您可以在工作树之间共享引用。如果您想从另一个本地分支比较或借用更改,现在就可以了。

        • 李< / ol > < / >

一个明显的用法是同时比较不同版本的行为(不是源)——例如,一个网站的不同版本或仅仅是一个网页。

我在当地试过。

  • 创建一个目录page1

  • 在里面创建目录srcgit init

  • src中创建带有少量内容的page1.html并提交。

  • $ git branch ver0

  • $ git worktree add ../V0 ver0

  • src master中添加更多文本到page1.html并提交。

  • $ git branch sty1

  • sty1分支中编辑page1.html(添加一些独特的CSS样式)并添加提交。

  • $ git worktree add ../S1 sty1

您现在可以使用网页浏览器同时打开和查看这3个版本:

  • ..\page1\src\page1.html // git的当前值

  • ..\page1\V0\page1.html //初始版本

  • ..\page1\S1\page1.html //实验风格的版本

我最初是在想这些花哨的工作树可以用来做什么时偶然发现这个问题的。从那以后,我将它们整合到我的工作流程中,尽管我最初持怀疑态度,但我逐渐发现它们相当有用。

我在一个相当大的代码库上工作,这需要相当长的时间来编译。我通常在我的机器上有当前的开发分支,以及我当前正在工作的特性分支,再加上主分支,它代表了活动系统的当前状态。

对我来说,最大的好处之一显然是,每次切换分支(即工作树)时,我都不必重新编译整个东西。一个很好的副作用是,我可以去开发工作树,在那里做一些事情,为我当前的特性分支更改目录,然后重新建立它,而不需要先拉。

我有一个相当不寻常的:我在同一台机器上做Windows和Linux开发。我的Windows盒子里有一个运行Linux的VirtualBox。VirtualBox挂载一些Windows目录,并直接在Linux机器内部使用它们。这让我可以使用Windows来管理文件,但可以在Linux中构建。这是一个跨平台的项目,所以它构建在Windows和Linux上,使用相同的目录结构。

问题是,Linux和Windows的构建系统在同一个目录下使用时会互相崩溃;有一些复杂的构建步骤用于下载使用相同目录名的库等。构建系统的Windows版本下载特定于Windows的库,而构建系统的Linux版本下载特定于Linux的库。

在理想的情况下,构建系统将被修改,以便Windows &Linux可以在目录中共存,但是现在,这个问题是通过工作树来解决的。“Linux”文件夹可以生成特定于Linux的构建构件,“Windows”文件夹可以生成特定于Windows的构建构件。虽然这不是一个理想的解决方案,但在等待构建系统错误得到解决时,这是一个很好的权宜之计。

诚然,工作树并不是为此而设计的;我必须把Windows版本和Linux版本放在不同的分支上,尽管我真的希望它们放在同一个分支上。尽管如此,它还是在发挥作用,并且是一个不同寻常的工作树拯救世界的例子。

在我的新项目中,我创建了一个功能。 但一些规格失败了。为了将结果与master进行比较,我创建了work-tree repo。我在运行代码中一步一步地比较结果,直到了解哪里出了问题

我正在使用git worktree进行机器学习开发。

我有一个主要的功能代码,然后我想拆分不同实验的分支(不同的算法和不同的超参数)。git worktree允许我将"与专门用于不同算法的不同版本的代码集成在一起。在运行所有的培训工作后,我评估最终的指标,并合并以掌握最好的分支/模型。

我最喜欢的,也可能是每个人都应该使用git worktree的最常见用例是检查队友的拉请求,同时仍然在主工作树中处理您的更改。😎