Search code examples
gitgit-cherry-pick

Is git cherry-pick actually the same as git show + git apply?


Could it be that

git cherry-pick <rev>

is in fact exactly the same as

git show <rev> | git apply -3 -

???

Since running either one causes exactly the same result for me and if I knew they are indeed equivalent, I could get a much better understanding of how cherry-picking with GIT actually works, as it doesn't always give me the result I'd expect, but that's probably because the sole change cannot be applied and cherry-picking falls back to a three-way-merge (that's what -3 does on the second command) and that would explain the unexpected result.


Solution

  • Besides Edmundo's answer, which is right and I've upvoted it, there are a bunch of other niggling details, including ephemient's comment about binary files (git show needs --binary to produce a binary patch) and that you may need --full-index as well, in some rare cases where an abbreviated Index: line is insufficient.1

    Also, of course, git apply (with or without -3) does not mind a dirty index and work-tree, while git cherry-pick requires a clean index and work-tree, unless you add -n. And, if you omit -n, git cherry-pick goes on to make a commit, which git apply never does.

    All that said, though, yes, these two should be functionally equivalent for normal cases.


    1To get this to occur, the blob hashes have to be non-unique upon abbreviation. This was made automatically-correct in Git version 1.7.2, though if you force a particular abbreviation length with core.abbrev or a command line flag, you can still get non-unique hash abbreviations. Adding --full-index ensures that you get unique ones.

    (If you were to save a diff for a long period, add a bunch of new objects to the repository, and then try to git apply -3 the diff, it's possible for abbreviated Index: lines that were unambiguous before to become ambiguous now.)