git 鼓励大量使用分支---"早建分支!多用分支!",这是因为即便创建再多的分支也不会造成存储或内存开销,并且分支的作用有助于我们分解逻辑工作,这样一样其实比维护单一臃肿分支要简单得多!

正因如此,每个新功能会创建合并分支,修复 bug 会创建合并分支等等,一段时间后再次回顾整个版本库的提交历史就会发现分支错综复杂,难以理清!

虽然"条条大路通罗马",但错综复杂的道路容易让人迷失方向,如果不使用分支,当然就不存在"分叉问题",所以在某些情况下我们希望寻求一种替代方案来解决分支合并带来的"分叉问题"!

回顾提交历史

查看提交历史: git log --pretty=oneline --graph --abbrev-commit

# 查看提交历史
$ git log --pretty=oneline --graph --abbrev-commit
* e60c8ad (HEAD -> dev, origin/master, origin/HEAD, master) fix bug about issue-110
* 3fe94c0 fast forward
* 22fbef7 git merge --no-ff dev
|\
| * 44d68f6 git checkout -b dev
|/
* 3b8f434 fix conflict
|\
| * 0fe95f8 git commit c2
* | 0949cc3 git commit c3
|/
* 5c482cd git commit c1
* 413a4d1 see https://snowdreams1006.github.io/git/usage/branch-overview.html
* 9c30e50 learn git branch
* b3d8193 see https://snowdreams1006.github.io/git/usage/remote-repository.html
* 8e62564 add test.txt
* 9b196aa Initial commit

仅仅是简单的演示项目的提交历史都已经出现"分叉问题",更何况真实的企业级开发项目呢?如果真的是多分支多人合作开发的话,"分叉现象"将更加明显,模拟效果图大概长这样:

整理提交历史

如果想要一条直路直达罗马,那我们必须规划好路径,摒弃小道,坚持主干道.git 的各种 dev,feature等分支就是需要治理的一条条分叉小道,而 master 主分支就是我们的大道.

演示项目有三个分支,主干master,开发dev,自定义snow,目标是将自定义 snow 分支的工作成功整理合并到主干分支,从而解决"分叉问题",dev 分支与项目演示无关,无需更改.

(1). 切换到 snow 分支并提交一个版本(learn git rebase)

# 切换到 `snow` 分支
$ git checkout snow
Switched to branch 'snow' # 追加新内容到 `test.txt` 文件
$ echo "learn git rebase" >> test.txt # 提交到版本库
$ git commit -am "learn git rebase"
[snow 7d21e80] learn git rebase
1 file changed, 1 insertion(+)
$

(2). 切换到 master 分支也提交一个版本(modify README)

# 切换回 `master` 分支
$ git checkout master
Switched to branch 'master'
Your branch is up to date with 'origin/master'. # 追加新内容到 `README.md` 文件
$ echo "learn git ,share git" >> README.md # 提交到版本库
$ git add README.md
$ git commit -m "modify README"
[master 3931d48] modify README
1 file changed, 1 insertion(+)
$

(3). 切换回 snow 分支,整理提交历史(git rebase)到 master 分支

# 切换到 `snow` 分支
$ git checkout snow
Switched to branch 'snow' # 改变基础版本(父版本),简称"变基"
$ git rebase master
HEAD is up to date. # 当前提交历史线
$ git log --pretty=oneline --graph --abbrev-commit
* e92f068 (HEAD) rebase
* 72f4c01 fix confict about happy coding
* 3931d48 (master) modify README
* e60c8ad (origin/master, origin/HEAD, dev) fix bug about issue-110
* 3fe94c0 fast forward
* 22fbef7 git merge --no-ff dev
|\
| * 44d68f6 git checkout -b dev
|/
* 3b8f434 fix conflict
|\
| * 0fe95f8 git commit c2
* | 0949cc3 git commit c3
|/
* 5c482cd git commit c1
* 413a4d1 see https://snowdreams1006.github.io/git/usage/branch-overview.html
* 9c30e50 learn git branch
* b3d8193 see https://snowdreams1006.github.io/git/usage/remote-repository.html
* 8e62564 add test.txt
* 9b196aa Initial commit
$

(4). 切换回 master 主干分支再次变基合并 snow 分支

# 切换回 `master` 分支
$ git checkout master
Warning: you are leaving 2 commits behind, not connected to
any of your branches: e92f068 rebase
72f4c01 fix confict about happy coding If you want to keep them by creating a new branch, this may be a good time
to do so with: git branch <new-branch-name> e92f068 Switched to branch 'master'
Your branch is ahead of 'origin/master' by 1 commit.
(use "git push" to publish your local commits) # 改变父版本为 `snow` 分支指向的版本
$ git rebase snow
First, rewinding head to replay your work on top of it...
Applying: modify README
$

(5). 整理分支完成,最终主干分支是一条直线

# 查看提交历史线
$ git log --pretty=oneline --graph --abbrev-commit # `modify README` 是 `master` 分支提交的版本
* dcce09c (HEAD -> master) modify README # `learn git rebase` 是 `snow` 分支提交的版本
* 7d21e80 (snow) learn git rebase
* a06a866 fix conflict
|\
| * e60c8ad (origin/master, origin/HEAD, dev) fix bug about issue-110
* | ab846f9 learn git stash
* | 93227ba Happy coding
|/
* 3fe94c0 fast forward
* 22fbef7 git merge --no-ff dev
|\
| * 44d68f6 git checkout -b dev
|/
* 3b8f434 fix conflict
|\
| * 0fe95f8 git commit c2
* | 0949cc3 git commit c3
|/
* 5c482cd git commit c1
* 413a4d1 see https://snowdreams1006.github.io/git/usage/branch-overview.html
* 9c30e50 learn git branch
* b3d8193 see https://snowdreams1006.github.io/git/usage/remote-repository.html
* 8e62564 add test.txt

这一次我们没有使用 git merge 而是采用 git rebase 方式完成了分支的合并,优点是提交历史更清晰,缺点是丢失了分支信息.

小结

git rebase 变基合并分支,实际上就是取出一系列的提交版本并“复制”到目标版本,从而形成一条新的提交历史线.

比如我们想要把 bugFix 分支里的工作直接移到 master 分支上,移动以后会使得两个分支的功能看起来像是按顺序开发,但实际上它们是并行开发的,这就是 git rebase 的作用.

git rebase 的优势是创造更线性的提交历史,使得代码库的提交历史变得异常清晰,劣势是缺失了分支信息,好像从没存在过该分支一样.

  1. 将目标分支上的工作成果转移到到主干分支 : git rebase master
  2. 主干分支接收已转移好的目标分支工作成果 : git rebase <branch>

git 入门教程之变基合并的更多相关文章

  1. git 入门教程

    git 入门教程之协同开发 前面我们已经介绍过远程仓库的相关概念,不过那时并没有深入探讨,只是讲解了如何创建远程仓库以及推送最新工作成果到远程仓库,实际上远程仓库对于团队协同开发很重要,不仅仅是团队协 ...

  2. git 入门教程之备忘录[译]

    备忘录[译] 创建 | Create 克隆一个已存在的仓库 | Clone an existing repository git clone git@github.com:snowdreams1006 ...

  3. 廖雪峰Git入门教程

    廖雪峰Git入门教程  2018-05-24 23:05:11     0     0     0 https://www.liaoxuefeng.com/wiki/00137395163059296 ...

  4. 创建与合并分支-git入门教程

    在版本回退里,你已经知道,每次提交,Git都把它们串成一条时间线,这条时间线就是一个分支.截止到目前,只有一条时间线,在Git里,这个分支叫主分支,即master分支.HEAD严格来说不是指向提交,而 ...

  5. git 入门教程之本地和远程仓库的本质

    本地仓库和远程仓库在本质上没有太大区别,只不过一个是本地电脑,一个是远程电脑. 远程仓库不一定非得是 github 那种专门的"中央服务器",甚至局域网的另外一台电脑也可以充当&q ...

  6. git 入门教程之分支策略

    默认情况下合并分支常常直接使用 git merge 命令,是最方便快速的合并方法.其实这种情况下 git 采用的是 fast forward 模式,特点是删除分支后,会丢失分支信息,好像从来没存在该分 ...

  7. git入门教程,主要命令详解。

    准备工作 git clone url / ssh  ----------------------------------------------------------------------从git ...

  8. git 入门教程之冲突合并

    如果足够幸运的话,团队成员互不影响,彼此相安无事,大家各自基于 master 分支的某个 commit 创建自己的分支,平时在分支上独立工作,等到一段时间后再合并 merge 到 master 分支, ...

  9. Git入门教程,详解Git文件的四大状态

    大家好,欢迎来到周一git专题. git clone 在上一篇文章当中我们聊了怎么在github当中创建一个属于自己的项目(repository),简称repo.除了建立自己的repo之外,我们更多的 ...

随机推荐

  1. 推荐一篇关于java集合的博文,写的很nice

    这也是我自己在网上看到的一篇博文,作者的博文都很棒,以后还会持续为大家推荐好的博文,只要大家不骂我只会转别人的博文,自己不会写,其实这些都是基础,前辈们已经在实践中总结的很细很全了,所以也没必要去总结 ...

  2. SQL中EXPLAIN命令详解

    explain显示了mysql如何使用索引来处理select语句以及连接表.可以帮助选择更好的索引和写出更优化的查询语句. 使用方法,在select语句前加上explain就可以了: 如: expla ...

  3. async/await异步处理demo

    async/await异步处理demo 下载地址: async/await异步处理demo

  4. 服务注册中心之ZooKeeper系列(三) 实现分布式锁

    通过ZooKeeper的有序节点.节点路径不回重复.还有节点删除会触发Wathcer事件的这些特性,我们可以实现分布式锁. 一.思路 zookeeper中创建一个根节点Locks,用于后续各个客户端的 ...

  5. 第6章 LVM详解

    6.1 LVM相关概念和机制 LVM(Logical Volume Manager)可以让分区变得弹性,可以随时随地的扩大和缩小分区大小,前提是该分区是LVM格式的. lvm需要使用的软件包为lvm2 ...

  6. Linux上磁盘热插拔

    首先获取scsi设备的信息. [root@server2 ~]# lsscsi [:::] disk VMware, VMware Virtual S 1.0 /dev/sda [:::] cd/dv ...

  7. 翻译:ZooKeeper OverView

    ZooKeeper系列文章:https://www.cnblogs.com/f-ck-need-u/p/7576137.html#zk ZooKeeper: 分布式协调服务 ZooKeeper是一个开 ...

  8. python模块之xml

    xml模块 xml结构 xml是种实现不同语言或程序之间进行数据交换的协议,跟json差不多,但没json使用简单.但是因为历史遗留问题,至今很多行业依然使用xml这种数据格式. xml的格式如下,是 ...

  9. HTTP状态码以及其含义大全

    HTTP状态码(英语:HTTP Status Code)是用以表示网页服务器超文本传输协议响应状态的3位数字代码.我们在开发过程中比较常见的状态码有:200(请求成功).301(页面重定向).404( ...

  10. Python正则进阶

    目录 1.Python正则表达式模块 1.1 正则表达式处理字符串主要有四大功能 1.2 Python中re模块使用正则表达式的两种方法 1.3 正则表达式对象的常用方法 1.4 匹配对象的属性与方法 ...