{"thread":{"id":"26324","subject":"[RFC] Add bad-branch-first option for git-bisect","startedAt":"2011-01-24T02:03:37Z","lastAt":"2011-01-26T10:40:16Z","messageCount":14,"participants":["Shuang He","Christian Couder","Johannes Sixt","Junio C Hamano","Avery Pennarun"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"159807","messageId":"4D3CDDF9.6080405@intel.com","threadId":"26324","inReplyTo":null,"subject":"[RFC] Add bad-branch-first option for git-bisect","fromName":"Shuang He","fromEmail":"shuang.he@intel.com","sentAt":"2011-01-24T02:03:37Z","receivedAt":"2011-01-24T02:03:37Z","isPatch":false,"sender":{"key":"shuang.he@intel.com","avatar":null},"body":"Hi\n      The default git-bisect algorithm will jump around the commit tree,\non the purpose of taking least steps to find the first culprit commit.\nWe may find it sometime would locate a old culprit commit that we're not\nconcerned about anymore.\n      In most software development, there's one or two main branch which\nis maintained for release, and a bunch of feature branches are created\nfor new feature development or bug fix.  For the reason that sometime\ngit-bisect will locate a old culprit commit would be:\n          1. Quality of those branches may not match the main branch,\nsome functionality are broken at first and fixed later on the feature\nbranch. If git-bisect jump to there by chance, git-bisect will only find that old\nculprit commit which only exists on that feature branch\n          2. Some of those branches may not synchronized with main\nbranch in time.  Say feature1 is broken when feature2 branch is created, and\nfeature1 is fixed just a moment later after feature2 branch is created,\nand when feature2's development is done, and developer want to merge\nfeature2 branch back to master branch, feature2 will be firstly\nsynchronized to master branch tip, then merge into master.  For the same\nreason addressed in issue 1, this will also lead git-bisect into wrong\ndirection.\n\n      In all, we think we do not care about branches that we're not\ncurrently working, unless we're sure the regression is caused by that\nbranch.\n\n      To address those issue, we propose to add a new config option:\n          core.bisectbadbranchfirst::\n              With this algorithm, git-bisect will always try to select\ncommits\n              that on the same branch current bad commit sits. And will\nfall back\n              to default git-bisect algorithm when bad-branch-first\nalgorithm does\n              not apply\n          +\n          This setting defaults to \"false\".\n\n      The draft patch will be sent out in a later email, so it could be\nreviewed inline.\n      Any question or suggestion is welcome  :-)\n\nThanks\n      --Shuang\n"},{"id":"159808","messageId":"1295834727-21765-1-git-send-email-shuang.he@intel.com","threadId":"26324","inReplyTo":"4D3CDDF9.6080405@intel.com","subject":"[PATCH] add config option core.bisectbadbranchfirst","fromName":"Shuang He","fromEmail":"shuang.he@intel.com","sentAt":"2011-01-24T02:05:27Z","receivedAt":"2011-01-24T02:05:27Z","isPatch":true,"sender":{"key":"shuang.he@intel.com","avatar":null},"body":"which enable recursive bad-branch-first algorithm for git-bisect.\nWith this algorithm, git-bisect will always try to select commits\nthat on the same branch current bad commit sits. And will fall back\nto default git-bisect algorithm when bad-branch-first algorithm does\nnot apply\n\nSigned-off-by: Shuang He <shuang.he@intel.com>\n---\n Documentation/config.txt |    8 ++\n bisect.c                 |  244 +++++++++++++++++++++++++++++++++++++++++-----\n bisect.h                 |    2 +-\n builtin/rev-list.c       |    2 +-\n cache.h                  |    1 +\n config.c                 |    6 +\n environment.c            |    1 +\n 7 files changed, 238 insertions(+), 26 deletions(-)\n\ndiff --git a/Documentation/config.txt b/Documentation/config.txt\nindex ff7c225..8502859 100644\n--- a/Documentation/config.txt\n+++ b/Documentation/config.txt\n@@ -558,6 +558,14 @@ core.sparseCheckout::\n \tEnable \"sparse checkout\" feature. See section \"Sparse checkout\" in\n \tlinkgit:git-read-tree[1] for more information.\n \n+core.bisectbadbranchfirst::\n+\tWith this algorithm, git-bisect will always try to select commits\n+\tthat on the same branch current bad commit sits. And will fall back\n+\tto default git-bisect algorithm when bad-branch-first algorithm does\n+\tnot apply\n++\n+This setting defaults to \"false\".\n+\n add.ignore-errors::\n add.ignoreErrors::\n \tTells 'git add' to continue adding files when some files cannot be\ndiff --git a/bisect.c b/bisect.c\nindex 060c042..57c410d 100644\n--- a/bisect.c\n+++ b/bisect.c\n@@ -189,6 +189,46 @@ static struct commit_list *best_bisection(struct commit_list *list, int nr)\n \treturn best;\n }\n \n+static struct commit_list *best_bisection_first_parent(struct commit_list *list, struct commit_list *list2, int nr)\n+{\n+\tstruct commit_list *p, *best;\n+\tstruct commit_list *p2;\n+\tint best_distance = -1;\n+\n+\tbest = NULL;\n+\tfor (p2 = list2; p2; p2 = p2->next) {\n+\t\tint distance;\n+\t\tint on_branch;\n+\n+\t\ton_branch = 0;\n+\t\tfor (p = list; p; p = p->next) {\n+\t\t\tunsigned flags = p->item->object.flags;\n+\t\t\tif (flags & TREESAME)\n+\t\t\t\tcontinue;\n+\t\t\tif (!hashcmp(p->item->object.sha1, p2->item->object.sha1)) {\n+\t\t\t\ton_branch = 1;\n+\t\t\t\tbreak;\n+\t\t\t}\n+\t\t}\n+\n+\t\tif (!on_branch)\n+\t\t\tcontinue;\n+\n+\t\tweight_set(p2, weight(p));\n+\t\tdistance = weight(p);\n+\t\tif (nr - distance < distance)\n+\t\t\tdistance = nr - distance;\n+\t\tif (distance > best_distance) {\n+\t\t\tbest = p;\n+\t\t\tbest_distance = distance;\n+\t\t}\n+\n+\t}\n+\n+\treturn list2;\n+}\n+\n+\n struct commit_dist {\n \tstruct commit *commit;\n \tint distance;\n@@ -253,7 +293,7 @@ static struct commit_list *best_bisection_sorted(struct commit_list *list, int n\n  * unknown.  After running count_distance() first, they will get zero\n  * or positive distance.\n  */\n-static struct commit_list *do_find_bisection(struct commit_list *list,\n+static struct commit_list *do_find_bisection(struct commit_list *list, struct commit_list *list2,\n \t\t\t\t\t     int nr, int *weights,\n \t\t\t\t\t     int find_all)\n {\n@@ -314,7 +354,7 @@ static struct commit_list *do_find_bisection(struct commit_list *list,\n \t\tclear_distance(list);\n \n \t\t/* Does it happen to be at exactly half-way? */\n-\t\tif (!find_all && halfway(p, nr))\n+\t\tif (!list2 && !find_all && halfway(p, nr))\n \t\t\treturn p;\n \t\tcounted++;\n \t}\n@@ -352,20 +392,27 @@ static struct commit_list *do_find_bisection(struct commit_list *list,\n \t\t\t\tweight_set(p, weight(q));\n \n \t\t\t/* Does it happen to be at exactly half-way? */\n-\t\t\tif (!find_all && halfway(p, nr))\n+\t\t\tif (!list2 && !find_all && halfway(p, nr))\n \t\t\t\treturn p;\n \t\t}\n \t}\n \n \tshow_list(\"bisection 2 counted all\", counted, nr, list);\n \n+\tif (list2) {\n+\t\tstruct commit_list *t;\n+\t\tt = best_bisection_first_parent(list, list2, nr);\n+\t\tt = best_bisection_sorted(t, nr);\n+\t\treturn t;\n+\t}\n+\n \tif (!find_all)\n \t\treturn best_bisection(list, nr);\n \telse\n \t\treturn best_bisection_sorted(list, nr);\n }\n \n-struct commit_list *find_bisection(struct commit_list *list,\n+struct commit_list *find_bisection(struct commit_list *list, struct commit_list *list2,\n \t\t\t\t\t  int *reaches, int *all,\n \t\t\t\t\t  int find_all)\n {\n@@ -400,7 +447,7 @@ struct commit_list *find_bisection(struct commit_list *list,\n \tweights = xcalloc(on_list, sizeof(*weights));\n \n \t/* Do the real work of finding bisection commit. */\n-\tbest = do_find_bisection(list, nr, weights, find_all);\n+\tbest = do_find_bisection(list, list2, nr, weights, find_all);\n \tif (best) {\n \t\tif (!find_all)\n \t\t\tbest->next = NULL;\n@@ -683,6 +730,33 @@ static void bisect_rev_setup(struct rev_info *revs, const char *prefix,\n \tsetup_revisions(rev_argv.argv_nr, rev_argv.argv, revs, NULL);\n }\n \n+static void bisect_rev_setup_first_parent(struct rev_info *revs, const char *prefix,\n+\t\t\t     const char *bad_format, const char *good_format,\n+\t\t\t     int read_paths)\n+{\n+\tstruct argv_array rev_argv = { NULL, 0, 0 };\n+\tint i;\n+\n+\tinit_revisions(revs, prefix);\n+\trevs->abbrev = 0;\n+\trevs->commit_format = CMIT_FMT_UNSPECIFIED;\n+\n+\t/* rev_argv.argv[0] will be ignored by setup_revisions */\n+\targv_array_push(&rev_argv, xstrdup(\"bisect_rev_setup_first_parent\"));\n+\targv_array_push_sha1(&rev_argv, current_bad_sha1, bad_format);\n+\tfor (i = 0; i < good_revs.sha1_nr; i++)\n+\t\targv_array_push_sha1(&rev_argv, good_revs.sha1[i],\n+\t\t\t\t     good_format);\n+\targv_array_push(&rev_argv, xstrdup(\"--first-parent\"));\n+\targv_array_push(&rev_argv, xstrdup(\"--\"));\n+\tif (read_paths)\n+\t\tread_bisect_paths(&rev_argv);\n+\targv_array_push(&rev_argv, NULL);\n+\n+\tsetup_revisions(rev_argv.argv_nr, rev_argv.argv, revs, NULL);\n+}\n+\n+\n static void bisect_common(struct rev_info *revs)\n {\n \tif (prepare_revision_walk(revs))\n@@ -944,6 +1018,24 @@ static void show_diff_tree(const char *prefix, struct commit *commit)\n \tlog_tree_commit(&opt, commit);\n }\n \n+int is_merge_commit(struct commit_list *entry) {\n+\tint nr = 0;\n+\tstruct commit *commit;\n+\tstruct commit_list *p;\n+\n+\tif (entry) {\n+\t\tp = entry->item->parents;\n+\n+\t\twhile (p) {\n+\t\t\tnr += 1;\n+\t\t\tp = p->next;\n+\t\t}\n+\t}\n+\n+\treturn nr - 1;\n+}\n+\n+\n /*\n  * We use the convention that exiting with an exit code 10 means that\n  * the bisection process finished successfully.\n@@ -952,41 +1044,145 @@ static void show_diff_tree(const char *prefix, struct commit *commit)\n int bisect_next_all(const char *prefix)\n {\n \tstruct rev_info revs;\n+\tstruct rev_info first_parent_revs;\n \tstruct commit_list *tried;\n \tint reaches = 0, all = 0, nr, steps;\n+\tstruct object_array pending_copy;\n+\tstruct object_array pending_copy2;\n \tconst unsigned char *bisect_rev;\n+\tint i;\n \tchar bisect_rev_hex[41];\n+\tint bad_branch_first_working = 1;\n \n \tif (read_bisect_refs())\n \t\tdie(\"reading bisect refs failed\");\n \n \tcheck_good_are_ancestors_of_bad(prefix);\n+\tstruct argv_array rev_argv = { NULL, 0, 0 };\n+\t\n+\tread_bisect_paths(&rev_argv);\n+\tif (rev_argv.argv_nr > 0)\n+\t\tcore_bisect_bad_branch_first = 0;\n+\n+\tif (core_bisect_bad_branch_first) {\n+\t\tbisect_rev_setup_first_parent(&first_parent_revs, prefix, \"%s\", \"^%s\", 1);\n+\t\tmemset(&pending_copy, 0, sizeof(pending_copy));\n+\t\tfor (i = 0; i < first_parent_revs.pending.nr; i++)\n+\t\t\tadd_object_array(first_parent_revs.pending.objects[i].item,\n+\t\t\t\t\t first_parent_revs.pending.objects[i].name,\n+\t\t\t\t\t &pending_copy);\n+\n+\t\tbisect_common(&first_parent_revs);\n+\n+\t\t/* Clean up objects used, as they will be reused. */\n+\t\tfor (i = 0; i < pending_copy.nr; i++) {\n+\t\t\tstruct object *o = pending_copy.objects[i].item;\n+\t\t\tclear_commit_marks((struct commit *)o, ALL_REV_FLAGS);\n+\t\t}\n+\t}\n \n-\tbisect_rev_setup(&revs, prefix, \"%s\", \"^%s\", 1);\n-\trevs.limited = 1;\n \n-\tbisect_common(&revs);\n \n-\trevs.commits = find_bisection(revs.commits, &reaches, &all,\n-\t\t\t\t       !!skipped_revs.sha1_nr);\n-\trevs.commits = managed_skipped(revs.commits, &tried);\n+\tif (core_bisect_bad_branch_first) {\n+\t\tbisect_rev_setup(&revs, prefix, \"%s\", \"^%s\", 1);\n+\t\tmemset(&pending_copy2, 0, sizeof(pending_copy2));\n+\t\tfor (i = 0; i < revs.pending.nr; i++)\n+\t\t\tadd_object_array(revs.pending.objects[i].item,\n+\t\t\t\t\t revs.pending.objects[i].name,\n+\t\t\t\t\t &pending_copy2);\n+\n+\t\trevs.limited = 1;\n+\n+\t\tbisect_common(&revs);\n+\n+\t\trevs.commits = find_bisection(revs.commits, first_parent_revs.commits, &reaches, &all,\n+\t\t\t\t\t       !!skipped_revs.sha1_nr);\n+\t\t/* TODO: Check if this is a first bad commit on bad branch, and if it's a merge commit */\n+\t\t/* If this is a merge commit, we need to try all of its parents, until we found the merged bad branch */\n+\t\t/* If all parents are good, we just announce it as first bad commit */\n+\t\tif (!hashcmp(revs.commits->item->object.sha1, current_bad_sha1)) {\n+\t\t\tprintf(\"%s is the first bad commit\\n\", sha1_to_hex(current_bad_sha1));\n+\n+\t\t\tif (is_merge_commit(revs.commits)) {\n+\t\t\t\tint all_parents_good = 1;\n+\t\t\t\tstruct commit_list *p;\n+\n+\t\t\t\tprintf(\"%s is a merge commit\\n\", sha1_to_hex(current_bad_sha1));\n+\t\t\t\tprintf(\"need to try each merged branch\\n\", sha1_to_hex(current_bad_sha1));\n+\t\t\t\tp = revs.commits->item->parents;\n+\n+\t\t\t\twhile (p) {\n+\t\t\t\t\tif (!hashcmp(p->item->object.sha1, current_bad_sha1)) {\n+\t\t\t\t\t\tfprintf(stderr, \"should not get here\\n\");\n+\t\t\t\t\t\texit(1);\n+\t\t\t\t\t} else if (0 <= lookup_sha1_array(&good_revs, p->item->object.sha1)) {\n+\t\t\t\t\t\tfprintf(stderr, \"good parent %s\\n\", sha1_to_hex(p->item->object.sha1));\n+\t\t\t\t\t} else if (0 <= lookup_sha1_array(&skipped_revs, p->item->object.sha1)) {\n+\t\t\t\t\t\tfprintf(stderr, \"skipped parent %s\\n\", sha1_to_hex(p->item->object.sha1));\n+\t\t\t\t\t\tall_parents_good = 0;\n+\t\t\t\t\t} else {\n+\t\t\t\t\t\tprintf(\"try merged branch %s\\n\", sha1_to_hex(p->item->object.sha1));\n+\t\t\t\t\t\texit(bisect_checkout(sha1_to_hex(p->item->object.sha1)));\n+\t\t\t\t\t}\n+\t\t\t\t\tp = p->next;\n+\t\t\t\t}\n+\n+\t\t\t\tif (all_parents_good) {\n+\t\t\t\t\tshow_diff_tree(prefix, revs.commits->item);\n+\t\t\t\t\texit(10);\n+\t\t\t\t}\n+\t\t\t}\n+\t\t\telse {\n+\t\t\t\tshow_diff_tree(prefix, revs.commits->item);\n+\t\t\t\texit(10);\n+\t\t\t}\n+\t\t}\n+\n+\t\trevs.commits = managed_skipped(revs.commits, &tried);\n \n-\tif (!revs.commits) {\n-\t\t/*\n-\t\t * We should exit here only if the \"bad\"\n-\t\t * commit is also a \"skip\" commit.\n-\t\t */\n-\t\texit_if_skipped_commits(tried, NULL);\n+\t\tif (!revs.commits || !all) {\n+\t\t\tbad_branch_first_working = 0;\n+\t\t\tfprintf(stderr, \"fall back to default git-bisect algorithm\\n\");\n+\t\t}\n+\t\telse\n+\t\t\tfprintf(stderr, \"proceed with core_bisect_bad_branch_first algorithm\\n\");\n \n-\t\tprintf(\"%s was both good and bad\\n\",\n-\t\t       sha1_to_hex(current_bad_sha1));\n-\t\texit(1);\n+\t\t/* Clean up objects used, as they will be reused. */\n+\t\tfor (i = 0; i < pending_copy2.nr; i++) {\n+\t\t\tstruct object *o = pending_copy2.objects[i].item;\n+\t\t\tclear_commit_marks((struct commit *)o, ALL_REV_FLAGS);\n+\t\t}\n \t}\n \n-\tif (!all) {\n-\t\tfprintf(stderr, \"No testable commit found.\\n\"\n-\t\t\t\"Maybe you started with bad path parameters?\\n\");\n-\t\texit(4);\n+\n+\tif (!core_bisect_bad_branch_first || !bad_branch_first_working) {\n+\t\tbisect_rev_setup(&revs, prefix, \"%s\", \"^%s\", 1);\n+\t\trevs.limited = 1;\n+\n+\t\tbisect_common(&revs);\n+\t\tshow_list(\"fall back\", 0, 0, revs.commits);\n+\n+\t\trevs.commits = find_bisection(revs.commits, NULL, &reaches, &all,\n+\t\t\t\t\t       !!skipped_revs.sha1_nr);\n+\t\trevs.commits = managed_skipped(revs.commits, &tried);\n+\n+\t\tif (!revs.commits) {\n+\t\t\t/*\n+\t\t\t * We should exit here only if the \"bad\"\n+\t\t\t * commit is also a \"skip\" commit.\n+\t\t\t */\n+\t\t\texit_if_skipped_commits(tried, NULL);\n+\t\n+\t\t\tprintf(\"%s was both good and bad\\n\",\n+\t\t\t       sha1_to_hex(current_bad_sha1));\n+\t\t\texit(1);\n+\t\t}\n+\n+\t\tif (!all) {\n+\t\t\tfprintf(stderr, \"No testable commit found.\\n\"\n+\t\t\t\t\"Maybe you started with bad path parameters?\\n\");\n+\t\t\texit(4);\n+\t\t}\n \t}\n \n \tbisect_rev = revs.commits->item->object.sha1;\ndiff --git a/bisect.h b/bisect.h\nindex 0862ce5..fad4fbe 100644\n--- a/bisect.h\n+++ b/bisect.h\n@@ -1,7 +1,7 @@\n #ifndef BISECT_H\n #define BISECT_H\n \n-extern struct commit_list *find_bisection(struct commit_list *list,\n+extern struct commit_list *find_bisection(struct commit_list *list, struct commit_list *list2,\n \t\t\t\t\t  int *reaches, int *all,\n \t\t\t\t\t  int find_all);\n \ndiff --git a/builtin/rev-list.c b/builtin/rev-list.c\nindex ba27d39..ab56f6b 100644\n--- a/builtin/rev-list.c\n+++ b/builtin/rev-list.c\n@@ -399,7 +399,7 @@ int cmd_rev_list(int argc, const char **argv, const char *prefix)\n \tif (bisect_list) {\n \t\tint reaches = reaches, all = all;\n \n-\t\trevs.commits = find_bisection(revs.commits, &reaches, &all,\n+\t\trevs.commits = find_bisection(revs.commits, NULL, &reaches, &all,\n \t\t\t\t\t      bisect_find_all);\n \n \t\tif (bisect_show_vars)\ndiff --git a/cache.h b/cache.h\nindex d83d68c..bfd4448 100644\n--- a/cache.h\n+++ b/cache.h\n@@ -559,6 +559,7 @@ extern int read_replace_refs;\n extern int fsync_object_files;\n extern int core_preload_index;\n extern int core_apply_sparse_checkout;\n+extern int core_bisect_bad_branch_first;\n \n enum safe_crlf {\n \tSAFE_CRLF_FALSE = 0,\ndiff --git a/config.c b/config.c\nindex 625e051..b37a70c 100644\n--- a/config.c\n+++ b/config.c\n@@ -660,6 +660,12 @@ static int git_default_core_config(const char *var, const char *value)\n \t\treturn 0;\n \t}\n \n+\tif (!strcmp(var, \"core.bisectbadbranchfirst\")) {\n+\t\tcore_bisect_bad_branch_first = git_config_bool(var, value);\n+\t\treturn 0;\n+\t}\n+\n+\n \t/* Add other config variables here and to Documentation/config.txt. */\n \treturn 0;\n }\ndiff --git a/environment.c b/environment.c\nindex 9564475..cf813af 100644\n--- a/environment.c\n+++ b/environment.c\n@@ -55,6 +55,7 @@ enum object_creation_mode object_creation_mode = OBJECT_CREATION_MODE;\n char *notes_ref_name;\n int grafts_replace_parents = 1;\n int core_apply_sparse_checkout;\n+int core_bisect_bad_branch_first = 0;\n struct startup_info *startup_info;\n \n /* Parallel index stat data preload? */\n-- \n1.7.4.rc2.21.g7f7a8\n"},{"id":"159816","messageId":"AANLkTimUkv9+g_+wFcyGhwMjE9zYAKjMn32GL-WOVmoe@mail.gmail.com","threadId":"26324","inReplyTo":"4D3CDDF9.6080405@intel.com","subject":"Re: [RFC] Add bad-branch-first option for git-bisect","fromName":"Christian Couder","fromEmail":"christian.couder@gmail.com","sentAt":"2011-01-24T09:53:15Z","receivedAt":"2011-01-24T09:53:15Z","isPatch":false,"sender":{"key":"christian.couder@gmail.com","avatar":"https://avatars.githubusercontent.com/u/208954?v=4"},"body":"Hi,\n\nOn Mon, Jan 24, 2011 at 3:03 AM, Shuang He <shuang.he@intel.com> wrote:\n> Hi\n>     The default git-bisect algorithm will jump around the commit tree,\n> on the purpose of taking least steps to find the first culprit commit.\n> We may find it sometime would locate a old culprit commit that we're not\n> concerned about anymore.\n\nYes, it can be a problem.\n\n>     In most software development, there's one or two main branch which\n> is maintained for release, and a bunch of feature branches are created\n> for new feature development or bug fix.  For the reason that sometime\n> git-bisect will locate a old culprit commit would be:\n>         1. Quality of those branches may not match the main branch,\n> some functionality are broken at first and fixed later on the feature\n> branch. If git-bisect jump to there by chance, git-bisect will only find\n> that old\n> culprit commit which only exists on that feature branch\n\nIf the quality of these branches is too bad, I think they should not\nhave been merged in the first place.\nIf they are not merged (and not marked as good), then git bisect will\nnot look at them, since it will look only at commits that are\nancestors of the bad commit it is given.\n\nOr if one is merged but it causes too many problems, then perhaps a\nreplacement commit could be used to unmerge the branch.\n\nAnother possibility is to have in a file a list of commits that are\nthe last commits on these branches before the merge commits, and do a:\n\ngit bisect good $(cat good_commits_file.txt)\n\nat the beginning of each bisection.\n\nSo I think the long term solution in this case is not what your are suggesting.\n\n>         2. Some of those branches may not synchronized with main\n> branch in time.  Say feature1 is broken when feature2 branch is created, and\n> feature1 is fixed just a moment later after feature2 branch is created,\n> and when feature2's development is done, and developer want to merge\n> feature2 branch back to master branch, feature2 will be firstly\n> synchronized to master branch tip, then merge into master.  For the same\n> reason addressed in issue 1, this will also lead git-bisect into wrong\n> direction.\n\nI am not sure what you mean by \" feature2 will be firstly synchronized\nto master branch tip\", and I think this should mean a rebase that\nwould fix the bug if feature1 has already been merged into the master\nbranch.\n\nBut anyway in this case, I think that git bisect will find that the\nfirst bad commit is the last commit in the branch, just before it was\nmerged. And by looking at the branch graph it should be quite easy to\nunderstand what happened.\n\nAnd then the obvious thing to do is to decide to just start a new\nbisection like it was started the first time but with an added \"git\nbisect good <merge_commit>\", where <merge_commit> is the commit that\nmerges the branch.\n\n>     In all, we think we do not care about branches that we're not\n> currently working, unless we're sure the regression is caused by that\n> branch.\n>\n>     To address those issue, we propose to add a new config option:\n>         core.bisectbadbranchfirst::\n>             With this algorithm, git-bisect will always try to select\n> commits\n>             that on the same branch current bad commit sits. And will\n> fall back\n>             to default git-bisect algorithm when bad-branch-first\n> algorithm does\n>             not apply\n>         +\n>         This setting defaults to \"false\".\n\nI am not opposed to an option to bisect on the first parents of the\nbad commit only. And after a very fast look at your patch it seems to\nbe what it does. By the way Avery Pennarun's gitbuilder\n(https://github.com/apenwarr/gitbuilder) does the same thing. So I\nknow some people are interested in such a feature.\n\nBut here are some suggestions/comments:\n\n- your explanations about why it could be useful should be improved,\n- the name \"bisectbadbranchfirst\" seems wrong to me, because git\nbranches are just some special tags; \"firstparentsonly\" would be a\nbetter name,\n- before having a config option for it, why not have it first as an\noption to \"git bisect start\",\n- if there is a config option, then there should probably be an option\nto \"git bisect start\" to use the regular algorithm,\n- it seems to me that bisecting only on first parents could fail only\nif some \"good\" commits are not ancestors of the bad commit, and if the\nbug is fixed on a branch where such a commit is; so I don't see the\npoint in defaulting to the usual algorithm in this case because in\nthis case the usual algorithm just stops,\n- perhaps the message given when the first bad commit is found should\nbe changed a little bit when this option is used.\n\nMaybe I am missing something, because as I said I didn't read your\npatch carefully, but in this case please try to give a concrete\nexample.\n\nThanks,\nChristian.\n"},{"id":"159817","messageId":"4D3D54D3.7040801@intel.com","threadId":"26324","inReplyTo":"AANLkTimUkv9+g_+wFcyGhwMjE9zYAKjMn32GL-WOVmoe@mail.gmail.com","subject":"Re: [RFC] Add bad-branch-first option for git-bisect","fromName":"Shuang He","fromEmail":"shuang.he@intel.com","sentAt":"2011-01-24T10:30:43Z","receivedAt":"2011-01-24T10:30:43Z","isPatch":false,"sender":{"key":"shuang.he@intel.com","avatar":null},"body":"On 2011/1/24 17:53, Christian Couder wrote:\n> Hi,\n>\n> On Mon, Jan 24, 2011 at 3:03 AM, Shuang He<shuang.he@intel.com>  wrote:\n>> Hi\n>>      The default git-bisect algorithm will jump around the commit tree,\n>> on the purpose of taking least steps to find the first culprit commit.\n>> We may find it sometime would locate a old culprit commit that we're not\n>> concerned about anymore.\n> Yes, it can be a problem.\n\nI'm honored to be given so much comment :)\nThank you\n\n>>      In most software development, there's one or two main branch which\n>> is maintained for release, and a bunch of feature branches are created\n>> for new feature development or bug fix.  For the reason that sometime\n>> git-bisect will locate a old culprit commit would be:\n>>          1. Quality of those branches may not match the main branch,\n>> some functionality are broken at first and fixed later on the feature\n>> branch. If git-bisect jump to there by chance, git-bisect will only find\n>> that old\n>> culprit commit which only exists on that feature branch\n> If the quality of these branches is too bad, I think they should not\n> have been merged in the first place.\n> If they are not merged (and not marked as good), then git bisect will\n> not look at them, since it will look only at commits that are\n> ancestors of the bad commit it is given.\n>\n> Or if one is merged but it causes too many problems, then perhaps a\n> replacement commit could be used to unmerge the branch.\n>\n> Another possibility is to have in a file a list of commits that are\n> the last commits on these branches before the merge commits, and do a:\n>\n> git bisect good $(cat good_commits_file.txt)\n>\n> at the beginning of each bisection.\n>\n> So I think the long term solution in this case is not what your are suggesting.\n\nYeah, I agree that the issue I addressed above will not be a problem if \nall those branches are maintained very well.\nActually we've implemented a automated bisect system for Intel Linux \nGraphics Driver Project, and so we'd like the system\nhelps us to locate issue in an more automatic way when branches are not \nmaintained as good as expected.\n\n>>          2. Some of those branches may not synchronized with main\n>> branch in time.  Say feature1 is broken when feature2 branch is created, and\n>> feature1 is fixed just a moment later after feature2 branch is created,\n>> and when feature2's development is done, and developer want to merge\n>> feature2 branch back to master branch, feature2 will be firstly\n>> synchronized to master branch tip, then merge into master.  For the same\n>> reason addressed in issue 1, this will also lead git-bisect into wrong\n>> direction.\n> I am not sure what you mean by \" feature2 will be firstly synchronized\n> to master branch tip\", and I think this should mean a rebase that\n> would fix the bug if feature1 has already been merged into the master\n> branch.\n>\n> But anyway in this case, I think that git bisect will find that the\n> first bad commit is the last commit in the branch, just before it was\n> merged. And by looking at the branch graph it should be quite easy to\n> understand what happened.\n>\n> And then the obvious thing to do is to decide to just start a new\n> bisection like it was started the first time but with an added \"git\n> bisect good<merge_commit>\", where<merge_commit>  is the commit that\n> merges the branch.\n\nFor the same reason, that we're implementing automated bisect system , \nso we want git-bisect to\nbe able to help with this condition also.\n\n>>      In all, we think we do not care about branches that we're not\n>> currently working, unless we're sure the regression is caused by that\n>> branch.\n>>\n>>      To address those issue, we propose to add a new config option:\n>>          core.bisectbadbranchfirst::\n>>              With this algorithm, git-bisect will always try to select\n>> commits\n>>              that on the same branch current bad commit sits. And will\n>> fall back\n>>              to default git-bisect algorithm when bad-branch-first\n>> algorithm does\n>>              not apply\n>>          +\n>>          This setting defaults to \"false\".\n> I am not opposed to an option to bisect on the first parents of the\n> bad commit only. And after a very fast look at your patch it seems to\n> be what it does. By the way Avery Pennarun's gitbuilder\n> (https://github.com/apenwarr/gitbuilder) does the same thing. So I\n> know some people are interested in such a feature.\n>\n> But here are some suggestions/comments:\n>\n> - your explanations about why it could be useful should be improved,\n\nI don't have much data to prove it. I could just say it could help if \nbranches are not maintained very well.\n\n> - the name \"bisectbadbranchfirst\" seems wrong to me, because git\n> branches are just some special tags; \"firstparentsonly\" would be a\n> better name,\n\nIt's recursively applying bad branch first algorithm, not just \nconstantly stick to first parent.\nGiven this condition:\n     A -> B -> C -> D -> E -> F -> G -> H   (master)\n          \\ a  -> b -> c -> d -> e /  (feature 1)\n               \\ x -> y -> z/      (feature 2)\nstart with H as bad commit, and A as good commit, if y is the target bad \ncommit. bad-branch-first algorithm will do it like this:\n     1. In first round stick to master branch, so it will locate G as \nfirst bad commit\n     2. In second round stick to feature1 branch, then it will locate d \nas first bad commit\n     3. In third round stick to feature2 branch, then it will finally \nlocate y as first bad commit\nSo you could see, it's always sticking to branch where current bad \ncommit sit\n\n\n> - before having a config option for it, why not have it first as an\n> option to \"git bisect start\",\n\nAgree, I have thought about it. Haven't done it yet\n\n> - if there is a config option, then there should probably be an option\n> to \"git bisect start\" to use the regular algorithm,\n\nAgree\n\n> - it seems to me that bisecting only on first parents could fail only\n> if some \"good\" commits are not ancestors of the bad commit, and if the\n> bug is fixed on a branch where such a commit is; so I don't see the\n> point in defaulting to the usual algorithm in this case because in\n> this case the usual algorithm just stops,\n\nIt should stop as default git-bisect do, when\nThere are a few cases that this algorithm will fall back to default \nalgorithm:\n     when bisect path is specified. Since --first-parent seems not \nworking as expected when file path is specified\n     when bad branch first algorithm could not find a commit to bisect\n\n> - perhaps the message given when the first bad commit is found should\n> be changed a little bit when this option is used.\n\nYeah, agree\n\n> Maybe I am missing something, because as I said I didn't read your\n> patch carefully, but in this case please try to give a concrete\n> example.\n>\n> Thanks,\n> Christian.\n"},{"id":"159818","messageId":"4D3D5989.50903@viscovery.net","threadId":"26324","inReplyTo":"4D3D54D3.7040801@intel.com","subject":"Re: [RFC] Add bad-branch-first option for git-bisect","fromName":"Johannes Sixt","fromEmail":"j.sixt@viscovery.net","sentAt":"2011-01-24T10:50:49Z","receivedAt":"2011-01-24T10:50:49Z","isPatch":false,"sender":{"key":"j6t@kdbg.org","avatar":"https://avatars.githubusercontent.com/u/14810926?v=4"},"body":"Am 1/24/2011 11:30, schrieb Shuang He:\n> It's recursively applying bad branch first algorithm, not just constantly\n> stick to first parent.\n> Given this condition:\n>     A -> B -> C -> D -> E -> F -> G -> H   (master)\n>          \\ a  -> b -> c -> d -> e /  (feature 1)\n>               \\ x -> y -> z/      (feature 2)\n> start with H as bad commit, and A as good commit, if y is the target bad\n> commit. bad-branch-first algorithm will do it like this:\n>     1. In first round stick to master branch, so it will locate G as first\n> bad commit\n>     2. In second round stick to feature1 branch, then it will locate d as\n> first bad commit\n>     3. In third round stick to feature2 branch, then it will finally\n> locate y as first bad commit\n> So you could see, it's always sticking to branch where current bad commit sit\n\nOk, so you explain what your algorithm does.\n\nBut you did not illustrate your problem. The history above is ordinary,\nsomewhat branchy, has *ONE* commit that introduces a regression, and *NO*\ncommit that fixes the regression. But in your rationale you said something\nabout \"feature1 is fixed just a moment later after feature2 branch is\ncreated\". How does this fit into the picture, where is the problem, and\nhow does your algorithm solve it?\n\n-- Hannes\n"},{"id":"159820","messageId":"4D3D5CE5.4050108@intel.com","threadId":"26324","inReplyTo":"4D3D5989.50903@viscovery.net","subject":"Re: [RFC] Add bad-branch-first option for git-bisect","fromName":"Shuang He","fromEmail":"shuang.he@intel.com","sentAt":"2011-01-24T11:05:09Z","receivedAt":"2011-01-24T11:05:09Z","isPatch":false,"sender":{"key":"shuang.he@intel.com","avatar":null},"body":"On 2011/1/24 18:50, Johannes Sixt wrote:\n> Am 1/24/2011 11:30, schrieb Shuang He:\n>> It's recursively applying bad branch first algorithm, not just constantly\n>> stick to first parent.\n>> Given this condition:\n>>      A ->  B ->  C ->  D ->  E ->  F ->  G ->  H   (master)\n>>           \\ a  ->  b ->  c ->  d ->  e /  (feature 1)\n>>                \\ x ->  y ->  z/      (feature 2)\n>> start with H as bad commit, and A as good commit, if y is the target bad\n>> commit. bad-branch-first algorithm will do it like this:\n>>      1. In first round stick to master branch, so it will locate G as first\n>> bad commit\n>>      2. In second round stick to feature1 branch, then it will locate d as\n>> first bad commit\n>>      3. In third round stick to feature2 branch, then it will finally\n>> locate y as first bad commit\n>> So you could see, it's always sticking to branch where current bad commit sit\n> Ok, so you explain what your algorithm does.\n>\n> But you did not illustrate your problem. The history above is ordinary,\n> somewhat branchy, has *ONE* commit that introduces a regression, and *NO*\n> commit that fixes the regression. But in your rationale you said something\n> about \"feature1 is fixed just a moment later after feature2 branch is\n> created\". How does this fit into the picture, where is the problem, and\n> how does your algorithm solve it?\n>\n> -- Hannes\n\nIf A is bad commit, and C fixed it, and then F is bad again,\n\nA ->  B ->  C ->  D ->  E ->  F ->  G ->  H   (master)\n   \\                    \\      /\n     a  ->  b... c ->  d ->  e->f  (feature 1)\n\nStart with H as bad commit, and D as good commit, it's possible git-bisect would jump to c, and it will lead to wrong direction\n\nIf bad-branch-first is used, it would be:\n1. first round found F\n2. end\n\nThanks\n\t--Shuang\n\nThanks\n\t--Shuang\n"},{"id":"159826","messageId":"7v8vyam5la.fsf@alter.siamese.dyndns.org","threadId":"26324","inReplyTo":"4D3D5CE5.4050108@intel.com","subject":"Re: [RFC] Add bad-branch-first option for git-bisect","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2011-01-24T20:04:01Z","receivedAt":"2011-01-24T20:04:01Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Shuang He <shuang.he@intel.com> writes:\n\n> If A is bad commit, and C fixed it, and then F is bad again,\n>\n> A ->  B ->  C ->  D ->  E ->  F ->  G ->  H   (master)\n>   \\                    \\      /\n>     a  ->  b... c ->  d ->  e->f  (feature 1)\n>\n> Start with H as bad commit, and D as good commit, it's possible git-bisect would jump to c, and it will lead to wrong direction\n>\n> If bad-branch-first is used, it would be:\n> 1. first round found F\n> 2. end\n\nIt is unclear from the way you drew the picture if \"F\" is supposed to be a\nmerge of \"E\" and \"f\", but I'd assume that it is.\n\nSo what you are saying in 1. is \"skip from H until you hit a first merge\n(without testing any intermediate commit), find F and stop to check it,\nand find that it is broken\".\n\nWhat makes you decide \"2. end\"?  The fact that both of its parents \"E\" and\n\"f\" are Ok?  IOW, it won't be \"2. end\" if one of the parents of the merge\nis broken?\n\nWhat if there is _no_ merge from a side branch but there were breakages in\nA (fixed in C) and then F in your original picture, i.e.\n\n  A---B---C---D---E---F---G---H (broken)\n  x       o           x       \n\nand you are hunting for the bug starting from H?  How does your algorithm\nhelp?  I grossed over the linear part by saying \"skip from H until you hit\na first merge\", but in general, what is your plan to handle linear part of\nthe history?\n\nA totally unacceptable answer is \"It does not help linear case, but it\nhelps when there are merges\".  The a-thru-f side branch in your picture,\nor any \"culprit side branch that was merged\" your algorithm finds in\ngeneral, would eventually have a linear segment, and having x-o-x in the\nhistory fundmentally breaks \"bisect\"---your band-aid will not help.\n\nThe whole idea behind using \"bisect\" to gain efficiency in isolating the\nissue depends on \"Once you see a Good commit, you do not have to search\nbeyond its ancestors\", as it is to look for a single breakage that\npersists to the \"Bad\" commit you give, and as far as \"bisect\" is\nconcerned, the breakage at A in your example is an unrelated breakage that\ndid not persist through the history to the \"Bad\" commit H.\n"},{"id":"159828","messageId":"AANLkTinwbm9gcZhGeQCbOEPov0_xV7uJyQvC7J13qO15@mail.gmail.com","threadId":"26324","inReplyTo":"AANLkTimUkv9+g_+wFcyGhwMjE9zYAKjMn32GL-WOVmoe@mail.gmail.com","subject":"Re: [RFC] Add bad-branch-first option for git-bisect","fromName":"Avery Pennarun","fromEmail":"apenwarr@gmail.com","sentAt":"2011-01-24T20:28:50Z","receivedAt":"2011-01-24T20:28:50Z","isPatch":false,"sender":{"key":"apenwarr@gmail.com","avatar":"https://avatars.githubusercontent.com/u/20592?v=4"},"body":"On Mon, Jan 24, 2011 at 1:53 AM, Christian Couder\n<christian.couder@gmail.com> wrote:\n> I am not opposed to an option to bisect on the first parents of the\n> bad commit only. And after a very fast look at your patch it seems to\n> be what it does. By the way Avery Pennarun's gitbuilder\n> (https://github.com/apenwarr/gitbuilder) does the same thing. So I\n> know some people are interested in such a feature.\n\nJust some notes on gitbuilder's algorithm, since I haven't spent the\ntime to fully understand Shuang's proposal.\n\nI do understand at least one of his concerns, that is, that people\nlike to do a lot of \"messy\" development on a branch, and when the\nbranch is done, merge the whole messy branch into the \"mainline\".  The\nmessy branch would then have a lot of commits that break a lot of\nthings before fixing them again later.\n\nIn a corporate environment, this method allows people to work all day,\nmake frequent commits, pull from other branches at will, and never\nrisk their lives by doing poorly-educated rebases.  It works pretty\nwell *until* you try to bisect, at which time all these messy commits\nstart to bite you.\n\ngitbuilder's bisection is a total hack around this situation, although\nit happens to work perfectly in the workflow it was designed for, thus\nmaking me feel clever.\n\nBasically, we push/fetch *all* the branches from *everybody* into a\nsingle repo, and build all of them as frequently as we can.  If you\nthink about it, if you have all the branches that someone might have\npulled/merged from, then you don't have to think of the git history as\na whole complicated DAG; you can just think of it as a whole bunch of\nseparate chunks of linear history.  Moreover, as long as people are\ncareful to only pull from a branch when that branch is passing all\ntests - which you can easily see by looking at the gitbuilder console\n- then playing inside each of these chunks of linear history can help\nyou figure out where particular bugs were introduced during \"messy\"\nbranches.\n\nIt also allows you a nice separation of concerns.  The owner of the\nmainline branch (the \"integration manager\" person) only really cares\nabout which branch they merged that caused a problem, because that\nperson doesn't want to fix bugs, he/she simply wants to know who owns\nthe failing branch, so that person can fix *their* bug and their\nbranch will merge without breaking things.\n\nSo this is why gitbuilder uses \"git rev-list --first-parent\" during\nits \"fake bisection\" operation: because a different person is\nresponsible for each \"linear chunk\" of history.\n\nNote that you have to use --no-ff when merging if you want this to\nwork reliably.  But the build manager person can just remember to do\nthat.  Combining --no-ff and --ff-only (which sound mutually exclusive\nbut aren't) is a way to be extra specially sure.\n\nNow, if you aren't using gitbuilder, what we want from \"bisection\" is\nnot quite the same, but let's imagine that you at least have a similar\nsetup, where people *only* ever merge into the mainline by using\n--no-ff.  In that case, you'd like a bisect operation that *starts* by\nusing --first-parent, which will tell you which merge caused the\nproblem.  After that, you might want to bisect into the branch.\n\n(I don't actually remember if 'git bisect' understands --first-parent\ncorrectly.  gitbuilder doesn't exactly bisect either, but that's\nanother story and not relevant right now.)\n\nI can actually imagine that there are many more projects that do what\nI'm talking about - \"messy\" branches that get broken and fixed over\ntime, then merge into a \"clean\" mainline - than projects (like the\nkernel and git.git) that try to keep all branches clean at all times.\nThus, I could see some argument that a \"--first-parents first\"\nbisection would actually help out a lot of people, and maybe even\ndeserves to be the default.\n\nI don't really care though, I just use gitbuilder :)\n\nHave fun,\n\nAvery\n"},{"id":"159839","messageId":"4D3E432B.70905@intel.com","threadId":"26324","inReplyTo":"7v8vyam5la.fsf@alter.siamese.dyndns.org","subject":"Re: [RFC] Add bad-branch-first option for git-bisect","fromName":"Shuang He","fromEmail":"shuang.he@intel.com","sentAt":"2011-01-25T03:27:39Z","receivedAt":"2011-01-25T03:27:39Z","isPatch":false,"sender":{"key":"shuang.he@intel.com","avatar":null},"body":"On 2011/1/25 4:04, Junio C Hamano wrote:\n> Shuang He<shuang.he@intel.com>  writes:\n>\n>> If A is bad commit, and C fixed it, and then F is bad again,\n>>\n>> A ->   B ->   C ->   D ->   E ->   F ->   G ->   H   (master)\n>>    \\                    \\      /\n>>      a  ->   b... c ->   d ->   e->f  (feature 1)\n>>\n>> Start with H as bad commit, and D as good commit, it's possible git-bisect would jump to c, and it will lead to wrong direction\n>>\n>> If bad-branch-first is used, it would be:\n>> 1. first round found F\n>> 2. end\n> It is unclear from the way you drew the picture if \"F\" is supposed to be a\n> merge of \"E\" and \"f\", but I'd assume that it is.\n\nOh, I lost this mail\nThat graph is different from what I meant, when shown in different email \nclient.\nIt's G which is merged from e and F\n\n> So what you are saying in 1. is \"skip from H until you hit a first merge\n> (without testing any intermediate commit), find F and stop to check it,\n> and find that it is broken\".\n>\n> What makes you decide \"2. end\"?  The fact that both of its parents \"E\" and\n> \"f\" are Ok?  IOW, it won't be \"2. end\" if one of the parents of the merge\n> is broken?\n\nI think the correction above should have answer those two questions.\n\n> What if there is _no_ merge from a side branch but there were breakages in\n> A (fixed in C) and then F in your original picture, i.e.\n>\n>    A---B---C---D---E---F---G---H (broken)\n>    x       o           x\n>\n> and you are hunting for the bug starting from H?  How does your algorithm\n> help?  I grossed over the linear part by saying \"skip from H until you hit\n> a first merge\", but in general, what is your plan to handle linear part of\n> the history?\n\nIf the history is linear, the new algorithm won't help, it will just \nbehavior like default git-bisect algorithm.\n\n> A totally unacceptable answer is \"It does not help linear case, but it\n> helps when there are merges\".  The a-thru-f side branch in your picture,\n> or any \"culprit side branch that was merged\" your algorithm finds in\n> general, would eventually have a linear segment, and having x-o-x in the\n> history fundmentally breaks \"bisect\"---your band-aid will not help.\n>\n> The whole idea behind using \"bisect\" to gain efficiency in isolating the\n> issue depends on \"Once you see a Good commit, you do not have to search\n> beyond its ancestors\", as it is to look for a single breakage that\n> persists to the \"Bad\" commit you give, and as far as \"bisect\" is\n> concerned, the breakage at A in your example is an unrelated breakage that\n> did not persist through the history to the \"Bad\" commit H.\n\nIn the example above (after we know G is merged from e and F),\nThose commits are old bad commit: A, B, a, b, ..., c, d (but we don't \ncare about those old bad commits, we cared about latest bad commit that \nwe met which is F)\nIt's possible that default git-bisect would jump to these old bad \ncommits, and will finally find an old first bad commit\nWith bad-branch-first, it could help us to get away from the trouble \nthat old culprit commit exist on feature1 branch for a period of time \nnot fixed\n\nThanks\n     --Shuang\n"},{"id":"159849","messageId":"AANLkTin1rS-ZBDx4j-UNFH4z9tnTiv5LBodLO-G2U2UF@mail.gmail.com","threadId":"26324","inReplyTo":"4D3D54D3.7040801@intel.com","subject":"Re: [RFC] Add bad-branch-first option for git-bisect","fromName":"Christian Couder","fromEmail":"christian.couder@gmail.com","sentAt":"2011-01-25T09:20:29Z","receivedAt":"2011-01-25T09:20:29Z","isPatch":false,"sender":{"key":"christian.couder@gmail.com","avatar":"https://avatars.githubusercontent.com/u/208954?v=4"},"body":"On Mon, Jan 24, 2011 at 11:30 AM, Shuang He <shuang.he@intel.com> wrote:\n> On 2011/1/24 17:53, Christian Couder wrote:\n>>\n>> Hi,\n>>\n>> On Mon, Jan 24, 2011 at 3:03 AM, Shuang He<shuang.he@intel.com>  wrote:\n>>>\n>>> Hi\n>>>     The default git-bisect algorithm will jump around the commit tree,\n>>> on the purpose of taking least steps to find the first culprit commit.\n>>> We may find it sometime would locate a old culprit commit that we're not\n>>> concerned about anymore.\n>>\n>> Yes, it can be a problem.\n>\n> I'm honored to be given so much comment :)\n> Thank you\n\nI am honored by your interest in git bisect and the fact that you\nprovided a patch :-)\nThanks!\n\n\n>> If the quality of these branches is too bad, I think they should not\n>> have been merged in the first place.\n>> If they are not merged (and not marked as good), then git bisect will\n>> not look at them, since it will look only at commits that are\n>> ancestors of the bad commit it is given.\n>>\n>> Or if one is merged but it causes too many problems, then perhaps a\n>> replacement commit could be used to unmerge the branch.\n>>\n>> Another possibility is to have in a file a list of commits that are\n>> the last commits on these branches before the merge commits, and do a:\n>>\n>> git bisect good $(cat good_commits_file.txt)\n>>\n>> at the beginning of each bisection.\n>>\n>> So I think the long term solution in this case is not what your are\n>> suggesting.\n>\n> Yeah, I agree that the issue I addressed above will not be a problem if all\n> those branches are maintained very well.\n> Actually we've implemented a automated bisect system for Intel Linux\n> Graphics Driver Project, and so we'd like the system\n> helps us to locate issue in an more automatic way when branches are not\n> maintained as good as expected.\n\nI think there is always a price to pay when you bisect if the branches\nare not well maintained.\nMaybe your algorithm could help in some cases, but my opinion is that\nthere will probably still be many problems and a human will often have\nto take a look.\n\n>>>         2. Some of those branches may not synchronized with main\n>>> branch in time.  Say feature1 is broken when feature2 branch is created,\n>>> and\n>>> feature1 is fixed just a moment later after feature2 branch is created,\n>>> and when feature2's development is done, and developer want to merge\n>>> feature2 branch back to master branch, feature2 will be firstly\n>>> synchronized to master branch tip, then merge into master.  For the same\n>>> reason addressed in issue 1, this will also lead git-bisect into wrong\n>>> direction.\n>>\n>> I am not sure what you mean by \" feature2 will be firstly synchronized\n>> to master branch tip\", and I think this should mean a rebase that\n>> would fix the bug if feature1 has already been merged into the master\n>> branch.\n>>\n>> But anyway in this case, I think that git bisect will find that the\n>> first bad commit is the last commit in the branch, just before it was\n>> merged. And by looking at the branch graph it should be quite easy to\n>> understand what happened.\n\nNow I think I was wrong here, as git bisect will probably find that\nthe first commit in the branch (not the last one) is the first bad\ncommit.\n\n[...]\n\n>> - the name \"bisectbadbranchfirst\" seems wrong to me, because git\n>> branches are just some special tags; \"firstparentsonly\" would be a\n>> better name,\n>\n> It's recursively applying bad branch first algorithm, not just constantly\n> stick to first parent.\n> Given this condition:\n>    A -> B -> C -> D -> E -> F -> G -> H   (master)\n>         \\ a  -> b -> c -> d -> e /  (feature 1)\n>              \\ x -> y -> z/      (feature 2)\n> start with H as bad commit, and A as good commit, if y is the target bad\n> commit. bad-branch-first algorithm will do it like this:\n>    1. In first round stick to master branch, so it will locate G as first\n> bad commit\n>    2. In second round stick to feature1 branch, then it will locate d as\n> first bad commit\n>    3. In third round stick to feature2 branch, then it will finally locate y\n> as first bad commit\n> So you could see, it's always sticking to branch where current bad commit\n> sit\n\nI see. It is interesting, but why not develop a \"firstparentsonly\"\nalgorithm first?\n\nAs Avery explains in his email, it is already interesting to have a\n\"firstparentsonly\" algorithm because some people are only interested\nto know from which branch the bug comes from.\nWhen they know that, they can just contact the relevant people and be\ndone with it.\n\nAnd when we have a \"firstparentsonly\" algorithm, then your algorithm\ncould be just a script that repeatedly uses git bisect with the\n\"firstparentsonly\" algorithm. And this script might be integrated in\nthe \"contrib\" directory if it not considered important to be\nintegrated as an algorithm into git bisect.\n\nThanks,\nChristian.\n"},{"id":"159875","messageId":"4D3FC912.4020404@intel.com","threadId":"26324","inReplyTo":"AANLkTinwbm9gcZhGeQCbOEPov0_xV7uJyQvC7J13qO15@mail.gmail.com","subject":"Re: [RFC] Add bad-branch-first option for git-bisect","fromName":"Shuang He","fromEmail":"shuang.he@intel.com","sentAt":"2011-01-26T07:11:14Z","receivedAt":"2011-01-26T07:11:14Z","isPatch":false,"sender":{"key":"shuang.he@intel.com","avatar":null},"body":"On 2011/1/25 4:28, Avery Pennarun wrote:\n> On Mon, Jan 24, 2011 at 1:53 AM, Christian Couder\n> <christian.couder@gmail.com>  wrote:\n>> I am not opposed to an option to bisect on the first parents of the\n>> bad commit only. And after a very fast look at your patch it seems to\n>> be what it does. By the way Avery Pennarun's gitbuilder\n>> (https://github.com/apenwarr/gitbuilder) does the same thing. So I\n>> know some people are interested in such a feature.\n> Just some notes on gitbuilder's algorithm, since I haven't spent the\n> time to fully understand Shuang's proposal.\n>\n> I do understand at least one of his concerns, that is, that people\n> like to do a lot of \"messy\" development on a branch, and when the\n> branch is done, merge the whole messy branch into the \"mainline\".  The\n> messy branch would then have a lot of commits that break a lot of\n> things before fixing them again later.\n>\n> In a corporate environment, this method allows people to work all day,\n> make frequent commits, pull from other branches at will, and never\n> risk their lives by doing poorly-educated rebases.  It works pretty\n> well *until* you try to bisect, at which time all these messy commits\n> start to bite you.\n>\n> gitbuilder's bisection is a total hack around this situation, although\n> it happens to work perfectly in the workflow it was designed for, thus\n> making me feel clever.\n>\n> Basically, we push/fetch *all* the branches from *everybody* into a\n> single repo, and build all of them as frequently as we can.  If you\n> think about it, if you have all the branches that someone might have\n> pulled/merged from, then you don't have to think of the git history as\n> a whole complicated DAG; you can just think of it as a whole bunch of\n> separate chunks of linear history.  Moreover, as long as people are\n> careful to only pull from a branch when that branch is passing all\n> tests - which you can easily see by looking at the gitbuilder console\n> - then playing inside each of these chunks of linear history can help\n> you figure out where particular bugs were introduced during \"messy\"\n> branches.\n>\n> It also allows you a nice separation of concerns.  The owner of the\n> mainline branch (the \"integration manager\" person) only really cares\n> about which branch they merged that caused a problem, because that\n> person doesn't want to fix bugs, he/she simply wants to know who owns\n> the failing branch, so that person can fix *their* bug and their\n> branch will merge without breaking things.\n>\n> So this is why gitbuilder uses \"git rev-list --first-parent\" during\n> its \"fake bisection\" operation: because a different person is\n> responsible for each \"linear chunk\" of history.\n>\n> Note that you have to use --no-ff when merging if you want this to\n> work reliably.  But the build manager person can just remember to do\n> that.  Combining --no-ff and --ff-only (which sound mutually exclusive\n> but aren't) is a way to be extra specially sure.\n>\n> Now, if you aren't using gitbuilder, what we want from \"bisection\" is\n> not quite the same, but let's imagine that you at least have a similar\n> setup, where people *only* ever merge into the mainline by using\n> --no-ff.  In that case, you'd like a bisect operation that *starts* by\n> using --first-parent, which will tell you which merge caused the\n> problem.  After that, you might want to bisect into the branch.\n>\n> (I don't actually remember if 'git bisect' understands --first-parent\n> correctly.  gitbuilder doesn't exactly bisect either, but that's\n> another story and not relevant right now.)\n>\n> I can actually imagine that there are many more projects that do what\n> I'm talking about - \"messy\" branches that get broken and fixed over\n> time, then merge into a \"clean\" mainline - than projects (like the\n> kernel and git.git) that try to keep all branches clean at all times.\n> Thus, I could see some argument that a \"--first-parents first\"\n> bisection would actually help out a lot of people, and maybe even\n> deserves to be the default.\n>\n> I don't really care though, I just use gitbuilder :)\n>\n> Have fun,\n>\n> Avery\n\nThanks for helping explaining those stuff, and also glad to learn more \nabout gitbuilder :)\n\nThanks\n     --Shuang\n"},{"id":"159876","messageId":"4D3FCBB3.2090508@intel.com","threadId":"26324","inReplyTo":"AANLkTin1rS-ZBDx4j-UNFH4z9tnTiv5LBodLO-G2U2UF@mail.gmail.com","subject":"Re: [RFC] Add bad-branch-first option for git-bisect","fromName":"Shuang He","fromEmail":"shuang.he@intel.com","sentAt":"2011-01-26T07:22:27Z","receivedAt":"2011-01-26T07:22:27Z","isPatch":false,"sender":{"key":"shuang.he@intel.com","avatar":null},"body":"On 2011/1/25 17:20, Christian Couder wrote:\n> On Mon, Jan 24, 2011 at 11:30 AM, Shuang He<shuang.he@intel.com>  wrote:\n>> On 2011/1/24 17:53, Christian Couder wrote:\n>>> Hi,\n>>>\n>>> On Mon, Jan 24, 2011 at 3:03 AM, Shuang He<shuang.he@intel.com>    wrote:\n>>>> Hi\n>>>>      The default git-bisect algorithm will jump around the commit tree,\n>>>> on the purpose of taking least steps to find the first culprit commit.\n>>>> We may find it sometime would locate a old culprit commit that we're not\n>>>> concerned about anymore.\n>>> Yes, it can be a problem.\n>> I'm honored to be given so much comment :)\n>> Thank you\n> I am honored by your interest in git bisect and the fact that you\n> provided a patch :-)\n> Thanks!\n\nI'm glad to see that git community is so hot.\n\n>\n>>> If the quality of these branches is too bad, I think they should not\n>>> have been merged in the first place.\n>>> If they are not merged (and not marked as good), then git bisect will\n>>> not look at them, since it will look only at commits that are\n>>> ancestors of the bad commit it is given.\n>>>\n>>> Or if one is merged but it causes too many problems, then perhaps a\n>>> replacement commit could be used to unmerge the branch.\n>>>\n>>> Another possibility is to have in a file a list of commits that are\n>>> the last commits on these branches before the merge commits, and do a:\n>>>\n>>> git bisect good $(cat good_commits_file.txt)\n>>>\n>>> at the beginning of each bisection.\n>>>\n>>> So I think the long term solution in this case is not what your are\n>>> suggesting.\n>> Yeah, I agree that the issue I addressed above will not be a problem if all\n>> those branches are maintained very well.\n>> Actually we've implemented a automated bisect system for Intel Linux\n>> Graphics Driver Project, and so we'd like the system\n>> helps us to locate issue in an more automatic way when branches are not\n>> maintained as good as expected.\n> I think there is always a price to pay when you bisect if the branches\n> are not well maintained.\n> Maybe your algorithm could help in some cases, but my opinion is that\n> there will probably still be many problems and a human will often have\n> to take a look.\n>\n\nYes, I agree. What we trying to do is just make the machine to do more \nhelp for human.\n\n>>>>          2. Some of those branches may not synchronized with main\n>>>> branch in time.  Say feature1 is broken when feature2 branch is created,\n>>>> and\n>>>> feature1 is fixed just a moment later after feature2 branch is created,\n>>>> and when feature2's development is done, and developer want to merge\n>>>> feature2 branch back to master branch, feature2 will be firstly\n>>>> synchronized to master branch tip, then merge into master.  For the same\n>>>> reason addressed in issue 1, this will also lead git-bisect into wrong\n>>>> direction.\n>>> I am not sure what you mean by \" feature2 will be firstly synchronized\n>>> to master branch tip\", and I think this should mean a rebase that\n>>> would fix the bug if feature1 has already been merged into the master\n>>> branch.\n>>>\n>>> But anyway in this case, I think that git bisect will find that the\n>>> first bad commit is the last commit in the branch, just before it was\n>>> merged. And by looking at the branch graph it should be quite easy to\n>>> understand what happened.\n> Now I think I was wrong here, as git bisect will probably find that\n> the first commit in the branch (not the last one) is the first bad\n> commit.\n>\n> [...]\n>\n>>> - the name \"bisectbadbranchfirst\" seems wrong to me, because git\n>>> branches are just some special tags; \"firstparentsonly\" would be a\n>>> better name,\n>> It's recursively applying bad branch first algorithm, not just constantly\n>> stick to first parent.\n>> Given this condition:\n>>     A ->  B ->  C ->  D ->  E ->  F ->  G ->  H   (master)\n>>          \\ a  ->  b ->  c ->  d ->  e /  (feature 1)\n>>               \\ x ->  y ->  z/      (feature 2)\n>> start with H as bad commit, and A as good commit, if y is the target bad\n>> commit. bad-branch-first algorithm will do it like this:\n>>     1. In first round stick to master branch, so it will locate G as first\n>> bad commit\n>>     2. In second round stick to feature1 branch, then it will locate d as\n>> first bad commit\n>>     3. In third round stick to feature2 branch, then it will finally locate y\n>> as first bad commit\n>> So you could see, it's always sticking to branch where current bad commit\n>> sit\n> I see. It is interesting, but why not develop a \"firstparentsonly\"\n> algorithm first?\n>\n> As Avery explains in his email, it is already interesting to have a\n> \"firstparentsonly\" algorithm because some people are only interested\n> to know from which branch the bug comes from.\n> When they know that, they can just contact the relevant people and be\n> done with it.\n>\n> And when we have a \"firstparentsonly\" algorithm, then your algorithm\n> could be just a script that repeatedly uses git bisect with the\n> \"firstparentsonly\" algorithm. And this script might be integrated in\n> the \"contrib\" directory if it not considered important to be\n> integrated as an algorithm into git bisect.\n\nSorry to reply so late, since I was on a long journey home for Chinese \nNew Year vacation ;)\nI agree that's also an good option.\nIs it acceptable to add option to git-bisect stuff, so user could choose \nwhich algorithm to use at every step at will.\nAnd we have tested previous attached patch with t6002-rev-list-bisect.sh \nand t6030-bisect-porcelain.sh, and we get:\n     with bad-branch-first disabled (which is the default setting):\n         t6002-rev-list-bisect.sh: # passed all 45 test(s)\n         t6030-bisect-porcelain.sh: # passed all 40 test(s)\n     and with bad-branch-first enabled:\n         t6002-rev-list-bisect.sh: # passed all 45 test(s)\n         t6030-bisect-porcelain.sh: # failed 5 among 40 test(s), and I \nhave spent some time digging into those failures ,and it seems they're \nall false negative since they're using hard-coded bisect path to \nvalidate specific case\n\nThanks\n     --Shuang\n> Thanks,\n> Christian.\n"},{"id":"159881","messageId":"AANLkTi=T+oapfn1CTu_smU1P+JEraihE4BUKJcB=uBHw@mail.gmail.com","threadId":"26324","inReplyTo":"4D3FCBB3.2090508@intel.com","subject":"Re: [RFC] Add bad-branch-first option for git-bisect","fromName":"Christian Couder","fromEmail":"christian.couder@gmail.com","sentAt":"2011-01-26T09:44:04Z","receivedAt":"2011-01-26T09:44:04Z","isPatch":false,"sender":{"key":"christian.couder@gmail.com","avatar":"https://avatars.githubusercontent.com/u/208954?v=4"},"body":"On Wed, Jan 26, 2011 at 8:22 AM, Shuang He <shuang.he@intel.com> wrote:\n> On 2011/1/25 17:20, Christian Couder wrote:\n>>\n>>>\n>>> Yeah, I agree that the issue I addressed above will not be a problem if\n>>> all\n>>> those branches are maintained very well.\n>>> Actually we've implemented a automated bisect system for Intel Linux\n>>> Graphics Driver Project, and so we'd like the system\n>>> helps us to locate issue in an more automatic way when branches are not\n>>> maintained as good as expected.\n>>\n>> I think there is always a price to pay when you bisect if the branches\n>> are not well maintained.\n>> Maybe your algorithm could help in some cases, but my opinion is that\n>> there will probably still be many problems and a human will often have\n>> to take a look.\n>>\n>\n> Yes, I agree. What we trying to do is just make the machine to do more help\n> for human.\n\nYeah, this is the way to go. And by the way I am happy to know that\nyou have implemented an automated bisect system. That's great and I\nhope it already helps.\n\n>>>> - the name \"bisectbadbranchfirst\" seems wrong to me, because git\n>>>> branches are just some special tags; \"firstparentsonly\" would be a\n>>>> better name,\n>>>\n>>> It's recursively applying bad branch first algorithm, not just constantly\n>>> stick to first parent.\n>>> Given this condition:\n>>>    A ->  B ->  C ->  D ->  E ->  F ->  G ->  H   (master)\n>>>         \\ a  ->  b ->  c ->  d ->  e /  (feature 1)\n>>>              \\ x ->  y ->  z/      (feature 2)\n>>> start with H as bad commit, and A as good commit, if y is the target bad\n>>> commit. bad-branch-first algorithm will do it like this:\n>>>    1. In first round stick to master branch, so it will locate G as first\n>>> bad commit\n>>>    2. In second round stick to feature1 branch, then it will locate d as\n>>> first bad commit\n>>>    3. In third round stick to feature2 branch, then it will finally\n>>> locate y\n>>> as first bad commit\n>>> So you could see, it's always sticking to branch where current bad commit\n>>> sit\n>>\n>> I see. It is interesting, but why not develop a \"firstparentsonly\"\n>> algorithm first?\n>>\n>> As Avery explains in his email, it is already interesting to have a\n>> \"firstparentsonly\" algorithm because some people are only interested\n>> to know from which branch the bug comes from.\n>> When they know that, they can just contact the relevant people and be\n>> done with it.\n>>\n>> And when we have a \"firstparentsonly\" algorithm, then your algorithm\n>> could be just a script that repeatedly uses git bisect with the\n>> \"firstparentsonly\" algorithm. And this script might be integrated in\n>> the \"contrib\" directory if it not considered important to be\n>> integrated as an algorithm into git bisect.\n>\n> Sorry to reply so late, since I was on a long journey home for Chinese New\n> Year vacation ;)\n\nNo problem. I am not in a hurry at all. In fact I don't have much time\nthese days so I reply very late too.\n\n> I agree that's also an good option.\n> Is it acceptable to add option to git-bisect stuff, so user could choose\n> which algorithm to use at every step at will.\n\nAre you sure it is needed to be able to change the algorithm at every step?\n\nThis means that you would like a new \"git bisect strategy <strategy>\"\nsubcommand ?\n\nFirst I thought that we could just add a \"--strategy <strategy>\"\noption to \"git bisect start\".\nBut anyway, I think it should be easy to add afterward, and it can be\ndone in a separated patch that can be discussed on its own.\n\n> And we have tested previous attached patch with t6002-rev-list-bisect.sh and\n> t6030-bisect-porcelain.sh, and we get:\n>    with bad-branch-first disabled (which is the default setting):\n>        t6002-rev-list-bisect.sh: # passed all 45 test(s)\n>        t6030-bisect-porcelain.sh: # passed all 40 test(s)\n>    and with bad-branch-first enabled:\n>        t6002-rev-list-bisect.sh: # passed all 45 test(s)\n>        t6030-bisect-porcelain.sh: # failed 5 among 40 test(s), and I have\n> spent some time digging into those failures ,and it seems they're all false\n> negative since they're using hard-coded bisect path to validate specific\n> case\n\nYes, there are some hard coded commits that depend on the algorithm.\nAnyway I did not look in depth at your patch yet, and as I said it\nwould be better if you could split it into a patch series where a\n\"firstparentsonly\" algorithm is implemented first.\nThis way it will be easier to review, and we can start to integrate\nsome non controversial features, and then discuss the other ones on\ntheir own merit.\n\nThanks in advance,\nChristian.\n"},{"id":"159886","messageId":"4D3FFA10.4010807@intel.com","threadId":"26324","inReplyTo":"AANLkTi=T+oapfn1CTu_smU1P+JEraihE4BUKJcB=uBHw@mail.gmail.com","subject":"Re: [RFC] Add bad-branch-first option for git-bisect","fromName":"Shuang He","fromEmail":"shuang.he@intel.com","sentAt":"2011-01-26T10:40:16Z","receivedAt":"2011-01-26T10:40:16Z","isPatch":false,"sender":{"key":"shuang.he@intel.com","avatar":null},"body":"On 2011/1/26 17:44, Christian Couder wrote:\n> On Wed, Jan 26, 2011 at 8:22 AM, Shuang He<shuang.he@intel.com>  wrote:\n>> On 2011/1/25 17:20, Christian Couder wrote:\n>>>> Yeah, I agree that the issue I addressed above will not be a problem if\n>>>> all\n>>>> those branches are maintained very well.\n>>>> Actually we've implemented a automated bisect system for Intel Linux\n>>>> Graphics Driver Project, and so we'd like the system\n>>>> helps us to locate issue in an more automatic way when branches are not\n>>>> maintained as good as expected.\n>>> I think there is always a price to pay when you bisect if the branches\n>>> are not well maintained.\n>>> Maybe your algorithm could help in some cases, but my opinion is that\n>>> there will probably still be many problems and a human will often have\n>>> to take a look.\n>>>\n>> Yes, I agree. What we trying to do is just make the machine to do more help\n>> for human.\n> Yeah, this is the way to go. And by the way I am happy to know that\n> you have implemented an automated bisect system. That's great and I\n> hope it already helps.\n>\n>>>>> - the name \"bisectbadbranchfirst\" seems wrong to me, because git\n>>>>> branches are just some special tags; \"firstparentsonly\" would be a\n>>>>> better name,\n>>>> It's recursively applying bad branch first algorithm, not just constantly\n>>>> stick to first parent.\n>>>> Given this condition:\n>>>>     A ->    B ->    C ->    D ->    E ->    F ->    G ->    H   (master)\n>>>>          \\ a  ->    b ->    c ->    d ->    e /  (feature 1)\n>>>>               \\ x ->    y ->    z/      (feature 2)\n>>>> start with H as bad commit, and A as good commit, if y is the target bad\n>>>> commit. bad-branch-first algorithm will do it like this:\n>>>>     1. In first round stick to master branch, so it will locate G as first\n>>>> bad commit\n>>>>     2. In second round stick to feature1 branch, then it will locate d as\n>>>> first bad commit\n>>>>     3. In third round stick to feature2 branch, then it will finally\n>>>> locate y\n>>>> as first bad commit\n>>>> So you could see, it's always sticking to branch where current bad commit\n>>>> sit\n>>> I see. It is interesting, but why not develop a \"firstparentsonly\"\n>>> algorithm first?\n>>>\n>>> As Avery explains in his email, it is already interesting to have a\n>>> \"firstparentsonly\" algorithm because some people are only interested\n>>> to know from which branch the bug comes from.\n>>> When they know that, they can just contact the relevant people and be\n>>> done with it.\n>>>\n>>> And when we have a \"firstparentsonly\" algorithm, then your algorithm\n>>> could be just a script that repeatedly uses git bisect with the\n>>> \"firstparentsonly\" algorithm. And this script might be integrated in\n>>> the \"contrib\" directory if it not considered important to be\n>>> integrated as an algorithm into git bisect.\n>> Sorry to reply so late, since I was on a long journey home for Chinese New\n>> Year vacation ;)\n> No problem. I am not in a hurry at all. In fact I don't have much time\n> these days so I reply very late too.\n>\n>> I agree that's also an good option.\n>> Is it acceptable to add option to git-bisect stuff, so user could choose\n>> which algorithm to use at every step at will.\n> Are you sure it is needed to be able to change the algorithm at every step?\n\nI don't think it's needed, it would just give user more control over the \nalgorithm.\n\n> This means that you would like a new \"git bisect strategy<strategy>\"\n> subcommand ?\n>\n> First I thought that we could just add a \"--strategy<strategy>\"\n> option to \"git bisect start\".\n> But anyway, I think it should be easy to add afterward, and it can be\n> done in a separated patch that can be discussed on its own.\n\nYeah, agree. We could discuss this later\n\n>> And we have tested previous attached patch with t6002-rev-list-bisect.sh and\n>> t6030-bisect-porcelain.sh, and we get:\n>>     with bad-branch-first disabled (which is the default setting):\n>>         t6002-rev-list-bisect.sh: # passed all 45 test(s)\n>>         t6030-bisect-porcelain.sh: # passed all 40 test(s)\n>>     and with bad-branch-first enabled:\n>>         t6002-rev-list-bisect.sh: # passed all 45 test(s)\n>>         t6030-bisect-porcelain.sh: # failed 5 among 40 test(s), and I have\n>> spent some time digging into those failures ,and it seems they're all false\n>> negative since they're using hard-coded bisect path to validate specific\n>> case\n> Yes, there are some hard coded commits that depend on the algorithm.\n> Anyway I did not look in depth at your patch yet, and as I said it\n> would be better if you could split it into a patch series where a\n> \"firstparentsonly\" algorithm is implemented first.\n> This way it will be easier to review, and we can start to integrate\n> some non controversial features, and then discuss the other ones on\n> their own merit.\n>\n> Thanks in advance,\n> Christian.\n\nThanks for the good suggestion, I'll start the work soon.\n\nThanks\n     --Shuang\n"}]}