Git笔记(33) Rerere

  • 1. 重用记录的解决方案
  • 2. 干净的合并和变基
  • 3. 举例

1. 重用记录的解决方案

git rerere 功能是一个隐藏的功能
正如它的名字“重用记录的解决方案(reuse recorded resolution)”所示
它允许让 Git 记住解决一个块冲突的方法, 这样在下一次看到相同冲突时,Git 可以为你自动地解决它

要启用 rerere 功能,只需运行以下配置选项即可:

$ git config --global rerere.enabled true

你也可以通过在特定的仓库中创建 .git/rr-cache 目录来开启它
但是设置选项更干净并且可以应用到全局


2. 干净的合并和变基

想要保证一个长期分支会干净地合并
但是又不想要一串中间的合并提交弄乱你的提交历史

rerere 功能开启后,可以试着偶尔合并,解决冲突,然后退出合并
如果你持续这样做,那么最终的合并会很容易,因为 rerere 可以为自动做所有的事情

可以将同样的策略用在维持一个变基的分支时
这样就不用每次解决同样的变基冲突了

或者你将一个分支合并并修复了一堆冲突后想要用变基来替代合并
可能并不想要再次解决相同的冲突

当偶尔将一堆正在改进的主题分支合并到一个可测试的头时
如果测试失败,可以倒回合并之前
然后在去除导致测试失败的那个主题分支后重做合并
而不用再次重新解决所有的冲突


3. 举例

假设有一个名为 hello.rb 的文件如下:

#! /usr/bin/env rubydef helloputs 'hello world'
end

在一个分支中修改单词 “hello” 为 “hola
然后在另一个分支中修改 “world” 为 “mundo

当合并两个分支到一起时,我们将会得到一个合并冲突:

$ git merge i18n-world
Auto-merging hello.rb
CONFLICT (content): Merge conflict in hello.rb
Recorded preimage for 'hello.rb'
Automatic merge failed; fix conflicts and then commit the result.

会注意到那个新行 Recorded preimage for FILE
除此之外它应该看起来就像一个普通的合并冲突

在这个时候,rerere 可以告诉我们几件事
和往常一样,在这个时候你可以运行 git status 来查看所有冲突的内容:

$ git status
# On branch master
# Unmerged paths:
#   (use "git reset HEAD <file>..." to unstage)
#   (use "git add <file>..." to mark resolution)
#
#   both modified:      hello.rb
#

然而,git rerere 也会通过 git rerere status 告诉你它记录的合并前状态

$ git rerere status
hello.rb

并且 git rerere diff 将会显示解决方案的当前状态(开始解决前与解决后的样子)

$ git rerere diff
--- a/hello.rb
+++ b/hello.rb
@@ -1,11 +1,11 @@#! /usr/bin/env rubydef hello
-<<<<<<<
-  puts 'hello mundo'
-=======
+<<<<<<< HEADputs 'hola world'
->>>>>>>
+=======
+  puts 'hello mundo'
+>>>>>>> i18n-worldend

同样可以使用 git ls-files -u 来查看冲突文件的之前、左边与右边版本:

$ git ls-files -u
100644 39804c942a9c1f2c03dc7c5ebcd7f3e3a6b97519 1   hello.rb
100644 a440db6e8d1fd76ad438a49025a9ad9ce746f581 2   hello.rb
100644 54336ba847c3758ab604876419607e9443848474 3   hello.rb

现在可以通过改为 puts 'hola mundo' 来解决它
可以再次运行 git rerere diff 命令来查看 rerere 将会记住的内容:

$ git rerere diff
--- a/hello.rb
+++ b/hello.rb
@@ -1,11 +1,7 @@#! /usr/bin/env rubydef hello
-<<<<<<<
-  puts 'hello mundo'
-=======
-  puts 'hola world'
->>>>>>>
+  puts 'hola mundo'end

现在我们可以将它标记为已解决并提交它:

$ git add hello.rb
$ git commit
Recorded resolution for 'hello.rb'.
[master 68e16e5] Merge branch 'i18n'

可以看到它 “Recorded resolution for FILE

现在如果想撤消那个合并然后将它变基到 master 分支顶部来替代它
可以通过使用之前在 Git笔记(31) 重置揭密 看到的 git reset 来回滚分支

$ git reset --hard HEAD^
HEAD is now at ad63f15 i18n the hello

我们的合并被撤消了

现在变基主题分支

$ git checkout i18n-world
Switched to branch 'i18n-world'$ git rebase master
First, rewinding head to replay your work on top of it...
Applying: i18n one word
Using index info to reconstruct a base tree...
Falling back to patching base and 3-way merge...
Auto-merging hello.rb
CONFLICT (content): Merge conflict in hello.rb
Resolved 'hello.rb' using previous resolution.
Failed to merge in the changes.
Patch failed at 0001 i18n one word

现在,正像我们期望的一样,得到了相同的合并冲突
但是看一下 Resolved FILE using previous resolution 这行
如果看这个文件,会发现它已经被解决了,而且在它里面没有合并冲突标记

#! /usr/bin/env rubydef helloputs 'hola mundo'
end

同样,git diff 将会显示出它是如何自动地重新解决的:

$ git diff
diff --cc hello.rb
index a440db6,54336ba..0000000
--- a/hello.rb
+++ b/hello.rb
@@@ -1,7 -1,7 +1,7 @@@#! /usr/bin/env rubydef hello
-   puts 'hola world'-  puts 'hello mundo'
++  puts 'hola mundo'end


可以通过 git checkout 命令重新恢复到冲突时候的文件状态:

$ git checkout --conflict=merge hello.rb
$ cat hello.rb
#! /usr/bin/env rubydef helloputs 'hello mundo'
end

