(演示过程大部分操作使用idea内置支持的Version Control工具,用该工具操作git更加高效)
这个仓库里一共有三个贡献者,分别是管理员、创作者诸葛亮和归有光。
首先管理员创建了两个分支,一个master 一个ci分支。主分支master用来发布,而ci分支用来内部审阅测试。
仓库建好之后,大家纷纷从主分支创建出自己的分支,开始创作。诸葛亮创建了分支 ZGL_出师表 要写出师表,归有光创建了分支 GYG_项脊轩志 要写项脊轩志。他们俩忙的不亦说乎。
归有光同学才思泉涌,一气呵成。兴冲冲的要将自己的作品发布。但是在发布之前必须先通过内部审阅。于是他切换到ci分支。在idea里将鼠标指到了自己分支的那个提交上。点了右上角的小樱桃按钮进行cherry-pick操作。一切顺利,没有冲突。此时自己的作品就成功合并到了ci分支上,只需要将ci分支推送到远程仓库,由运维和测试同学集成部署并审阅就可以了。
cherry-pick 过程
cherry-pick 执行成功之后,我们可以看到ci分支上也有了一个相似的提交,虽然没有冲突,但是也生成了一个新的提交,内容一样hash不一样。
诸葛亮同学心情沉重,在自己的分支上提交了三次才算把出师表写完了。
恰就在这时候,管理员发布了几条注意事项,并提交到了git仓库里,嘱咐大家要按着注意事项里面的要求来写。
但是这个注意事项的文件呢是在master分支上,诸葛同学本地分支上没有这个文件,要看只能去提交历史里面去看了。这就有点不方便。那该怎么办。像归有光同学那样把注意事项pick到自己的分支?可行。但是管理员提交了两次,我需要cherry-pick两遍。这还是管理员提交的次数较少。显然这不是最好的解决办法。那怎么做才最高效呢?
那就用merge吧 ,于是诸葛亮在命令行执行了
git merge master
没有冲突,master分支的注意事项文件顺利地合并到了自己的分支上。但是令诸葛亮有点头疼的是,即使没有冲突也在自己的分支上留下了合并记录。诸葛亮并不想要这个记录。
诸葛亮忽然想到刚学的rebase命令也可以用来合并代码,于是他将代码回滚到合并之前,并小心翼翼的在命令行敲下
git rebase master
一个错误也没有,诸葛亮同学第一次rebase操作顺利完成。主分支的注意事项文件成功的合并到了自己的当前分支上。并且没有留下像merge那样的’多余‘的合并记录。 但是让诸葛亮同学感到意外的是自己之前的提交历史都变成了新的 (如上图)。每个提交的hash都与原先不一样了,而且都被移到到master分支最新提交的后面,但是内容没丢。诸葛亮恍然大悟,原来这就是 rebase合并的真谛, 变基-重新提交。看完注意事项中的要求后,诸葛亮对自己的文章进行了修改。又提交了一个版本。此时诸葛亮同学自己的分支上已经有四个提交了,而且做得都是一件事情。 如果直接cherry-pick到ci分支,看起来有点傻,而且需要pick多次。所以在pick之前应该将这四个提交合并成一个提交,像归有光那样只往ci分支上pick一个总提交,看起来既美观又高大上。于是诸葛亮同学用idea提供的工具操作了rebase合并。如下 最后欢快的将自己的作品pick到了ci分支上。没多久内部审阅通过归有光和诸葛亮同学的两篇作品,并由管理员cherry-pick到master 分支,发布给所有人查看。最终效果rebase 雷区
那么上面可以注意到,将别的分支代码合并到master分支采用的是cherry-pick,那么可以用 rebase吗? 绝对不行!使用 git rebase合并代码要遵循一个原则: 不要在公共分支上执行rebase合并其他分支的代码。如果你理解透rebase原理就能知道禁止这么做的原因。 因为master,ci等公共分支上有别人提交的而你分支上没有的提交,也就是说,你的分支相对master这类分支提交” 不够健全“,如果你在master分支执行了 git rebase your_branch 那么就会以你的分支为新的基线,所有你分支上没有的提交都会被重新提交,虽然内容没变,但是hash变了!在你的同事想要在将master分支上的修改merge到他自己的分支时就会出现重复提交。以下我故意用诸葛亮这个作者在master分支上执行了rebase , 结果可以看到诸葛亮把master上归有光的提交给重新提交了一遍。 此时再推送提示本地代码不是最新的需要合并或者rebase。如下图 如果选择merge或者放弃推送使用push -force强推,在别人拉下来代码时就会出现重复的提交。如下图(直接选择merge的情况,强推也一样) 一般使用idea工具在公共分支操作rebase合并其他分支时也会出现警告。如下图, 提示会造成重复提交,非常不建议这么做。 所以,使用rebase需要遵循上面那个原则, 就是如果当前分支有多人在维护就不要使用rebase来合并其他分支的代码,可以使用cherry-pick代替。 也就是说,rebase合并代码 一般用在两种情况下,一是将主(公共)分支(健全分支)的代码合并到到个人分支(缺胳膊短腿分支)。二是 在 公共分支下,合并 远端 公共分支代码到 本地 公共分支(因为远端公共分支除了你本地的新提交外,已经包含了本地公共分支的所有其他人的历史提交,因此不会造成重复提交) 。祝你一切都好。