发现问题
之前写过一篇博客《30分钟教你轻松使用Git做代码管理》,其中有提到本地提交代码的一些步骤:
-
如果新参与一个项目,首先需要本地clone远程仓库。之后会有一个master(若不特殊说明,均指代本地master)和远端的master(以下称为remote/master)是关联的,即remote/master是本地master的up-stream。
从远程仓库进行克隆
-
做开发时,要新建一个分支,如dev1,作为你的开发分支。开发完新特性后,将工作区(work tree)的修改提交至暂存区(index),然后commit,此时会在dev1分支上生成一个新的commit单号。
提交你的修改
-
切换回master分支,然后使用pull或者fetch+merge命令与remote/master同步一下(此时可能会有来自其他开发者的提交),再合并(merge)dev1分支的,如果有冲突,则解决冲突。最后推送代码到远端仓库。
更新本地主分支
场景描述
rebase会做如下操作:- 把dev1分支上的c1和c2“拆”下来,并临时保存成c1'和c2'。git里将其称为patch
-
将master分支上更新的提交c3和c4合并进dev1分支上。
连接patch
此时dev1分支包含master分支的所有commit,并且超前了两个commit。如果你现在切换至master分支,并执行git merge dev1
操作,由于没有不同于dev1的提交,merge操作就不会产生merge commit了。此时推送代码,也只会有两个commit。同时,master分支树笔直前进,分支很清晰地展示一个个提交。并且,上述的更新和提交代码的过程,是在dev1分支上修改冲突的,相对来说会比在master分支上修改更安全,如果不小心改混了,也能通过切换回master分支来找到稳定代码。
在master分支上合并dev1分支
基于上述内容,可以使用如下流程来提交代码:
- 在dev1分支上进行开发,然后commit提交,在dev1分支上生成一个提交单。
- 切换到master分支,与remote/master分支同步。
- 切换回dev1分支,将master分支rebase到dev1分支上,如果有冲突,修改冲突。rebase操作的冲突修改与merge不一样,修改完冲突后,保存进index,然后直接
git rebase --continue
即可,不同再多做一次提交。 - 切换回master分支,合并dev1分支,此时合并会非常顺畅。然后push。
rebase的风险
之前提到,rebase会将当前分支的新提交拆下来,保存成patch,然后合并进其他分支新的commit,最后将patch接进当前分支。这是rebase对多条分支的操作。对于单条分支,rebase还能够合并多个commit单号,将多个提交合并成一个提交。
git rebase -i [commit id]
命令能够合并(整改)commit id
之前的所有commit单。加上-i
选项能够提供一个交互界面,分阶段修改commit信息并rebase。但这里就会出现一个问题:如果你合并多个单号时,一不小心合并多了,将别人的提交也合并了,此时你本地的commit history和远程仓库的commit history不一样了,无论你如何push,都无法推送你的代码了。如果你并不记得rebase之前的HEAD指向的commit的commit ID的话,git reflog都救不了你。
tips: 你可以push时带上-f参数,强制覆盖远程commit history,你这样做估计会被打,因为覆盖之后,团队的其他人的本地commit history就与远程的不一样了,都无法推送了。
因此,请保证仅仅对自己私有的提交单进行rebase操作,对于已经合并进远程仓库的历史提交单,不要使用rebase操作合并commit单。
网友评论