3

ok, this looks so simple but I can't find an easy solution. Let's say there are two branches:

a - b - c - d - e - f <current_branch>
         \
          g - h - i <temp_branch>

I simply want all missing commits in <temp_branch> to be on top of <current_branch> without touching <temp_branch> and without merge commit:

a - b - c - d - e - f - g' - h' - i' <current_branch>
         \
          g - h - i <temp_branch>

What didn't work:

  • git rebase : I could first rebase <temp_branch> on top of <current_branch> and merge back fast-forward. But that's not what I want and it is too complicated.
  • git cherry-pick : if there is no automatic way, manually looking up the commit-range is required

A simple one-liner would be great, like

git rebase --reverse-order temp_branch HEAD

Or some other command I don't know of?

ABika
  • 597
  • 1
  • 5
  • 11
  • By "missing commits", do you mean that you *do* want to skip otherwise-identical commits the way `git rebase` would? – torek Jul 19 '16 at 17:16
  • that would be a nice-to-have but is not required. I know that the commits are not diff-identical. – ABika Jul 19 '16 at 17:18

2 Answers2

4

The easy way:

$ git status  # just to make sure you're on the current branch :-)

Now that you know for sure you're on current_branch:

$ git cherry-pick HEAD..temp_branch

which relies on cherry-pick's internal sequencing to do them in the right order, but won't skip patch-equivalent commits.

The slightly harder way that skips patch-identical commits:

$ git cherry-pick $(git rev-list --reverse --topo-order \
    --right-only --cherry-pick HEAD...temp_branch)

or the same with --left-only and temp_branch...HEAD (these should be precisely the same).

(I have not tested either one, but git rebase --interactive uses:

git rev-list $merges_option --format="%m%H ${format:-%s}" \
    --reverse --left-right --topo-order \
    $revisions ${restrict_revision+^$restrict_revision} | \
    sed -n "s/^>//p" | ...

where $merges_option is --no-merges --cherry-pick, $revisions is $upstream...$orig_head where those are the obvious, and $restrict_revision is via --fork-point if specified). The sed command deletes the right-side commits. You may want an explicit --no-merges as well, though this is not needed for the illustrated case.)

torek
  • 448,244
  • 59
  • 642
  • 775
  • `git cherry-pick ..temp_branch` ! That's what I was looking for. Didn't know you can specify the commit differences like that not only for `log` but also for `cherry-pick` (and probably everywhere else). Thanks! – ABika Jul 19 '16 at 17:59
0

You can use rebase in this way (having current_branch checked out):

git reset --hard temp_branch && git rebase ORIG_HEAD

which automatically skips redundant commits.

Credits go to my colleague Michael Adam, who came up with that idea.

ansiwen
  • 1,061
  • 8
  • 13