随着工程量的提升*.git*文件夹会变得越来越大。特别是我们只在master一个分支上进行提交,由于里面有很多没用的中间提交,所以希望能够将这些提交删除或者合并,这就用到git rebase
这个命令。
有的时候我们有若干个branch,对一个branch进行rebase会影响到其他的branch么?这里做了个实验
rebase对branch的影响
新建git仓库
1 | git init |
查看此时log
1 | $ git log |
rebase master
将master分支的3号commit合并到2号commit上
1 | $ git rebase -i --root |
这里选项-i
表示使用交互式的修改方法,你可以使用vim等编辑器来进行修改。
选项--root
表示从头开始,如果只想对最近的n个提交进行修改,可以使用HEAD~n
rebase命令如果不跟分支,默认为当前分支。
再次查看master的git log
1 | $ git log |
发现已经成功合并。
这里额外说明一下,提交2和提交3的备注信息”2”和”3”被合并到了一起作为一个新提交,这是由于squash选项造成的,如果我们选择fixup选项,那么提交2和提交3会直接消失
1 | $ git log |
回到我们刚才squash得到的结果,查看0.1分支的git log
1 | $ git checkout 0.1 |
发现并没有变化
于是结论很显然,git rebase只会影响当前分支。rebase会导致git生成一系列全新的提交,但内容包括时间是保留的。
rebase对annotation tag的影响
新建tag
按照上面的步骤重新构建了一个git仓库,下面对提交2(a8ede39f9ff56c4a43ee89e80ba30c0aad8f2f26)打tag
1 | $ git tag -a v0.1 a8ede3 |
切换到v0.1的tag
1 | $ git checkout v0.1 |
注意到这里说明现在在一个’detached HEAD’ state,这是因为tag 相当于是一个快照,是不能更改它的代码的,如果要在 tag 代码的基础上做修改,新建一个分支。
下面看一下这个detached HEAD的提交历史
1 | $ git log |
发现提交1还在
下面回到master分支,并将master分支压缩成一个分支
1 | $ git rebase -i --root |
再次查看log
1 | $ git log |
发现tag的log并没有改变
git rebase的合并冲突解决
这常发生在试图将一个分支整体与另一个分支合并的情况下
首先使用git status
查看冲突的文件,解决冲突后git add .
,然后git rebase --continue
在任何时候如果发现之前的冲突解决错误,可以通过git rebase --abort
回滚到rebase前的状态
其他的修改提交的方法
amend
git commit --amend
指令能够修改最近的一次提交。不过commit id会变
amend前
1 | $ git log |
amend后
1 | $ git log |
不过如果在amend之前将原commit push到远程仓库了的话,那会引起冲突,最省事的办法就是很不优雅地git push origin --force
。对于gitlab这样的代码仓库,可能还要将Branch Protect去掉才能强行push。