{"thread":{"id":"33007","subject":"Merging submodules - best merge-base","startedAt":"2013-02-25T16:44:05Z","lastAt":"2013-03-11T20:30:22Z","messageCount":7,"participants":["Daniel Bratell","Heiko Voigt","Jens Lehmann"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"210252","messageId":"op.ws2l3rgnrbppqq@cicero.linkoping.osa","threadId":"33007","inReplyTo":null,"subject":"Merging submodules - best merge-base","fromName":"Daniel Bratell","fromEmail":"bratell@opera.com","sentAt":"2013-02-25T16:44:05Z","receivedAt":"2013-02-25T16:44:05Z","isPatch":false,"sender":{"key":"bratell@opera.com","avatar":null},"body":"I can phrase this in two ways and I'll start with the short way:\n\nWhy does a merge of a git submodule use as merge-base the commit that was  \nactive in the merge-base of the parent repo, rather than the merge-base of  \nthe two commits that are being merged?\n\nThe long question is:\n\nA submodule change can be merged, but only if the merge is a  \n\"fast-forward\" which I think is a fair demand, but currently it checks if  \nit's a fast-forward from a commit that might not be very interesting  \nanymore.\n\nIf two branches A and B split at a point when they used submodule commit  \nS1 (based on S), and both then switched to S2 (also based on S) and B then  \nswitched to S21, then it's today not possible to merge B into A, despite  \nS21 being a descendant of S2 and you get a conflict and this warning:\n\nwarning: Failed to merge submodule S (commits don't follow merge-base)\n\n(attempt at ASCII gfx:\n\nSubmodule tree:\n\nS ---- S1\n   \\\n    \\ - S2 -- S21\n\nMain tree:\n\nA' (uses S1) --- A (uses S2)\n   \\\n    \\ --- B' (uses S2) -- B (uses S21)\n\n\nI would like it to end up as:\n\nA' (uses S1) --- A (uses S2) ------------ A+ (uses S21)\n   \\                                     /\n    \\ --- B' (uses S2) -- B (uses S21)- /\n\nAnd that should be legal since S21 is a descendant of S2.\n\n/Daniel\n"},{"id":"210705","messageId":"20130306181156.GA4114@sandbox-ub","threadId":"33007","inReplyTo":"op.ws2l3rgnrbppqq@cicero.linkoping.osa","subject":"Re: Merging submodules - best merge-base","fromName":"Heiko Voigt","fromEmail":"hvoigt@hvoigt.net","sentAt":"2013-03-06T18:12:05Z","receivedAt":"2013-03-06T18:12:05Z","isPatch":false,"sender":{"key":"hvoigt@hvoigt.net","avatar":"https://avatars.githubusercontent.com/u/184958?v=4"},"body":"On Mon, Feb 25, 2013 at 05:44:05PM +0100, Daniel Bratell wrote:\n> I can phrase this in two ways and I'll start with the short way:\n> \n> Why does a merge of a git submodule use as merge-base the commit that was  \n> active in the merge-base of the parent repo, rather than the merge-base of  \n> the two commits that are being merged?\n> \n> The long question is:\n> \n> A submodule change can be merged, but only if the merge is a  \n> \"fast-forward\" which I think is a fair demand, but currently it checks if  \n> it's a fast-forward from a commit that might not be very interesting  \n> anymore.\n> \n> If two branches A and B split at a point when they used submodule commit  \n> S1 (based on S), and both then switched to S2 (also based on S) and B then  \n> switched to S21, then it's today not possible to merge B into A, despite  \n> S21 being a descendant of S2 and you get a conflict and this warning:\n> \n> warning: Failed to merge submodule S (commits don't follow merge-base)\n> \n> (attempt at ASCII gfx:\n> \n> Submodule tree:\n> \n> S ---- S1\n>    \\\n>     \\ - S2 -- S21\n> \n> Main tree:\n> \n> A' (uses S1) --- A (uses S2)\n>    \\\n>     \\ --- B' (uses S2) -- B (uses S21)\n> \n> \n> I would like it to end up as:\n> \n> A' (uses S1) --- A (uses S2) ------------ A+ (uses S21)\n>    \\                                     /\n>     \\ --- B' (uses S2) -- B (uses S21)- /\n> \n> And that should be legal since S21 is a descendant of S2.\n\nSo to summarize what you are requesting: You want a submodule merge be\ntwo way in the view of the superproject and calculate the merge base\nin the submodule from the two commits that are going to be merged?\n\nIt currently sounds logical but I have to think about it further and\nwhether that might break other use cases.\n\nCheers Heiko\n"},{"id":"210754","messageId":"op.wtklj7e9rbppqq@cicero.linkoping.osa","threadId":"33007","inReplyTo":"20130306181156.GA4114@sandbox-ub","subject":"Re: Merging submodules - best merge-base","fromName":"Daniel Bratell","fromEmail":"bratell@opera.com","sentAt":"2013-03-07T09:49:09Z","receivedAt":"2013-03-07T09:49:09Z","isPatch":false,"sender":{"key":"bratell@opera.com","avatar":null},"body":"Den 2013-03-06 19:12:05 skrev Heiko Voigt <hvoigt@hvoigt.net>:\n\n> On Mon, Feb 25, 2013 at 05:44:05PM +0100, Daniel Bratell wrote:\n>> I can phrase this in two ways and I'll start with the short way:\n>>\n>> Why does a merge of a git submodule use as merge-base the commit that  \n>> was\n>> active in the merge-base of the parent repo, rather than the merge-base  \n>> of\n>> the two commits that are being merged?\n>>\n>> The long question is:\n>>\n>> A submodule change can be merged, but only if the merge is a\n>> \"fast-forward\" which I think is a fair demand, but currently it checks  \n>> if\n>> it's a fast-forward from a commit that might not be very interesting\n>> anymore.\n>>\n>> If two branches A and B split at a point when they used submodule commit\n>> S1 (based on S), and both then switched to S2 (also based on S) and B  \n>> then\n>> switched to S21, then it's today not possible to merge B into A, despite\n>> S21 being a descendant of S2 and you get a conflict and this warning:\n>>\n>> warning: Failed to merge submodule S (commits don't follow merge-base)\n>>\n>> (attempt at ASCII gfx:\n>>\n>> Submodule tree:\n>>\n>> S ---- S1\n>>    \\\n>>     \\ - S2 -- S21\n>>\n>> Main tree:\n>>\n>> A' (uses S1) --- A (uses S2)\n>>    \\\n>>     \\ --- B' (uses S2) -- B (uses S21)\n>>\n>>\n>> I would like it to end up as:\n>>\n>> A' (uses S1) --- A (uses S2) ------------ A+ (uses S21)\n>>    \\                                     /\n>>     \\ --- B' (uses S2) -- B (uses S21)- /\n>>\n>> And that should be legal since S21 is a descendant of S2.\n>\n> So to summarize what you are requesting: You want a submodule merge be\n> two way in the view of the superproject and calculate the merge base\n> in the submodule from the two commits that are going to be merged?\n>\n> It currently sounds logical but I have to think about it further and\n> whether that might break other use cases.\n\nMaybe both could be legal even. The current code can't be all wrong, and  \nthis case also seems to be straightforward.\n\n/Daniel\n"},{"id":"210783","messageId":"20130307185906.GA9661@sandbox-ub.fritz.box","threadId":"33007","inReplyTo":"op.wtklj7e9rbppqq@cicero.linkoping.osa","subject":"Re: Merging submodules - best merge-base","fromName":"Heiko Voigt","fromEmail":"hvoigt@hvoigt.net","sentAt":"2013-03-07T18:59:07Z","receivedAt":"2013-03-07T18:59:07Z","isPatch":false,"sender":{"key":"hvoigt@hvoigt.net","avatar":"https://avatars.githubusercontent.com/u/184958?v=4"},"body":"On Thu, Mar 07, 2013 at 10:49:09AM +0100, Daniel Bratell wrote:\n> Den 2013-03-06 19:12:05 skrev Heiko Voigt <hvoigt@hvoigt.net>:\n> \n> >On Mon, Feb 25, 2013 at 05:44:05PM +0100, Daniel Bratell wrote:\n> >>A submodule change can be merged, but only if the merge is a\n> >>\"fast-forward\" which I think is a fair demand, but currently it\n> >>checks if\n> >>it's a fast-forward from a commit that might not be very interesting\n> >>anymore.\n> >>\n> >>If two branches A and B split at a point when they used submodule commit\n> >>S1 (based on S), and both then switched to S2 (also based on S)\n> >>and B then\n> >>switched to S21, then it's today not possible to merge B into A, despite\n> >>S21 being a descendant of S2 and you get a conflict and this warning:\n> >>\n> >>warning: Failed to merge submodule S (commits don't follow merge-base)\n> >>\n> >>(attempt at ASCII gfx:\n> >>\n> >>Submodule tree:\n> >>\n> >>S ---- S1\n> >>   \\\n> >>    \\ - S2 -- S21\n> >>\n> >>Main tree:\n> >>\n> >>A' (uses S1) --- A (uses S2)\n> >>   \\\n> >>    \\ --- B' (uses S2) -- B (uses S21)\n> >>\n> >>\n> >>I would like it to end up as:\n> >>\n> >>A' (uses S1) --- A (uses S2) ------------ A+ (uses S21)\n> >>   \\                                     /\n> >>    \\ --- B' (uses S2) -- B (uses S21)- /\n> >>\n> >>And that should be legal since S21 is a descendant of S2.\n> >\n> >So to summarize what you are requesting: You want a submodule merge be\n> >two way in the view of the superproject and calculate the merge base\n> >in the submodule from the two commits that are going to be merged?\n> >\n> >It currently sounds logical but I have to think about it further and\n> >whether that might break other use cases.\n> \n> Maybe both could be legal even. The current code can't be all wrong,\n> and this case also seems to be straightforward.\n\nOk I have thought about it further and I did not come up with a simple\n(and stable) enough strategy that would allow your use case to merge\ncleanly without user interaction.\n\nThe problem is that your are actually doing a rewind from base to both\ntips. The fact that a rewind is there makes git suspicious and we simply\ngive up. IMO, thats the right thing to do in such a situation.\n\nWhat should a merge strategy do? It infers from two changes what the\nfinal intention might be. For submodules we can do that when the changes\non both sides point forward. Since thats the typical progress of\ndevelopment. If not there is some reason for it we do not know about. So\nthe merge gives up.\n\nPlease see this post about why we need to forbid rewinds from the\ninitial design discussion:\n\nhttp://article.gmane.org/gmane.comp.version-control.git/149003\n\nI am not saying that the current behavior is perfect but I think a merge\ncontaining a rewind needs user support. We could give the user a hint\nand say: \"Hey I gave up but the two sides are contained in each other\nand this is the commit containing both\". Then the user can choose to use\nthat suggested solution. We already do the same for the merge commit\nsearch.\n\nCheers Heiko\n"},{"id":"210902","messageId":"513B7554.4020700@web.de","threadId":"33007","inReplyTo":"20130307185906.GA9661@sandbox-ub.fritz.box","subject":"Re: Merging submodules - best merge-base","fromName":"Jens Lehmann","fromEmail":"jens.lehmann@web.de","sentAt":"2013-03-09T17:45:56Z","receivedAt":"2013-03-09T17:45:56Z","isPatch":false,"sender":{"key":"jens.lehmann@web.de","avatar":"https://avatars.githubusercontent.com/u/135220?v=4"},"body":"Am 07.03.2013 19:59, schrieb Heiko Voigt:\n> On Thu, Mar 07, 2013 at 10:49:09AM +0100, Daniel Bratell wrote:\n>> Den 2013-03-06 19:12:05 skrev Heiko Voigt <hvoigt@hvoigt.net>:\n>>\n>>> On Mon, Feb 25, 2013 at 05:44:05PM +0100, Daniel Bratell wrote:\n>>>> A submodule change can be merged, but only if the merge is a\n>>>> \"fast-forward\" which I think is a fair demand, but currently it\n>>>> checks if\n>>>> it's a fast-forward from a commit that might not be very interesting\n>>>> anymore.\n>>>>\n>>>> If two branches A and B split at a point when they used submodule commit\n>>>> S1 (based on S), and both then switched to S2 (also based on S)\n>>>> and B then\n>>>> switched to S21, then it's today not possible to merge B into A, despite\n>>>> S21 being a descendant of S2 and you get a conflict and this warning:\n>>>>\n>>>> warning: Failed to merge submodule S (commits don't follow merge-base)\n>>>>\n>>>> (attempt at ASCII gfx:\n>>>>\n>>>> Submodule tree:\n>>>>\n>>>> S ---- S1\n>>>>   \\\n>>>>    \\ - S2 -- S21\n>>>>\n>>>> Main tree:\n>>>>\n>>>> A' (uses S1) --- A (uses S2)\n>>>>   \\\n>>>>    \\ --- B' (uses S2) -- B (uses S21)\n>>>>\n>>>>\n>>>> I would like it to end up as:\n>>>>\n>>>> A' (uses S1) --- A (uses S2) ------------ A+ (uses S21)\n>>>>   \\                                     /\n>>>>    \\ --- B' (uses S2) -- B (uses S21)- /\n>>>>\n>>>> And that should be legal since S21 is a descendant of S2.\n>>>\n>>> So to summarize what you are requesting: You want a submodule merge be\n>>> two way in the view of the superproject and calculate the merge base\n>>> in the submodule from the two commits that are going to be merged?\n>>>\n>>> It currently sounds logical but I have to think about it further and\n>>> whether that might break other use cases.\n>>\n>> Maybe both could be legal even. The current code can't be all wrong,\n>> and this case also seems to be straightforward.\n> \n> Ok I have thought about it further and I did not come up with a simple\n> (and stable) enough strategy that would allow your use case to merge\n> cleanly without user interaction.\n> \n> The problem is that your are actually doing a rewind from base to both\n> tips. The fact that a rewind is there makes git suspicious and we simply\n> give up. IMO, thats the right thing to do in such a situation.\n> \n> What should a merge strategy do? It infers from two changes what the\n> final intention might be. For submodules we can do that when the changes\n> on both sides point forward. Since thats the typical progress of\n> development. If not there is some reason for it we do not know about. So\n> the merge gives up.\n> \n> Please see this post about why we need to forbid rewinds from the\n> initial design discussion:\n> \n> http://article.gmane.org/gmane.comp.version-control.git/149003\n\nI agree that rewinds are a very good reason not merge two branches using\na fast-forward strategy, but I believe Daniel's use case is a (and maybe\nthe only) valid exception to that rule: both branches contain *exactly*\nthe same rewind. In that case I don't see any problem to just do a fast\nforward to S21, as both agree on the commits to rewind.\n"},{"id":"210985","messageId":"20130310170953.GA1248@sandbox-ub.fritz.box","threadId":"33007","inReplyTo":"513B7554.4020700@web.de","subject":"Re: Merging submodules - best merge-base","fromName":"Heiko Voigt","fromEmail":"hvoigt@hvoigt.net","sentAt":"2013-03-10T17:09:53Z","receivedAt":"2013-03-10T17:09:53Z","isPatch":false,"sender":{"key":"hvoigt@hvoigt.net","avatar":"https://avatars.githubusercontent.com/u/184958?v=4"},"body":"On Sat, Mar 09, 2013 at 06:45:56PM +0100, Jens Lehmann wrote:\n> Am 07.03.2013 19:59, schrieb Heiko Voigt:\n> > On Thu, Mar 07, 2013 at 10:49:09AM +0100, Daniel Bratell wrote:\n> >> Den 2013-03-06 19:12:05 skrev Heiko Voigt <hvoigt@hvoigt.net>:\n> >>> So to summarize what you are requesting: You want a submodule merge be\n> >>> two way in the view of the superproject and calculate the merge base\n> >>> in the submodule from the two commits that are going to be merged?\n> >>>\n> >>> It currently sounds logical but I have to think about it further and\n> >>> whether that might break other use cases.\n> >>\n> >> Maybe both could be legal even. The current code can't be all wrong,\n> >> and this case also seems to be straightforward.\n> > \n> > Ok I have thought about it further and I did not come up with a simple\n> > (and stable) enough strategy that would allow your use case to merge\n> > cleanly without user interaction.\n> > \n> > The problem is that your are actually doing a rewind from base to both\n> > tips. The fact that a rewind is there makes git suspicious and we simply\n> > give up. IMO, thats the right thing to do in such a situation.\n> > \n> > What should a merge strategy do? It infers from two changes what the\n> > final intention might be. For submodules we can do that when the changes\n> > on both sides point forward. Since thats the typical progress of\n> > development. If not there is some reason for it we do not know about. So\n> > the merge gives up.\n> > \n> > Please see this post about why we need to forbid rewinds from the\n> > initial design discussion:\n> > \n> > http://article.gmane.org/gmane.comp.version-control.git/149003\n> \n> I agree that rewinds are a very good reason not merge two branches using\n> a fast-forward strategy, but I believe Daniel's use case is a (and maybe\n> the only) valid exception to that rule: both branches contain *exactly*\n> the same rewind. In that case I don't see any problem to just do a fast\n> forward to S21, as both agree on the commits to rewind.\n\nThat is different than using the merge base of the two commits needing\nmerge. I agree that rewinding to exactly the same commits is probably a\nvalid exception. Will have a look into extending the submodule merge\nstrategy to include this case.\n\nCheers Heiko\n"},{"id":"211074","messageId":"20130311203021.GA21951@sandbox-ub.fritz.box","threadId":"33007","inReplyTo":"20130310170953.GA1248@sandbox-ub.fritz.box","subject":"[RFC/PATCH] submodule: allow common rewind when merging submodules","fromName":"Heiko Voigt","fromEmail":"hvoigt@hvoigt.net","sentAt":"2013-03-11T20:30:22Z","receivedAt":"2013-03-11T20:30:22Z","isPatch":true,"sender":{"key":"hvoigt@hvoigt.net","avatar":"https://avatars.githubusercontent.com/u/184958?v=4"},"body":"Allow merge of two commits that are contained in each other and do the\nsame rewind. The rewind is calculated using the commit recorded in the\nmerge base of the superproject.\n\nSigned-off-by: Heiko Voigt <hvoigt@hvoigt.net>\n---\n\nOn Sun, Mar 10, 2013 at 06:09:53PM +0100, Heiko Voigt wrote:\n> On Sat, Mar 09, 2013 at 06:45:56PM +0100, Jens Lehmann wrote:\n> > I agree that rewinds are a very good reason not merge two branches using\n> > a fast-forward strategy, but I believe Daniel's use case is a (and maybe\n> > the only) valid exception to that rule: both branches contain *exactly*\n> > the same rewind. In that case I don't see any problem to just do a fast\n> > forward to S21, as both agree on the commits to rewind.\n> \n> That is different than using the merge base of the two commits needing\n> merge. I agree that rewinding to exactly the same commits is probably a\n> valid exception. Will have a look into extending the submodule merge\n> strategy to include this case.\n\nSo here is the patch that implements this case. I am still a little bit\nunsure about the user experience.\n\nI had to extend the merge test setup to include a loose commit h because\notherwise we get a different merge case.\n\nE.g. if you have this in the subproject\n\n\ta---b---d\n\t \\     /\n          --c-+----h\n\nAnd the superproject records\n\n\tBASE(b)---A(d)\n\t \\\n\t  ---B(c)\n\nWhen you merge A and B the change from b to d can either be represented\nas a forward change or as a rewind to a and then adding c, d. Since we\ncalculate the rewind using merge bases we find a forward change here. So\nhere we fail to merge as before.\n\nIf the superproject records\n\n\tBASE(b)---A(h)\n\t \\\n\t  ---B(c)\n\nWe will now find a rewind to a for both sides and merge cleanly since b\nis not contained in h.\n\nSo the problem with the user experience here is:\n\nImagine a project does this kind of rewind because a bug is discovered\nin b and then adds some other things using commits like c, h and so on. Then\nthere are more commits after b which will eventually fix it. Now the\nproject merges the b line into the h line in the submodule and can get a\nmerge conflict in the superproject like explained in the first case.\n\nThis might feel strange to them since the step to h (moving b -> c)\nresolved cleanly but then a merge which *looks like* it just involves a\nfast-forward in the submodule will fail.\n\nAnyway its nothing technically wrong with our merge strategy just that\nwe can not decide which way the user went and so the merge fails.\n\nOne step I have in mind but not yet taken: If I see this correctly we\ncould simplify the code by just doing the is_common_rewind() check and\ndrop the commits_follow_merge_base() check since it is already contained\nin the former.\n\nThe testsuite passes with this commit. You can also find this on github:\n\nhttps://github.com/hvoigt/git/commits/hv/submodule-merge-bases-series1\n\nCheers Heiko\n\n submodule.c                | 42 +++++++++++++++++++++++++++++++++++++++---\n t/t7405-submodule-merge.sh | 39 +++++++++++++++++++++++++++++++++++++--\n 2 files changed, 76 insertions(+), 5 deletions(-)\n\ndiff --git a/submodule.c b/submodule.c\nindex 9ba1496..e24d630 100644\n--- a/submodule.c\n+++ b/submodule.c\n@@ -911,6 +911,44 @@ static void print_commit(struct commit *commit)\n #define MERGE_WARNING(path, msg) \\\n \twarning(\"Failed to merge submodule %s (%s)\", path, msg);\n \n+static int is_common_rewind(struct commit *base, struct commit *a, struct commit *b)\n+{\n+\tstruct commit_list *merge_bases_a, *merge_bases_b;\n+\tint result;\n+\n+\t/* find single rewind commit for a */\n+\tmerge_bases_a = get_merge_bases(a, base, 1);\n+\tif (!merge_bases_a || commit_list_count(merge_bases_a) != 1)\n+\t\treturn 0;\n+\n+\t/* find single rewind commit for b */\n+\tmerge_bases_b = get_merge_bases(b, base, 1);\n+\tif (!merge_bases_b || commit_list_count(merge_bases_b) != 1)\n+\t\treturn 0;\n+\n+\t/* see if we rewind to the same commit */\n+\tresult = !hashcmp(merge_bases_a->item->object.sha1,\n+\t\t\t  merge_bases_b->item->object.sha1);\n+\tfree_commit_list(merge_bases_a);\n+\tfree_commit_list(merge_bases_b);\n+\n+\treturn result;\n+}\n+\n+static int commits_follow_merge_base(struct commit *commit_base,\n+\t\tstruct commit *commit_a, struct commit *commit_b)\n+{\n+\t/* check whether both changes are forward */\n+\tif (in_merge_bases(commit_base, commit_a) &&\n+\t    in_merge_bases(commit_base, commit_b))\n+\t\treturn 1;\n+\n+\tif (is_common_rewind(commit_base, commit_a, commit_b))\n+\t\treturn 1;\n+\n+\treturn 0;\n+}\n+\n int merge_submodule(unsigned char result[20], const char *path,\n \t\t    const unsigned char base[20], const unsigned char a[20],\n \t\t    const unsigned char b[20], int search)\n@@ -944,9 +982,7 @@ int merge_submodule(unsigned char result[20], const char *path,\n \t\treturn 0;\n \t}\n \n-\t/* check whether both changes are forward */\n-\tif (!in_merge_bases(commit_base, commit_a) ||\n-\t    !in_merge_bases(commit_base, commit_b)) {\n+\tif (!commits_follow_merge_base(commit_base, commit_a, commit_b)) {\n \t\tMERGE_WARNING(path, \"commits don't follow merge-base\");\n \t\treturn 0;\n \t}\ndiff --git a/t/t7405-submodule-merge.sh b/t/t7405-submodule-merge.sh\nindex 0d5b42a..66520c6 100755\n--- a/t/t7405-submodule-merge.sh\n+++ b/t/t7405-submodule-merge.sh\n@@ -60,7 +60,7 @@ test_expect_success setup '\n #           /   \\\n #  init -- a     d\n #    \\      \\   /\n-#     g       c\n+#     g       c---h\n #\n # a in the main repository records to sub-a in the submodule and\n # analogous b and c. d should be automatically found by merging c into\n@@ -109,7 +109,17 @@ test_expect_success 'setup for merge search' '\n \t(cd sub &&\n \t git checkout -b sub-g sub-c) &&\n \tgit add sub &&\n-\tgit commit -a -m \"g\")\n+\tgit commit -a -m \"g\" &&\n+\n+\tgit checkout -b h c &&\n+\t(cd sub &&\n+\t git checkout -b sub-h sub-c &&\n+\t echo \"file-h\" >file-h &&\n+\t git add file-h &&\n+\t git commit -m \"sub-h\") &&\n+\tgit add sub &&\n+\tgit commit -a -m \"h\"\n+\t)\n '\n \n test_expect_success 'merge with one side as a fast-forward of the other' '\n@@ -146,6 +156,31 @@ test_expect_success 'merging should fail for ambiguous common parent' '\n \tgit reset --hard)\n '\n \n+test_expect_success 'merging should succeed with common rewind' '\n+\t(cd merge-search &&\n+\t\tgit checkout -b common-rewind-base init &&\n+\t\t(cd sub &&\n+\t\t\tgit checkout sub-b\n+\t\t) &&\n+\t\tgit add sub &&\n+\t\tgit commit -m \"common-rewind-base\" &&\n+\t\tgit checkout -b common-rewind-a common-rewind-base &&\n+\t\t(cd sub &&\n+\t\t\tgit checkout sub-c\n+\t\t) &&\n+\t\tgit add sub &&\n+\t\tgit commit -m \"common-rewind-a\" &&\n+\t\tgit checkout -b common-rewind-b common-rewind-base &&\n+\t\t(cd sub &&\n+\t\t\tgit checkout sub-h\n+\t\t) &&\n+\t\tgit add sub &&\n+\t\tgit commit -m \"common-rewind-b\" &&\n+\t\tgit checkout -b common-rewind-merge common-rewind-a &&\n+\t\tgit merge common-rewind-b\n+\t)\n+'\n+\n # in a situation like this\n #\n # submodule tree:\n-- \n1.8.2.rc2.5.gab0ecbc\n"}]}