Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1306427
  • 博文数量: 254
  • 博客积分: 1586
  • 博客等级: 上尉
  • 技术积分: 2295
  • 用 户 组: 普通用户
  • 注册时间: 2009-01-15 16:38
个人简介

linux学习中

文章分类

全部博文(254)

文章存档

2016年(6)

2015年(2)

2014年(74)

2013年(93)

2012年(12)

2011年(2)

2010年(51)

2009年(14)

分类: LINUX

2014-01-24 10:59:25


git真是博大精深。

  想通了这一点,再遇到什么奇怪的现象都不奇怪了,查文档就是了。

  今天来谝一谝git使用中遇到的一个有趣的场景:本地有master,spike两个branch。因为spike的内容和master完全不想相关,所以在spike上工作了若干天都没理master,直到有一天觉得差不多了,就做了以下几件事情。

  git co master

  git merge spike

  git pull --rebase

  然后奇怪的事情就发生了,那么到底发生了什么奇怪的事情呢,我还是决定把问题稍微简化一下,然后再慢慢道来。因为大家知道git pull --rebase其实就等于git fetch + git rebase。只不过rebase的upstream是远程的一个分支而已。本着git之内,本地分支和远程分支皆平等的原则,上面的那个例子使用本地分支做演示也是等效的。先看下面的这个历史:

  我除了一个master分支,还有两个分支,名为br1和br2。然后来做个git co master + git merge br1,历史变成了这样:

  多了一个合并提交,不好看。然后我们再尝试把master rebase到br2上面。那么具体git会怎么做呢。说到这里我想暂停下,大概说下git rebase到底是怎么工作的。简单的说,git rebase接受最多三个参数:

  git rebase --onto newbase upstream branch。

  把这句话翻译成中文就是:从branch指定的那个分支的HEAD开始往前找提交,直到找到第一个和upstream分支共同的祖先,然后把前面找到的那些提交(不包含找到的那个共同的提交)依次的安放到newbase指定的那个branch的HEAD上。如果看完没感觉,那。。。看后面的例子吧。

  为什么说最多接受三个参数呢?因为它还可以接受如下两种参数形式:

  git rebase upstream branch // upstream即newbase

  git rebase upstream            // current branch即branch

  好,我们接着刚才那个例子看。如果这个时候,我做一个 git co master + git rebase br2,会怎样?  

  没错,这个就是结果,那么这个结果如何的出来的呢?请跟着我的节奏把刚才那个定义过一遍。首先我们把这个接受一个参数的命令补全成为接受三个参数的命令

  git rebase --onto br2 br2 master

  即首先从master开始往前找和br2的共同祖先提交,找到了两个:2和3。而2和3之后的那些被找到的提交就是5和6了,由于我们做rebase,那个合并提交就没有存在的必要了,所以接下来就要把5和6这两次提交放到br2的HEAD上面。br2的HEAD现在是4,所以master就变成了上图的那个样子。但是你们master和br2在那做rebase,不能影响人家br1吧。所以br1该是啥样子,还是啥样子,人家本来HEAD就在5上,现在还是保持在5上面。这样就造成了两个奇怪的现象:

  1,原来的那个合并提交不见了,原来从2提交分出去的那个两个分支现在都乖乖的顺次摞在br2上面了,分支不复存在了。

  2,由于提交5之前同时被master和br1这两个分支占着,当master移走了之后,就出现了5这次提交出现了两次,一个在master上面,一个在br1上。

  那么如果我再做一次git rebase br1 master,会怎样呢?让我们再顺一遍刚才的那个定义。从master往前找和br1的共同祖先提交之后的那些提交,即4,5,6。然后再把4,5,6顺次放到br1的HEAD,即5上。就变成了5,4,5,6。

  嗯。。。看起来不是很对,master上的5这次提交和br1上的5这次提交虽然事实上是两次不同的提交(提交号不一样),但其内容是一模一样的(也就是那些insertion和deletion)。这时候git就比较聪明了,看到两次一样的提交,就丢掉了后面那个。事实上的结果变成了:5,4,6。即:

  最后需要提醒一下的是,前面提到的那些1,2,3,4,5,6都是提交的message而已,message相同是因为提交的内容相同,也就是diff相同,但是是不同的提交,因为提交号不一样。在git的历史里面不可能出现两个提交号一模一样的提交的。

  大概就说到这里,总结一下就是,git非常灵活,灵活到经常可能被误用。所以当出现上面提到的那个“奇怪的现象”的时候,就要考虑下是不是自己用的不大对头喽。

阅读(1142) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~