I have two branches: branchA, branchB
The following returns no output (including no differences, at least for the git diff
command):
git cherry branchA branchB
git diff branchA branchB
git diff branchB branchA
When I run this however:
git cherry branchB branchA
I get a list of commit ids all with a plus sign in front of them:
e.g.
+ c5f84105c242939a9d18fb9d6355534a80735277
+ 41acd0a40bfeaf3d68185a540c131838651cd889
+ 4859fd89c5dafeed6a68f0881ea6ad081a53fd68
+ 7226c9e5acf5a9d2d33b6aef3e5abf9b040f0b76
+ 4fc3206508d6ce7a19477e4c006608c78bb28801
+ 8816c66ed72da762b9b34858eec5b52a16d0ea99
+ 692d271ab07d4b92e54e72bcda09ee067654acee
Can someone please explain what this implies? Looking to understand why git diff shows no differences but git cherry shows differences.
With the cherry-pick command, Git lets you incorporate selected individual commits from any branch into your current Git HEAD branch. When performing a git merge or git rebase , all the commits from a branch are combined. The cherry-pick command allows you to select individual commits for integration.
git cherry-pick is a powerful command that enables arbitrary Git commits to be picked by reference and appended to the current working HEAD. Cherry picking is the act of picking a commit from a branch and applying it to another. git cherry-pick can be useful for undoing changes.
Diffing is a function that takes two input data sets and outputs the changes between them. git diff is a multi-use Git command that when executed runs a diff function on Git data sources. These data sources can be commits, branches, files and more.
When you are performing a regular cherry-pick, you will get a new commit hash but the commit message will be the same. However, there is a way to append the origin of a cherry-pick to the commit message : by using the cherry-pick with the “-x” option.
Git diff shows no output as the files in both branches are identical in content. However the commit ID (SHA string) might be different.
git cherry branchA branxhB is giving no output as all the commits (SHA and not file contents) in branch B is present in branch A. However vice versa is not true. There are some commits in branch A that are not in branch B and hence the output of git cherry branchB branchA. This is very well explained with example here. http://jafrog.com/2012/03/22/git-cherry.html
It means that the content of branchA
and branchB
are the same, but for some reason there are commits on branchB that are not on branchA.
These commits are being displayed. However, the sum total of these commits results in the same content, so you will not see any diff. You will not see anything with git cherry branchA branchB
either, because there are no commits on branchB
that are not on branchA
.
I'm not at all sure where your confusion comes from, especially since git diff
and git cherry
do very different things.
It would probably help (as is almost always true in Git) to draw the commit graph, or at least the relevant part, e.g., run git log --graph --oneline --all --decorate
, or snip some window image from gitk
, or (this is just the documentation's suggestion from below, modified to match your branch names, but it would show just what we need):
git log --oneline --graph --boundary branchA...branchB
(In some cases leaving out --boundary
can make this significantly clearer, when there are very many commits that lie on the boundary of the symmetric difference, but for most simple cases it just adds the merge base commit and thus aids in reading the result.)
Now, let's also take a look at the git cherry documentation, which has a nice example of how we use the three-dot symmetric difference notation to understand the output of git cherry
:
In a situation where [branch]
topic
consisted of three commits, and the maintainer applied two of them, the situation might look like:$ git log --graph --oneline --decorate --boundary origin/master...topic * 7654321 (origin/master) upstream tip commit [... snip some other commits ...] * cccc111 cherry-pick of C * aaaa111 cherry-pick of A [... snip a lot more that has happened ...] | * cccc000 (topic) commit C | * bbbb000 commit B | * aaaa000 commit A |/ o 1234567 branch point
Here, commit 1234567
is the one that --boundary
included. Normally the three-dot notation would have selected only the origin/master
(left side) commits like 7654321
, cccc1111
, and aaaa111
for the left half of the ...
, and the master
(right side) commits like cccc000
, bbbb000
, and aaaa000
commits for the right half. Adding --boundary
adds the shared commit that, in effect, separates these left and right halves.
Look at what our maintainer guy upstream did: he accepted our commit A
and our commit C
, copying them change-for-change into his master
which we see in our origin/master
. He did not accept our commit B
, or at least, not change-for-change (we can't tell from this, nor from git cherry
, if he has taken some alternate version of our change).
Now look at the sample output from running git cherry
:
In such cases, git-cherry shows a concise summary of what has yet to be applied:
$ git cherry origin/master topic - cccc000... commit C + bbbb000... commit B - aaaa000... commit A
This shows us all three commits on the right side (topic
), while not showing us any of the commits on the left side (origin/master
), of our log [flags] origin/master...topic
listing.
For the commits it does show—those exclusively on the right—it marks each one with -
(taken) or +
(not taken).
We don't have a graph fragment, though, so let's work with what we do have at the moment.
git cherry branchA branchB
[is empty, but]
git cherry branchB branchA
(includes at least)
+ c5f84105c242939a9d18fb9d6355534a80735277 + 41acd0a40bfeaf3d68185a540c131838651cd889 + 4859fd89c5dafeed6a68f0881ea6ad081a53fd68 + 7226c9e5acf5a9d2d33b6aef3e5abf9b040f0b76 + 4fc3206508d6ce7a19477e4c006608c78bb28801 + 8816c66ed72da762b9b34858eec5b52a16d0ea99 + 692d271ab07d4b92e54e72bcda09ee067654acee
This mean that there are no commits on branchB that are not also on branchA, while there are many (at least the 7 listed above) commits on branchA that not on branchB. In fact, all of those 7 listed are all not-copied as well—not surprising, none of the exclusive-to-right-side branchA
commits could possibly have been copied, if there are no exlusive-to-left-side (branchB
) commits at all.
This means we can draw an approximation of the graph we would have gotten, if we had asked for one (I may have the wrong abbreviated hashes here):
* 692d271 (branchB) commit 7
* ....... commit 6
* ....... commit 5
* ....... commit 4
* ....... commit 3
* ....... commit 2
* c5f8410 commit 1
* xxxxxxx (branchA) branch point
This is a way—probably the only way—to get the output you saw.
Meanwhile:
git diff branchA branchB git diff branchB branchA
(both produce no output at all.)
This just means that the source tree attached to branchA
matches the source tree attached to branchB
(after, perhaps, any filtering you selected when doing the diff). There are a bunch of ways to achieve that and it is hard to say which one(s) may have been used, but here is an example of what would do that:
$ git branch remember-where-we-parked-kids
$ echo new file > new-file && git add new-file
$ echo add another line >> existing-file && git add existing-file
$ git commit -m 'commit a change'
[master 643b37e] commit a change
2 files changed, 2 insertions(+)
create mode 100644 new-file
$ git revert --no-edit HEAD
[master 0af7c6a] Revert "commit a change"
2 files changed, 2 deletions(-)
delete mode 100644 new-file
The first commit contains a change that adds a file and modifies a file. The second (revert) commit contains a change that removes the added file new-file
and puts the old file existing-file
back the way it was just a moment ago, removing the added line. Comparing the current commit to the commit made two steps ago will show no differences, since the sum total of the two commits was to do nothing after all.
Using git cherry
on branch remember-where-we-parked-kids
, we would see that neither of the two added commits (the modification and its revert) are in the "other" branch (which is just two commits behind from where we are now):
$ git cherry remember-where-we-parked-kids master
+ 643b37ef242fdc35dfdd4551b42393af3eb91a85
+ 0af7c6a3cf5e49928de132c341c848be80ab84c7
(these are our two commits, the revert, 0af7c6a
, and the initial change, 643b37e
). Reversing the arguments to git-cherry
, we get nothing, and of course the git diff
is equally empty:
$ git cherry master remember-where-we-parked-kids
$ git diff master remember-where-we-parked-kids
$
It's not possible to say how you got where you are now without more information, but this is what the output you have seen means.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With