美文网首页iOS学习git使用笔记
使用git rebase来消除提交历史分叉

使用git rebase来消除提交历史分叉

作者: 一一小知 | 来源:发表于2018-01-07 17:10 被阅读2097次

    在很多时候,随着开发团队的扩容,大家提交代码一段时间过后,就产生很多的合并(merge)节点,对于有代码洁癖的人来说,这个总会觉得很不爽。

    master分支混乱的提交历史

    那么,merge是如何产生的呢?下面我挑一个常见的冲突的场景,示例一下:

    用merge来解决冲突

    我们来在master分支模拟一次merge的情况,针对README.md,首先A用户编写了首行代码,并提交到了git服务器上内容如下:

    # A用户编写首行代码
    

    同时,B用户在本地编写了首行代码,内容如下:

    # B用户编写首行代码
    

    B用户只是在本地电脑上进行了git commit,如下:

    $ git commit -am "B用户编写首行代码"
    [master c8bfe4f] B用户编写首行代码
     1 file changed, 1 insertion(+), 1 deletion(-)
    

    接下来,B用户使用git pull命令将git服务器代码下载并合并到本地,可以看到产生了冲突:

    bianxh@DESKTOP-BIANXH MINGW64 /d/Workspaces/gitee/test (master)
    $ git pull
    remote: Counting objects: 3, done.
    remote: Compressing objects: 100% (2/2), done.
    remote: Total 3 (delta 0), reused 0 (delta 0)
    Unpacking objects: 100% (3/3), done.
    From gitee.com:yyxz/test
       45bc85e..fc2c29a  master     -> origin/master
    Auto-merging README.md
    CONFLICT (content): Merge conflict in README.md
    Automatic merge failed; fix conflicts and then commit the result.
    

    接下来,B用户,修改有冲突的README.md文件,解决冲突,如下:

    bianxh@DESKTOP-BIANXH MINGW64 /d/Workspaces/gitee/test (master|MERGING)
    $ git status
    On branch master
    Your branch and 'origin/master' have diverged,
    and have 1 and 1 different commits each, respectively.
      (use "git pull" to merge the remote branch into yours)
    You have unmerged paths.
      (fix conflicts and run "git commit")
      (use "git merge --abort" to abort the merge)
    
    Unmerged paths:
      (use "git add <file>..." to mark resolution)
    
            both modified:   README.md
    
    no changes added to commit (use "git add" and/or "git commit -a")
    
    bianxh@DESKTOP-BIANXH MINGW64 /d/Workspaces/gitee/test (master|MERGING)
    $ git add README.md
    
    bianxh@DESKTOP-BIANXH MINGW64 /d/Workspaces/gitee/test (master|MERGING)
    $ git commit -m "合并A和B用户编写的首行代码"
    [master 5aa451d] 合并A和B用户编写的首行代码
    

    修改后的README.md文件内容如下:

    # 合并A和B用户编写的首行代码
    

    现在B将代码提交到git服务器上,可以看到有两个commit(一个是B对首行代码的提交:c8bfe4f,一个是B刚才的merge动作),如下:

    bianxh@DESKTOP-BIANXH MINGW64 /d/Workspaces/gitee/test (master)
    $ git status
    On branch master
    Your branch is ahead of 'origin/master' by 2 commits.
      (use "git push" to publish your local commits)
    nothing to commit, working tree clean
    
    bianxh@DESKTOP-BIANXH MINGW64 /d/Workspaces/gitee/test (master)
    $ git push
    Counting objects: 6, done.
    Delta compression using up to 4 threads.
    Compressing objects: 100% (4/4), done.
    Writing objects: 100% (6/6), 695 bytes | 0 bytes/s, done.
    Total 6 (delta 0), reused 0 (delta 0)
    To gitee.com:yyxz/test.git
       fc2c29a..5aa451d  master -> master
    
    bianxh@DESKTOP-BIANXH MINGW64 /d/Workspaces/gitee/test (master)
    $ git log --oneline --graph
    *   5aa451d (HEAD -> master, origin/master, origin/HEAD) 合并A和B用户编写的首行代码
    |\
    | * fc2c29a A用户编写首行代码
    * | c8bfe4f B用户编写首行代码
    |/
    * 45bc85e 初始状态
    

    可以看到,提交历史产生了分叉,接下来我们看看如何使用git rebase消除分叉:

    git rebase消除分叉

    A再次修改首行代码,并提交至git服务器,README.md内容如下:

    A再次修改首行代码
    

    B再次在本地修改首行代码,并提交至本地,README.md内容如下:

    B再次修改首行代码
    

    commit如下:

    bianxh@DESKTOP-BIANXH MINGW64 /d/Workspaces/gitee/test (master)
    $ git commit -am "B再次修改首行代码"
    [master 21a6c2a] B再次修改首行代码
     1 file changed, 1 insertion(+), 1 deletion(-)
    

    接下来,使用git pull --rabase,可以看到冲突,并且进入了rebase状态:

    bianxh@DESKTOP-BIANXH MINGW64 /d/Workspaces/gitee/test (master)
    $ git pull --rebase
    remote: Counting objects: 3, done.
    remote: Compressing objects: 100% (2/2), done.
    remote: Total 3 (delta 0), reused 0 (delta 0)
    Unpacking objects: 100% (3/3), done.
    From gitee.com:yyxz/test
       5aa451d..ccbb4ff  master     -> origin/master
    First, rewinding head to replay your work on top of it...
    Applying: B再次修改首行代码
    error: Failed to merge in the changes.
    Using index info to reconstruct a base tree...
    M       README.md
    Falling back to patching base and 3-way merge...
    Auto-merging README.md
    CONFLICT (content): Merge conflict in README.md
    Patch failed at 0001 B再次修改首行代码
    The copy of the patch that failed is found in: .git/rebase-apply/patch
    
    When you have resolved this problem, run "git rebase --continue".
    If you prefer to skip this patch, run "git rebase --skip" instead.
    To check out the original branch and stop rebasing, run "git rebase --abort".
    
    
    bianxh@DESKTOP-BIANXH MINGW64 /d/Workspaces/gitee/test (master|REBASE 1/1)
    $
    

    此时,B在本地打开README.md文件,可以看到冲突内容如下:

    <<<<<<< HEAD
    A再次修改首行代码
    =======
    B再次修改首行代码
    >>>>>>> B再次修改首行代码
    

    解决冲突:修改README.md文件,内容如下:

    再次合并A和B修改的首行代码
    

    使用git add README.md标注冲突已解决:

    bianxh@DESKTOP-BIANXH MINGW64 /d/Workspaces/gitee/test (master|REBASE 1/1)
    $ git add README.md
    
    bianxh@DESKTOP-BIANXH MINGW64 /d/Workspaces/gitee/test (master|REBASE 1/1)
    $ git rebase --continue
    Applying: B再次修改首行代码
    
    bianxh@DESKTOP-BIANXH MINGW64 /d/Workspaces/gitee/test (master)
    $ git log --oneline --graph
    * 1e4c421 (HEAD -> master) B再次修改首行代码
    * ccbb4ff (origin/master, origin/HEAD) A再次修改首行代码
    *   5aa451d 合并A和B用户编写的首行代码
    |\
    | * fc2c29a A用户编写首行代码
    * | c8bfe4f B用户编写首行代码
    |/
    * 45bc85e 初始状态
    

    可以看到B用户第二次修改是在A修改之后,但是B的提交commit编号21a6c2a被新的编号1e4c421所取代,commit的内容不变。

    这时我们看到HEAD -> master,origin/master, origin/HEAD不一致。是因为B用户在本地的修改还未提交至git服务器,通过git status也可以看出来,有1 commit未提交至git服务器:

    bianxh@DESKTOP-BIANXH MINGW64 /d/Workspaces/gitee/test (master)
    $ git status
    On branch master
    Your branch is ahead of 'origin/master' by 1 commit.
      (use "git push" to publish your local commits)
    nothing to commit, working tree clean
    

    提交后,就OK了。如下:

    bianxh@DESKTOP-BIANXH MINGW64 /d/Workspaces/gitee/test (master)
    $ git push
    Counting objects: 3, done.
    Delta compression using up to 4 threads.
    Compressing objects: 100% (2/2), done.
    Writing objects: 100% (3/3), 355 bytes | 0 bytes/s, done.
    Total 3 (delta 0), reused 0 (delta 0)
    To gitee.com:yyxz/test.git
       ccbb4ff..1e4c421  master -> master
    
    bianxh@DESKTOP-BIANXH MINGW64 /d/Workspaces/gitee/test (master)
    $ git log --oneline --graph
    * 1e4c421 (HEAD -> master, origin/master, origin/HEAD) B再次修改首行代码
    * ccbb4ff A再次修改首行代码
    *   5aa451d 合并A和B用户编写的首行代码
    |\
    | * fc2c29a A用户编写首行代码
    * | c8bfe4f B用户编写首行代码
    |/
    * 45bc85e 初始状态
    

    现在我们登录到服务器看下最新的内容,如下:

    使用rebase解决冲突后的README.md文件内容

    可以通过项目网络图直观地看到,如下:


    项目网络图

    相关文章

      网友评论

        本文标题:使用git rebase来消除提交历史分叉

        本文链接:https://www.haomeiwen.com/subject/xycmnxtx.html