Re: [WIP PATCH 0/3] implement merge strategy for submodule links

4 messages, 3 authors, 2016-06-15 · open the first message on its own page

Re: [WIP PATCH 0/3] implement merge strategy for submodule links

From: Junio C Hamano <hidden>
Date: 2016-06-15 22:48:59

Johan Herland [off-list ref] writes:
I still don't like this, as IMHO it's too subtle, and possibly conflicts 
with explicitly tracking submodule branches (which, to me, is a more 
important feature).
If you mean, by "explicitly tracking", to say "I don't care which commit
from the submodule appears at this path, as long as it is at the tip of
this branch", I still don't think it makes much sense, but what I outlined
is not _incompatible_ with such a scheme.  In fact I think it would rather
fit naturally as a sanity/safety measure.

I presume that in your "explicitly tracked" world, if the user tries to
commit at the superproject level with a submodule commit that is
inconsistent with that "explicitly tracked" branch (e.g. the commit is not
reachable from the tip of that branch), you would issue a warning of some
sort, using that knowledge.  What I outlined uses the exact same knowledge
of which branch in the submodule the superproject branch is tied to to
reject irrelevant existing merges as resolution candidates.

Of course, this ".gitmodule in superproject can tell you which branch of
submodule it follows" is optional; the user needs to take responsibility
of picking the right one among I, E and G, of course, if the information
does not exist or is not available.

Re: [WIP PATCH 0/3] implement merge strategy for submodule links

From: Johan Herland <hidden>
Date: 2016-06-15 22:48:59

On Monday 21 June 2010, Junio C Hamano wrote:
Johan Herland [off-list ref] writes:
quoted
I still don't like this, as IMHO it's too subtle, and possibly
conflicts with explicitly tracking submodule branches (which, to me,
is a more important feature).
If you mean, by "explicitly tracking", to say "I don't care which commit
from the submodule appears at this path, as long as it is at the tip of
this branch", I still don't think it makes much sense, but what I
outlined is not _incompatible_ with such a scheme.  In fact I think it
would rather fit naturally as a sanity/safety measure.
I'll first try to explain where I'm coming from, to hopefully eliminate any 
confusion about my position:

IMHO, there should be 2 primary modes for submodules in Git:

A. Explicitly tracking submodule commits. This is the existing submodule 
behaviour. The superproject refers directly (in its tree) to a submodule 
commit. The .gitmodules file contains associated information 
(submodule.<name>.path, .url and .update).

B. Explicitly tracking submodule branches. An extra setting 
(submodule.<name>.branch) is added to the .gitmodules file, to determine 
which submodule branch to checkout. This setting overrides whatever 
submodule commit, if any, is stored in the superproject tree. There are two 
sub-modes for this mode:

B.1. There is no submodule entry at all in the superproject tree. This 
indicates that you are not at all interested in tracking the history of the 
submodule relative to the superproject. You are always interested in 
checking out the tip of submodule.<name>.branch in the submodule, even when 
digging into the superproject's history.

B.2. There is a submodule entry in the superproject tree. This "hybrid" 
approach indicates that although you primarily want to track a branch in the 
submodule (i.e. you mostly want the latest version of the submodule's 
branch), you still want a record of where your submodule has been pointing, 
in your superproject's history. Exactly when (or how often) the 
superproject's submodule entry should be updated is yet TBD. So is when to 
check out according to .branch, and when to use the recorded submodule 
commit. In the end, it'll probably be a policy decision for the projects 
that choose this approach.

Ok, that hopefully explains the basic idea of tracking submodule commits (A) 
vs. tracking submodule branches (B). Now, how would this apply to merging 
submodules?

In case of B, I'd argue that the submodule merging should _only_ look at the 
value of submodule.<name>.branch from the superproject's .gitmodules. If 
this setting is ambiguous (because of merge conflicts in .gitmodules), Git 
should not touch the submodule at all (until .gitmodules is resolved). 
Otherwise, Git's only task is to checkout whatever branch is specified by 
.gitmodules. If the commit that is checked out does not descend from all of 
the merge alternatives, a warning should be printed.

With that in mind, I enter this discussion because it might provide insight 
on how to solve the problem of merging submodules in scenario A.

In mode A there is no submodule.<name>.branch setting, and I would not like 
to add an additional setting (let's call it submodule.<name>.merge_branch 
for now) that is "weaker" than submodule.<name>.branch (meaning that it does 
not trigger the transition from mode A to mode B). There are two major 
reasons for this:

