git rebase总结及git使用规范

一、git规范

  场景一:如果代码commit到本地库了,但是commit之前忘记pull了,远程代码也已更新,此时不能使用pull直接拉取远程代码(分支会产生merge的记录):

    解决方法:commit之后,使用git fetch,拉取远程代码到缓存区,然后使用git rebase origin/dev,此时会产生冲突,解决冲突后即可提交,这样分支不会产生merge的记录

  场景二:commit提交之前先使用pull总是没问题的,但如果pull不下来,是因为代码和远程代码冲突了,此时有两种解决办法:

    1.使用git stash 保存本地修改的代码到缓存区,此时代码会还原为没修改之前的,此时在使用git pull拉取代码,然后使用git stash pop恢复缓存区的代码,此时解决冲突即可提交

    2.先commit提交本地代码到本地库,这时候不要直接pull(分支会产生merge的记录),先使用git fetch,拉取远程代码到缓存区,然后使用git rebase origin/dev,此时会产生冲突,解决冲突后即可提交,这样分支不会产生merge的记录

  场景三:dev代码修改后,test分支需要同步更新修改:

    解决方法:dev修改后push代码,切换到test分支,pull保证与远程代码一致,此时不能merge dev,而是使用git rebase dev(或者git rebase origin/dev),此时会把dev的代码都更新到本地test分支,然后在push到远程test分支,这样分支不会产生merge的记录

  场景四:取消merging状态

    git reset --hard HEAD (or sha_1)

  场景五:多人同时开发一个分支:

    1、git pull

        如果pull不下来,说明本地代码和远程分支有冲突,代码更新不了

    2、git commit -m "xxx"
        将本地代码添加到本地缓冲区

      git commit -a -m "xxx"
    3、git stash
        如果本地有不需要提交的代码,git stash把你的修改保存起来,恢复到和你没修改之前一致
    4、git fetch
        更新远程代码到本地暂存区
    5、git rebase
        把本地暂存区的代码更新到工作区
    6、有冲突的话把冲突解决
    7、git status
      git add . 将解决完冲突的文件添加提交
    8、git rebase --continue
    9、git push origin dev 提交远程分支
    10、git stash pop 恢复不需要提交的文件

二、rebase总结

  1. 如果新参与一个项目,首先需要本地clone远程仓库。之后会有一个master(若不特殊说明,均指代本地master)和远端的master(以下称为remote/master)是关联的,即remote/master是本地master的up-stream。


    从远程仓库进行克隆
  2. 做开发时,要新建一个分支,如dev1,作为你的开发分支。开发完新特性后,将工作区(work tree)的修改提交至暂存区(index),然后commit,此时会在dev1分支上生成一个新的commit单号。


    提交你的修改
  3. 切换回master分支,然后使用pull或者fetch+merge命令与remote/master同步一下(此时可能会有来自其他开发者的提交),再合并(merge)dev1分支的,如果有冲突,则解决冲突。最后推送代码到远端仓库。


    更新本地主分支

    合并dev1分支,推送
    合并dev1分支,推送

    这是我刚开始实习时,常用的一个开发,推送代码的流程。久而久之,我发现了几个问题:

  • 在master分支上解决冲突,可能会有些风险。比如一不注意,冲突没有正确解决,导致本地修改与别人的修改混在一起,本来稳定的与远程保持同步的master分支被你改混乱了,且没有其他的备份了。

  • 在master分支上merge开发分支,如果master分支上有dev1没有的commit单号,则会产生一个携带merge信息的提交单。这个commit你也要推送到远端。企业开发一般会有一个评审分支,主管会对commit单号进行review,然后submit合并进remote/master分支中。merge信息的提交单也会让reviewer做一次review,然而没什么必要的。

  • 一个人提交时,会有一个merge commit,那么10个人提交,就会有10个merge commit,此时分支树看起来会很混乱。零零散散的merge commit信息穿插在你的特性commit之间。

因此,我考虑使用另外一种本地分支管理策略,来改善这样的问题。

使用rebase命令。

先简要说下rebase命令的作用。

比如在dev1分支上,你提交了2个单,c1和c2。然后你在dev1分支上将master分支rebase到当前分支git rebase master。此时,如果master分支已经与remote/master做了同步,更新了2个来自其他人的提交,c3和c4。

 
场景描述

rebase会做如下操作:
  1. 把dev1分支上的c1和c2“拆”下来,并临时保存成c1'和c2'。git里将其称为patch
  2. 将master分支上更新的提交c3和c4合并进dev1分支上。


    rebase操作,拆分提交
    rebase操作,拆分提交
  3. 将c1'和c2',再按顺序接在c3和c4的提交后面,如果没有冲突,则rebase成功。此时c1'和c2'虽然和c1和c2的修改完全一样,但却已经不是原来的提交了,commit id已经变化了。
     
    连接patch

    此时dev1分支包含master分支的所有commit,并且超前了两个commit。如果你现在切换至master分支,并执行git merge dev1操作,由于没有不同于dev1的提交,merge操作就不会产生merge commit了。此时推送代码,也只会有两个commit。同时,master分支树笔直前进,分支很清晰地展示一个个提交。并且,上述的更新和提交代码的过程,是在dev1分支上修改冲突的,相对来说会比在master分支上修改更安全,如果不小心改混了,也能通过切换回master分支来找到稳定代码。
     
    在master分支上合并dev1分支

    基于上述内容,可以使用如下流程来提交代码:

 

  1. 在dev1分支上进行开发,然后commit提交,在dev1分支上生成一个提交单。
  2. 切换到master分支,与remote/master分支同步。
  3. 切换回dev1分支,将master分支rebase到dev1分支上,如果有冲突,修改冲突。rebase操作的冲突修改与merge不一样,修改完冲突后,保存进index,然后直接git rebase --continue即可,不同再多做一次提交。
  4. 切换回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单。

猜你喜欢

转载自www.cnblogs.com/pluto-yang/p/9723771.html
今日推荐