Re: inexplicable failure to merge recursively across cherry-picks

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 




On Wed, 10 Oct 2007, martin f krafft wrote:
> 
> There are five commits between mdadm-2.6.2 and
> mdadm-2.6.3+200709292116+4450e59 that affect Monitor.c:
> 
>   01d9299
>   e4dc510
> * 66f8bbb
>   98127a6
>   4450e59
> 
> The third commit, the one with the asterisk is the one that
> I cherry-picked (as 845eef9); the other two cherries I picked do not
> touch Monitor.c.

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?

> I branched master2 off 845eef9b~1, cherry-picked the first two
> commits that touch Monitor.c, cherry-picked all the commits
> 845eef9b..master into master2 and merge upstream...

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@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Linux Kernel Development]     [Gcc Help]     [IETF Annouce]     [DCCP]     [Netdev]     [Networking]     [Security]     [V4L]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux SCSI]     [Fedora Users]

  Powered by Linux