乐趣区

关于golang:学会gitrebase看这一篇就可以了

前言

哈喽,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,自然而然的成为了最当先的分支,而且没有 mergecommit 记录,是不是感觉很难受了。

咱们在应用 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, 我拉你入群。欢送各位的关注,咱们下期见~~~

举荐往期文章:

  • 手把手教姐姐写音讯队列
  • 详解 Context 包,看这一篇就够了!!!
  • go-ElasticSearch 入门看这一篇就够了(一)
  • 面试官:go 中 for-range 应用过吗?这几个问题你能解释一下起因吗
  • 学会 wire 依赖注入、cron 定时工作其实就这么简略!
  • 据说你还不会 jwt 和 swagger- 饭我都不吃了带着实际我的项目我就来了
  • 把握这些 Go 语言个性,你的程度将进步 N 个品位(二)
  • go 实现多人聊天室,在这里你想聊什么都能够的啦!!!
  • grpc 实际 - 学会 grpc 就是这么简略
  • go 规范库 rpc 实际
  • 2020 最新 Gin 框架中文文档 asong 又捡起来了英语,用心翻译
  • 基于 gin 的几种热加载形式
  • boss: 这小子还不会应用 validator 库进行数据校验,开了~~~
退出移动版