Necessity of "evil" merge and topic branches

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

 



When you are maintaining two codebases (one is slightly ahead of
the other, e.g. "master" and "next"), you would expect that a
topic branch based on "master" would apply well to "next".

So your "make guts of ls-files accessible from others, and make
git-add a built-in" is stored in "lt/dirwalk" topic branch,
based on a commit on "master".  By itself, it passes all tests.

When it is merged into "next", which has other stuff, literal
merging did not really work (not your fault).  Many tests that
involve writing trees (typically to create new commits) fail
miserably.

   o---o---o---o---o---o---o---o master
  .     \
  .      o---o---o lt/dirwalk -- contains builtin-add
  \               \ 
   o---o---o---o---o next -- up to date with "master" but
                             has many other stuff in it.

This is because the rule to manupulate the index is a bit
different on "next" branch, where it has jc/cache-tree topic.

With cache-tree, when you modify the index, you need to either
invalidate the path (and its parent directories up to root) in
the cached tree information, or discard the whole cache-tree,
whichever is easier [*1*].  So I have an "evil merge" that
merges the lt/dirwalk topic to next (it is ae12e59a).  It
changes the code like this:

        $ git diff lt/dirwalk next -- builtin-add.c
        diff --git a/builtin-add.c b/builtin-add.c
        index 089c7a8..7083820 100644
        --- a/builtin-add.c
        +++ b/builtin-add.c
        @@ -8,6 +8,7 @@ #include <fnmatch.h>
         #include "cache.h"
         #include "builtin.h"
         #include "dir.h"
        +#include "cache-tree.h"

         static const char builtin_add_usage[] =
         "git-add [-n] [-v] <filepattern>...";
        @@ -197,6 +198,7 @@ static int add_file_to_index(const char 
                        die("unable to add %s to index",path);
                if (verbose)
                        printf("add '%s'\n", path);
        +	cache_tree_invalidate_path(active_cache_tree, path);
                return 0;
         }

Obviously, this is a semantic adjustment, not a simple textual
merge, so no automated merge algorithm would help doing this for
me.  I literally edited the automerged builtin-add.c (the merge
is "one adds a new file, the other does not do anything" case,
so it trivially automerges at the tree level) and amended the
commit when I made the merge.

Now, unlike "pu", I never rewind "next", so once I did this
"evil merge", I do not have to worry about this anymore while
the topic is still on "next".  However, when jc/cache-tree topic
and lt/dirwalk topic both graduate to "master", I will somehow
need to remember to do this again.  That sounds somewhat painful
and quite error prone.

I am not going to rewind "next", so this evil merge will stay
there, but I am wondering if there was a better way I could have
handled this.

If I _know_ lt/dirwalk is going to graduate first (and I think
that is the case), I could have pulled lt/dirwalk into
jc/cache-tree topic, done an equivalent "evil merge" as the
above on jc/cache-tree topic, and pulled the result into "next".
That way, when lt/dirwalk alone graduates, I can just pull it
into "master".  Later, when the jc/cache-tree graduates, the
necessary "evil merge" will be pulled along with it, so I can
truly forget and not worry about it after I do the evil merge
once.

But in general, you would not know which one will graduate
first, so pulling one topic into another is not always a good
idea.  If I pull lt/dirwalk into jc/cache-tree, making
jc/cache-tree graduate alone becomes impossible.  Depending on
the readiness of these two topics, it may not be acceptable to
create such a dependency between topics.

One possibility I can think of is that I could have created
another topic branch that merged jc/cache-tree and lt/dirwalk in
the evil way, and pulled that into "next".  Then either one of
the topics can independently graduate to "master" without
waiting for the other.  I still have to remember that I need to
merge the third topic with evil merge when I make both of them
graduate to "master", but at least I do not have to remember the
details of how that evil merge should look like when I do so.  I
only need to remember that it needs to be done.

In practice, when I merge a topic branch into "master", I note
the paths that merge touches from "master", and run diff between
"master" and "next" for them to see if the remaining changes on
them are reasonable.  I will hopefully remember the need for
(and the details of) the evil merge that way when I pull these
two branches to "master", so what I did would not cause trouble
down the road (with some luck ;-), but I feel there should be a
better way to handle this situation.

Thoughts?


[Footnotes]

*1* In this message, let's not discuss if cache-tree is a good
  idea to begin with, if we should rip it out and/or if we
  should replace it with tree objects in the index.  I'd like to
  discuss SCM issue to handle somewhat interrelated topic
  branches here, not cache-tree.

-
: 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]