Side note - run
gitk --merge
when you have a merge conflict, and it will basically show you the thing
graphically (ie history as it is relevant to the merge, and only to the
files that get conflicts).
But basically, both sides have modified the code *around* that line, and
they have modified it differently.
Do this in your partial merge tree on 'master':
git diff ...mdadm-2.6.3+200709292116+4450e59 Monitor.c
git diff mdadm-2.6.3+200709292116+4450e59... Monitor.c
which will show you the diff from the common base ancestor. And in
particular, it will show how one branch did this:
@@ -399,9 +401,8 @@ int Monitor(mddev_dev_t devlist,
struct mdstat_ent *mse;
for (mse=mdstat; mse; mse=mse->next)
if (mse->devnum != MAXINT &&
- (strcmp(mse->level, "raid1")==0 ||
- strcmp(mse->level, "raid5")==0 ||
- strcmp(mse->level, "multipath")==0)
+ (strcmp(mse->level, "raid0")!=0 &&
+ strcmp(mse->level, "linear")!=0)
) {
struct state *st = malloc(sizeof *st);
mdu_array_info_t array;
and the other one did
@@ -398,10 +402,9 @@ int Monitor(mddev_dev_t devlist,
if (scan) {
struct mdstat_ent *mse;
for (mse=mdstat; mse; mse=mse->next)
- if (mse->devnum != MAXINT &&
- (strcmp(mse->level, "raid1")==0 ||
- strcmp(mse->level, "raid5")==0 ||
- strcmp(mse->level, "multipath")==0)
+ if (mse->devnum != INT_MAX &&
+ (strcmp(mse->level, "raid0")!=0 &&
+ strcmp(mse->level, "linear")!=0)
) {
struct state *st = malloc(sizeof *st);
mdu_array_info_t array;
And now maybe git's behaviour makes more sense. See? You basically had two
different branches that made *almost* the same changes to the same area,
but not quite. So how is git to know which one was the *right* one to
pick? The one that changed the "if (mse->devnum != MAXINT &&" line, or the
one that left it alone?
Cherry-picking is immaterial. It doesn't matter how the changes come into
the tree. It doesn't matter what the history is. The only thing git cares
about is the content, and the end result.
Git knows that the two branches got to two different end results. They
were identical except for that one line, and it asks you to say which
branch was "right" wrt that one line.
In other words, git never looks at individual commits when trying to
merge. It doesn't try to figure out what the "meaning" of the changes are,
it purely looks at the content.
And btw, it *has* to work that way, because if you don't work that way,
then you get different results depending on which path the development
took (eg you might get different results if something was considered a
"revert", for example, or if something was split up into two patches on
one side but not the other etc etc).
But in this case it's pretty obvious: the commit from one side (the one
that changes MAXINT->INT_MAX: "Monitor.c s/MAXINT/INT_MAX/g") merged fine
into the result *except* for that one section that had touched the same
general area for other reasons. And that one area was seen as a conflict
because of those other reasons being in the same hunk.
And yes, in this case the "other reasons" happened to be cherry-picked and
thus "the same" on both sides, but that doesn't mean that they should have
been considered in any way special: the result of cherry-picking is
context-dependent and is a part of the history of the target, and does not
equate any kind of "identity" with the source. Cherry-picking is 100%
equivalent to re-doing the commit entirely, and for all git knows, there
was a reason why it wasn't done together with that s/MAXINT/INT_MAX/g
change.
(Not that git even thinks in those terms - git literally just says: "I
cannot resolve the _content_ independently and without understanding the
history and thinking behind the differences, so you'd better help me")
Linus
-
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html