让一个 git 分支“变老”会有什么危害吗?

6
我听说过使用Git的分支-每个特性工作流程,也读过一些为什么这可能是一个不好的想法 的原因。
我的真正问题是:如果我只开发一个小功能(比如一个简单的正则表达式时间解析器),在将该分支合并回主干后,该分支会发生什么(或者应该发生什么)?它只是无所事事吗?由于我为这个非常特定的功能创建了它,我想不到我必须回去使用这个分支的理由。我应该如何标记这个分支已经废弃了,还是我只是继续向前并忘记它呢?
谢谢。

3
你完成后可以删除该分支,对吗?(git branch -d - Platinum Azure
1
是的,git branch -d 命令总是安全的,它不会丢失任何可能随后被垃圾回收的修订版本。git branch -D 命令将删除包含未在其他地方找到的更改的分支。这在确定方法完全行不通时非常有用。考虑到磁盘空间的便宜,您应该尽量避免使用 git branch -D 命令。 - tialaramex
也许这样记忆会更加清晰:分支只是指向提交的指针。一旦你完成了对分支的工作,并合并了该提交,你就不再需要指向它了。 - Cascabel
啊,@Platinum 和 @tialaramex,我想那就是我的困惑所在——我之前使用了 -D 开关,它警告我可能会丢失提交。我没有意识到还有一个 -d,虽然我不确定为什么,因为大多数选项都有小写变体。吸取教训!(看看它能坚持多久...) - Wayne Werner
5个回答

14

在使用功能分支时,我喜欢保留一个事实,即一个功能是在一个分支中开发完成并合并。这使得浏览历史记录变得更加容易。它将更改按特性或错误分组,使得更容易知道最重要的事情:为什么进行了更改。

这就是为什么在合并时,我故意使用 git merge --no-ff 禁用快进合并。这样可以在历史记录中保留分支的结构。然后,我就可以自由地删除分支标签 (git branch -d branch_name),合并点包含了分支名称,并清理一组分支。

相反,当在一个分支上工作时,我更喜欢将上游分支进行变基操作。这可以使分支的历史记录保持整洁,避免了很多上游合并噪声和冲突解决。在合并之前,我通常会对上游进行变基操作,以使集成工作更容易(作为分支作者,我可以解决冲突和破碎的测试),并使得结果更加清晰。

这种方法保留了分支的历史记录,同时防止了不再开发的旧分支堵塞事情。这使得使用 gitk 或 GitX 可视化历史记录变得非常有用。

我同意您链接文章中的基本观点,随着同时开发的大型特性分支越来越多,冲突和集成问题的机会也越来越多。使它们如此有用的隔离变成了一个负担。解决之一是不要有大的、旧的特性分支。如果您可以将一个特性分支分解成更小的部分,可以完成和集成,那么就避免了这个问题。这对许多其他原因也很有用,比如要审查代码的人。

如果可以将特性分支持续集成到主线,那么特性分支必须具有有用、工作、测试、文档化的工作。如果有这些,那么它们可以被切成自己的分支。

我承认我的解读可能过于夸张,但文章中可能存在一个有意义的缺陷,就是分支的名称是以人名而非功能名称命名。这表明每个分支都是为了"Jim正在开发的任何东西"而不是"添加蓝色小部件"。这暗示了一些开发问题...

  • 特性和分支由个人或团队拥有
  • 分支不是针对独立的特性
    • 相反,分支是个人的乐园
    • 没有定义的特性,他们可以无休止地进行下去
  • 开发在孤立中完成
    • 个人不经常相互沟通
    • 个人不共同在分支上工作
    • 个人在集成之前不讨论自己的更改

其中很多问题不是技术问题,而是社交问题。大部分问题可以通过使用一个与版本控制强相关的好问题跟踪器进行解决,例如Github。

  • 分支应该针对已定义的特性
  • 开发人员在进行大量工作之前应该先报告问题
  • 没有人"拥有"一个特性(尽管他们可能为其负责)

不幸的是,大多数项目的错误跟踪政策都不鼓励第二个要点。想在报告问题之前准备好一个补丁是一种非常强烈的冲动。

良好的分支管理需要良好的社交技能,并通过一个具有强大版本控制集成和友好政策的优秀问题跟踪器来推动这一过程。


4

如果您不再需要它,请删除它。 如果您后来意识到需要它,可以重新创建它。由于您已将更改合并回“主干”,因此没有任何损失。


3
Git和分支的好处在于每个分支本质上都是一个指向提交的指针。一旦合并了您的分支,以前形成您的分支的提交现在已经成为主要历史的一个组成部分。
                                  your branch
                                    main
                                      |
  (main)  -------x----x----x-x---x----x
                  \                  /
  (your branch)    \--x--x-x--x-x---/

如果你使用"git branch -d"删除你的分支,你将得到以下结果:

                                    main
                                      |
  (main)  -------x----x----x-x---x----x
                  \                  /
  (your branch)    \--x--x-x--x-x---/

正如您所看到的,您分支的提交仍然是安全的。只是名为“您的分支”的指针已被删除。

请注意,如果您没有合并到主分支,则“git branch -d”将会失败。如果您在那个时候强制删除它,您将会留下:

                                  main
                                    |
  (main)  -------x----x----x-x---x--x
                  \
  (your branch)    \--x--x-x--x-x

在这个阶段,由于没有分支指针,提交内容处于“悬空”状态,将在Git执行垃圾回收时被删除。

简而言之,如果你的分支已经合并了,你可以并且应该删除它。如果它还没有被合并,你就不应该删除它。


1

需要考虑两件事:

  1. 在提交之前,也许你应该养成将这些分支变基到主干(或其他地方)顶端的习惯。这样,它们就像KingCrush上面建议的那样是严格冗余的,如果你发现问题,可以销毁它们以便稍后重新创建。

  2. 使用重命名来标记那些你不确定是否还需要的分支,加上特定的前缀,这样当你知道你不再需要一个过时的功能分支时,可以快速浏览分支列表。

你可以使用这些技术的某种混合方式,例如总是变基,然后将分支foo重命名为landed-foo,然后在一定时间间隔(比如一个发布周期或30天)之后删除landed-foo分支。

请注意,如果你不进行变基(并在变基后运行任何测试),你就无法确定在提交后发现的错误实际上是否是在开发代码中引入的,而不是由于在开发后合并所造成的影响,因此在这种情况下,你可能需要保留分支一段时间。这种情况通常发生在具有侵入性/非常大的更改中,而不像你的问题场景。


重新定位并不总是一个好主意,因为它会破坏功能开发的方式。正确合并没有任何危害,而且git实际上是为处理广泛的分支和合并而开发的。在历史记录中显示清晰的分支,以后可以显示该功能是单独开发的,并且如果需要,您可以很容易地在以后识别它。同样,完全安全地删除分支,因为它们只是指向历史记录中的提交的指针。删除分支不会删除它所属的历史记录;历史记录将始终显示分支/合并。 - poke

0

我能想到你希望保留它的唯一原因是:

  • 你想要记录上次工作时间的历史。
  • 你可以推断出开发它的时间。

1
你可以通过查看历史记录来获取两者的信息,即使没有实际分支指向提交。当与分支相关的工作完成并合并到其他分支时,没有必要保留该分支。 - poke
同意。不过,我认为看到一个有用的分支名称会更容易,而不是从提交消息中反向工程化分支所做的事情。 - Andy

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接