学会git-rebase看这一篇就可以了
source link: https://segmentfault.com/a/1190000030688343
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
前言
哈喽,everybody,不知不觉8天的小长假也接近了尾声,玩耍了这么多天,今天也要收一收心,开始学习了呦~。明天就要上班啦,今天姐姐突然问我git-rebase指令是干什么的,怎么用?其实我是不想给他讲的,但是还是没有逃过姐姐的软磨硬泡,那么我们就一起来看一看什么是git-rebase吧!!!
缘起
话说,我和姐姐的缘分是在那一个月黑风高的晚上,啪,姐姐一巴掌打在了我的脸上并说了一句:能不能讲重点~~~。哈哈,不开玩笑了,直接说重点吧。我们先来看一个场景,我查看了一下我github上的个人仓库, commit
提交次数很多,提交内容如下:
这么多的提交,有很多没有规范的命名,因为是自己使用,就随便开整了,这确实不好,还有一些没有必要的提交,其实是可以合并到一起的,这样会导致如下问题:
- 造成分支污染,项目中充满了许多
commit
记录,当出现紧急问题需要回滚代码时,就只能一条条的查看了。 - 代码
review
不方便,当你要做code review
时,一个很小的功能却提交了很多次,看起来就不是很方便了。
这一篇文章我们先不讲 git
提交规范,我们先来解决一下如何合并多次提交记录。
rebase作用一:合并提交记录
通过上面的场景,我们可以引申出 git-rebase
的第一个作用:合并提交记录。现在我们想合并最近5次的提交记录,执行:
$ git rebase -i HEAD~2
执行该指令后会自动弹出 vim
编辑模式:
pick e2c71c6 update readme pick 3d2c660 wip: merge` # Rebase 5f47a82..3d2c660 onto 5f47a82 (2 commands) # # Commands: # p, pick <commit> = use commit # r, reword <commit> = use commit, but edit the commit message # e, edit <commit> = use commit, but stop for amending # s, squash <commit> = use commit, but meld into previous commit # f, fixup <commit> = like "squash", but discard this commit's log message # x, exec <command> = run command (the rest of the line) using shell # b, break = stop here (continue rebase later with 'git rebase --continue') # d, drop <commit> = remove commit # l, label <label> = label current HEAD with a name # t, reset <label> = reset HEAD to a label # m, merge [-C <commit> | -c <commit>] <label> [# <oneline>] # . create a merge commit using the original merge commit's # . message (or the oneline, if no original merge commit was # . specified). Use -c <commit> to reword the commit message. # # These lines can be re-ordered; they are executed from top to bottom. # # If you remove a line here THAT COMMIT WILL BE LOST. # # However, if you remove everything, the rebase will be aborted. # # Note that empty commits are commented out
从这里我们可以看出前面5行是我们要合并的记录,不过前面都带了一个相同的指令: pick
,这是什么指令呢,不要慌,这不,下面已经给出了 commands
:
pick:保留该commit(缩写:p) reword:保留该commit,但我需要修改该commit的注释(缩写:r) edit:保留该commit, 但我要停下来修改该提交(不仅仅修改注释)(缩写:e) squash:将该commit和前一个commit合并(缩写:s) fixup:将该commit和前一个commit合并,但我不要保留该提交的注释信息(缩写:f) exec:执行shell命令(缩写:x) drop:我要丢弃该commit(缩写:d) label:用名称标记当前HEAD(缩写:l) reset:将HEAD重置为标签(缩写:t) merge:创建一个合并分支并使用原版分支的commit的注释(缩写:m)
根据这些指令,我们可以进行修改,如下:
pick e2c71c6 update readme s 3d2c660 wip: merge`
修改好后,我们点击保存退出,就会进入注释界面:
# This is a combination of 2 commits. # This is the 1st commit message: update readme # This is the commit message #2: wip: merge` # Please enter the commit message for your changes. Lines starting # with '#' will be ignored, and an empty message aborts the commit. # # Date: Thu Sep 17 22:03:52 2020 +0800 # # interactive rebase in progress; onto 5f47a82 # Last commands done (2 commands done): # pick e2c71c6 update readme # squash 3d2c660 wip: merge` # No commands remaining. # You are currently rebasing branch 'master' on '5f47a82'. # # Changes to be committed: # new file: hash/.idea/.gitignore # new file: hash/.idea/hash.iml # new file: hash/.idea/misc.xml # new file: hash/.idea/modules.xml # new file: hash/.idea/vcs.xml # new file: hash/go.mod # new file: hash/hash/main.go # modified: snowFlake/Readme.md
上面把每一次的提交的 meassage
都列出了,因为我们要合并这两次的 commit
,所以提交注释可以修改成一条,最终编辑如下:
# This is a combination of 2 commits. # This is the 1st commit message: fix: merge update and wip: merge` # Please enter the commit message for your changes. Lines starting # with '#' will be ignored, and an empty message aborts the commit. # # Date: Thu Sep 17 22:03:52 2020 +0800 # # interactive rebase in progress; onto 5f47a82 # Last commands done (2 commands done): # pick e2c71c6 update readme # squash 3d2c660 wip: merge` # No commands remaining. # You are currently rebasing branch 'master' on '5f47a82'. # # Changes to be committed: # new file: hash/.idea/.gitignore # new file: hash/.idea/hash.iml # new file: hash/.idea/misc.xml # new file: hash/.idea/modules.xml # new file: hash/.idea/vcs.xml # new file: hash/go.mod # new file: hash/hash/main.go # modified: snowFlake/Readme.md
编辑好后,保存退出就可以了。这样就完成了一次合并 commit
。我们来验证一下:
$ git log 15ace34 (HEAD -> master) fix: merge update and wip: merge` 5f47a82 update snowFlake code
从这里我们可以看到,两次提交变成了一次,减少了无用的提交信息。
作用二:分支合并
这个作用我们使用的很少,但是还是要知道,下面我们一起来看一下使用场景。
假设我们现在有一个新项目,现在我们要从 master
分支切出来一个 dev
分支,进行开发:
$ git checkout -b dev
这时候,你的同事完成了一次 hotfix
,并合并入了 master
分支,此时 master
已经领先于你的 dev
分支了:
同事修复完事后,在群里通知了一声,正好是你需要的部分,所以我们现在要同步 master
分支的改动,使用 merge
进行合并:
$ git merge master
图中绿色的点就是我们合并之后的结果,执行 git log
就会在记录里发现一些 merge
的信息,但是我们觉得这样污染了 commit
记录,想要保持一份干净的 commit
,怎么办呢?这时候, git rebase
就派上用场了。
所以现在我们来试一试使用 git rebase
,我们先回退到同事 hotfix
后合并 master
的步骤,我现在不使用 merge
进行合并了,直接使用 rebase
指令
$ git rebase master
这时, git
会把 dev
分支里面的每个 commit
取消掉,然后把上面的操作临时保存成 patch
文件,存在 .git/rebase
目录下;然后,把 dev
分支更新到最新的 master
分支;最后,把上面保存的 patch
文件应用到 dev
分支上;
从 commit
记录我们可以看出来, dev
分支是基于 hotfix
合并后的 master
,自然而然的成为了最领先的分支,而且没有 merge
的 commit
记录,是不是感觉很舒服了。
我们在使用 rebase
合并分支时,也会出现 conflict
,在这种情况下, git
会停止 rebase
并会让你去解决冲突。在解决完冲突后,用 git add
命令去更新这些内容。然后再次执行 git rebase --continue
,这样 git
会继续应用余下的 patch
补丁文件。
假如我们现在不想在执行这次 rebase
操作了,都可以通过 --abort
回到开始前状态:
git rebase --abort
rebase
是存在危险的操作 - 慎用
我们现在使用 rebase
操作看起来是完美的,但是他也是存在一定危险的,下面我们就一起来看一看。
现在假设我们在 dev
分支进行开发,执行了 rebase
操作后,在提交代码到远程之前,是这样的:
提交 dev
分支到远程代码仓库后,就变成了这样:
而此时你的同事也在 dev
上开发,他的分支依然还是以前的 dev
,并没有进行同步 master
:
那么当他 pull
远程 master
的时候,就会有丢失提交纪录。这就是为什么我们经常听到有人说 git rebase
是一个危险命令,因为它改变了历史,我们应该谨慎使用。
不过,如果你的分支上需要 rebase
的所有 commits
历史还没有被 push
过,就可以安全地使用 git-rebase
来操作。
总结
在 asong
的细心讲解下,姐姐完全搞懂了怎么使用 git rebase
,我们来看一下姐姐的总结:
- 当我们在一个过时的分支上面开发的时候,执行
rebase
以此同步master
分支最新变动; - 假如我们要启动一个放置了很久的并行工作,现在有时间来继续这件事情,很显然这个分支已经落后了。这时候需要在最新的基准上面开始工作,所以
rebase
是最合适的选择。 -
git-rebase
很完美,解决了我们的两个问题:commit merge
- 使用
rebase
操作要注意一个问题,如果你的分支上需要rebase
的所有commits
历史还没有被push
过,就可以安全地使用git-rebase
来操作。
看来姐姐是真的学会了,那你们呢?
没有学会不要紧,亲自试验一下才能更好的理解呦~~~。
好啦这一篇文章到这里就结束了,我们下期见。
结尾给大家发一个小福利吧,最近我在看[微服务架构设计模式]这一本书,讲的很好,自己也收集了一本PDF,有需要的小伙可以到自行下载。获取方式:关注公众号:[Golang梦工厂],后台回复:[微服务],即可获取。
我翻译了一份GIN中文文档,会定期进行维护,有需要的小伙伴后台回复[gin]即可下载。
我是asong,一名普普通通的程序猿,让我一起慢慢变强吧。我自己建了一个 golang
交流群,有需要的小伙伴加我 vx
,我拉你入群。欢迎各位的关注,我们下期见~~~
Recommend
-
8
在我们日常工作中,代码写着写着就出现下列的一些臭味。但是还好我们有SOLID这把‘尺子’, 可以拿着它不断去衡量我们写的代码,除去代码臭味。这就是我们要学习SOLID原则的原因所在。 设计的臭味 僵化性 具有联动性,...
-
20
上一篇讲 Git 的文章发出来没想到效果特别好,很多读者都要求继续深入的写。 那今天齐姐简单讲下 Git 的实现原理,知其所以然才能知其然;并且梳理了日常最常用的 12 个命令,分为三大类分享给你。 本文的结构如下:
-
6
在日常工作中,经常会用到Git操作。但是对于新人来讲,刚上来对Git很陌生,操作起来也很懵逼。本篇文章主要针对刚开始接触Git的新人,理解Git的基本原理,掌握常用的一些命令。 一、Git工作流程 以上包括一些简单而...
-
37
原文链接 前言 嗨,everybody,我是asong,这是我的第十二篇文章,今天给大家介绍一下雪花算法。介绍雪花算法是次要的,因为大家都太熟悉了,主...
-
74
了解NodeJS看这一篇就够了
-
82
-
95
关于 JVM 知识看这一篇就够了
-
72
介绍Kotlin编程语言的基础知识,以及如何在Android开发中使用Kotlin
-
81
本文由 玉刚说写作平台 提供写作赞助 原作者:ZedeChan 版权声明:本文版权归微信公众号 玉刚说 所有,未经许可,不得以任何形式转载 0. 简介 RxJava 其实就是提供一套异步编程的 API,这套 API 是基于观察者模式的,而且是链式调用的,所以
-
56
营销文案写作十五字诀:懂策略、说人话、吸眼球、有人味、促销售。 一、营销文案写作十五字诀:懂策略 首先我们要问:什么是策略? 其实,策略是一个抽象、难以理解、没有统一标准的词汇。原本是不应该拿来作为通俗理论来阐述,因为这增加了读者的阅读与理解的障碍...
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK