15

There's something I don't understand when I rebase after cherry-picking in git. Would someone please tell me what's going on?

The scenario like this:

I am working on the master and topic branches as follows and the topic has two commits.

      C---D  topic
     /
A---B      master

I had a problem with the topic branch, so I decided to just cherry-pick D and merge it into the master. I create a release branch and cherry-pick it.

      C---D  topic
     /
A---B      master
     \
      D'  release

I merge release into master.

      C---D  topic
     /
A---B----E   master
     \  /
      D'  release

The base branch of the topic has changed, so I rebase it to the latest master.

           C  topic
          /
A---B----E   master
     \  /
      D'  release

Finally, the commit of D that cherry-picked disappeared from the topic. This is the intended result for me. But I don't understand why git found them to be the same, even though the commit hashes are different.

mitsuruog
  • 1,259
  • 3
  • 12
  • 21

1 Answers1

17

A cherry-pick would change the metadata associates to a commit (like the date or its parent).
But it would not change its content (the tree SHA1 it references)

As explained in "How does git rebase skip the commit which its change already has in upstream?", the patch id associated to the commit D is the same as D', which is already merged.
So it is not repeated by the rebase.

With Git 2.34 (Q4 2021), you will actually see those skipped commits, as rebase will tell you:

skipped previously applied commit xxx
use git rebase --reapply-cherry-picks to include skipped commits

From the man page:

--reapply-cherry-picks

--no-reapply-cherry-picks

Reapply all clean cherry-picks of any upstream commit instead of preemptively dropping them. (If these commits then become empty after rebasing, because they contain a subset of already upstream changes, the behavior towards them is controlled by the --empty flag.)

By default (or if --no-reapply-cherry-picks is given), these commits will be automatically dropped.
Because this necessitates reading all upstream commits, this can be expensive in repos with a large number of upstream commits that need to be read.
When using the merge backend, warnings will be issued for each dropped commit (unless --quiet is given). Advice will also be issued unless advice.skippedCherryPicks is set to false.

--reapply-cherry-picks allows rebase to forgo reading all upstream commits, potentially improving performance.

VonC
  • 1,262,500
  • 529
  • 4,410
  • 5,250
  • 4
    To reword it : when rebasing, git compares the *diffs* generated by each commit, to determine if a commit has already been applied. – LeGEC Jun 05 '20 at 07:42
  • 1
    @LeGEC Indeed. The path-ID I reference is the SHA1 of the diff you mention (https://mirrors.edge.kernel.org/pub/software/scm/git/docs/git-patch-id.html) – VonC Jun 05 '20 at 07:46
  • thanks for the link. Out of curiosity : does git store the patch-id for each commit somewhere ? or are they recomputed when needed ? – LeGEC Jun 05 '20 at 07:50
  • 1
    @LeGEC From what torek mentioned in https://stackoverflow.com/a/52790107/6309, it is computed when needed. – VonC Jun 05 '20 at 07:52
  • note to self that git-rebase docs also give a useful explanation: https://git-scm.com/docs/git-rebase/2.35.0#Documentation/git-rebase.txt---reapply-cherry-picks – Kay V Mar 02 '22 at 19:27
  • @KayV Good point, thank you. I have included the relevant man page extract in the answer for more visibility. – VonC Mar 02 '22 at 23:15
  • To what command is "hint: use --reapply-cherry-picks to include skipped commits" connected? "git rebase"? "git pull"? – Ken Ingram Apr 26 '22 at 16:40
  • @KenIngram rebase: this comes from the sequencer in charge to manage the sequence of commits to rebase. – VonC Apr 26 '22 at 20:05
  • Ok. what's the proper command that includes --reapply? – Ken Ingram Apr 28 '22 at 00:56
  • 1
    @KenIngram [`git rebase --reapply-cherry-picks`](https://git-scm.com/docs/git-rebase#Documentation/git-rebase.txt---reapply-cherry-picks) – VonC Apr 28 '22 at 06:20