https://medium.freecodecamp.org/an-introduction-to-git-merge-and-rebase-what-they-are-and-how-to-use-them-131b863785zhicheng Miya
大部分开发者都有遇到过该用 Merge 还是 Rebase 的问题,网络上的各种相关介绍几乎都认为:“不要使用 Rebase,因为它会产生各种问题”。这里我将介绍 merge 和 rebase 的概念,为什么你应该(或者不应该)使用它们,以及怎么用。
Git Merge 和 Git Rebase 目的相同,它们都是把不同分支的提交合并到一起。虽然最终目的是一致的,但是其过程却颇为不同。了解它们之间的区别之后,你会成为一个更出色的开发者。
Git 社区对这个问题有很大争论,一些人坚持应该只用 rebase,另外一些人认为只用 merge,事实上两种方式各有优势。
Git Merge
对于使用版本控制系统的开发者来说,Merging 是常规操作。不管创建的分支是用来测试、修复 bug,还是别的什么原因,可能都会需要把分支的提交 merging 到其它的分支上。具体来说,merging 就是把源分支的提交放到目标分支里面。在这个过程里,只有目标分支改变,而源分支保持原样。
Merge Master->Featuer branch
优点
简单易上手
保留了提交历史和时间次序
保留了分支的结构
缺点
提交历史被大量的 merge 提交污染了
使用 git bisect 调试变得更困难了
怎样做
使用 checkout 和 merge 命令把 master 分支 merge 到 feature 分支。
$ git checkout feature
$ git merge master
(or)
$ git merge master feature
这将会在 feature 分支上创建一个新的 “Merge 提交” 用来保留所有分支的记录。
Git Rebase
Rebase 是合并两个分支的另一种方式。Rebase 把所有的提交压缩成一个 “patch”。然后把 patch 添加到目标分支里。
和 merging 不同,rebasing 清除了历史,因为它完全是从一个分支转移到了另一个分支。在这个过程中,多余的记录被移除了。
Rebases 的提交从顶部按次序向下排列,而 merges 则自下而上。
Rebase feature branch into master
优点
把复杂的历史变成优雅的提交线
操作单个提交变得很简单(比如,reverting)
避免了庞大的仓库、海量的分支以及烦人的 merge 提交
线性合并清除了中间的无用提交,对于 DevOps 团队来说是个好消息
缺点
Rebase 后 feature 分支间的上下文模糊了
在团队里 rebasing 公共分支是高风险的事
工作变多了:feature 分支需要经常更新
Rebasing 到远程分支需要 force push。最大的问题是人们经常已经 force push 了,才发现忘记了设置 git push 默认值。结果本地远程所有同名的分支都进行了更新,清理起来很要命。
如果你 rebase 出错并且很不幸重写了历史,很棘手,所以一定要明白操作的意义。
怎样做
下面的命令把 feature 分支 rebase 到 master 分支上。
$ git checkout feature
$ git rebase master
它把整个 feature 分支的提交移动到了 master 分支上。通过给每个源(feature) 分支创建了一个 brand 来 re-writing 项目的历史。
Interactive Rebasing
这个命令可以在移动 commit 前改变它们。这比普通的 rebase 更加强大,它提供了对分支提交历史的完整控制。另外,在合并 feature 分支到 master 前,还可以用它来清理混乱的提交历史。
$ git checkout feature
$ git rebase -i master
他会打开编辑器列出将要被移动的提交。
pick 22d6d7c Commit message#1
pick 44e8a9b Commit message#2
pick 79f1d2h Commit message#3
它清晰地展示了分支在 rebase 后的样子。通过重新调整,提交历史可以变成任何你想要的样子。如,可以把 pick 换成 fixup , squash , edit 等命令。
选哪个
所以,哪个是最好的?有没有专业的建议呢?很难明确告诉你该选哪一个,毕竟每个团队的情况不同。但还是有章可循。
团队在制定他们的 Git rebase vs. merge 策略时需要考虑很多问题。事实证明,工作流之间并无明显的高下之分,一切都取决于团队情况。
选择更直白的 rebasing 还是历史可塑性更强的 merging,要考虑团队对 rebasing 的了解情况以及 Git 熟悉程度。
最后,决定使用 merging 还是 rebasing 还应该考虑到分支策略。团队有必要制定一个合适的分支策略。
我的建议
随着团队增长,通过 merge 策略很难管理和追踪到每个提交。为了提交历史更清晰、更易于理解,使用 Rebase 是一个明智、高效的选择。
下面是针对不同环境的建议,可以最大限度地发挥 Rebase 的优势:
本地开发:如果你没有和别人协同工作,你应该使用 rebasing 而不是 merging ,这样历史记录会很清晰。如果你已经从仓库拉取了你的个人 fork,并且不准备和别的开发者一起工作,在分支 push 前 rebase 也是可以的。
你的代码准备好了被 review: 你创建了 pull request。别人正在 review 你的代码,可能把它拉到了本地 review。如果这样,你最好别 rebase 你的代码。你应该创建一个 “rework” 提交来更新你的 feature 分支。它会让 pull request 的可塑性更强,也能避免历史突然丢失。
review 已经完成并且已经准备好了合并到目标分支。恭喜!你就要删除你的 feature 分支了。由于别的开发者不需要拉取、合并这些更改,这是你清理记录的好机会。你可以改写记录,折叠原始提交、“pr rework” 提交和 "merge"提交,使之成为一整个清晰的提交。作为可选,你还可以给这些提交创建一个明确的 merge,这样做实际上很有用。它会记录 feature 并入master 的时间。
结论
希望这些解释能让你对 Git merge 和 Git rebase 更了解。Merge .vs. rebase 策略之争永无止境。希望这篇文章可以帮助你扫清迷惑,找到一个适合自己的团队的方向。
团队项目的Git分支如何管理?
Git 是目前最流行的源代码管理工具。大量的软件项目由 GitHub、Bitbucket 和 GitLab 这样的云服务平台或是私有的 Git 仓库来管理。在使用 Git 时通常会遇到的一个问题是采用何种分支管理实践,即如何管理仓库中作用不同的各类分支。和软件开发中的其他实践一样,Git 分支管理并没有普遍适用的最佳做法,而只有对每个团队和项目而言最适合的做法。简单来说,在项目开发中使用多个分支会带来额外的管理和维护开销,但是多个分支对于项目的团队合作、新功能开发和发布管理都是有一定好处的。不同的团队可以根据团队人员组成和意愿、项目的发布周期等因素选择最适合的策略,找到最适合团队的管理方式。这里讲一下三种常见的 Git 分支管理方式。
单主干
单主干的分支实践(Trunk-based development,TBD)在 SVN 中比较流行。Google 和 Facebook 都使用这种方式。trunk 是 SVN 中主干分支的名称,对应到 Git 中则是 master 分支。TBD 的特点是所有团队成员都在单个主干分支上进行开发。当需要发布时,先考虑使用标签(tag),即 tag 某个 commit 来作为发布的版本。如果仅靠 tag 不能满足要求,则从主干分支创建发布分支。bug 修复在主干分支中进行,再 cherry-pick 到发布分支。图 1 是 TBD 中分支流程的示意图。
图 1. TBD 中的分支流程的示意图
由于所有开发人员都在同一个分支上工作,团队需要合理的分工和充分的沟通来保证不同开发人员的代码尽可能少的发生冲突。持续集成和自动化测试是必要的,用来及时发现主干分支中的 bug。因为主干分支是所有开发人员公用的,一个开发人员引入的 bug 可能对其他很多人造成影响。不过好处是由于分支所带来的额外开销非常小。开发人员不需要频繁在不同的分支之间切换。
GitHub flow
GitHub flow 是 GitHub 所使用的一种简单的流程。该流程只使用两类分支,并依托于 GitHub 的 pull request 功能。在 GitHub flow 中,master 分支中包含稳定的代码。该分支已经或即将被部署到生产环境。master 分支的作用是提供一个稳定可靠的代码基础。任何开发人员都不允许把未测试或未审查的代码直接提交到 master 分支。
对代码的任何修改,包括 bug 修复、hotfix、新功能开发等都在单独的分支中进行。不管是一行代码的小改动,还是需要几个星期开发的新功能,都采用同样的方式来管理。当需要进行修改时,从 master 分支创建一个新的分支。新分支的名称应该简单清晰地描述该分支的作用。所有相关的代码修改都在新分支中进行。开发人员可以自由地提交代码和 push 到远程仓库。
当新分支中的代码全部完成之后,通过 GitHub 提交一个新的 pull request。团队中的其他人员会对代码进行审查,提出相关的修改意见。由持续集成服务器(如 Jenkins)对新分支进行自动化测试。当代码通过自动化测试和代码审查之后,该分支的代码被合并到 master 分支。再从 master 分支部署到生产环境。图 2 是 GitHub flow 分支流程的示意图。
图 2. Github flow 中的分支流程的示意图
GitHub flow 的好处在于非常简单实用。开发人员需要注意的事项非常少,很容易形成习惯。当需要进行任何修改时,总是从 master 分支创建新分支。完成之后通过 pull request 和相关的代码审查来合并回 master 分支。GitHub flow 要求项目有完善的自动化测试、持续集成和部署等相关的基础设施。每个新分支都需要测试和部署,如果这些不能自动化进行,会增加开发人员的工作量,导致无法有效地实施该流程。这种分支实践也要求团队有代码审查的相应流程。
git-flow
git-flow 应该是目前流传最广的 Git 分支管理实践。git-flow 围绕的核心概念是版本发布(release)。因此 git-flow 适用于有较长版本发布周期的项目。虽然目前推崇的做法是持续集成和随时发布。有的项目甚至可以一天发布很多次。随时发布对于 SaaS 服务类的项目来说是很适合的。不过仍然有很大数量的项目的发布周期是几个星期甚至几个月。较长的发布周期可能是由于非技术相关的因素造成的,比如人员限制、管理层决策和市场营销策略等。
git-flow 流程中包含 5 类分支,分别是 master、develop、新功能分支(feature)、发布分支(release)和 hotfix。这些分支的作用和生命周期各不相同。master 分支中包含的是可以部署到生产环境中的代码,这一点和 GitHub flow 是相同的。develop 分支中包含的是下个版本需要发布的内容。从某种意义上来说,develop 是一个进行代码集成的分支。当 develop 分支集成了足够的新功能和 bug 修复代码之后,通过一个发布流程来完成新版本的发布。发布完成之后,develop 分支的代码会被合并到 master 分支中。
其余三类分支的描述如表 1所示。这三类分支只在需要时从 develop 或 master 分支创建。在完成之后合并到 develop 或 master 分支。合并完成之后该分支被删除。这几类分支的名称应该遵循一定的命名规范,以方便开发人员识别。
表 1. git-flow 分支类型
对于开发过程中的不同任务,需要在对应的分支上进行工作并正确地进行合并。每个任务开始前需要按照指定的步骤完成分支的创建。例如当需要开发一个新的功能时,基本的流程如下:
- 从 develop 分支创建一个新的 feature 分支,如 feature/my-awesome-feature。
- 在该 feature 分支上进行开发,提交代码,push 到远端仓库。
- 当代码完成之后,合并到 develop 分支并删除当前 feature 分支。
在进行版本发布和 hotfix 时也有类似的流程。当需要发布新版本时,采用的是如下的流程:
- 从 develop 分支创建一个新的 release 分支,如 release/1.4。
- 把 release 分支部署到持续集成服务器上进行测试。测试包括自动化集成测试和手动的用户接受测试。
- 对于测试中发现的问题,直接在 release 分支上提交修改。完成修改之后再次部署和测试。
- 当 release 分支中的代码通过测试之后,把 release 分支合并到 develop 和 master 分支,并在 master 分支上添加相应的 tag。
因为 git-flow 相关的流程比较繁琐和难以记忆,在实践中一般使用辅助脚本来完成相关的工作。比如同样的开发新功能的任务,可以使用 git flow feature start my-awesome-feature 来完成新分支的创建,使用 git flow feature finish my-awesome-feature 来结束 feature 分支。辅助脚本会完成正确的分支创建、切换和合并等工作。
Git算不算程序员的必备技能?
企业里面都是怎么进行代码管理的?
本人编程出身,7年多开发经验,想了解更多互联网和开发相关知识,欢迎关注本人号。
先给出结论:当然是必备的。
1. 大部分使用情况
Git作为一个分布式版本控制工具,在敏捷开发和项目代码管理时非常方便。我知道的大部分公司都使用Git来做代码管理,甚至有些使用Git来做文档管理。
Git是用来做项目管理的,不但可以用来管理代码,即便是很多非程序员也使用Git来管理文件等项目。
2. 与世界交流的工具
各大知名的代码托管网站都使用Git来做代码管理,因此作为一个程序员,在学习和获取新知识是后不可避免的要使用GIT学习源代码(当然可以下载压缩包,不嫌麻烦的话)。
同时,个人在参与开源项目或者开源个人项目的时候也是需要使用Git管理代码和文档的。
3. 工作能力
当然,现在有些公司尤其是企业级应用为主的公司使用svn来管理代码,但是作为一个程序员不可能一直在一个地方养老(就算你愿意,公司也不一定愿意),如果更换工作,为了让自己有更好的适应性,Git也是必知必会的基本要求。
4. 学习成本
Git非常简单易学,分清楚几个基本概念,如果使用命令行的情况下,只需要记住7-10个命令,就可以玩得很溜了。 这样得学习成本,对于知识更新毕竟快得程序员队伍是不值一提的。
最后我只想问下,有不会Git的程序员吗?