{"thread":{"id":"23171","subject":"[RFC/PATCH 1/5] revert: use strbuf to refactor the code that writes the merge message","startedAt":"2010-03-25T04:58:12Z","lastAt":"2010-03-25T04:58:17Z","messageCount":6,"participants":["Christian Couder"],"isPatch":true,"patchVersion":1,"patchTotal":5},"messages":[{"id":"137775","messageId":"20100325045519.14832.65964.chriscool@tuxfamily.org","threadId":"23171","inReplyTo":null,"subject":"[RFC/PATCH 0/5] add a --strategy option to \"git cherry-pick\"","fromName":"Christian Couder","fromEmail":"chriscool@tuxfamily.org","sentAt":"2010-03-25T04:58:12Z","receivedAt":"2010-03-25T04:58:12Z","isPatch":true,"sender":{"key":"christian.couder@gmail.com","avatar":"https://avatars.githubusercontent.com/u/208954?v=4"},"body":"The purpose of this series is to make it possible to test how \"git cherry-pick\"\nwould work with another merge strategy than the recursive one.\n\nJunio suggested:\n\n\"It might not be a bad idea to teach a hidden primarily-for-debugging\noption to \"cherry-pick\" to let it use resolve instead of recursive for\ncases like this.\"\n\nChristian Couder (5):\n  revert: use strbuf to refactor the code that writes the merge message\n  revert: refactor merge recursive code into its own function\n  merge: refactor code that calls \"git merge-STRATEGY\"\n  merge: make function try_merge_command non static\n  revert: add \"--strategy\" option to choose merge strategy\n\n builtin/merge.c   |   81 ++++++++++++++-----------\n builtin/revert.c  |  174 ++++++++++++++++++++++++++++++----------------------\n cache.h           |    3 -\n merge-recursive.h |    4 +\n 4 files changed, 149 insertions(+), 113 deletions(-)\n"},{"id":"137771","messageId":"20100325045818.14832.29691.chriscool@tuxfamily.org","threadId":"23171","inReplyTo":"20100325045519.14832.65964.chriscool@tuxfamily.org","subject":"[RFC/PATCH 1/5] revert: use strbuf to refactor the code that writes the merge message","fromName":"Christian Couder","fromEmail":"chriscool@tuxfamily.org","sentAt":"2010-03-25T04:58:13Z","receivedAt":"2010-03-25T04:58:13Z","isPatch":true,"sender":{"key":"christian.couder@gmail.com","avatar":"https://avatars.githubusercontent.com/u/208954?v=4"},"body":"\nSigned-off-by: Christian Couder <chriscool@tuxfamily.org>\n---\n builtin/revert.c |   70 ++++++++++++++++++++++++++---------------------------\n 1 files changed, 34 insertions(+), 36 deletions(-)\n\ndiff --git a/builtin/revert.c b/builtin/revert.c\nindex 0651e34..3cd62ae 100644\n--- a/builtin/revert.c\n+++ b/builtin/revert.c\n@@ -138,28 +138,17 @@ static char *get_encoding(const char *message)\n \treturn NULL;\n }\n \n-static struct lock_file msg_file;\n-static int msg_fd;\n-\n-static void add_to_msg(const char *string)\n-{\n-\tint len = strlen(string);\n-\tif (write_in_full(msg_fd, string, len) < 0)\n-\t\tdie_errno (\"Could not write to MERGE_MSG\");\n-}\n-\n-static void add_message_to_msg(const char *message)\n+static void add_message_to_msg(struct strbuf *msgbuf, const char *message)\n {\n \tconst char *p = message;\n \twhile (*p && (*p != '\\n' || p[1] != '\\n'))\n \t\tp++;\n \n \tif (!*p)\n-\t\tadd_to_msg(sha1_to_hex(commit->object.sha1));\n+\t\tstrbuf_addstr(msgbuf, sha1_to_hex(commit->object.sha1));\n \n \tp += 2;\n-\tadd_to_msg(p);\n-\treturn;\n+\tstrbuf_addstr(msgbuf, p);\n }\n \n static void set_author_ident_env(const char *message)\n@@ -235,6 +224,19 @@ static char *help_msg(const char *name)\n \treturn strbuf_detach(&helpbuf, NULL);\n }\n \n+static void write_message(struct strbuf *msgbuf, const char *filename)\n+{\n+\tstatic struct lock_file msg_file;\n+\n+\tint msg_fd = hold_lock_file_for_update(&msg_file, filename,\n+\t\t\t\t\t       LOCK_DIE_ON_ERROR);\n+\tif (write_in_full(msg_fd, msgbuf->buf, msgbuf->len) < 0)\n+\t\tdie_errno(\"Could not write to %s.\", filename);\n+\tstrbuf_release(msgbuf);\n+\tif (commit_lock_file(&msg_file) < 0)\n+\t\tdie(\"Error wrapping up %s\", filename);\n+}\n+\n static struct tree *empty_tree(void)\n {\n \tstruct tree *tree = xcalloc(1, sizeof(struct tree));\n@@ -280,6 +282,7 @@ static int revert_or_cherry_pick(int argc, const char **argv)\n \tstruct merge_options o;\n \tstruct tree *result, *next_tree, *base_tree, *head_tree;\n \tstatic struct lock_file index_lock;\n+\tstruct strbuf msgbuf = STRBUF_INIT;\n \n \tgit_config(git_default_config, NULL);\n \tme = action == REVERT ? \"revert\" : \"cherry-pick\";\n@@ -368,9 +371,6 @@ static int revert_or_cherry_pick(int argc, const char **argv)\n \t * reverse of it if we are revert.\n \t */\n \n-\tmsg_fd = hold_lock_file_for_update(&msg_file, defmsg,\n-\t\t\t\t\t   LOCK_DIE_ON_ERROR);\n-\n \tencoding = get_encoding(message);\n \tif (!encoding)\n \t\tencoding = \"UTF-8\";\n@@ -389,25 +389,25 @@ static int revert_or_cherry_pick(int argc, const char **argv)\n \n \t\tbase = commit;\n \t\tnext = parent;\n-\t\tadd_to_msg(\"Revert \\\"\");\n-\t\tadd_to_msg(oneline_body + 1);\n-\t\tadd_to_msg(\"\\\"\\n\\nThis reverts commit \");\n-\t\tadd_to_msg(sha1_to_hex(commit->object.sha1));\n+\t\tstrbuf_addstr(&msgbuf, \"Revert \\\"\");\n+\t\tstrbuf_addstr(&msgbuf, oneline_body + 1);\n+\t\tstrbuf_addstr(&msgbuf, \"\\\"\\n\\nThis reverts commit \");\n+\t\tstrbuf_addstr(&msgbuf, sha1_to_hex(commit->object.sha1));\n \n \t\tif (commit->parents->next) {\n-\t\t\tadd_to_msg(\", reversing\\nchanges made to \");\n-\t\t\tadd_to_msg(sha1_to_hex(parent->object.sha1));\n+\t\t\tstrbuf_addstr(&msgbuf, \", reversing\\nchanges made to \");\n+\t\t\tstrbuf_addstr(&msgbuf, sha1_to_hex(parent->object.sha1));\n \t\t}\n-\t\tadd_to_msg(\".\\n\");\n+\t\tstrbuf_addstr(&msgbuf, \".\\n\");\n \t} else {\n \t\tbase = parent;\n \t\tnext = commit;\n \t\tset_author_ident_env(message);\n-\t\tadd_message_to_msg(message);\n+\t\tadd_message_to_msg(&msgbuf, message);\n \t\tif (no_replay) {\n-\t\t\tadd_to_msg(\"(cherry picked from commit \");\n-\t\t\tadd_to_msg(sha1_to_hex(commit->object.sha1));\n-\t\t\tadd_to_msg(\")\\n\");\n+\t\t\tstrbuf_addstr(&msgbuf, \"(cherry picked from commit \");\n+\t\t\tstrbuf_addstr(&msgbuf, sha1_to_hex(commit->object.sha1));\n+\t\t\tstrbuf_addstr(&msgbuf, \")\\n\");\n \t\t}\n \t}\n \n@@ -431,27 +431,25 @@ static int revert_or_cherry_pick(int argc, const char **argv)\n \trollback_lock_file(&index_lock);\n \n \tif (!clean) {\n-\t\tadd_to_msg(\"\\nConflicts:\\n\\n\");\n+\t\tstrbuf_addstr(&msgbuf, \"\\nConflicts:\\n\\n\");\n \t\tfor (i = 0; i < active_nr;) {\n \t\t\tstruct cache_entry *ce = active_cache[i++];\n \t\t\tif (ce_stage(ce)) {\n-\t\t\t\tadd_to_msg(\"\\t\");\n-\t\t\t\tadd_to_msg(ce->name);\n-\t\t\t\tadd_to_msg(\"\\n\");\n+\t\t\t\tstrbuf_addch(&msgbuf, '\\t');\n+\t\t\t\tstrbuf_addstr(&msgbuf, ce->name);\n+\t\t\t\tstrbuf_addch(&msgbuf, '\\n');\n \t\t\t\twhile (i < active_nr && !strcmp(ce->name,\n \t\t\t\t\t\tactive_cache[i]->name))\n \t\t\t\t\ti++;\n \t\t\t}\n \t\t}\n-\t\tif (commit_lock_file(&msg_file) < 0)\n-\t\t\tdie (\"Error wrapping up %s\", defmsg);\n+\t\twrite_message(&msgbuf, defmsg);\n \t\tfprintf(stderr, \"Automatic %s failed.%s\\n\",\n \t\t\tme, help_msg(commit_name));\n \t\trerere(allow_rerere_auto);\n \t\texit(1);\n \t}\n-\tif (commit_lock_file(&msg_file) < 0)\n-\t\tdie (\"Error wrapping up %s\", defmsg);\n+\twrite_message(&msgbuf, defmsg);\n \tfprintf(stderr, \"Finished one %s.\\n\", me);\n \n \t/*\n-- \n1.7.0.2.398.g89bc8ce\n"},{"id":"137776","messageId":"20100325045818.14832.94770.chriscool@tuxfamily.org","threadId":"23171","inReplyTo":"20100325045519.14832.65964.chriscool@tuxfamily.org","subject":"[RFC/PATCH 2/5] revert: refactor merge recursive code into its own function","fromName":"Christian Couder","fromEmail":"chriscool@tuxfamily.org","sentAt":"2010-03-25T04:58:14Z","receivedAt":"2010-03-25T04:58:14Z","isPatch":true,"sender":{"key":"christian.couder@gmail.com","avatar":"https://avatars.githubusercontent.com/u/208954?v=4"},"body":"\nSigned-off-by: Christian Couder <chriscool@tuxfamily.org>\n---\n builtin/revert.c |  101 +++++++++++++++++++++++++++++------------------------\n 1 files changed, 55 insertions(+), 46 deletions(-)\n\ndiff --git a/builtin/revert.c b/builtin/revert.c\nindex 3cd62ae..054f442 100644\n--- a/builtin/revert.c\n+++ b/builtin/revert.c\n@@ -271,17 +271,67 @@ static int fast_forward_to(const unsigned char *to, const unsigned char *from)\n \treturn write_ref_sha1(ref_lock, to, \"cherry-pick\");\n }\n \n+static void do_recursive_merge(struct commit *base, struct commit *next,\n+\t\t\t       unsigned char *head, char *oneline,\n+\t\t\t       struct strbuf *msgbuf, char *defmsg)\n+{\n+\tstruct merge_options o;\n+\tstruct tree *result, *next_tree, *base_tree, *head_tree;\n+\tint clean, index_fd;\n+\tstatic struct lock_file index_lock;\n+\n+\tindex_fd = hold_locked_index(&index_lock, 1);\n+\n+\tread_cache();\n+\tinit_merge_options(&o);\n+\to.branch1 = \"HEAD\";\n+\to.branch2 = oneline;\n+\n+\thead_tree = parse_tree_indirect(head);\n+\tnext_tree = next ? next->tree : empty_tree();\n+\tbase_tree = base ? base->tree : empty_tree();\n+\n+\tclean = merge_trees(&o,\n+\t\t\t    head_tree,\n+\t\t\t    next_tree, base_tree, &result);\n+\n+\tif (active_cache_changed &&\n+\t    (write_cache(index_fd, active_cache, active_nr) ||\n+\t     commit_locked_index(&index_lock)))\n+\t\tdie(\"%s: Unable to write new index file\", me);\n+\trollback_lock_file(&index_lock);\n+\n+\tif (!clean) {\n+\t\tint i;\n+\t\tstrbuf_addstr(msgbuf, \"\\nConflicts:\\n\\n\");\n+\t\tfor (i = 0; i < active_nr;) {\n+\t\t\tstruct cache_entry *ce = active_cache[i++];\n+\t\t\tif (ce_stage(ce)) {\n+\t\t\t\tstrbuf_addch(msgbuf, '\\t');\n+\t\t\t\tstrbuf_addstr(msgbuf, ce->name);\n+\t\t\t\tstrbuf_addch(msgbuf, '\\n');\n+\t\t\t\twhile (i < active_nr && !strcmp(ce->name,\n+\t\t\t\t\t\tactive_cache[i]->name))\n+\t\t\t\t\ti++;\n+\t\t\t}\n+\t\t}\n+\t\twrite_message(msgbuf, defmsg);\n+\t\tfprintf(stderr, \"Automatic %s failed.%s\\n\",\n+\t\t\tme, help_msg(commit_name));\n+\t\trerere(allow_rerere_auto);\n+\t\texit(1);\n+\t}\n+\twrite_message(msgbuf, defmsg);\n+\tfprintf(stderr, \"Finished one %s.\\n\", me);\n+}\n+\n static int revert_or_cherry_pick(int argc, const char **argv)\n {\n \tunsigned char head[20];\n \tstruct commit *base, *next, *parent;\n-\tint i, index_fd, clean;\n \tchar *oneline, *reencoded_message = NULL;\n \tconst char *message, *encoding;\n \tchar *defmsg = git_pathdup(\"MERGE_MSG\");\n-\tstruct merge_options o;\n-\tstruct tree *result, *next_tree, *base_tree, *head_tree;\n-\tstatic struct lock_file index_lock;\n \tstruct strbuf msgbuf = STRBUF_INIT;\n \n \tgit_config(git_default_config, NULL);\n@@ -382,8 +432,6 @@ static int revert_or_cherry_pick(int argc, const char **argv)\n \n \toneline = get_oneline(message);\n \n-\tindex_fd = hold_locked_index(&index_lock, 1);\n-\n \tif (action == REVERT) {\n \t\tchar *oneline_body = strchr(oneline, ' ');\n \n@@ -411,46 +459,7 @@ static int revert_or_cherry_pick(int argc, const char **argv)\n \t\t}\n \t}\n \n-\tread_cache();\n-\tinit_merge_options(&o);\n-\to.branch1 = \"HEAD\";\n-\to.branch2 = oneline;\n-\n-\thead_tree = parse_tree_indirect(head);\n-\tnext_tree = next ? next->tree : empty_tree();\n-\tbase_tree = base ? base->tree : empty_tree();\n-\n-\tclean = merge_trees(&o,\n-\t\t\t    head_tree,\n-\t\t\t    next_tree, base_tree, &result);\n-\n-\tif (active_cache_changed &&\n-\t    (write_cache(index_fd, active_cache, active_nr) ||\n-\t     commit_locked_index(&index_lock)))\n-\t\tdie(\"%s: Unable to write new index file\", me);\n-\trollback_lock_file(&index_lock);\n-\n-\tif (!clean) {\n-\t\tstrbuf_addstr(&msgbuf, \"\\nConflicts:\\n\\n\");\n-\t\tfor (i = 0; i < active_nr;) {\n-\t\t\tstruct cache_entry *ce = active_cache[i++];\n-\t\t\tif (ce_stage(ce)) {\n-\t\t\t\tstrbuf_addch(&msgbuf, '\\t');\n-\t\t\t\tstrbuf_addstr(&msgbuf, ce->name);\n-\t\t\t\tstrbuf_addch(&msgbuf, '\\n');\n-\t\t\t\twhile (i < active_nr && !strcmp(ce->name,\n-\t\t\t\t\t\tactive_cache[i]->name))\n-\t\t\t\t\ti++;\n-\t\t\t}\n-\t\t}\n-\t\twrite_message(&msgbuf, defmsg);\n-\t\tfprintf(stderr, \"Automatic %s failed.%s\\n\",\n-\t\t\tme, help_msg(commit_name));\n-\t\trerere(allow_rerere_auto);\n-\t\texit(1);\n-\t}\n-\twrite_message(&msgbuf, defmsg);\n-\tfprintf(stderr, \"Finished one %s.\\n\", me);\n+\tdo_recursive_merge(base, next, head, oneline, &msgbuf, defmsg);\n \n \t/*\n \t *\n-- \n1.7.0.2.398.g89bc8ce\n"},{"id":"137772","messageId":"20100325045818.14832.28912.chriscool@tuxfamily.org","threadId":"23171","inReplyTo":"20100325045519.14832.65964.chriscool@tuxfamily.org","subject":"[RFC/PATCH 3/5] merge: refactor code that calls \"git merge-STRATEGY\"","fromName":"Christian Couder","fromEmail":"chriscool@tuxfamily.org","sentAt":"2010-03-25T04:58:15Z","receivedAt":"2010-03-25T04:58:15Z","isPatch":true,"sender":{"key":"christian.couder@gmail.com","avatar":"https://avatars.githubusercontent.com/u/208954?v=4"},"body":"In the try_merge_strategy() function, when the strategy is \"recursive\"\nor \"subtree\", the merge_recursive() function is called.\nOtherwise we launch a \"git merge-STRATEGY\" process.\n\nTo make it possible to reuse code that launches a \"git merge-STRATEGY\"\nprocess, this patch refactors this code into a new try_merge_command()\nfunction.\n\nSigned-off-by: Christian Couder <chriscool@tuxfamily.org>\n---\n builtin/merge.c |   81 ++++++++++++++++++++++++++++++------------------------\n 1 files changed, 45 insertions(+), 36 deletions(-)\n\ndiff --git a/builtin/merge.c b/builtin/merge.c\nindex c043066..f163d53 100644\n--- a/builtin/merge.c\n+++ b/builtin/merge.c\n@@ -548,13 +548,53 @@ static void write_tree_trivial(unsigned char *sha1)\n \t\tdie(\"git write-tree failed to write a tree\");\n }\n \n-static int try_merge_strategy(const char *strategy, struct commit_list *common,\n-\t\t\t      const char *head_arg)\n+static int try_merge_command(const char *strategy, struct commit_list *common,\n+\t\t\t     const char *head_arg, struct commit_list *remotes)\n {\n \tconst char **args;\n \tint i = 0, x = 0, ret;\n \tstruct commit_list *j;\n \tstruct strbuf buf = STRBUF_INIT;\n+\n+\targs = xmalloc((4 + xopts_nr + commit_list_count(common) +\n+\t\t\tcommit_list_count(remotes)) * sizeof(char *));\n+\tstrbuf_addf(&buf, \"merge-%s\", strategy);\n+\targs[i++] = buf.buf;\n+\tfor (x = 0; x < xopts_nr; x++) {\n+\t\tchar *s = xmalloc(strlen(xopts[x])+2+1);\n+\t\tstrcpy(s, \"--\");\n+\t\tstrcpy(s+2, xopts[x]);\n+\t\targs[i++] = s;\n+\t}\n+\tfor (j = common; j; j = j->next)\n+\t\targs[i++] = xstrdup(sha1_to_hex(j->item->object.sha1));\n+\targs[i++] = \"--\";\n+\targs[i++] = head_arg;\n+\tfor (j = remotes; j; j = j->next)\n+\t\targs[i++] = xstrdup(sha1_to_hex(j->item->object.sha1));\n+\targs[i] = NULL;\n+\tret = run_command_v_opt(args, RUN_GIT_CMD);\n+\tstrbuf_release(&buf);\n+\ti = 1;\n+\tfor (x = 0; x < xopts_nr; x++)\n+\t\tfree((void *)args[i++]);\n+\tfor (j = common; j; j = j->next)\n+\t\tfree((void *)args[i++]);\n+\ti += 2;\n+\tfor (j = remotes; j; j = j->next)\n+\t\tfree((void *)args[i++]);\n+\tfree(args);\n+\tdiscard_cache();\n+\tif (read_cache() < 0)\n+\t\tdie(\"failed to read the cache\");\n+\tresolve_undo_clear();\n+\n+\treturn ret;\n+}\n+\n+static int try_merge_strategy(const char *strategy, struct commit_list *common,\n+\t\t\t      const char *head_arg)\n+{\n \tint index_fd;\n \tstruct lock_file *lock = xcalloc(1, sizeof(struct lock_file));\n \n@@ -567,12 +607,13 @@ static int try_merge_strategy(const char *strategy, struct commit_list *common,\n \trollback_lock_file(lock);\n \n \tif (!strcmp(strategy, \"recursive\") || !strcmp(strategy, \"subtree\")) {\n-\t\tint clean;\n+\t\tint clean, x = 0;\n \t\tstruct commit *result;\n \t\tstruct lock_file *lock = xcalloc(1, sizeof(struct lock_file));\n \t\tint index_fd;\n \t\tstruct commit_list *reversed = NULL;\n \t\tstruct merge_options o;\n+\t\tstruct commit_list *j;\n \n \t\tif (remoteheads->next) {\n \t\t\terror(\"Not handling anything other than two heads merge.\");\n@@ -612,39 +653,7 @@ static int try_merge_strategy(const char *strategy, struct commit_list *common,\n \t\trollback_lock_file(lock);\n \t\treturn clean ? 0 : 1;\n \t} else {\n-\t\targs = xmalloc((4 + xopts_nr + commit_list_count(common) +\n-\t\t\t\t\tcommit_list_count(remoteheads)) * sizeof(char *));\n-\t\tstrbuf_addf(&buf, \"merge-%s\", strategy);\n-\t\targs[i++] = buf.buf;\n-\t\tfor (x = 0; x < xopts_nr; x++) {\n-\t\t\tchar *s = xmalloc(strlen(xopts[x])+2+1);\n-\t\t\tstrcpy(s, \"--\");\n-\t\t\tstrcpy(s+2, xopts[x]);\n-\t\t\targs[i++] = s;\n-\t\t}\n-\t\tfor (j = common; j; j = j->next)\n-\t\t\targs[i++] = xstrdup(sha1_to_hex(j->item->object.sha1));\n-\t\targs[i++] = \"--\";\n-\t\targs[i++] = head_arg;\n-\t\tfor (j = remoteheads; j; j = j->next)\n-\t\t\targs[i++] = xstrdup(sha1_to_hex(j->item->object.sha1));\n-\t\targs[i] = NULL;\n-\t\tret = run_command_v_opt(args, RUN_GIT_CMD);\n-\t\tstrbuf_release(&buf);\n-\t\ti = 1;\n-\t\tfor (x = 0; x < xopts_nr; x++)\n-\t\t\tfree((void *)args[i++]);\n-\t\tfor (j = common; j; j = j->next)\n-\t\t\tfree((void *)args[i++]);\n-\t\ti += 2;\n-\t\tfor (j = remoteheads; j; j = j->next)\n-\t\t\tfree((void *)args[i++]);\n-\t\tfree(args);\n-\t\tdiscard_cache();\n-\t\tif (read_cache() < 0)\n-\t\t\tdie(\"failed to read the cache\");\n-\t\tresolve_undo_clear();\n-\t\treturn ret;\n+\t\treturn try_merge_command(strategy, common, head_arg, remoteheads);\n \t}\n }\n \n-- \n1.7.0.2.398.g89bc8ce\n"},{"id":"137773","messageId":"20100325045818.14832.7391.chriscool@tuxfamily.org","threadId":"23171","inReplyTo":"20100325045519.14832.65964.chriscool@tuxfamily.org","subject":"[RFC/PATCH 4/5] merge: make function try_merge_command non static","fromName":"Christian Couder","fromEmail":"chriscool@tuxfamily.org","sentAt":"2010-03-25T04:58:16Z","receivedAt":"2010-03-25T04:58:16Z","isPatch":true,"sender":{"key":"christian.couder@gmail.com","avatar":"https://avatars.githubusercontent.com/u/208954?v=4"},"body":"and while at it let's move declaration of checkout_fast_forward()\ninto \"merge-recursive.h\" instead of \"cache.h\"\n\nSigned-off-by: Christian Couder <chriscool@tuxfamily.org>\n---\n builtin/merge.c   |    4 ++--\n cache.h           |    3 ---\n merge-recursive.h |    4 ++++\n 3 files changed, 6 insertions(+), 5 deletions(-)\n\ndiff --git a/builtin/merge.c b/builtin/merge.c\nindex f163d53..fc240f9 100644\n--- a/builtin/merge.c\n+++ b/builtin/merge.c\n@@ -548,8 +548,8 @@ static void write_tree_trivial(unsigned char *sha1)\n \t\tdie(\"git write-tree failed to write a tree\");\n }\n \n-static int try_merge_command(const char *strategy, struct commit_list *common,\n-\t\t\t     const char *head_arg, struct commit_list *remotes)\n+int try_merge_command(const char *strategy, struct commit_list *common,\n+\t\t      const char *head_arg, struct commit_list *remotes)\n {\n \tconst char **args;\n \tint i = 0, x = 0, ret;\ndiff --git a/cache.h b/cache.h\nindex ded3090..f7e501e 100644\n--- a/cache.h\n+++ b/cache.h\n@@ -1056,7 +1056,4 @@ void overlay_tree_on_cache(const char *tree_name, const char *prefix);\n char *alias_lookup(const char *alias);\n int split_cmdline(char *cmdline, const char ***argv);\n \n-/* builtin/merge.c */\n-int checkout_fast_forward(const unsigned char *from, const unsigned char *to);\n-\n #endif /* CACHE_H */\ndiff --git a/merge-recursive.h b/merge-recursive.h\nindex be8410a..8640c00 100644\n--- a/merge-recursive.h\n+++ b/merge-recursive.h\n@@ -53,4 +53,8 @@ int merge_recursive_generic(struct merge_options *o,\n void init_merge_options(struct merge_options *o);\n struct tree *write_tree_from_memory(struct merge_options *o);\n \n+/* builtin/merge.c */\n+int checkout_fast_forward(const unsigned char *from, const unsigned char *to);\n+int try_merge_command(const char *strategy, struct commit_list *common, const char *head_arg, struct commit_list *remotes);\n+\n #endif\n-- \n1.7.0.2.398.g89bc8ce\n"},{"id":"137774","messageId":"20100325045818.14832.74751.chriscool@tuxfamily.org","threadId":"23171","inReplyTo":"20100325045519.14832.65964.chriscool@tuxfamily.org","subject":"[RFC/PATCH 5/5] revert: add \"--strategy\" option to choose merge strategy","fromName":"Christian Couder","fromEmail":"chriscool@tuxfamily.org","sentAt":"2010-03-25T04:58:17Z","receivedAt":"2010-03-25T04:58:17Z","isPatch":true,"sender":{"key":"christian.couder@gmail.com","avatar":"https://avatars.githubusercontent.com/u/208954?v=4"},"body":"This patch makes it possible to use a different merge strategy when\ncherry-picking. This is usefull mainly for debugging purposes as it\nallows to see if some failures are caused by the merge strategy used or\nnot.\n\nSigned-off-by: Christian Couder <chriscool@tuxfamily.org>\n---\n builtin/revert.c |   21 ++++++++++++++++++++-\n 1 files changed, 20 insertions(+), 1 deletions(-)\n\ndiff --git a/builtin/revert.c b/builtin/revert.c\nindex 054f442..808eb53 100644\n--- a/builtin/revert.c\n+++ b/builtin/revert.c\n@@ -43,6 +43,7 @@ static const char *commit_name;\n static int allow_rerere_auto;\n \n static const char *me;\n+static const char *strategy;\n \n #define GIT_REFLOG_ACTION \"GIT_REFLOG_ACTION\"\n \n@@ -60,6 +61,7 @@ static void parse_args(int argc, const char **argv)\n \t\tOPT_BOOLEAN('s', \"signoff\", &signoff, \"add Signed-off-by:\"),\n \t\tOPT_INTEGER('m', \"mainline\", &mainline, \"parent number\"),\n \t\tOPT_RERERE_AUTOUPDATE(&allow_rerere_auto),\n+\t\tOPT_STRING(0, \"strategy\", &strategy, \"strategy\", \"merge strategy\"),\n \t\tOPT_END(),\n \t\tOPT_END(),\n \t\tOPT_END(),\n@@ -459,7 +461,24 @@ static int revert_or_cherry_pick(int argc, const char **argv)\n \t\t}\n \t}\n \n-\tdo_recursive_merge(base, next, head, oneline, &msgbuf, defmsg);\n+\tif (!strategy || !strcmp(strategy, \"recursive\") || action == REVERT)\n+\t\tdo_recursive_merge(base, next, head, oneline, &msgbuf, defmsg);\n+\telse {\n+\t\tint res;\n+\t\tstruct commit_list *common = NULL;\n+\t\tstruct commit_list *remotes = NULL;\n+\t\twrite_message(&msgbuf, defmsg);\n+\t\tcommit_list_insert(base, &common);\n+\t\tcommit_list_insert(next, &remotes);\n+\t\tres = try_merge_command(strategy, common,\n+\t\t\t\t\tsha1_to_hex(head), remotes);\n+\t\tif (res) {\n+\t\t\tfprintf(stderr, \"Automatic %s with strategy %s failed.%s\\n\",\n+\t\t\t\tme, strategy, help_msg(commit_name));\n+\t\t\trerere(allow_rerere_auto);\n+\t\t\texit(1);\n+\t\t}\n+\t}\n \n \t/*\n \t *\n-- \n1.7.0.2.398.g89bc8ce\n"}]}