Thursday, November 19, 2020

git rebase


We should discuss the difference between fast-forward and the 3-way merge before introducing the 'git rebase'


*Fast-forward

When the merging branch (bugFix)  has all commits from the current branch (master), Git will not create a new merging commit. Instead, it will move the 'master' branch pointer to the latest commit of the 'bugfix' branch. It is a line (linear path) relationship.


*3 way merge

When the current branch (master) contains commits that the merging branch (bugfix) doesn't have, Git will create a new merging commit that merges two branches without modifying the existing branches. It is a tree (with a cycle) relationship.


Therefore, if we don't want to make it to create a new commit that is used for merging two branches, then we need to try to make the git structure to be Fast-Forward. Then the 'git rebase' command can help! 


Rebase

Copies commit on top of another branch without creating a commit, which keeps a linear history. Git will delete the old changes and rewrite them (with new sha1) on the top of the latest target (master) branch.


// Each branch has a new commit.

(master)

C1 -> C2

-> C3

(bugfix)


// After rebase, it turns into linear history

(master)

C1 -> C2

-> C2 -> C4 (rewritten commit from C3)

(bugfix)


NOTE:

1. Conflicts might be happened as usual, and we need to resolve them manually.

2. Rebase is not suitable if multiple people use the same branch.

3. The master branch is better not to do rebase

Below are the logs from my experiment (Rebasing without conflicts)


Step 1:


Check the status of the master branch


    $ git log
    commit cd1374abfde32ce13bc55f1abbb77571f230dedc (HEAD -> master)
    Author: Frank <frank@demo.com>
    Date:   Timestamp

        second commit by master

    commit 54a804e5f7e75c74f5380cc097336957ca756f9f
    Author: Frank <frank@demo.com>
    Date:   Timestamp

        first commit


Step 2:


Switch to the bugFix branch and check the status.


    git checkout bugFix
    Switched to branch 'bugFix'

    $ git log
    commit 38b42c91af547bd80692fae406ab6b325300b173 (HEAD -> bugFix)
    Author: Frank <frank@demo.com>
    Date:   Timestamp

        first commit in bugFix

    commit 54a804e5f7e75c74f5380cc097336957ca756f9f
    Author: Frank <frank@demo.com>
    Date:   Timestamp

        first commit


Step 3:


Check the git structure.


    $ tree .git/
    .git/
    ├── COMMIT_EDITMSG
    ├── HEAD
    ├── config
    ├── description
    ├── hooks
    ├── index
    ├── info
    │   └── exclude
    ├── logs
    │   ├── HEAD
    │   └── refs
    │       └── heads
    │           ├── bugfix
    │           └── master
    ├── objects
    │   ├── 18
    │   │   └── 0cf8328022becee9aaa2577a8f84ea2b9f3827
    │   ├── 34
    │   │   └── 84292db2aec3ad938ac17d3daf55dac8b03075
    │   ├── 38
    │   │   └── b42c91af547bd80692fae406ab6b325300b173
    │   ├── 54
    │   │   └── a804e5f7e75c74f5380cc097336957ca756f9f
    │   ├── 81
    │   │   └── fa9d1c5348f86326ce5e7a86d11b54c8140d8d
    │   ├── a5
    │   │   └── bce3fd2565d8f458555a0c6f42d0504a848bd5
    │   ├── b4
    │   │   └── 1fb42483f661a1de6202b2a872de08638acb9c
    │   ├── c0
    │   │   └── da834e42dcbf7b2b1c4a97925bef105d3863a3
    │   ├── cd
    │   │   └── 1374abfde32ce13bc55f1abbb77571f230dedc
    │   ├── info
    │   └── pack
    └── refs
        ├── heads
        │   ├── bugfix
        │   └── master
        └── tags

    20 directories, 20 files


Step 4:


Run the 'git rebase' command from master in the current bugFix branch.


    $ git rebase master
    First, rewinding head to replay your work on top of it...
    Applying: first commit in bugfix


 According to the message above, the commit 'first commit in bugfix' will be rewritten.


Step 5:


Check the status of the bugFix branch.

 
    $ git log
    commit 0238eb360ced00720a6efffbbc6c8f372eaf3c0d (HEAD -> bugFix)
    Author: Frank <frank@demo.com>
    Date:   Timestamp

        first commit in bugFix

    commit cd1374abfde32ce13bc55f1abbb77571f230dedc (master)
    Author: Frank <frank@demo.com>
    Date:   Timestamp

        second commit by master

    commit 54a804e5f7e75c74f5380cc097336957ca756f9f
    Author: Frank <frank@demo.com>
    Date:   Timestamp

        first commit

1. Now, the new commit cd1374 from the master branch is copied to the bugfix branch.

2. You will notice that the sha1 of 'first commit in bugfix' is changed from '38b42c' to '0238eb'.


Step 6:


Compare the git structure.


    $ tree .git/
    .git/
    ├── COMMIT_EDITMSG
    ├── HEAD
    ├── ORIG_HEAD (NEW FILE)
    ├── config
    ├── description
    ├── hooks
    ├── index
    ├── info
    │   └── exclude
    ├── logs
    │   ├── HEAD
    │   └── refs
    │       └── heads
    │           ├── bugfix
    │           └── master
    ├── objects
    │   ├── 02 (NEW FOLDER)
    │   │   └── 38eb360ced00720a6efffbbc6c8f372eaf3c0d (NEW FILE, rewritten commit)
    │   ├── 18
    │   │   └── 0cf8328022becee9aaa2577a8f84ea2b9f3827
    │   ├── 34
    │   │   └── 84292db2aec3ad938ac17d3daf55dac8b03075
    │   ├── 38
    │   │   └── b42c91af547bd80692fae406ab6b325300b173
    │   ├── 54
    │   │   └── a804e5f7e75c74f5380cc097336957ca756f9f
    │   ├── 5a (NEW FOLDER)
    │   │   └── 3d043807c15183f3936b4e179acee9c0e2f26a (NEW FILE)
    │   ├── 81
    │   │   └── fa9d1c5348f86326ce5e7a86d11b54c8140d8d
    │   ├── a5
    │   │   └── bce3fd2565d8f458555a0c6f42d0504a848bd5
    │   ├── b4
    │   │   └── 1fb42483f661a1de6202b2a872de08638acb9c
    │   ├── c0
    │   │   └── da834e42dcbf7b2b1c4a97925bef105d3863a3
    │   ├── cd
    │   │   └── 1374abfde32ce13bc55f1abbb77571f230dedc
    │   ├── info
    │   └── pack
    └── refs
        ├── heads
        │   ├── bugfix
        │   └── master
        └── tags

    22 directories, 23 files

Check the rewritten commit.


    $ git cat-file -p 0238eb
    tree 5a3d043807c15183f3936b4e179acee9c0e2f26a
    parent cd1374abfde32ce13bc55f1abbb77571f230dedc
    author Frank <frank@demo.com>
    committer Frank <frank@demo.com>

        first commit in bugfix



    $ git cat-file -p 5a3d04
    100644 blob b41fb42483f661a1de6202b2a872de08638acb9c    test1.txt
    100644 blob 180cf8328022becee9aaa2577a8f84ea2b9f3827    test2.txt


Step 7:


Switch to the master branch and do the 'git merge' command.


    $ git checkout master
    Switched to branch 'master'



    $ git merge bugFix
    Updating cd1374a..0238eb3
    Fast-forward
    test2.txt | 1 +
    1 file changed, 1 insertion(+)
    create mode 100644 test2.txt


It is fast-forward, not 3 way merge

No comments:

Post a Comment