git rebase --onto never gets past rewinding head

Viewed 306

I have the following branches:

 ─┬──────────────────────────────────────┬──  master
  │                                      │
  │                                      │
  │                                      └── staging
  │
  │
  └─X───Y─┬─────────────────────────────────  develop
          │                         ▲
          │                         │
          └────A────────B──────C────┴──┬────  feature/abc
                                       │
                                       │
                                       └────  merge/feature/abc

Quick explanation of each one:

  • master: this is the production branch - anything merged here goes to production.
  • staging: this branch is used to temporarily group a bunch of different features that will go to production together as a release. Before a release, a fresh staging is cut from master.
  • develop: mainline branch - regular branch that features are continually integrated into, as they are completed.
  • feature/abc: a typical feature branch, cut from develop.
  • merge/feature/abc: a working branch that I am trying to rebase, so that I can prepare the feature to be rebased off staging, as I prepare to do a release. (I just don't want to mess up the feature/abc.)

I want to make the merge/feature/abc rebased off staging, so that it contains only the relevant commits in feature/abc. i.e. I want merge/feature/abc to contain only commits A, B, and C, but not X and Y. This would happen after the feature/abc branch has been merged and tested on develop.

According to the git manual, the commands I want is:

git rebase --onto staging develop merge/feature/abc

When I do that, the output says:

First, rewinding head to replay your work on top of it...

... and that's it - no other output. It just stops. As I understand it, there's supposed to be more output as git rebase applies commits. The merge/feature/abc branch does get rebased, but it does *not contain any commits from feature/abc, if I do git log. If I run git status, it says:

On branch merge/feature/abc
nothing to commit, working tree clean

If I run git diff staging, there is no diff. So it's basically reset to staging.

What am I doing wrong?

1 Answers

This command:

git rebase --onto staging develop merge/feature/abc

is short for:

git checkout merge/feature/abc
git rebase --onto staging develop

Here develop is the upstream argument, which should disable fork-point mode. If for some reason it does not disable fork-point mode, adding --no-fork-point might help, but in any case, you might wish to run:

git log develop..merge/feature/abc

to see which commits would be candidates for copying here. If the list is empty, that's the answer right away: there are no candidate commits to be copied. If the list isn't empty, the next step is to examine these candidate commits:

  • Any merge commits will be omitted. Are the listed commits all merges? If so, they will all be omitted.
  • Any commits whose patch ID matches one in the upstream will be omitted.

This second point is what TTT is alluding to in this comment:

... (or their equivalents) ...

Finding patch-ID-equivalent commands is a bit trickier. The --left-right --cherry-mark options to git log / git rev-list, and the git cherry command, can do this. When using --cherry-mark with git log or git rev-list, it's necessary to use the three-dot symmetric difference operator:

git log --left-right --cherry-mark --oneline develop...merge/feature/abc

The cherry-mark option makes git log (or git rev-list) run each commit through the patch-ID generator and then marks equivalent commits with = instead of < or >. If there are commits listed by git log develop..merge/feature/abc, they would be right-hand-side > commits in this output; if they become marked with =, they're already in develop (or more precisely, Git thinks they are) so git rebase does not copy them.

If this is the issue, the --reapply-cherry-picks flag can help. This flag is relatively new, having first appeared in Git 2.27.0.

Note: a command for listing everything all at once, with merge commits omitted without you having to do anything, is:

git rev-list --left-right --cherry-mark --no-merges develop...merge/feature/abc

Only commits marked > would be copied. (Consider using git log --oneline for this as well, since that shows subject lines.)

Related