Today,

I will be explaining git rebase, git merge, purpose for these and when to use these.

Both git rebase and git merge are used to integrate the changes of one branch to another branch

let’s suppose this is the scenario:

Feature —- e-f-g | Main -> a-b—-c–d

Now to have c,d commits in feature branch, we have 2 options

  • Merge

    git checkout feature && git merge main 
    

    This makes a new commit in feature branch let suppose it is g' which contains main commits c and d.

    Feature —- e-f-g-g' | Main -> a-b—-c–d

    The above case is the recursive merge. If suppose there isn’t commits e and f, then merge just need to add commits c and d. The latter case is called the fast-fowarded where the commit history is linear and it doesn’t need to add a commit. In this case

    git merge main // won't create a new commit but if we use `--no-ff` then it will create a new commit
    

To reset merge:

git reset --hard HEAD~1 this command can be used to reset merge if the last commit is merge commit or you can get the commit from git reflog and do git reset --hard #commit

  • Rebase
git checkout feature && git rebase main

This adds all the commits in main and then adds the latest commits of feature. Basically changes the parent of first different commit in the feature branch and child of the last main commit.

Feature e'-f'-g' | Main -> a-b—-c–d

To reset the rebase:

git reset --hard ORIG_HEAD Rebase stores the old state before rebase in ORIG_HEAD or you can get the commit from git reflog and do git reset --hard #commit

Feature —- e-f-g | Main -> a-b—-c–d

If c and e has same changes and the committer info is different basically if both the checksum is same then in git rebase main feature, the final history of feature will look like a->b->c->d->f->g. It skips the e in the feature branch.

If git rebase doesn’t take merge commits, then mention -p to take merge commits into consideration while rebasing

Pro’s and Con’s of each:

Rebase pros are the commit history will be linear so all the commits of a feature will be present at one place.

Cons are as the commit history changes, the will be problem of reaching a commit and the resolving conflicts will be a problem

Merge pros and cons are the vice-versa of rebase.

So rebase will be useful you are IC(individual contributor) and merge will be useful if there are many people.

Squash:

For squashing, you can use git rebase -i HEAD~3 and have s for the commits to squash it.

Best solution:

It is best to use rebase on the feature branch (i.e while getting the latest changes) and use merge in main branch

  • Use rebase while pulling the main changes into feature branch.
  • Add git config --add branch.master.mergeoptions --ff-only or git config --add branch.main.mergeoptions --ff-only and squash the feature commits before merge

You can get the best of both worlds: rebase local changes before pushing to clean up your work, but never rebase anything that you’ve pushed somewhere.

There is --onto flag in git rebase which is much useful. In git rebase --help, it has been explained clearly. For real case scenario -> https://stackoverflow.com/questions/51194261/git-rebase-with-merged-commits

This repo has all the cases using git merge and git rebase. Use git reflog and git log --graph to understand the commit history