Git中的merge命令实现和工作方式
想象一下有例如以下情形:代码库中存在两个分支,而且每一个分支都进行了改动。最后你想要将当中的一个分支合并到其它的分支中。个人博客网址 http://swinghu.github.com/
那么要问合并的处理过程是怎么样的呢?Git是对每一个分支,根据分支的历史数据依照序列化操作,还是它仅仅是合并每一个分支里文件的最后版本号?这是一个问题,我想对git的merge操作有必要进行分析一下。
回顾一下。我们知道Git的版本号库内部结构是以有向无环图(directed)组织起来的:每一次
acyclic graphcommit都会生成一个版本号树的快照(snapshot),而且该快照保存了一个指向其父节点(该分支的近期上一次的提交快照)的引用(通常当前提交仅仅有一个父节点,可是初试提交快照没有父节点,而一次合并(merge)操作有2个或多个父节点)。
就像这样。每次提交都递归的建立某些节点集指向父节点的引用。
有时候,当我们考虑提交的父节点提交树和当前节提交节点树做差异比較时(diff),将一次提交想象成一次修补补丁(patch)是有助于我们理解git 的工作机理。依照这样的方式,我们能够这样觉得,提交树就是集成应用了全部父节点的补丁修补。一颗在两个分支上做merge操作的树,因此就能够觉得是两个分支应用了其各自全部的父节点修补补丁程序,然后做一次联合操作Union。
可是那不是git merge 的真正运行方式。原因是。首先。假设以那样工作的话。运行会很的慢!,而且在运行过程中它要再一次又一次处理全部的之前合并时造成的冲突。如此,git 真正是怎样操作的呢?
merge
我喜欢用数学的思维方式思考:给定两个提交 A和 B,合并提交(commit)操作 A∨B 就能够描写叙述为: [A∨B ]=[ A]+[ B]−[ C ] 这里的 C是A 和 B的合并共同拥有项(近期提交树祖先共同含有的部分)。我们必需要“减去” C。由于假设不这种话,我们就会有两个A∧B。
这个操作x+y−z 被叫做三向合并。
你能够觉得运行路径为将x−z 应用到x 上,或者将 x−z应用到y 上。
其实diff和patch操作并没有字面上依照上面的的操作行事,相反而是使用了:最长公共子序列算法来实现。x−w和序列x,序列w的差异就是我们知道的在求最长公共子序列时的赋值(中间可能要去除到两个序列的公共部分)。为了构造三向合并x+y−w,我们对x和w在求公共子序列的时候进行赋值。对y和w在求公共子序列的时候赋值。然后输出每一个要么:
- 三个序列的共同拥有部分,或者
- 在x 中出现。可是在y 和 w 中不存在的部分,或者
- 在y 中出现,可是在x 和w 中没有出现的部分
同一时候我们要删除那些序列,要么:
- 出如今y 和 w可是在x中没有出现,或者
- 出如今x和w中可是在y中没有出现。
举个栗子,下面是x,y,z 运行merge操作后的结果:
x: w: y: ↦ merged:milk milk milk milkjuice juiceflour flour flour floursausage sausagegiteggs eggs eggs eggsbutter butter
在x,y与w的行序可能只说明了一种在三向合并的输出行上的一种偏序关系。假设是这种话,因为相同的块w,在x,y 之间以不同的方式被编辑-因此我们说那就是一个合并冲突。将会输出该信息,让用户手动解决。
当git 向你显示合并冲突的时候,默认情况下,你将会看到x和的冲突块:
然而,冲突块会变得更easy解决,当你可以看到合并基准w的时候。
我建议打开开关:
~/.gitconfig
通过设置merge.conflictstyle 为diff3,则
git config --global merge.conflictstyle diff3
如今你能够看到解决方案为:
I had two eggs and three sausages for breakfast.
(注意,这个操作会对称性的(关于w和结果进行交换,因此你真正须要的是查看w)这里有另外两种其它的案例须要考虑,可能行为:
- 出如今x和y中,可是在w中没有出现
- 出如今w中。可是没有在x 和y 中出现
某些三向合并算法常常将这样的行标记为冲突行。
然而Git,将会优雅的输出或者直接删除该行,依次,假定该行没有改变。
这样的效果叫做意外清理合并。偶尔某些情形在实际应用中非常实用,尤其是用户把版本号搞砸了,各自合并同一个补丁的两个不同的版本号。
可是我觉得掩盖这样的错误不是一种好的行事方式,我希望这样的行为能够并关闭。尽量避免由于他所能带来的这样的长处而使用它吧。
假设你细致。非常有观察力,你可能已经发现我在上述说明中存在的一个漏洞了:因为commit提交 A和B可能各自又包括commit,他们近期的共同祖先可能不是唯一的!
一般。他们最有可能的情形是,近期的共同祖先是 C1,C2,C3,C4,⋯Ck−1,Ck ,在这样的情况下,git 操作将会递归的运行:它首先构造合并 C=C1∨C2∨C3⋯Ck−1∨Ck 。并以此作为三向合并[ A ]+[ B ]−[ C ] 的基础(
mergebase)。
这就是为什么Git的默认合并策略并称为递归的。
假定两个分支例如以下图所看到的。A,B,C,D,E是master分支的历史快照(snapshot);A,B,X,Y,Z是feature分子的历史快照。
命令
git merge feature
首先查找“master”(当前分支)和“feature”的共同祖先。它或多或少的等价于下面命令:
git merge-base master feature
在我们的举的样例里,他们的共同祖先是B。
假设在C,D,E和X,Y,Z提交中没有冲突,git 将会创建一次“merge”
commit merge commit会有两到多个父亲。 新的图将会是以下这个样子。
每一次git 提交都会生成一棵树,一到多个“父亲节点”。作者的名字,
commitemail,日期和提交者的姓名。email,日期。
merge提交和普通的提交的唯一差别就是祖先的数量。
在第二幅图中,merge commit提交被以M标注出来了。
假设提交存在冲突,用户就会被要求解决冲突,并手动创建合并提交,在冲突解决后
git commit -a
将会创建合并提交。这条命令没什么特殊的语法。Git 已经知道了用户已经在进行合并了(已经在尝试合并)。
Git中的merge命令实现和工作方式的更多相关文章
- Git中的merge命令实现中出现问题及其解决
Git中的merge命令实现和工作方式 2015年8月17日星期一 丹丹 git代码在合并两个分支的时候总是会出现一下的错误提示,不能正常的完成合并分支,错误提示如图所示: 但是在其他的终端是可以完成 ...
- GIT中常用的命令
最近项目中使用到了GIT,所以记录一下GIT中常用的命令. GIT使用的客户端有Git Bash:http://code.google.com/p/msysgit/ 还有乌龟TortoiseGit:h ...
- 总结下git中一些常用命令
一.目录操作 1.cd 即change directory,改变目录,如 cd d:/www,切换到d盘的www目录. 2.cd .. cd+空格+两个点,回退到上一目录. 3.pwd 即 print ...
- Git知识总览(五) Git中的merge、rebase、cherry-pick以及交互式rebase
上篇博客聊了<git分支管理之rebase 以及 cherry-pick相关操作>本篇博客我们就以Learning Git中的关卡进行展开.下方列举了LearningGit中的 merge ...
- Git中分支merge和rebase的适用场景及区别
Git merge是用来合并两个分支的. git merge b # 将b分支合并到当前分支 同样 git rebase b,也是把 b分支合并到当前分支 原理 如下: 假设你现在基于远程分 ...
- Git中特别的命令
Rebase 假设我们的分支结构如下: rebase 会把从 Merge Base 以来的所有提交,以补丁的形式一个一个重新达到目标分支上.这使得目标分支合并该分支的时候会直接 Fast Forwar ...
- 关于Git中分支merge和rebase的适用场景及区别
最近刚接触Git,下面对一些基本的使用做一下总结. 本文是转载于CSDN:http://blog.csdn.net/rryqsh/article/details/8230560 几乎所有的版本控制工具 ...
- git中的merge与rebase
之前一直对git的merge与rebase很困惑,而且一般也只使用merge而不是使用rebase.今天受高人指点理清了两者的区别. 首先对于两者而言,他们的结果是一样的,差异在于合并的方式(产生的结 ...
- git 中的 merge 和 rebase
示例分支:master . dev 把 dev 分支上的新内容合并到 master 上 先切换分支到master git checkout master 合并操作 git merge dev 或者 g ...
随机推荐
- MVC与WebForm的简单的比较
MVC与WebForm的简单的比较 ASP 强制程序员将业务逻辑和展示页放到一个文件中 WebForm 允许程序员将业务逻辑与页面展示分开到不同的文件中,并且提供强大的开发平台来写 业务逻辑代码 ...
- <转载>使CSS文字图片div元素居中方法之水平居中的几个方法
文字居中,文字垂直居中水平居中,图片居中,图片水平居中垂直居中,块元素垂直居中?当我们在做前端开发是时候关于css居中的问题是很常见的.情 况有很多种,不同的情况又有不同的解决方式.水平居中的方式解决 ...
- JQuery - MD5加密
效果: JS代码: 命名为任意名称,一般为:Jquery.md5.js /** * jQuery MD5 hash algorithm function * * <code> * Calc ...
- java 基于JDK中的源码总结下String二
申明:转载请注明出处,如有商用目的请务必知会本人,感谢. 上一篇文章:http://blog.csdn.net/ts1122/article/details/8738336,介绍了String一些易错 ...
- Java面试题精选(三) JSP/Servlet Java面试逻辑题
-- JSP/Servlet Java面试逻辑题 -- 很显然,Servlet/JSP的WEB前端动态制作的重要性比HTML/CSS/JS的价值高很多,但我们都知道他们都是建立在HT ...
- Mac上利用Eclipse编译Cocos2d-x
目前使用较多的Cocos2d-x开发平台是XCode,应该是由于大部分Cocos2d-x开发者都是iOS开发出生.但是当我们将XCode开发的Cocos2d-x工程发布Android版本时,每次都需要 ...
- VxWorks6.6 pcPentium BSP 使用说明(二):创建启动盘
本篇介绍从Solaris.Linux.Windows或VxWorks创建VxWorks启动盘的方法. 从Solaris或Linux创建启动盘 使用Solaris或Linux自带的工具/usr/bin/ ...
- 用js制作的几个效果
一,表格光柱效果(奇偶行不同颜色,鼠标移上变色) <html xmlns="http://www.w3.org/1999/xhtml"><head>< ...
- 解决Ajax.BeginForm还是刷新页面的问题
在.net mvc中用Ajax.BeginForm来实现异步提交,在Ajax.BeginForm里面还是可以用submit按钮,一般来说 submit按钮是提交整个页面的数据.但是在Ajax.Begi ...
- VC++2005、VC2008中Release版本设置为可调试的设置方法
一.很多时候需要在Release版本下调试程序,可以使用以下方法设置: 1.无效断点所在的项目和启动项目的设置:项目->属性->配置属性->C/C++->常规->调试信息 ...