欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

深入了解一下Git rebase和git merge的区别---简单易懂

程序员文章站 2022-05-18 11:43:56
...

一、第一篇解释

1、前言

如果你作为一名开发人员,许多时候必须在 Merge和 Rebase 之间进行选择。 我们从互联网上获得的所有参考文档文章,几乎都告诉我们“不要使用 Rebase,它可能会导致严重的问题。”在这里,我将解释什么是 merge 和 rebase,为什么你应该(或者不应该)使用它们,以及如何做。Git Merge 和 Git Rebase 其实是都是为了完成同样的目的。 它们旨在将来自多个分支的更改集成到一个分支中。 虽然最终目标是相同的,但这两种方法以不同的方式实现。这个问题在 Git 社区中引起了分歧。有些人认为应该总是使用 rebase ,而另一些人则认为应该总是使用 merge 。双方都有一些令人信服的好处。

2、git merge

  1. merge 是一种常见的做法,不管创建分支是为了测试、修复 bug 还是其他原因,将提交更改合并到另一个位置。 更具体地说,merge 获取源分支的内容并将它们与目标分支集成。 在此过程中,仅更改目标分支。 源分支历史保持不变。
    深入了解一下Git rebase和git merge的区别---简单易懂
  2. 优点:
  • 简单而又熟悉
  • 保留完整的历史和时间顺序
  • 维持分支的上下文
  1. 缺点:
  • 提交历史记录可能会被许多合并提交污染
  • 使用 git bisect 进行调试会变得更难
  1. 如何操作(假设A、B两个分支,需要将A分支合并到B分支上):
		git checkout B    切换到B分支上
 		git merge A        将A分支合并到B分支上

或是通过:

		git merge A B      将A分支合并到B分支上

3、git rebase

  1. Rebase 是将更改从一个分支集成到另一个分支的另一种方法。 Rebase 将所有更改压缩为单个“补丁”。然后它将补丁集成到目标分支上。与 merge 不同,重定位使历史变得扁平,因为它将完成的工作从一个分支转移到另一个分支。在这个过程中,不需要的历史记录被消除。Rebases 是更改应从层次结构顶部向下传递的方式,并且 Merge 是它们向上流回的方式
    深入了解一下Git rebase和git merge的区别---简单易懂
  2. 优点:
  • 简化可能复杂的历史记录
  • 操作单个提交很容易(例如还原它们)
  • 避免分支频繁合并提交,频繁回购。
  • 通过将它们作为单个提交来清理中间提交,这对DevOps团队很有帮助
  1. 缺点:
  • 将该功能分解为少量提交可以隐藏上下文
  • 在团队合作时,重新定位公共存储库可能会很危险
  • 可能带来更多的工作:使用rebase 来保持您的 feature 分支始终更新
  • 使用远程分支 Rebase 需要强制推送。人们面临的最大问题是他们强制推送,但还没有设置 git push 默认值。这会导致对本地和远程上具有相同名称的所有分支进行更新,这是非常可怕的,并且处理起来非常糟糕。
  1. 如何操作(将 feature 分支 Rebase 到主分支上):
    	git checkout feature
    	git rebase master
  • 这会将整个 feature 分支移动到主分支的顶部。它通过为 原始(feature)分支中的每个提交创建全新的提交来重写项目历史。

4、交互式的 rebase

这允许在将提交移动到新分支时更改提交。 这比自动 rebase 更强大,因为它提供了对分支的提交历史的完全控制。 通常,这用于在将 feature 分支合并到主分支之前,清理杂乱的历史记录。
bash 代码:

		$ git checkout feature
		$ git rebase -i master

这将通过打开编辑器,列出即将移动的所有提交。
bash 代码:

		pick 22d6d7c Commit message#1
 		pick 44e8a9b Commit message#2
   		pick 79f1d2h Commit message#3

这精确定义了 rebase 执行后分支的确切内容。通过重新排序实体,可以使历史记录看起来像您想要的任何内容。例如,可以使用 fixup ,squash ,edit 等命令代替 pick。
深入了解一下Git rebase和git merge的区别---简单易懂

5、我们应选择哪种方式

团队在设置 Git rebase 与 merge 策略时,需要考虑几个问题:

  • 考虑跨组织的重基和Git能力级别。确定相对于可追溯性和合并历史,您更重视重基的简单性的程度。
  • 考虑整个组织的 rebase 和 Git能力水平。 相对于 merge 的可追溯性和历史记录,确定您重视 rebase 的简单程度。
  • 最后,应该在清晰的分支策略的上下文中考虑关于 merge 和 rebase 的决策,成功的分支策略是围绕团队组织设计的。

6、个人意见

随着团队的增长,使用始终 merge 策略管理或跟踪开发更改将变得非常困难。要有一个清晰易懂的提交历史记录,使用 Rebase 是合理和有效的。

