git版本控制 merge 、 rebase 学习笔记
扯淡
有时候确实很烦,写的这些东西,网上都有现成的大把的资料=.=,只能说将自己的学习心得,尽量用最通俗易懂(:P 达不到这种境界 😂)记录下来,以便自己加深记忆,如果存在有误的地方,欢迎探讨交流。
参考资料
正文
一、 merge (合并)
顾名思义,就是用来合并分支的,而这个命令会根据具体情况有两种不同的合并方式:
- 快进合并
- 三方合并
下边就分别来说一下2种方式:
快进合并
举个🌰:
1.首先,容我先上张图介绍一下前情提要:
请叫我盗图王
图中现在有三条分支:
1.master (主分支) :用来发布版本的主分支。
2.iss53(工作分支):为了处理iss53 问题 而分出来的分支。
3.hotfix(紧急修复分支): 在开发过程中(我正在iss53 分支上美滋滋的搬砖,尼玛,线上出现了个紧急的问题需要先修复 :P 或许能帮助理解)紧急创建的修复分支,并做了一次修改 :C4。
- 现在那个紧急问题已经修复完成,需要合并到master上,发布新的版本。
3.这时候用到了 merge 命令 :
“$ git checkout master
$ git merge hotfix
Updating f42c576..3a0874c
Fast-forward
index.html | 2 ++
1 file changed, 2 insertions(+)”
摘录来自: Scott Chacon, Ben Straub. “Pro Git”
4.然后就会变成这样:
操作结果
5.结果:
在执行merge 命令的时候,有个“Fast-forward ”字眼,根据截图(操作结果)可以发现:master 指针只是简单的向后移动了指针。这是因为:P敲黑板,划重点了:
由于当前 master 分支所指向的提交是你当前提交(有关 hotfix 的提交)的直接上游,所以 Git 只是简单的将指针向前移动,换句话说,当你试图合并两个分支时,如果顺着一个分支走下去能够到达另一个分支,那么 Git 在合并两者的时候,只会简单的将指针向前推进(指针右移),因为这种情况下的合并操作没有需要解决的分歧——这就叫做 “快进(fast-forward)”。
摘录来自: Scott Chacon, Ben Straub. “Pro Git”。 iBooks.
6.现在最新的修改已经在master 分支的最新快照中了,可以着手尽心发布版本了。
:P 理解起来感觉挺简单,咋写出来却这么费劲! 概括一下就是如果两个分支在一条线(没分叉)上,就可以通过指针移动进行合并。
三方合并
简单来说:三个快照进行合并呗( :P想想 三方会谈 就理解了)
接着上个例子中的🌰:
1.现在切回到之前的工作分支并进行了一次提交如图:
三方合并-1
2.现在iss53 工作已经完成,要进行合并(master 和 iss53)操作
3.(:P你会发现:哎呦,分叉了啊 这个,不一样了哦),让我们执行命令:
“$ git checkout master
Switched to branch 'master'
$ git merge iss53
Merge made by the 'recursive' strategy.
index.html | 1 +
1 file changed, 1 insertion(+)”
摘录来自: Scott Chacon, Ben Straub. “Pro Git”。 iBooks.
结果:
三方合并-2
4.这种情况下 就属于三方合并:git 发现提交历史 从更早的地方开始分叉,git 会使用 两个分支的末端(c4 和 c5)快照,以及分支的共同祖先 c2 快照进行三方合并。
git 会将这次合并结果做一个新的快照,并生成一次新的提交指向它。这个操作被称作一次合并提交,它的不同之处是它不只有一个父提交。
:P 终于解释完了 ,感觉也挺简单的吧,喝个☕️。
二、 rebase (变基、衍合) :P反正叫啥都那个意思
当我第一次,见到这个命令时,反正我是一脸懵逼的(:P 什么叼命令,看着这么的抽象),不过通过自己的查阅资料、书籍,也一点点揭开了它脸上糊的面纱(:P装什么🐘呢)。
个人理解:
首先这个命令也是用来合并两个分支的。
在目标分支的基础上,将当前分支上提取的“某些”提交重演一遍(也就是将这些提交的代码在重新提交一遍)。
举个...(🌰不能停啊) :
:P 摘自 摘录来自: Scott Chacon, Ben Straub. “Pro Git”。
现在要合并 分支 experiment 和 master 有两种方式:merge 、rebase。
-
使用merge (上面已经介绍过)的结果:
basic-rebase-2.png -
使用 rebase 命令
1.🌰:
“你可以提取在 C4 中引入的补丁和修改,然后在 C3 的基础上再应用一次。 在 Git 中,这种操作就叫做 变基。 你可以使用 rebase 命令将提交到某一分支上的所有修改都移至另一分支上,就好像“重新播放”一样。”
执行命令:
“$ git checkout experiment
$ git rebase master
First, rewinding head to replay your work on top of it...
Applying: added staged command”
basic-rebase-3.png“它的原理是首先找到这两个分支(即当前分支 experiment、变基操作的目标基底分支 master)的最近共同祖先 C2,然后对比当前分支相对于该祖先的历次提交,提取相应的修改并存为临时文件,然后将当前分支指向目标基底 C3, 最后以此将之前另存为临时文件的修改依序应用。”
现在只需要 将master 分支进行快进合并,master 上就是最新的代码了 :
basic-rebase-4.png
最两种合并方式的理解
“这两种整合方法的最终结果没有任何区别,但是变基使得提交历史更加整洁。 你在查看一个经过变基的分支的历史记录时会发现,尽管实际的开发工作是并行的,但它们看上去就像是先后串行的一样,提交历史是一条直线没有分叉。
一般我们这样做的目的是为了确保在“向远程分支推送时能保持提交历史的整洁——例如向某个别人维护的项目贡献代码时。 在这种情况下,你首先在自己的分支里进行开发,当开发完成时你需要先将你的代码变基到 origin/master 上,然后再向主项目提交修改。 这样的话,该项目的维护者就不再需要进行整合工作,只需要快进合并便可。
请注意,无论是通过变基,还是通过三方合并,整合的最终结果所指向的快照始终是一样的,只不过提交历史不同罢了。 变基是将一系列提交按照原有次序依次应用到另一分支上,而合并是把最终结果合在一起。”
摘录(图)来自: Scott Chacon, Ben Straub. “Pro Git”。
上面对rebase 的介绍只是 一个简单的功能介绍,当然还有有趣的变基例子(☺ 就不在 介绍了)。
2.变基的风险(严肃脸)
在某些情况下,应该避免使用rebase命令,需要遵循一条准则:不要对在你的仓库外有副本的分支执行变基。如果你遵循这个金科玉律,就不会出差错,否则人民群众会仇恨你,你的朋友、家人就会嘲笑你,唾弃你(😌 有那么严重么。。。)
在Git 分支 - 分支的衍合最后 就说到了这一点,并举了个例子,也是能够帮助我们理解的。
总结
在开发过程中 ,要根据实际情况来选择合适的合并命令(恩,就酱)。