Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

interactive rebase with --preserve-merges of all commits in the current branch

There seem to be some similar questions already, but none of them are exactly what I want.

Let's say I have commit history like this

* xxxxxxxH (HEAD -> B) Latest commit
* (more commits)
* xxxxxxxG (B) More commits
*   xxxxxxxF Merge branch 'master' into B
|\  
| * xxxxxxxE (master) Another commit on master
| * (more commits here)
| * xxxxxxxD Commit on master
* | xxxxxxxC Another commit 
* | (more commits here)
* | xxxxxxxB First commit on branch A
|/  
* xxxxxxxA (master) some commit

Now I want to rewrite the history of branch A, potentially merging or editing some commits, but I also want to change the first commit on branch A, and also I want to preserve merges, so that I keep the merge of master into A.

I first intuitively tried git rebase -i -p xxxxxxxB, but obviously that didn't include the xxxxxxxB commit itself. So another attempt was git rebase -i -p xxxxxxxB^ which did include that commit, but now it didn't actually to preserve merges.

Another option that looked promising was --root, but this one starts from the very first commit in the whole repository which is also not what I want.

Is there any way to do what I want?

like image 604
barteks2x Avatar asked Jul 01 '18 22:07

barteks2x


1 Answers

After longer than I considered reasonable, I was able to get a solution on irc:

git rebase -i -m -r firstCommitInBranch^ does exactly what I need.

From git documentation:

   -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.
       (...)
       The --rebase-merges mode is similar in spirit to --preserve-merges, but in
       contrast to that option works well in interactive rebases: commits can be
       reordered, inserted and dropped at will.

and

   -m, --merge
       Use merging strategies to rebase. When the recursive (default) merge strategy is
       used, this allows rebase to be aware of renames on the upstream side.

I also missed the part of documentation that said to not use -p together with -i:

   -p, --preserve-merges
       Recreate merge commits instead of flattening the history by replaying commits a
       merge commit introduces. Merge conflict resolutions or manual amendments to merge
       commits are not preserved.

       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).
like image 88
barteks2x Avatar answered Oct 05 '22 23:10

barteks2x