通过考虑以下情况和指南,您可以充分利用 Rebase :

  1. 你在本地开发:如果您还没有与其他人合作。此时,你应该更喜欢 rebase 而不是 merge 以保持历史的整洁。如果您拥有存储库的个人分支并且未与其他开发人员共享,那么即使您已经推送到分支之后,也可以安全地进行 rebase 。
  2. 您的代码已经准备好接受评审:您创建了一个 pull 请求。其他人正在评审您的工作,并可能将其提取到他们的分支中进行本地评审。此时,您不应该 rebase 你的工作。您应该创建 rework 提交并更新您的 feature 分支。这有助于拉取请求中的可追溯性,并防止意外的历史记录破坏。
  3. 评审已经完成,准备集成到目标分支中:恭喜你!您将要删除您的 feature 分支。考虑到其他开发人员从现在起不会在这些更改中进行获取合并,这是您清理历史记录的机会。此时,您可以重写历史记录并折叠原始提交,并将那些讨厌的’pr rework’和’merge’提交到一小组重点提交中。为这些提交创建显式合并是可选的,但有价值。它记录了该功能何时升级为 master 。

二、第二篇解释

1、什么是 rebase?

  1. git rebase 你其实可以把它理解成是“重新设置基线”,将你的当前分支重新设置开始点。这个时候才能知道你当前分支于你需要比较的分支之间的差异。
    原理很简单:rebase需要基于一个分支来设置你当前的分支的基线,这基线就是当前分支的开始时间轴向后移动到最新的跟踪分支的最后面,这样你的当前分支就是最新的跟踪分支。这里的操作是基于文件事务处理的,所以你不用怕中间失败会影响文件的一致性。在中间的过程中你可以随时取消rebase 事务。
    官方解释: https://git-scm.com/book/zh/v2/Git-分支-变基

2、git rebase 和 git merge 有啥区别?

  1. rebase会把你当前分支的 commit 放到公共分支的最后面,所以叫变基。就好像你从公共分支又重新拉出来这个分支一样。
    举例:如果你从 master 拉了个feature分支出来,然后你提交了几个 commit,这个时候刚好有人把他开发的东西合并到 master 了,这个时候 master 就比你拉分支的时候多了几个 commit,如果这个时候你 rebase master 的话,就会把你当前的几个 commit,放到那个人 commit 的后面。
    深入了解一下Git rebase和git merge的区别---简单易懂
  2. merge 会把公共分支和你当前的commit 合并在一起,形成一个新的 commit 提交。
    深入了解一下Git rebase和git merge的区别---简单易懂

3、注意:

  • 不要在公共分支使用rebase
  • 本地和远端对应同一条分支,优先使用rebase,而不是merge

4、抛出问题:

  1. 为什么不要再公共分支使用rebase?
    因为往后放的这些 commit 都是新的,这样其他从这个公共分支拉出去的人,都需要再 rebase,相当于你 rebase 东西进来,就都是新的 commit 了
    1-2-3 是现在的分支状态
    这个时候从原来的master ,checkout出来一个prod分支
    然后master提交了4.5,prod提交了6.7
    这个时候master分支状态就是1-2-3-4-5,prod状态变成1-2-3-6-7
    如果在prod上用rebase master ,prod分支状态就成了1-2-3-4-5-6-7
    如果是merge
    1-2-3-6-7-8
    … |4-5|
    会出来一个8,这个8的提交就是把4-5合进来的提交

  2. merge和rebase实际上只是用的场景不一样
    更通俗的解释一波,比如rebase,你自己开发分支一直在做,然后某一天,你想把主线的修改合到你的分支上,做一次集成,这种情况就用rebase比较好.把你的提交都放在主线修改的头上如果用merge,脑袋上顶着一笔merge的8,你如果想回退你分支上的某个提交就很麻烦,还有一个重要的问题,rebase的话,本来我的分支是从3拉出来的,rebase完了之后,就不知道我当时是从哪儿拉出来的我的开发分支同样的,如果你在主分支上用rebase, rebase其他分支的修改,是不是要是别人想看主分支上有什么历史,他看到的就不是完整的历史课,这个历史已经被你篡改了

5、常用指令

  • git rebase -I dev 可以将dev分支合并到当前分支
    这里的”-i“是指交互模式。就是说你可以干预rebase这个事务的过程,包括设置commit message,暂停commit等等。

  • git rebase –abort 放弃一次合并

  • 合并多次commit操作:
    1 git rebase -i dev
    2 修改最后几次commit记录中的pick 为squash
    3 保存退出,弹出修改文件,修改commit记录再次保存退出(删除多余的change-id 只保留一个)
    4 git add .
    5 git rebase --continue