Search code examples
gitmergegit-mergerebasegit-rebase

How to preserve --no-ff merges after a rebase


Say you have a master and develop branches. Further more, say you workflow is like that:

  • on develop you checkout a new feature branch;
  • work on it;
  • check out develop again;
  • merge the feature branch with --no-ff.

This way you can nicely see which commits belong to which feature.

* Merge branch 'feature' into develop
|\
| * Commit 3
| * Commit 2
| * Commit 1
|/
* Some old commit

At some point you pull master and want to rebase develop on it. However, after the rebase git log displays all commits on develop in a linear way, without showing the feature branches and omitting the generic merge commits:

* Commit 3
* Commit 2
* Commit 1
* Some old commit

Why is that and how can I preserve them after a rebase?


Solution

  • Before Git 2.18, pass -p to git rebase to preserve merges:

    -p
    --preserve-merges
    
        Instead of ignoring merges, try to recreate them.
    
        This uses the --interactive machinery internally, but combining it with the --interactive option explicitly is generally not a good idea unless you know what you are doing (see BUGS below).
    

    With Git 2.18 onward, use -r to rebase merges:

    -r
    --rebase-merges[=(rebase-cousins|no-rebase-cousins)]
    
        By default, a rebase will simply drop merge commits from the todo list, and put the rebased commits into a single, linear branch. With --rebase-merges, the rebase will instead try to preserve the branching structure within the commits that are to be rebased, by recreating the merge commits. Any resolved merge conflicts or manual amendments in these merge commits will have to be resolved/re-applied manually.
    

    This option does no suffer from the above limitations with interactive rebases anymore and "commits can be reordered, inserted and dropped at will".