文档章节

使用Git的rebase操作优化提交历史

 閒散人員
发布于 01/18 12:16
字数 1572
阅读 100
收藏 0

理解rebase的过程原理

rebase是另一种可以用来合并分支的机制,有些人翻译成“变基操作”,它和merge合并分支的原理完全不同,对于merge来说除了fast-forward合并,其他合并方式都会生成一次新的提交对象,假如目前的项目状态是:
     E---F---G  feature#1
     /
A---B----C---D     master(HEAD)

如果现在执行git merge feature#1,git会找到提交对象G和D的共同基点C,然后做三方比较合并,合并之后产生一个新的提交对象H,分支的演变如下:
     E---F---G  feature#1
     /    \
A---B----C---D-----H  master

但是如果我们采用git rebase feature#1则情况完全不同,git也会产生合并,但实际上是git先把master倒回(rewind)到C的提交点,然后把feature#1分支上的所有提交按顺序在master上重新执行一遍,然后把master上的在C之后的提交D进行一次fast-forward合并, 结果项目的分支情况就是下面这样:
     E---F---G      feature#1
     /
A---B----C---E'---F'---G'---D  master

现在我们从master上使用git log查看提交历史的话,看不到任何分支的分叉轨迹,完全是线性的,就好像所有的提交(包括实际上发生在feature#1分支上的提交)都是在master分支上发生的,并且可以看到原先master上的修改好像都是在feature#1的基础上进行的而不祖先C,这就是rebase表达的含义,它改变了master上所最新提交的历史基点。

正式由于rebase这样的结果,所以要根据具体情况来使用它,如果我们想要明确的保留项目的分叉合并历史演进情况,那么rebase不合适而应该使用merge。

注意,不要在一个已经向其他人公开了的分支上执行rebase,这会导致项目其他成员已经获得的分支历史纪录丢失。

适合使用rebase的情景

  1. 我们在一个私有的分支上对项目做了改动(增加新功能或解决缺陷),然后我们把私有分支rebase到主干上提交给项目管理人,这样主干上会获得一个非常干净直观的提交历史。

  2. 我们正在进行一个特性分支,但是由于已经发布的代码发现了缺陷,我们解决了缺陷然后发布到了主干上,继续回到特性分支上工作,这时我们想把刚刚解决的那个问题的代码合并到特性分支上,因为我们的新功能开发需要依赖有缺陷的那部分代码,这个时候非常适合使用rebase而不是merge,把主干rebase到特性分支上以后,结果就好像我们所有的新功能代码都是在解决了缺陷以后的基础上进行的。

  3. 某个分支产生了很多无效的提交,污染项目的分支提交历史,这种情况下使用rebase的交互式模式可以把已经发生的多次提交压缩成一次提交,得到了一个干净的提交历史,例如某个分支的提交历史情况如下:

    $ git log --pretty=oneline --abbrev-commit
    // 这些提交从e9782b9到a97cf60就是冗余的提交
    e9782b9 (HEAD -> feature#pos-nowpay, origin/feature#pos-nowpay) 修复缺陷
    a3880b3 修复缺陷
    6c0aa44 修复缺陷
    5b29942 优化代码
    e1e20f3 优化代码
    62340d1 修复缺陷
    e4f656a pom优化
    ad0f0c1 汉朔POS机支付接入现在支付平台
    a97cf60 汉朔POS机支付接入现在支付平台
    f8e7257 增加日志打印细节
    ......
    

    进入交互式模式的方式是执行:

    $ git rebase -i <base-commit>
    

    参数base-commit就是指明操作的基点提交对象,对于上述提交历史的例子,我们要把最后的一个提交对象(f8e7257)之前的提交压缩成一次提交,我们需要执行的命令格式是:

    $ git rebase -i f8e7257
    # 或者使用 HEAD~9也行
    $ git rebase -i HEAD~9
    

    接着git会进入一个交互式的文本编辑器中,编辑器中列出的信息类似下面这样:

    pick a97cf60 汉朔POS机支付接入现在支付平台
    pick ad0f0c1 汉朔POS机支付接入现在支付平台
    pick e4f656a pom优化
    pick 62340d1 修复缺陷
    pick e1e20f3 优化代码
    ...... # 这里省略一些提交对象
    
    # Rebase f8e7257..e9782b9 onto f8e7257 (9 commands)
    #
    # 下面列出了可以执行的命令及其含义
    # Commands:
    # p, pick = use commit
    # r, reword = use commit, but edit the commit message
    # e, edit = use commit, but stop for amending
    # s, squash = use commit, but meld into previous commit
    # f, fixup = like "squash", but discard this commit's log message
    # x, exec = run command (the rest of the line) using shell
    # d, drop = remove commit
    #
    # These lines can be re-ordered; they are executed from top to bottom.
    ......
    

    上面的命令中squash表示压缩的意思,我们保留第一个提交,把后面的提交前面的命令都改为squash或者s

    pick a97cf60 汉朔POS机支付接入现在支付平台
    squash ad0f0c1 汉朔POS机支付接入现在支付平台
    squash e4f656a pom优化
    squash 62340d1 修复缺陷
    squash e1e20f3 优化代码
    
    # Rebase f8e7257..e9782b9 onto f8e7257 (9 commands)
    ......
    

    然后保存并退出编辑器,接着git再次进入文本编辑模式,这一次我们可以重新编辑提交消息,编辑好提交消息后再次保存退出即可,接着git会继续rebase过程,完了之后就变成了一次提交,如下:

    $ git log --pretty=oneline --abbrev-commit
    # 压缩之后变成一次提交
    2b0e2e3 (HEAD -> feature#pos-nowpay) 汉朔POS机支付接入现在支付平台
    f8e7257 增加日志打印细节
    

    注意,不要在一个已经公开的分支上执行任何rebase操作,否则会导致其它项目成员丢失提交历史

© 著作权归作者所有

粉丝 0
博文 1
码字总数 1572
作品 0
昌平
私信 提问
加载中

评论(0)

git rebase VS git merge? 更优雅的 git 合并方式值得拥有

写在前面 如果你不能很好的应用 Git,那么这里为你提供一个非常棒的 Git 在线练习工具 Git Online ,你可以更直观的看到你所使用的命令会产生什么效果另外,你在使用 Git 合并分支时只会使用...

tan日拱一兵
2019/07/16
115
0
Git Rebase 操作的分析与整理

文前说明 作为码农中的一员,需要不断的学习,我工作之余将一些分析总结和学习笔记写成博客与大家一起交流,也希望采用这种方式记录自己的学习之旅。 本文仅供学习交流使用,侵权必删。 不用...

羽杰
2017/04/23
0
0
git merge 与 git rebase 的区别

merge 与 rebase 的区别 merge 现在假设我们有一个主分支 master 及一个开发分支 deve,仓库历史就像这样: 初始仓库历史 现在如果在 master 分支上 :Git 会自动根据两个分支的共同祖先即 ...

Hzhodor
2017/09/25
64
0
[Git] Git整理(四) git rebase 的使用

概述 在之前总结分支相关内容时说道,合并两个分支的提交可以使用git merge,然而除了这种方式之外,还有一种方式就是使用git rebase,这两种方式的最终结果都相同,但是合并历史却不同;git...

天王盖地虎626
2019/03/20
558
0
【git命令】git-rebase

修改历史提交记录 作用简要概括为:可以对某一段线性提交历史进行编辑、删除、复制、粘贴;因此,合理使用rebase命令可以使我们的提交历史干净、简洁! 前提:不要通过rebase对任何已经提交到...

echojson
2019/03/24
18
0

没有更多内容

加载失败,请刷新页面

加载更多

00-Java 面试准备

面试之前 面试前准备简历需要注意的几个方面: 写简历、改简历,这个一定要干的。简历有两个作用,一个是吸引别人,能让别人邀请你去面试,这是前提;另一个是引导面试的人,让面试的人问你所...

源程序
今天
54
0
OSChina 周二乱弹 —— 大王(@罗马的王)颜值制霸Osc社区

Osc乱弹歌单(2020)请戳(这里) 【今日歌曲】 @巴拉迪维 :Lunik的单曲《Seeing You Soar》 I hope you’re smiling,When seeing me soar. #今日歌曲推荐# 《Seeing You Soar》- Lunik 手...

小小编辑
今天
83
0
wordcount代码

1.写出map类 public class WCMapper extends Mapper<LongWritable,Text,Text,LongWritable>{ @Override protected void map(LongWritable key,Text value,Context context)throws IOExcepti......

七宝1
今天
59
0
Spring Batch 小任务(Tasklet)步骤

Chunk-Oriented Processing不是处理 step 的唯一方法。 考虑下面的一个场景,如果你仅仅需要调用一个存储过程,你可以在 ItemReader 中实现这个调用,然后在存储过程完成调用后返回 null。这...

honeymoose
今天
67
0
Linux日志分析

1. Linux日志文件的类型 2. 系统服务日志 2.1 syslogd的简介 2.2 syslogd的配置和使用 2.3 日志的安全性设置 2.4 远程日志记录服务 3. 日志的轮替 3.1 logrotate简介 3.2 logrotate的配置 3....

JiaMing
昨天
67
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部