1. submodule.<name>.merge_branch would add semantics to the case of merging 
submodules that would be similar in spirit to what submodule.<name>.branch 
does (the "spirit" here is the special relationship to a submodule branch 
that we're establishing), but still the .merge_branch setting would be 
different in practice, by (a) only applying to the case of merging 
submodules (while .branch changes the semantics of almost all submodule 
operations), and (b) not even in the case of merging submodules would the 
options do the same thing. I fear the semantics of the .merge_branch option 
would be too complicated for an average user, and that its similarity to 
.branch would cause confusion.

2. What would happen if you enabled _both_ .merge_branch and .branch? In the 
case of merging submodules which setting will "win"? Even worse, if you set 
.merge_branch to "foo", and .branch to "bar", what will then happen?

Ok, so if I oppose adding .merge_branch, what do I propose instead?

Currently, not much, I'm afraid. But I have a gut feeling that the use case 
presented by Heiko and Jens is best solved EITHER by having no special 
branch relationships between the superproject and submodule (which AFAICS is 
what we currently agree on in this thread, and Heiko has already submitted a 
patch to this effect), OR by employing a conservative version of mode B.2 in 
which we use .branch to track a submodule branch, but still keep a close 
look at the recorded submodule commit, and, if necessary, maybe introduce 
some other options to tell Git when to use the recorded commit, and when to 
use the branch tip.

In other words, I think we should explore the .branch direction before we 
add complexity and potential confusion by prematurely adding another option 
that it somewhat similar to .branch in some contexts.
I presume that in your "explicitly tracked" world, if the user tries to
commit at the superproject level with a submodule commit that is
inconsistent with that "explicitly tracked" branch (e.g. the commit is
not reachable from the tip of that branch), you would issue a warning of
some sort, using that knowledge.
Yes.
What I outlined uses the exact same
knowledge of which branch in the submodule the superproject branch is
tied to to reject irrelevant existing merges as resolution candidates.
True, but as I've argued above, I'm not sure that adding another setting 
(aka. .merge_branch) for this special/limited kind of branch tracking is 
worth it.
Of course, this ".gitmodule in superproject can tell you which branch of
submodule it follows" is optional; the user needs to take responsibility
of picking the right one among I, E and G, of course, if the information
does not exist or is not available.
Yes, of course. And this corresponds to what I've proposed for scenario A, 
when there is no branch-related setting specified for the submodule.


Hope this helps,

...Johan

-- 
Johan Herland, [off-list ref]
www.herland.net

Re: [WIP PATCH 0/3] implement merge strategy for submodule links

From: Junio C Hamano <hidden>
Date: 2016-06-15 22:48:59

Johan Herland [off-list ref] writes:
True, but as I've argued above, I'm not sure that adding another setting 
(aka. .merge_branch) for this special/limited kind of branch tracking is 
worth it.
I don't think .merge_branch is necessary nor even desired.  In fact, I
think your use of .branch, especially in the variant that does not have
any submodule entry in the superproject tree, of your version (B) does not
have conceptual advantage.  You checkout the superproject first (which
would be the natural thing to do, as you may get update to its .gitmodules
there), and checkout the then-tip of the named branch of the submodule,
you would immediately get a stale checkout when you then go fetch the
updates to the submodule.

And the worst part is that you wouldn't even _notice_ that your checkout
is stale, as there is no record in the superproject which commit you were
supposed to be using to be consistent with the version the committer of
the superproject commit used to record it.

I on the other hand think what you called "hybrid" makes sense (and I
don't even think it is hybrid but rather is a natural way to do this).
With the submodule.*.branch entry, you can:

 - make sure that your checkout is consistent; if your submodule checks
   out a different commit or branch from what the superproject records in
   its tree or in its .gitmodules (e.g. you forgot to update the submodule
   when you switched superproject branch), git can notice the situation
   and can help you implement policy decisions;

 - record a commit that is different from the tip of the submodule branch
   when making a superproject commit; git can notice the situation and can
   help you implement policy decisions (e.g. you could choose to reject
   and tell the user to advance the submodule branch first before making
   the commit in the superproject);

 - use it as an advisory "existing merge commit selector", as discussed in
   this thread.

Thinking about what would happen in your (B) that doesn't record the exact
commit, I think that it doesn't have any advantage over the "hybrid" one.
The "hybrid" one can help you to make sure that what you commit in the
superproject's .gitmodules and submodule's branch tip are kept consistent.
When they are kept consistent, then switching branches in the superproject
should always flip between the tips of branches, no?

Re: [WIP PATCH 0/3] implement merge strategy for submodule links

From: Johan Herland <hidden>
Date: 2016-06-15 22:48:59

On Tuesday 22 June 2010, Junio C Hamano wrote:
Johan Herland [off-list ref] writes:
quoted
True, but as I've argued above, I'm not sure that adding another
setting (aka. .merge_branch) for this special/limited kind of
branch tracking is worth it.
I don't think .merge_branch is necessary nor even desired.
Good.
In fact, 
I think your use of .branch, especially in the variant that does not
have any submodule entry in the superproject tree, of your version
(B) does not have conceptual advantage.  You checkout the
superproject first (which would be the natural thing to do, as you
may get update to its .gitmodules there), and checkout the then-tip
of the named branch of the submodule, you would immediately get a
stale checkout when you then go fetch the updates to the submodule.
Not if the initial checkout of the submodule included an implicit 
fetch/pull within the submodule (exact behaviour probably to be 
controlled with some config).
And the worst part is that you wouldn't even _notice_ that your
checkout is stale, as there is no record in the superproject which
commit you were supposed to be using to be consistent with the
version the committer of the superproject commit used to record it.
The idea (in B.1.) is that if you _truly_ don't care which version of 
the submodule you're checking out, then there should be no submodule 
entry in the superproject that would "pollute" your status/diffs.

Note that I'm not in this camp myself, as I would very much like to keep 
track of where my submodule is (and has been) checked out. So I'll stop 
trying to argue for a use case that I'm not going to use. At the time, 
it seemed like a logical conclusion of the tracking-submodule-branches 
debate, but if it's not going to be used in practice, there's no point 
in keeping it alive.
I on the other hand think what you called "hybrid" makes sense (and I
don't even think it is hybrid but rather is a natural way to do
this).
Agreed. I too believe that the "hybrid" is much more useful in practice 
than the extreme version (without a gitlink entry in the superproject).

But I also believe that Git shouldn't enforce specific workflows, so 
that if people actually want to track submodule branches in the 
non-"hybrid" (haphazard) manner, then Git should not stand in their 
way.

On the other hand, if nobody's gonna do this, there's no point in 
implementing support for it.
With the submodule.*.branch entry, you can: 

 - make sure that your checkout is consistent; if your submodule
checks out a different commit or branch from what the superproject
records in its tree or in its .gitmodules (e.g. you forgot to update
the submodule when you switched superproject branch), git can notice
the situation and can help you implement policy decisions;

 - record a commit that is different from the tip of the submodule
branch when making a superproject commit; git can notice the
situation and can help you implement policy decisions (e.g. you could
choose to reject and tell the user to advance the submodule branch
first before making the commit in the superproject);

 - use it as an advisory "existing merge commit selector", as
discussed in this thread.
Ah, I see. IINM you indeed prefer to use the same setting (aka. 
submodule.<name>.branch) for controlling both the merging of submodules 
(as discussed in this thread), and the other aspects of the submodule 
branch tracking feature. We agree here.

However, it seems you would like the .branch setting to be more advisory 
in nature: Instead of blindly checking out whatever .branch specifies, 
you'd rather have a more careful interplay where the .branch option 
should only check whether it is consistent with what happens to be 
checked out in the submodule, and warn when this is not the case.

This may be better than what I suggested, but it's hard to say anything 
for sure until the various alternatives are tested in practice.
Thinking about what would happen in your (B) that doesn't record the
exact commit, I think that it doesn't have any advantage over the
"hybrid" one. The "hybrid" one can help you to make sure that what
you commit in the superproject's .gitmodules and submodule's branch
tip are kept consistent. When they are kept consistent, then
switching branches in the superproject should always flip between the
tips of branches, no?
Yes, if branch "foo" in the superproject records "branch = subfoo" 
in .gitmodules, and the current tip of "subfoo" as a gitlink, and 
branch "bar" in the superproject records "branch = subbar" 
in .gitmodules and the current tip of "subbar" as a gitlink, then, 
indeed, switching between these two branches should auto-flip between 
the branch tips.

One of the remaining questions is what happens when the superproject 
does not change, but commits are added to the submodule branches. Now, 
when switching between branches in the superproject, should Git:

1. Do nothing (this is the current behaviour, the user is forced to 'git 
submodule update' after 'git checkout' in the superproject)

2. Only checkout the recorded gitlink (this defeats the purpose of 
branch-tracking, IMO)

3. Checkout the recorded gitlink, but warn about the updated branch tip 
(a valid behaviour IMO)

4. Checkout the updated branch tip of the submodule, and warn about the 
out-of-date gitlink entry (also a valid behaviour IMO)

5. Checkout the updated branch tip AND stage a new gitlink in the 
superproject (this is a bit to "magic", IMO)


...Johan

-- 
Johan Herland, [off-list ref]
www.herland.net
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help