About:

以前自己单打独斗的时候,使用git主要是记录版本,很少用git来协作,协作也不过是两个人的小打小闹,一直在pull, 或者fetch merge,大家也都在修改master分支,没有明确的管理,进了新公司,需要比较严格的code review,主分支的管理都是确定的,这时候用rebase,reset,revert代替pull, fetch , merge之类的就好的多啦。

Why:

为什么要从pull和merge迁移到rebase,reset,revert呢?

我们看看如下几个场景中直接merge会产生什么问题:

一.

协作人数:两人,A和B

项目权限:所有人对master可写

分支状况: A:develop-A, B:develop-B

A 产生了 commitA1, B产生了commitB1,

1.因为B觉得自己的更改是有效的,所以B首先提交了一次自己的更改给master, 此时,A的develop分支落后于主分支,所以A对于B提交的commitB1进行了一次pull(pull = fetch + merge) ,commit 记录里多了一次Merge,此时A将自己的分支develop -A 直接push到master分支,B如果再要更新Master,就必须先运行一起pull,将A的提交中包含Merge的commit合并到自己的本地分支,这样又会多产生一次分支。

如此推算……n次之后,整个项目的master分支产生了诸多难以维护的“Merge”提交,因为两个人始终再Merge对方的提交。

—————-

从第一个例子我们可以看出,只有一个人管理Master分支(使用pull的模式)的情况下,对于主分支的管理将会非常混乱,所以这种时候使用pull进行管理将会非常麻烦,而且每次产生冲突,则需要N个人同时处理冲突,失去了协作管理的意义,git也不再是分布式,变成了中心式。

二.

协作人数:两人,A和B

项目权限:A对Master可以写

分支状况: A:develop-A, B:develop-B

此时,如果master产生了两个bug,而两个人需要分开开发,两个人分别领先于主分支,创建了两个“补丁” BugFixA1和BugFixB1。

此时,为了使两个补丁单独可以被回退,需要使整个历史变成单条线性前进,

master---->BugFixA1---->BugFixB1

而不是

develop-A-->BugFixA1--|
                      |
master-------------->Merge------->NewMaster
                      |
develop-B-->BugFixB1--|

这个时候就需要是用rebase了

关于具体怎么用rebase修改分支,参考 :http://gitbook.liuhui998.com/4_2.html

三.

开发完成后, master分支有如下的commit

+--------+        +---------+       +---------+      +----------+
|        |        |         |       |         |      |          |
|   c1   +-------->   c2    +------->   c3    +------>   c3     |
|        |        |         |       |         |      |          |
+--------+        +---------+       +---------+      +----------+

1.需要修改一个commit 2,而commit2位于整个版本历史的中间位置

2.最后一次修改现在不想要了,想要删除这次提交

对于场景1,只能用rebase

范例

git rebase -i HEAD~3 #修改最后三次提交

对于场景2,既能使用rebase, 又能使用reset。

详细内容,参考


Git-重写历史 http://git-scm.com/book/zh/v1/Git-%E5%B7%A5%E5%85%B7-%E9%87%8D%E5%86%99%E5%8E%86%E5%8F%B2

Git-revert和reset http://my.oschina.net/MinGKai/blog/144932

git cherry-pick. 如何把已经提交的commit, 从一个分支放到另一个分支 http://sg552.iteye.com/blog/1300713

标签: git, cvs

添加新评论