在 Git笔记(32) 高级合并 中已看过这个例子
然而现在,通过运行 git rerere 来重新解决它:

$ git rerere
Resolved 'hello.rb' using previous resolution.
$ cat hello.rb
#! /usr/bin/env rubydef helloputs 'hola mundo'
end

通过 rerere 缓存的解决方案来自动重新解决了文件冲突
现在可以添加并继续变基来完成它

$ git add hello.rb
$ git rebase --continue
Applying: i18n one word

所以,如果做了很多次重新合并
或者想要一个主题分支始终与你的 master 分支保持最新但却不想要一大堆合并, 或者经常变基
打开 rerere 功能可以帮助你的工作


参考: git
以上内容,均根据git官网介绍删减、添加和修改组成


相关推荐:

Git笔记(32) 高级合并
Git笔记(31) 重置揭密
Git笔记(30) 重写历史
Git笔记(29) 搜索
Git笔记(28) 签署工作


谢谢

Git笔记(33) Rerere相关推荐

  1. Git笔记(38) 凭证存储

    Git笔记(38) 凭证存储 1. 凭证存储 2. 底层实现 3. 自定义凭证缓存 1. 凭证存储 如果使用的是 SSH 方式连接远端,并且设置了一个没有口令的密钥 就可以在不输入用户名和密码的情况下 ...

  2. Git笔记(37) 替换

    Git笔记(37) 替换 1. 替换 2. 举例 1. 替换 之前强调过,Git 对象数据库中的对象是不可改变的 然而 Git 提供了一种有趣的方式来用其他对象 假装 替换数据库中的 Git 对象 r ...

  3. Git笔记(36) 打包

    Git笔记(36) 打包 1. 打包 2. 举例 1. 打包 虽然我们已经了解了网络传输 Git 数据的常用方法(如 HTTP,SSH 等) 但还有另外一种不太常见却又十分有用的方式 Git 可以将它 ...

  4. Git笔记(34) 调试

    Git笔记(34) 调试 1. 文件标注 2. 二分查找 1. 文件标注 如果在追踪代码中的一个 bug,并且想知道是什么时候以及为何会引入 文件标注通常是最好用的工具 它能 显示任何文件中每行最后一 ...

  5. Git笔记(25) 选择修订版本

    Git笔记(25) 选择修订版本 1. 单个修订版本 1.1. 简短的 SHA-1 1.2. 分支引用 1.3. 引用日志 1.4. 祖先引用 2. 提交区间 2.1. 双点 2.2. 多点 2.3. ...

  6. Git笔记(24) 维护项目

    Git笔记(24) 维护项目 1. 在特性分支中工作 2. 应用来自邮件的补丁 2.1. 使用 apply 命令应用补丁 2.2. 使用 am 命令应用补丁 3. 检出远程分支 4. 确定引入了哪些东 ...

  7. Git笔记(23) 不同角色的贡献

    Git笔记(23) 不同角色的贡献 1. 私有小型团队 2. 私有管理团队 3. 派生的公开项目 4. 通过邮件的公开项目 1. 私有小型团队 可能会遇到的最简单的配置是有一两个开发者的私有(闭源)项 ...

  8. 【Git笔记2】必知习惯和如何版本回退

    良好的习惯会让工作和生活如鱼得水,在使用git的时候有些必知习惯和概念你要get一下,总有些许失误,如:已经提交了不合适的修改到版本库时还没有把自己的本地版本库推送到远程,想要撤销本次提交,或者已经p ...

  9. 【Git笔记3】关于撤销、删除、恢复的那些事儿

    在跻身于"国庆抢票大战"的我们,不要忘记学习,今天接着上篇 [Git笔记2]必知习惯和如何版本回退,继续开干!一起来瞅瞅如何撤销没有add的修改,如何撤销以及add到暂存区的修改, ...

最新文章

  1. 【Python】Python语言学习:设计模式、单例模式
  2. 2020 年最全 Python 面试题汇总 (五)
  3. docker 不挂断创建容器
  4. leetcode 687. Longest Univalue Path | 687. 最长同值路径(树形dp)
  5. 树莓派删除python2.7设置python3.5
  6. 周末狂欢赛1(玩游戏/Game,函数,JOIOI王国)
  7. Project Euler Problem 25 1000-digit Fibonacci number
  8. Windows的同步I/O和异步I/O
  9. QT tableWidget的使用及其实例
  10. Centos-6.3-x86_64 minimal 迷你版安装笔记 - Java篇
  11. ubuntu下如何对接斗鱼直播
  12. python爬去新浪微博_使用python抓取新浪微博数据
  13. 首都师范 博弈论 3 4 2反复剔除严格劣策略
  14. Python通过蒙特卡罗法计算π值
  15. 醇酰基转移酶基因对猕猴桃酯生物合成的作用
  16. Visual Studio 2010 项目属性配置
  17. Unity Direct3D 和 OpenGL
  18. java身高排队问题_抓狂的java之小朋友排队
  19. QMidi Pro for mac(好用的卡拉OK播放器)
  20. 音频播放AudioTrack之入门篇

热门文章

  1. 一步一步重写 CodeIgniter 框架 (8) —— 视图的嵌套输出与返回
  2. poi处理excel导出
  3. 算法高级(18)-Redis Cluster选举机制
  4. 冷热水龙头_冷热水龙头结构图是怎么样的
  5. 2018.09.19python学习第七天part1
  6. 解决eclipse 文件更新不自动刷新的问题
  7. vue 跨域:使用vue-cli 配置 proxyTable 实现跨域问题
  8. 详解c++指针的指针和指针的引用
  9. 关于机器学习会议的点评
  10. 2002-2003 ACM-ICPC Northeastern European Regional Contest (NEERC 02)