DEV Community

Héctor Pascual
Héctor Pascual

Posted on

Git merge, merge-squash and rebase simplified

Git merge, merge-squash and rebase simplified

Starting the repository with basic files

Lets create an empty repository and commit a file to the master branch:

$ git init 
$ touch m1
$ git add m1
$ git commit -m "m1"

Now we switch to a new branch named feature:

$ git checkout -b feature

Is time to create a file in the feature branch and commit it:

$ touch f1 
$ git add f1 
$ git commit -m "f1"

Now let's go back to the master and create another file :

$ git checkout master
$ touch m2 
$ git add m2
$ git commit -m "m2"

If we type $ git log we will see this :

* 60c3a2b - (1 second ago) m2 - Hector (HEAD -> master)
| * 7832858 - (87 seconds ago) f1 - Hector (feature)
|/  
* 0a950f5 - (5 minutes ago) m1 - Hector

Integrating changes from master to feature branch

Up to now we have one simple feature branch with a commit and two commits in the master branch, it is a common practice to integrate the commits from the master branch to our feature in order to avoid losing track of master changes, but there are a few ways to do it :

  • Git merge
$ git checkout feature 
$ git merge master

This is a non-destructive way, branches keep preserved its history and only a merge commit appears :

*   fad9250 - (11 seconds ago) Merge branch 'master' into feature - Hector (HEAD -> feature)
|\  
| * 60c3a2b - (5 minutes ago) m2 - Hector (master)
* | 7832858 - (7 minutes ago) f1 - Hector
|/  
* 0a950f5 - (11 minutes ago) m1 - Hector
  • Git merge --squash
$ git checkout feature 
$ git merge --squash master
$ git commit -m "Squash"

This is a non-destructive way as well, branches keep preserved its history but now no merge commit appears, all the changes in master are grouped into 1 commit named Squash in my case and appears as as a single commit in the feature branch, as you can see :

* dc4e5b7 - (10 seconds ago) Squash - Hector (HEAD -> feature)
* 7832858 - (19 minutes ago) f1 - Hector
| * 60c3a2b - (18 minutes ago) m2 - Hector (master)
|/  
* 0a950f5 - (23 minutes ago) m1 - Hector
  • Git rebase
$ git checkout feature 
$ git rebase master

With rebase instead, the history will be simpler, what it does in high-level words is to search for the last common commit and add master commits upon it but below our branch commits.

As you can see m2 commit is upon m1 (last common commit in both branches) and below f1 (our feature branch commit)

* 6074794 - (11 minutes ago) f1 - Hector (HEAD -> feature)
* 60c3a2b - (10 minutes ago) m2 - Hector (master)
* 0a950f5 - (15 minutes ago) m1 - Hector

Integrating changes from feature branch to master

Let's suppose we integrate master changes to feature branch with merge and we add some few changes to both branches, m3 and f2 resulting to this log :

* 83c98e1 - (1 second ago) m3 - Hector (HEAD -> master)
| * 0a3663c - (2 minutes ago) f2 - Hector (feature)
| *   edfda02 - (2 minutes ago) Merge branch 'master' into feature - Hector
| |\  
| |/  
|/|   
* | 60c3a2b - (29 minutes ago) m2 - Hector
| * 490a167 - (3 minutes ago) f1 - Hector
|/  
* 0a950f5 - (35 minutes ago) m1 - Hector

As before, we have the same 3 options :

  • Git merge

If we do a $ git merge feature it will result as it follows :

*   d6b643b - (4 seconds ago) Merge branch 'feature' - Hector (HEAD -> master)
|\  
| * 0a3663c - (4 minutes ago) f2 - Hector (feature)
| *   edfda02 - (4 minutes ago) Merge branch 'master' into feature - Hector
| |\  
| * | 490a167 - (4 minutes ago) f1 - Hector
* | | 83c98e1 - (2 minutes ago) m3 - Hector
| |/  
|/|   
* | 60c3a2b - (31 minutes ago) m2 - Hector
|/  
* 0a950f5 - (36 minutes ago) m1 - Hector
  • Git merge --squash

If we do a squash :

$ git merge --squash feature
$ git commit -m "Squash"

With the behaviour expected, not a merge commit and non-destructive history we get :

* 63f7387 - (10 seconds ago) Squash - Hector (HEAD -> master)
* 83c98e1 - (3 minutes ago) m3 - Hector
| * 0a3663c - (5 minutes ago) f2 - Hector (feature)
| *   edfda02 - (5 minutes ago) Merge branch 'master' into feature - Hector
| |\  
| |/  
|/|   
* | 60c3a2b - (32 minutes ago) m2 - Hector
| * 490a167 - (5 minutes ago) f1 - Hector
|/  
* 0a950f5 - (37 minutes ago) m1 - Hector
  • Git rebase

Finally, let's test what would happen with $ git rebase feature we obtain the following log :

* 6c6ba0e - (5 minutes ago) m3 - Hector (HEAD -> master)
* 0a3663c - (7 minutes ago) f2 - Hector (feature)
*   edfda02 - (7 minutes ago) Merge branch 'master' into feature - Hector
|\  
| * 60c3a2b - (35 minutes ago) m2 - Hector
* | 490a167 - (8 minutes ago) f1 - Hector
|/  
* 0a950f5 - (40 minutes ago) m1 - Hector

Rebase takes the last common commit, which is the merge commit and add places the f2 commit upon it, but below the m3 commit from master.

Top comments (0)