|This page refers to a draft policy which is still to be agreed and implemented. Please take it as a reference for a work in progress project.|
Rebasing and merging are two different strategies for synchronizing changesets between two or more branches. Besides aiming for the same purpose, they are completely different one from the other.
Let's try to explain what each method does. We assume of having a branch my-feature we want to synchronize with the master branch.
Suppose you want to rebase my-feature onto master. The rebase process finds which commits in my-feature are not present in master, and cherry-picks them. Afterwards, your branch is reset to the HEAD of the branch you want to rebase on (master in this case), and commits are sequentially applied afterwards.
This means that now all your commits sit on top of the other branch's HEAD, which is now a base for your branch.
It has the advantage of keeping a clean, linear history. It also does not create merge commits (as no merge is actually happening).
It has the disadvantage of rewriting commit hashes, and subsequently rewrite history, making it unsuitable for tracking remote branches.
In addition, rebase can be used for editing, amending, squashing and deleting commits.
When merging a branch into another one, the history of the two branches intersect. This means that the history order will be preserved in a chronological way: the commits will be ordered by date.
A merge can be either fast-forward or not: fast-forward means that no merging process has to be done: a fast-forward merge's result looks exactly the same as a rebase result (even though the process still remains very different).
If a merge is non fast-forward, the history of the two branches must be intersected. As a result of the process, an additional commit is added to the repository, carrying the merge result.
It has the advantage of keeping history consistent (commit hashes are not altered) and preserving chronological history.
It has the disadvantage of making it harder to track a branch's changes, and scattering a branch's commits throughout the repository
Merge is also able to use different merging strategies, and squash the merge in a single commit (strongly discouraged).
Merge and rebase have a very similar syntax, and their usage is quite similar. The most popular and used command related to merge and rebase is git pull.
git pull is nothing but a combination of git fetch and git merge. It fetches changes from the remote branch tracked by the local branch you have currently checked out, and merges them afterwards.
If git pull had ever generated merge commit messages, now you know why - and you should know how to prevent that. git pull has a --rebase option, which instead of fetching+merging does fetching+rebasing. It is good practice, as it will be explained afterwards, to always use git pull --rebase.
The bare rebase and merge commands accept as a compulsory argument the name of the branch you want to synchronize with. So, in your local checkout of the branch you want to synchronize, issue:
git rebase master
git merge master
As easy as that goes.
In particular, merge has a --no-ff options, which makes fast-forward merges behave as if they were non fast-forward, e.g.: generating a merge commit.
The main question is obviously which strategy is correct and which should be preferred. As already explained, those two methods serve for different purposes, and are orthogonal one to the other. So the decision on which one to use must be made depending on the situation.
In general, in 99% of the cases it applies...
Always rebase when dealing with branches used locally, always merge when dealing with branches you'll push remotely
It should be clear at this point that