Using merge and rebase together
I might have given the impression that git rebase is cleaner, and thus better, than git merge. This is not the case; there are pros and cons for each method.
git rebase rewrites, or alters, the existing history of the repository by trying to replicate changes on the sub-branch at the end of the main branch. This makes the history look cleaner and more linear, but loses the context of when and where changes are integrated together – we lose the information that social-login/twitter was originally branched off from social-login/main.
So, I'd advise using git rebase for feature/bug-fix branches. This allows you to commit small and often, making work-in-progress (WIP) commits, without having to care too much about cleanliness. After your feature is complete, you can then clean up your commit history using git rebase, before merging into the permanent branches.
On the other hand, when integrating changes from a feature branch into the dev branch, or from the dev branch into master, use git merge because it provides context as to where and when those features were added. Furthermore, we should add a --no-ff flag to git merge, which ensures the merge will always create a new commit, even when fast-forwarding is possible.
By combining both git merge and git rebase, it is possible to end up with a nice Git history:
We can even delete some branches to make the history even cleaner:
$ git branch -D social-login/facebook social-login/twitter
The branch structure is now much simpler to comprehend: