git 学习(4) ----- git rebase

时间:2022-05-16 23:09:02

  使用git rebase 的前提是多人协作下的分支开发,如果是单人开发,那就没有必要使用它了,这是由git rebase 的作用所决定的,git rebase 有两大作用:一个是与主分支保持同步,一个是在合并分支之前清理commit 信息。先看第一个作用。

  当多人协作进行开发的时候,通常都会有一个主分支,如master, 用于合并所有人的代码。而在本地开发的时候,每一个人都会开一个分支,进行分支开发。当我们新开一个分支的时候,就意味着,选择了主分支上的一个点作为开发的起点。如下图所示,

git 学习(4) ----- git rebase

  这时,本地开发的时候,我们每一个commit 都会提交到 new_feature 分支上, 同时,我们的同事也在开发功能, 他们开发完成后,都会把代码同步到master 分支上。我们从远程master 分支进行pull 操作,拉取到本地的master 分支上,随着时间的推移,就会形成如下状态,

git 学习(4) ----- git rebase

  现在怎么办?我们想使用master 分支上的新功能,你可能想到了merge, 但是new_feature 分支还没有开发完成,还没有到merge的时候,那就用git rebase 把。在 new_feature  分支上,使用git rebase master 命令就可以了。

git 学习(4) ----- git rebase

  使用git rebase 后,分支new_feature 以最新的master 作为了起点,这时就可以使用master 上的新功能了。rebase, re + base, 的意思,re 是再一次的意思, base 基的意思,再给它一个基础,就是改变以前的基础,改变分支以前的起点到新的起点上(change the starting point of your local branch)

  但是有的时候,git rebase 会出问题,我们想回到rebase 之前的状态,怎么办?本地分支上的操作,可以使作git reset 进行回退,但是也要找到回退到的commit id. 这时使用git reflog 命令,如果使用的是git rebase, git reflog 打印出的日志就是显示rebase ......, 找到最后一个rebase 后面没有rebase 的id. git 学习(4) ----- git rebase

  如上图所示,f883bbd, 就是 我们想要的id, 直接git reset --hard f883bdd 就可以了。

  现在说第二个作用,清理commit 日志。我们再以master 为基础,新建一个分支,就叫new_feature  分支好了,再在该分支上随便提交两次代码,我一次增加了index.js 再一次增加了style.css 文件,

git 学习(4) ----- git rebase

  现在我们想把这个提交日志合并,然后再合并到master 分支上。使用的命令是git rebase --interactive master 然后弹窗一个vim 编辑器,上面就是提交的分支的日起,下面就是一个命令的说明。

git 学习(4) ----- git rebase

  你可以看到,它的日志排列正好和git log 相反, 最后提交的在最下面。合并使用的是squash 命令, 把pick 07ab50c 前面的pick 换成squash, 就是把下面07ab50c 提交日志,合并到fc26711 上。

git 学习(4) ----- git rebase

  然后按esc 键退出 编辑操作,然后再输入:wq , 退出这个弹窗,这时又跳出一个弹窗。

git 学习(4) ----- git rebase

  这个弹窗主要是告诉你git  rebase 做了什么事情,直接  :wq 退出就可以了。

git 学习(4) ----- git rebase

  可以看到rebase 成功,同时git log 也可以看到 两条记录合并到一条记录上了。

git 学习(4) ----- git rebase

  这时,可以愉快地合并到master 分支上了。

  git rebase 冲突解决

  当使用rebase 的时候,有时会发生冲突,这主要是分支开发时间过长,而同事又大量的提交代码。最近我就遇到rebase 冲突的问题。

  当时,我在开发一个功能模块,大约需要两周的时间,而同事呢,都在修复bug, 他们每修复一个bug, 就向远程仓库提交代码,导致我在新建分支开发功能的时候,在master上的起点,大大落后于远程仓库的head. 当开发完这个功能模块的时候,我还是向往常一样,切换到master 分支,从远程仓库拉取代码,然后再git rebase ,但是 rebase 失败,然后就发现我本地有几个文件也被删除掉了,我这里使用的是图形界面化工具进形的rebase, 这时, 我真的有点慌,不知道发生了什么,rebase 失败,怎么会把我本地的文件删除掉呢?胡乱操作了一个晚上,也不知道在操作什么,最终还是没有解决问题,

  第二天,找了git的书籍关于git rebase 的内容又看了一遍,发现 我可以使用git reset --hard 进行回退,我晚上使用的git reset 没有加--hard 参数,所以工作区的内容没有发生变化。回退之后,我还要git rebase, 这时我想使用命令行的方式,进行rebase的操作. git rebase master,把master 分支上的内容合并到 我的开发分支上,同样你会现rebase 失败了。但是和图形化界面操作方式不同的是,它告诉你了冲突的文件,以及解决方式。这时看你的命令行中,你会发现(1/n), 到后来,我才发现这是在合并的时候,有n 个文件发生了冲突。我们现在正在解决第一个冲突,还有就是冲突的文件, 我这里是servcie/api.js, 最后是怎么操作, 有几个使用的命令, git add, git rebase --continue, git rebase --skipe, git rebase --abort。

  我们来解决api.js中的冲突,冲突解决后,要使用git add,  git add server/api.js 把它提交到暂存区,然后,再执行 git rebase --continue, 告诉git 继续rebase. 这时, git 会给出第2个冲突的地方,还是解决冲突,git add , 和git rebase --continue,  git 会依次给出所有冲突的文件,直到你把所有冲突解决掉。有时,在解决冲突的时候,发现搞错了,这时 git rebase --abort, 终止rebase, 回到 rebase 之前的状态,就像回滚。这里一定要注意,使用git add的时候,一定不要使用git commit,   git commit 不是git rebase 解决冲突的步骤,如果使用了,  git 会因为你使用步骤之外的命令来终止rebase 操作。

  现解决完冲突以后,我终于知道,为什么我使用图形化界面工具进行rebase的时候,会删除文件,因为有n个文件有冲突,然后,图形化界面工具一步到位,直接合并失败,没有多余的操作,所以就把有冲突的文件删除了。以后再使用rebase 命令的时候,很小使用图形化界面工具了。