前言
git rerere 功能是一个隐藏的功能。 正如它的名字 “reuse recorded resolution” 所指,它允许你让 Git 记住解决一个块冲突的方法,这样在下一次看到相同冲突时,Git 可以为你自动地解决它
(呜呼呼~ 最近真的有点忙,差点我都忘了写博客了!赶紧补上一篇)
相信大家也在平常工作中会用到 git,我也在不断持续学习 git,毕竟说实话 git 可能是 21 世纪里最流行的开源分布式版本控制系统了。
然后我在学习 git 的过程中,发现了一个隐蔽很深但相当实用的 git 工具命令 —— git rerere。以下我将带大家用从 0 到 1 建立仓库并演示一遍 git rerere 的使用流程。
准备工作
初始化一个示例仓库
$ mkdir git-rerere-example
$ cd git-rerere-example/
$ git init
复制代码
进行一个初始化提交
$ echo 'v1.0' > README.md
$ git add .
$ git commit -m "version 1.0"
复制代码
用 git status 查看当前工作树状态
$ git status
On branch master
nothing to commit, working tree clean
复制代码
ok,当前我们在 master 分支,我们来创建一个特性分支 feat 用来开发某个功能
$ git checkout -b feat
Switched to a new branch 'feat'
复制代码
很好此时我们有两个分支了。准备工作完成!
$ git branch
* feat
master
复制代码
等等!我们还没开启 git rerere 功能,这个很简单!我选择全局配置 git config。当然也可以只是配置当前仓库,把 --global 标识符给去掉即可。
$ git config --global rerere.enabled true
复制代码
查看是否配置成功,可以看到 rerere.enabled=true,于是准备工作 done!
$ git config --global --list
user.email=USERNAME@gmail.com
user.name=USERNAME
core.editor=vim
rerere.enabled=true
复制代码
演示冲突
假设团队成员 Tom 在 feat 分支上做了一些激动人心的功能,并且发了个特性版本!并且将 README.md 的版本内容声明改成了 v1.1,如下:
$ echo 'feat: blah' > feat-blah.txt
$ echo 'v1.1' > README.md
复制代码
于是成员 Tom 淡定的在 feat 分支上提交了一个 commit
$ git add .
$ git commit -m "version v1.1"
[feat b1c500b] version v1.1
2 files changed, 2 insertions(+), 1 deletion(-)
create mode 100644 feat-blah.txt
复制代码
查看当前提交情况,可知我们目前 HEAD 指针在 feat 分支,commit 领先于 master
$ git log --graph --oneline
* b1c500b (HEAD -> feat) version v1.1
* 03bf028 (master) version 1.0
复制代码
让我们切换到 master 分支,同时假设我们身份是另一个团队成员 Jerry。
$ git checkout master
Switched to branch 'master'
复制代码
成员 Jerry 默默地在 master 分支上工作,同时发了一个大版本 v2.0,如下:
$ echo 'enjoy weekend!' > daily.txt
$ echo 'v2.0' > README.md
$ git add .
$ git commit -m "version 2.0"
[master 4ab5514] version 2.0
2 files changed, 2 insertions(+), 1 deletion(-)
create mode 100644 daily.txt
复制代码
再查看当前提交情况!
$ git log --graph --oneline
* 4ab5514 (HEAD -> master) version 2.0
* 03bf028 version 1.0
复制代码
过了一段时间,成员 Jerry 觉得可以合并成员 Tom 的特性分支 feat 了~ 于是如下:
$ git merge feat
Auto-merging README.md
CONFLICT (content): Merge conflict in README.md
Recorded preimage for 'README.md'
Automatic merge failed; fix conflicts and then commit the result.
复制代码
看看冲突内容
$ cat README.md
<<<<<<< HEAD
v2.0
=======
v1.1
>>>>>>> feat
复制代码
但是留意以上 Recorded preimage for 'README.md' 这句提示,git 正在记录你解决冲突的操作!
成员 Jerry 保留自己的改动(因为 master 版本大于 feat 版本),解决了冲突!
$ git checkout --ours README.md
$ cat README.md
v2.0
复制代码
于是提交一个新的 commit!
$ git add .
$ git commit -m "merge feat"
Recorded resolution for 'README.md'.
[master f1ed9a5] merge feat
复制代码
此时发现 git 提示和以往不一样了,多了一句 Recorded resolution for 'README.md'.
使用 git rerere 自动解决冲突
在此之前,查看当前提交情况!可见成功合并了 feat,并且 HEAD 指针在 f1ed9a5
$ git log --graph --oneline
* f1ed9a5 (HEAD -> master) merge feat
|\
| * b1c500b (feat) version v1.1
* | 4ab5514 version 2.0
|/
* 03bf028 version 1.0
复制代码
既然 git 已经记录我们解决冲突的操作,此时让我们重置到 4ab5514(合并 feat 分支之前),也就是上一个提交,可用 HEAD^ 表示
$ git reset --hard HEAD^
HEAD is now at 4ab5514 version 2.0
复制代码
很好,让我们再尝试一下合并 feat 分支!
$ git merge feat
Auto-merging README.md
CONFLICT (content): Merge conflict in README.md
Resolved 'README.md' using previous resolution.
Automatic merge failed; fix conflicts and then commit the result.
复制代码
此时 git 提示我们 Resolved 'README.md' using previous resolution. 告诉我们自动用我们之前的冲突解决策略解决了 README.md 的冲突
亲眼见证一下!果然成功了,而且在它里面没有合并冲突标记
$ cat README.md
v2.0
复制代码
当然如果改变想法了,不想用之前的合并冲突策略,也可以
$ git checkout --conflict=merge README.md
$ cat README.md
<<<<<<< ours
v2.0
=======
v1.1
>>>>>>> theirs
复制代码
这时候就可以重新解决了!
然后你想了想,又想用回之前的合并冲突策略,这时候就直接可以用 git rerere 命令来指示 git 操作
$ git rerere
Resolved 'README.md' using previous resolution.
复制代码
变基
反而言之,我们变基特性分支 feat,一样可以!
$ git checkout feat
$ git rebase master
...
Auto-merging README.md
CONFLICT (content): Merge conflict in README.md
Resolved 'README.md' using previous resolution.
...
复制代码
同样 git 提示了我们 Resolved 'README.md' using previous resolution. 一样复用了之前的合并冲突策略
$ cat README.md
v2.0
复制代码
然后我们确认无误,如下操作进行提交
$ git add .
$ git rebase --continue
Applying: version v1.1
复制代码
此时我们查看 commit 提交情况,变基成功!
$ git log --graph --oneline
* 2e34640 (HEAD -> feat) version v1.1
* 4ab5514 (master) version 2.0
* 03bf028 version 1.0
复制代码
至此演示已经基本结束了,同学们 get 到了么?
应用场景
因为 git rerere 会记住解决一个块冲突的方法,因此至少有以下应用场景:
- 需要进行多次的重新合并的时候(比如合并 feat 分支,提交测试发现失败,然后重置回去重新合并)
- 某个特性分支与主开发分支一直保持最新,解决相同的块冲突!
- 经常使用变基(如以上 feat 分支变基)
总而言之,git rerere 是个相当不错的工具,使用得当的情况下,对工作效率的提升很有帮助~
小结
建议同学们可以根据以上流程在命令行中体验一次,然后也可以在工作中使用,说不定会有意外之喜~ 同时也建议大家可以参考官方文档 Git 工具 - Rerere 学习。
最后,这篇文章对大家如有助益,不胜荣幸~