{"thread":{"id":"50964","subject":"[PATCH/RFC 0/2] rebase: add switches to control todo-list setup","startedAt":"2019-04-22T00:07:33Z","lastAt":"2019-04-23T02:20:51Z","messageCount":11,"participants":["Phil Hord","Junio C Hamano","Phillip Wood","Denton Liu"],"isPatch":true,"patchVersion":1,"patchTotal":2},"messages":[{"id":"374208","messageId":"20190422000712.13584-1-phil.hord@gmail.com","threadId":"50964","inReplyTo":null,"subject":"[PATCH/RFC 0/2] rebase: add switches to control todo-list setup","fromName":"Phil Hord","fromEmail":"phil.hord@gmail.com","sentAt":"2019-04-22T00:07:10Z","receivedAt":"2019-04-22T00:07:33Z","isPatch":true,"sender":{"key":"phil.hord@gmail.com","avatar":"https://avatars.githubusercontent.com/u/123908?v=4"},"body":"From: Phil Hord <phil.hord@gmail.com>\n\nI have a local patch to rebase--interactive.sh that adds \"edit\" switches\nto rebase, permitting me to say, for example,\n\n    git rebase --drop $sha\n\nThis command creates a todo-list but drops the mentioned commit from the\nlist by changing the \"pick\" to \"drop\". Other switches let me edit or\nreword a commit in my local history, greatly simplifying my branch\ngrooming workflow.\n\nWith the conversion to rebase.c (yay!) my tools are going away. I'm\nporting them to the rewritten rebase*.c and I want to submit them here.\nBut rebase*.c is still in flux, and my changes have many conflicts with\nother inflight changes. I'm happy to wait for those, but in the\nmeantime, I'd appreciate some feedback on the utility and acceptability\nof my plan.\n\nHere's my patch series as it stands today. It lacks documentation and\ntests, but it mostly works. Errors are not handled gracefully, but this\nwill be rectified after I rebase onto pw/rebase-i-internal-rfc.\n\nCurrently it supports these switches:\n\n    usage: git rebase [-i] [options] [--exec <cmd>] ...\n       :\n    --break <revision>    stop before the mentioned ref\n    --drop <revision>     drop the mentioned ref from the todo list\n    --edit <revision>     edit the mentioned ref instead of picking it\n    --reword <revision>   reword the mentioned ref instead of picking it\n\nI have plans to add these, but I don't like how their \"onto\" will be\ncontrolled. More thinking is needed here.\n\n    --fixup <revision>    fixup the mentioned ref instead of picking it\n    --squash <revision>   squash the mentioned ref instead of picking it\n    --pick <revision>     pick the mentioned ref onto the start of the list\n\n\nPhil Hord (2):\n  rebase: add switches for drop, edit and reword\n  rebase: add --break switch\n\n builtin/rebase--interactive.c |  49 +++++++++++++++-\n builtin/rebase.c              |  48 ++++++++++++++++\n sequencer.c                   | 105 +++++++++++++++++++++++++++++-----\n sequencer.h                   |  22 ++++++-\n 4 files changed, 207 insertions(+), 17 deletions(-)\n\n--\n2.20.1\n"},{"id":"374209","messageId":"20190422000712.13584-2-phil.hord@gmail.com","threadId":"50964","inReplyTo":"20190422000712.13584-1-phil.hord@gmail.com","subject":"[PATCH/RFC 1/2] rebase: add switches for drop, edit and reword","fromName":"Phil Hord","fromEmail":"phil.hord@gmail.com","sentAt":"2019-04-22T00:07:11Z","receivedAt":"2019-04-22T00:07:41Z","isPatch":true,"sender":{"key":"phil.hord@gmail.com","avatar":"https://avatars.githubusercontent.com/u/123908?v=4"},"body":"From: Phil Hord <phil.hord@gmail.com>\n\nA common use for rebase is to drop or edit some commit in a\nfeature branch.  The commit to be changed is known in advance,\nso a user will say 'git rebase -i that-commit^' to see the todo\nlist in her editor.  Then she will change the command on the line\nfor \"that-commit\" to edit instead of pick, or delete the line\naltogether.\n\nThis involves 'git log' to find the commit in the first place,\nthe cli to start the rebase, the editor to make a single change, and\nsome mental context switch from \"that-commit\" to its hash so she can\nbe sure to edit the correct line.\n\nIntroduce some new \"edit-todo\" switches to the rebase command to\nsimplify this cycle.  Add 3 new switches to support common\ntodo-list operations.\n    '--drop <ref>' to drop a specific commit,\n    '--edit <ref>' to edit a specific commit,\n    '--reword <ref>' to reword a specific commit,\n\nAllow each switch to be used mutliple times on the command line so more\nthan one ref could be dropped, for example.\n\nComplain and abort the rebase if a mentioned ref is not in the\ntodo-list in the first place so the user doesn't get a wrong idea\nfrom a successful 'git rebase --drop foo' that did nothing since\nno foo was encountered.\n\nSigned-off-by: Phil Hord <phil.hord@gmail.com>\n---\n builtin/rebase--interactive.c | 46 +++++++++++++++-\n builtin/rebase.c              | 44 ++++++++++++++++\n sequencer.c                   | 98 ++++++++++++++++++++++++++++++-----\n sequencer.h                   | 21 +++++++-\n 4 files changed, 192 insertions(+), 17 deletions(-)\n\ndiff --git a/builtin/rebase--interactive.c b/builtin/rebase--interactive.c\nindex 4535523bf5..9285d05443 100644\n--- a/builtin/rebase--interactive.c\n+++ b/builtin/rebase--interactive.c\n@@ -140,6 +140,34 @@ static int get_revision_ranges(const char *upstream, const char *onto,\n \treturn 0;\n }\n\n+static int resolve_commit_list(const struct string_list *str,\n+\t\t\t       struct commit_list **revs)\n+{\n+\tstruct object_id oid;\n+\tint i;\n+\tfor (i = 0; i < str->nr; i++) {\n+\t\tstruct commit *r;\n+\t\tconst char * ref = str->items[i].string;\n+\t\tif (get_oid(ref, &oid))\n+\t\t\treturn error(_(\"cannot resolve %s\"), ref);\n+\n+\t\tr = lookup_commit_reference(the_repository, &oid);\n+\t\tif (!r)\n+\t\t\treturn error(_(\"%s is not a commit\"), ref);\n+\n+\t\tcommit_list_insert(r, revs);\n+\t\tstr->items[i].util = &(*revs)->item->object.oid;\n+\t}\n+\treturn 0;\n+}\n+\n+static int resolve_edits_commit_list(struct sequence_edits *edits)\n+{\n+\treturn resolve_commit_list(&edits->drop, &edits->revs) ||\n+\t       resolve_commit_list(&edits->edit, &edits->revs) ||\n+\t       resolve_commit_list(&edits->reword, &edits->revs);\n+}\n+\n static int init_basic_state(struct replay_opts *opts, const char *head_name,\n \t\t\t    const char *onto, const char *orig_head)\n {\n@@ -163,6 +191,7 @@ static int do_interactive_rebase(struct replay_opts *opts, unsigned flags,\n \t\t\t\t const char *onto, const char *onto_name,\n \t\t\t\t const char *squash_onto, const char *head_name,\n \t\t\t\t const char *restrict_revision, char *raw_strategies,\n+\t\t\t\t struct sequence_edits *edits,\n \t\t\t\t struct string_list *commands, unsigned autosquash)\n {\n \tint ret;\n@@ -197,7 +226,7 @@ static int do_interactive_rebase(struct replay_opts *opts, unsigned flags,\n\n \tret = sequencer_make_script(the_repository, &todo_list.buf,\n \t\t\t\t    make_script_args.argc, make_script_args.argv,\n-\t\t\t\t    flags);\n+\t\t\t\t    edits, flags);\n\n \tif (ret)\n \t\terror(_(\"could not generate todo list\"));\n@@ -233,6 +262,7 @@ int cmd_rebase__interactive(int argc, const char **argv, const char *prefix)\n \t\t*squash_onto = NULL, *upstream = NULL, *head_name = NULL,\n \t\t*switch_to = NULL, *cmd = NULL;\n \tstruct string_list commands = STRING_LIST_INIT_DUP;\n+\tstruct sequence_edits edits = SEQUENCE_EDITS_INIT;\n \tchar *raw_strategies = NULL;\n \tenum {\n \t\tNONE = 0, CONTINUE, SKIP, EDIT_TODO, SHOW_CURRENT_PATCH,\n@@ -272,6 +302,15 @@ int cmd_rebase__interactive(int argc, const char **argv, const char *prefix)\n \t\t\t   N_(\"restrict-revision\"), N_(\"restrict revision\")),\n \t\tOPT_STRING(0, \"squash-onto\", &squash_onto, N_(\"squash-onto\"),\n \t\t\t   N_(\"squash onto\")),\n+\t\tOPT_STRING_LIST(0, \"drop\", &edits.drop, N_(\"revision\"),\n+\t\t\t\tN_(\"drop the mentioned ref from the \"\n+\t\t\t\t   \"todo list\")),\n+\t\tOPT_STRING_LIST(0, \"edit\", &edits.edit, N_(\"revision\"),\n+\t\t\t\tN_(\"edit the mentioned ref instead of \"\n+\t\t\t\t   \"picking it\")),\n+\t\tOPT_STRING_LIST(0, \"reword\", &edits.reword, N_(\"revision\"),\n+\t\t\t\tN_(\"reword the mentioned ref instead of \"\n+\t\t\t\t   \"picking it\")),\n \t\tOPT_STRING(0, \"upstream\", &upstream, N_(\"upstream\"),\n \t\t\t   N_(\"the upstream commit\")),\n \t\tOPT_STRING(0, \"head-name\", &head_name, N_(\"head-name\"), N_(\"head name\")),\n@@ -325,6 +364,8 @@ int cmd_rebase__interactive(int argc, const char **argv, const char *prefix)\n \t\tstring_list_remove_empty_items(&commands, 0);\n \t}\n\n+\tresolve_edits_commit_list(&edits);\n+\n \tswitch (command) {\n \tcase NONE:\n \t\tif (!onto && !upstream)\n@@ -332,7 +373,7 @@ int cmd_rebase__interactive(int argc, const char **argv, const char *prefix)\n\n \t\tret = do_interactive_rebase(&opts, flags, switch_to, upstream, onto,\n \t\t\t\t\t    onto_name, squash_onto, head_name, restrict_revision,\n-\t\t\t\t\t    raw_strategies, &commands, autosquash);\n+\t\t\t\t\t    raw_strategies, &edits, &commands, autosquash);\n \t\tbreak;\n \tcase SKIP: {\n \t\tstruct string_list merge_rr = STRING_LIST_INIT_DUP;\n@@ -373,5 +414,6 @@ int cmd_rebase__interactive(int argc, const char **argv, const char *prefix)\n \t}\n\n \tstring_list_clear(&commands, 0);\n+\tfree_sequence_edits(&edits);\n \treturn !!ret;\n }\ndiff --git a/builtin/rebase.c b/builtin/rebase.c\nindex 2e41ad5644..a8101630cf 100644\n--- a/builtin/rebase.c\n+++ b/builtin/rebase.c\n@@ -78,6 +78,7 @@ struct rebase_options {\n \tchar *gpg_sign_opt;\n \tint autostash;\n \tchar *cmd;\n+\tchar *edit_switches;\n \tint allow_empty_message;\n \tint rebase_merges, rebase_cousins;\n \tchar *strategy, *strategy_opts;\n@@ -694,6 +695,8 @@ static int run_specific_rebase(struct rebase_options *opts)\n \t\t\t\t\t opts->switch_to);\n \t\tif (opts->cmd)\n \t\t\targv_array_pushf(&child.args, \"--cmd=%s\", opts->cmd);\n+\t\tif (opts->edit_switches)\n+\t\t\targv_array_split(&child.args, opts->edit_switches);\n \t\tif (opts->allow_empty_message)\n \t\t\targv_array_push(&child.args, \"--allow-empty-message\");\n \t\tif (opts->allow_rerere_autoupdate > 0)\n@@ -711,6 +714,9 @@ static int run_specific_rebase(struct rebase_options *opts)\n \t\tgoto finished_rebase;\n \t}\n\n+\tif (opts->edit_switches)\n+\t\tBUG(\"Unexpected rebase type with switches %d\", opts->type);\n+\n \tif (opts->type == REBASE_AM) {\n \t\tstatus = run_am(opts);\n \t\tgoto finished_rebase;\n@@ -988,6 +994,28 @@ static int check_exec_cmd(const char *cmd)\n \treturn 0;\n }\n\n+static void forward_switches(struct rebase_options *options,\n+\t\t\t     const char *sw_name,\n+\t\t\t     struct string_list *values)\n+{\n+\tint i;\n+\tstruct strbuf buf = STRBUF_INIT;\n+\n+\tif (!values->nr)\n+\t\treturn;\n+\n+\timply_interactive(options, sw_name);\n+\n+\tif (!!options->edit_switches)\n+\t\tstrbuf_addf(&buf, \"%s \", options->edit_switches);\n+\n+\tfor (i = 0; i < values->nr; i++)\n+\t\tstrbuf_addf(&buf, \"%s %s \", sw_name, values->items[i].string);\n+\tstrbuf_rtrim(&buf);\n+\toptions->edit_switches = xstrdup(buf.buf);\n+\n+\tstrbuf_release(&buf);\n+}\n\n int cmd_rebase(int argc, const char **argv, const char *prefix)\n {\n@@ -1025,6 +1053,9 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)\n \t\t\t\t\t      NULL };\n \tconst char *gpg_sign = NULL;\n \tstruct string_list exec = STRING_LIST_INIT_NODUP;\n+\tstruct string_list reword = STRING_LIST_INIT_NODUP;\n+\tstruct string_list edit = STRING_LIST_INIT_NODUP;\n+\tstruct string_list drop = STRING_LIST_INIT_NODUP;\n \tconst char *rebase_merges = NULL;\n \tint fork_point = -1;\n \tstruct string_list strategy_options = STRING_LIST_INIT_NODUP;\n@@ -1107,6 +1138,15 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)\n \t\tOPT_STRING_LIST('x', \"exec\", &exec, N_(\"exec\"),\n \t\t\t\tN_(\"add exec lines after each commit of the \"\n \t\t\t\t   \"editable list\")),\n+\t\tOPT_STRING_LIST(0, \"drop\", &drop, N_(\"revision\"),\n+\t\t\t\tN_(\"drop the mentioned ref from the \"\n+\t\t\t\t   \"todo list\")),\n+\t\tOPT_STRING_LIST(0, \"edit\", &edit, N_(\"revision\"),\n+\t\t\t\tN_(\"edit the mentioned ref instead of \"\n+\t\t\t\t   \"picking it\")),\n+\t\tOPT_STRING_LIST(0, \"reword\", &reword, N_(\"revision\"),\n+\t\t\t\tN_(\"reword the mentioned ref instead of \"\n+\t\t\t\t   \"picking it\")),\n \t\tOPT_BOOL(0, \"allow-empty-message\",\n \t\t\t &options.allow_empty_message,\n \t\t\t N_(\"allow rebasing commits with empty messages\")),\n@@ -1364,6 +1404,10 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)\n \t\toptions.cmd = xstrdup(buf.buf);\n \t}\n\n+\tforward_switches(&options, \"--drop\", &drop);\n+\tforward_switches(&options, \"--edit\", &edit);\n+\tforward_switches(&options, \"--reword\", &reword);\n+\n \tif (rebase_merges) {\n \t\tif (!*rebase_merges)\n \t\t\t; /* default mode; do nothing */\ndiff --git a/sequencer.c b/sequencer.c\nindex 546f281898..d7384d987c 100644\n--- a/sequencer.c\n+++ b/sequencer.c\n@@ -4259,9 +4259,81 @@ static const char *label_oid(struct object_id *oid, const char *label,\n \treturn string_entry->string;\n }\n\n+void free_sequence_edits(struct sequence_edits *edits)\n+{\n+\tstring_list_clear(&edits->drop, 0);\n+\tstring_list_clear(&edits->edit, 0);\n+\tstring_list_clear(&edits->reword, 0);\n+\tfree_commit_list(edits->revs);\n+}\n+\n+/* Find an unmatched oid in the util pointer of our edit refs. If it's found\n+   reset util to NULL and return 1. */\n+static int consume_oid(const struct object_id *oid,\n+\t\t       const struct string_list *refs)\n+{\n+\tint i;\n+\tfor (i = 0; i < refs->nr; i++)\n+\t\tif (refs->items[i].util && oideq(oid, refs->items[i].util)) {\n+\t\t\trefs->items[i].util = NULL;\n+\t\t\treturn 1;\n+\t\t}\n+\treturn 0;\n+}\n+\n+static int check_unused_refs(const struct string_list *refs)\n+{\n+\tint i;\n+\tfor (i = 0; i < refs->nr; i++)\n+\t\tif (refs->items[i].util)\n+\t\t\treturn error(_(\"did not find '%s' in todo list\"),\n+\t\t\t\t\trefs->items[i].string);\n+\treturn 0;\n+}\n+\n+static int check_unused_edits(const struct sequence_edits *edits)\n+{\n+\treturn check_unused_refs(&edits->drop) ||\n+\t\tcheck_unused_refs(&edits->edit) ||\n+\t\tcheck_unused_refs(&edits->reword);\n+}\n+\n+static void add_todo_cmd(struct strbuf *buf, enum todo_command cmd,\n+\t\t\t      unsigned flags)\n+{\n+\tif (flags & TODO_LIST_ABBREVIATE_CMDS)\n+\t\tstrbuf_addch(buf, command_to_char(cmd));\n+\telse\n+\t\tstrbuf_addstr(buf, command_to_string(cmd));\n+}\n+\n+static void add_todo_cmd_oid(struct strbuf *buf, enum todo_command cmd,\n+\t\t\t     unsigned flags, const struct object_id *oid)\n+{\n+\tadd_todo_cmd(buf, cmd, flags);\n+\tstrbuf_addf(buf, \" %s \", oid_to_hex(oid));\n+}\n+\n+static void add_edit_todo_inst(struct strbuf *buf, const struct object_id *oid,\n+\t\t\t\tconst struct sequence_edits *edits,\n+\t\t\t\tunsigned flags)\n+{\n+\tenum todo_command cmd = TODO_PICK;\n+\n+\tif (consume_oid(oid, &edits->drop))\n+\t\tcmd = TODO_DROP;\n+\telse if (consume_oid(oid, &edits->edit))\n+\t\tcmd = TODO_EDIT;\n+\telse if (consume_oid(oid, &edits->reword))\n+\t\tcmd = TODO_REWORD;\n+\n+\tadd_todo_cmd_oid(buf, cmd, flags, oid);\n+}\n+\n static int make_script_with_merges(struct pretty_print_context *pp,\n-\t\t\t\t   struct rev_info *revs, struct strbuf *out,\n-\t\t\t\t   unsigned flags)\n+\t\t\t\t   struct rev_info *revs,\n+\t\t\t\t   const struct sequence_edits *edits,\n+\t\t\t\t   struct strbuf *out, unsigned flags)\n {\n \tint keep_empty = flags & TODO_LIST_KEEP_EMPTY;\n \tint rebase_cousins = flags & TODO_LIST_REBASE_COUSINS;\n@@ -4277,8 +4349,7 @@ static int make_script_with_merges(struct pretty_print_context *pp,\n \tstruct label_state state = { OIDMAP_INIT, { NULL }, STRBUF_INIT };\n\n \tint abbr = flags & TODO_LIST_ABBREVIATE_CMDS;\n-\tconst char *cmd_pick = abbr ? \"p\" : \"pick\",\n-\t\t*cmd_label = abbr ? \"l\" : \"label\",\n+\tconst char *cmd_label = abbr ? \"l\" : \"label\",\n \t\t*cmd_reset = abbr ? \"t\" : \"reset\",\n \t\t*cmd_merge = abbr ? \"m\" : \"merge\";\n\n@@ -4322,9 +4393,9 @@ static int make_script_with_merges(struct pretty_print_context *pp,\n \t\t\tstrbuf_reset(&buf);\n \t\t\tif (!keep_empty && is_empty)\n \t\t\t\tstrbuf_addf(&buf, \"%c \", comment_line_char);\n-\t\t\tstrbuf_addf(&buf, \"%s %s %s\", cmd_pick,\n-\t\t\t\t    oid_to_hex(&commit->object.oid),\n-\t\t\t\t    oneline.buf);\n+\t\t\tadd_edit_todo_inst(&buf, &commit->object.oid, edits,\n+\t\t\t\t\t   flags);\n+\t\t\tstrbuf_addbuf(&buf, &oneline);\n\n \t\t\tFLEX_ALLOC_STR(entry, string, buf.buf);\n \t\t\toidcpy(&entry->entry.oid, &commit->object.oid);\n@@ -4481,18 +4552,18 @@ static int make_script_with_merges(struct pretty_print_context *pp,\n \thashmap_free(&state.labels, 1);\n \tstrbuf_release(&state.buf);\n\n-\treturn 0;\n+\treturn check_unused_edits(edits);\n }\n\n int sequencer_make_script(struct repository *r, struct strbuf *out, int argc,\n-\t\t\t  const char **argv, unsigned flags)\n+\t\t\t  const char **argv, const struct sequence_edits *edits,\n+\t\t\t  unsigned flags)\n {\n \tchar *format = NULL;\n \tstruct pretty_print_context pp = {0};\n \tstruct rev_info revs;\n \tstruct commit *commit;\n \tint keep_empty = flags & TODO_LIST_KEEP_EMPTY;\n-\tconst char *insn = flags & TODO_LIST_ABBREVIATE_CMDS ? \"p\" : \"pick\";\n \tint rebase_merges = flags & TODO_LIST_REBASE_MERGES;\n\n \trepo_init_revisions(r, &revs, NULL);\n@@ -4524,7 +4595,7 @@ int sequencer_make_script(struct repository *r, struct strbuf *out, int argc,\n \t\treturn error(_(\"make_script: error preparing revisions\"));\n\n \tif (rebase_merges)\n-\t\treturn make_script_with_merges(&pp, &revs, out, flags);\n+\t\treturn make_script_with_merges(&pp, &revs, edits, out, flags);\n\n \twhile ((commit = get_revision(&revs))) {\n \t\tint is_empty  = is_original_commit_empty(commit);\n@@ -4533,12 +4604,11 @@ int sequencer_make_script(struct repository *r, struct strbuf *out, int argc,\n \t\t\tcontinue;\n \t\tif (!keep_empty && is_empty)\n \t\t\tstrbuf_addf(out, \"%c \", comment_line_char);\n-\t\tstrbuf_addf(out, \"%s %s \", insn,\n-\t\t\t    oid_to_hex(&commit->object.oid));\n+\t\tadd_edit_todo_inst(out, &commit->object.oid, edits, flags);\n \t\tpretty_print_commit(&pp, commit, out);\n \t\tstrbuf_addch(out, '\\n');\n \t}\n-\treturn 0;\n+\treturn check_unused_edits(edits);\n }\n\n /*\ndiff --git a/sequencer.h b/sequencer.h\nindex a515ee4457..7887509fea 100644\n--- a/sequencer.h\n+++ b/sequencer.h\n@@ -130,6 +130,24 @@ int sequencer_continue(struct repository *repo, struct replay_opts *opts);\n int sequencer_rollback(struct repository *repo, struct replay_opts *opts);\n int sequencer_remove_state(struct replay_opts *opts);\n\n+/*\n+ * The string_lists here contain the edit refs from the command-line. Each\n+ * string_list_item's util pointer is pointed to the struct object_id * of\n+ * the ref's oid by resolve_oids(), and util is set back to NULL when the\n+ * ref is consumed during the todo-list generation.  After the todo-list is\n+ * generated, any !!util strings were not encountered.\n+ */\n+struct sequence_edits {\n+\tstruct commit_list *revs;\n+\tstruct string_list drop;\n+\tstruct string_list edit;\n+\tstruct string_list reword;\n+};\n+#define SEQUENCE_EDITS_INIT { NULL, STRING_LIST_INIT_NODUP, \\\n+\t\tSTRING_LIST_INIT_NODUP, STRING_LIST_INIT_NODUP }\n+void free_sequence_edits(struct sequence_edits *edits);\n+\n+\n #define TODO_LIST_KEEP_EMPTY (1U << 0)\n #define TODO_LIST_SHORTEN_IDS (1U << 1)\n #define TODO_LIST_ABBREVIATE_CMDS (1U << 2)\n@@ -143,7 +161,8 @@ int sequencer_remove_state(struct replay_opts *opts);\n #define TODO_LIST_APPEND_TODO_HELP (1U << 5)\n\n int sequencer_make_script(struct repository *r, struct strbuf *out, int argc,\n-\t\t\t  const char **argv, unsigned flags);\n+\t\t\t  const char **argv, const struct sequence_edits *edits,\n+\t\t\t  unsigned flags);\n\n void todo_list_add_exec_commands(struct todo_list *todo_list,\n \t\t\t\t struct string_list *commands);\n--\n2.20.1\n"},{"id":"374210","messageId":"20190422000712.13584-3-phil.hord@gmail.com","threadId":"50964","inReplyTo":"20190422000712.13584-1-phil.hord@gmail.com","subject":"[PATCH/RFC 2/2] rebase: add --break switch","fromName":"Phil Hord","fromEmail":"phil.hord@gmail.com","sentAt":"2019-04-22T00:07:12Z","receivedAt":"2019-04-22T00:07:41Z","isPatch":true,"sender":{"key":"phil.hord@gmail.com","avatar":"https://avatars.githubusercontent.com/u/123908?v=4"},"body":"From: Phil Hord <phil.hord@gmail.com>\n\nExpand the rebase edit switches to include the break switch. This\nswitch lets the user add a \"break\" instruction to the todo-list\nbefore the mentioned reference.\n\nThis switch is a little different from the ones added so far because\nit adds a new instruction between commits in the todo-list instead of\nchanging the command used to include a commit. It is a little like\n\"exec\" in this regard, except it doesn't add the command after every\ncommit.\n\nIt is not immediately clear whether we should add the break command\nbefore or after the referenced commit.  That is, when the user says\n'--break ref', does she mean to break after ref is picked or before\nit?  The answer comes when we realize that a 'break' after a ref\nis functionally the same as '--edit ref'. Since the user didn't\nsay '--edit ref', clearly she must have wanted to break _before_ ref\nis picked.  So, insert the break before the mentioned ref.\n\nAnnoyingly, however, when git stops at a break, it declares that the\nprevious commit is the one we stopped on, which is always different\nfrom the one the user specified. Does anyone care?  Should --break\neffectively be an alias for --edit?\n\n    '--break <ref>' to stop the rebase before the mentioned commit\n\nSigned-off-by: Phil Hord <phil.hord@gmail.com>\n---\n builtin/rebase--interactive.c | 3 +++\n builtin/rebase.c              | 4 ++++\n sequencer.c                   | 7 +++++++\n sequencer.h                   | 1 +\n 4 files changed, 15 insertions(+)\n\ndiff --git a/builtin/rebase--interactive.c b/builtin/rebase--interactive.c\nindex 9285d05443..a81fa9c1c5 100644\n--- a/builtin/rebase--interactive.c\n+++ b/builtin/rebase--interactive.c\n@@ -164,6 +164,7 @@ static int resolve_commit_list(const struct string_list *str,\n static int resolve_edits_commit_list(struct sequence_edits *edits)\n {\n \treturn resolve_commit_list(&edits->drop, &edits->revs) ||\n+\t       resolve_commit_list(&edits->breaks, &edits->revs) ||\n \t       resolve_commit_list(&edits->edit, &edits->revs) ||\n \t       resolve_commit_list(&edits->reword, &edits->revs);\n }\n@@ -302,6 +303,8 @@ int cmd_rebase__interactive(int argc, const char **argv, const char *prefix)\n \t\t\t   N_(\"restrict-revision\"), N_(\"restrict revision\")),\n \t\tOPT_STRING(0, \"squash-onto\", &squash_onto, N_(\"squash-onto\"),\n \t\t\t   N_(\"squash onto\")),\n+\t\tOPT_STRING_LIST(0, \"break\", &edits.breaks, N_(\"revision\"),\n+\t\t\t\tN_(\"stop before the mentioned ref\")),\n \t\tOPT_STRING_LIST(0, \"drop\", &edits.drop, N_(\"revision\"),\n \t\t\t\tN_(\"drop the mentioned ref from the \"\n \t\t\t\t   \"todo list\")),\ndiff --git a/builtin/rebase.c b/builtin/rebase.c\nindex a8101630cf..02079c4172 100644\n--- a/builtin/rebase.c\n+++ b/builtin/rebase.c\n@@ -1053,6 +1053,7 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)\n \t\t\t\t\t      NULL };\n \tconst char *gpg_sign = NULL;\n \tstruct string_list exec = STRING_LIST_INIT_NODUP;\n+\tstruct string_list breaks = STRING_LIST_INIT_NODUP;\n \tstruct string_list reword = STRING_LIST_INIT_NODUP;\n \tstruct string_list edit = STRING_LIST_INIT_NODUP;\n \tstruct string_list drop = STRING_LIST_INIT_NODUP;\n@@ -1138,6 +1139,8 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)\n \t\tOPT_STRING_LIST('x', \"exec\", &exec, N_(\"exec\"),\n \t\t\t\tN_(\"add exec lines after each commit of the \"\n \t\t\t\t   \"editable list\")),\n+\t\tOPT_STRING_LIST(0, \"break\", &breaks, N_(\"revision\"),\n+\t\t\t\tN_(\"stop before the mentioned ref\")),\n \t\tOPT_STRING_LIST(0, \"drop\", &drop, N_(\"revision\"),\n \t\t\t\tN_(\"drop the mentioned ref from the \"\n \t\t\t\t   \"todo list\")),\n@@ -1404,6 +1407,7 @@ int cmd_rebase(int argc, const char **argv, const char *prefix)\n \t\toptions.cmd = xstrdup(buf.buf);\n \t}\n\n+\tforward_switches(&options, \"--break\", &breaks);\n \tforward_switches(&options, \"--drop\", &drop);\n \tforward_switches(&options, \"--edit\", &edit);\n \tforward_switches(&options, \"--reword\", &reword);\ndiff --git a/sequencer.c b/sequencer.c\nindex d7384d987c..4a1a371757 100644\n--- a/sequencer.c\n+++ b/sequencer.c\n@@ -4261,6 +4261,7 @@ static const char *label_oid(struct object_id *oid, const char *label,\n\n void free_sequence_edits(struct sequence_edits *edits)\n {\n+\tstring_list_clear(&edits->breaks, 0);\n \tstring_list_clear(&edits->drop, 0);\n \tstring_list_clear(&edits->edit, 0);\n \tstring_list_clear(&edits->reword, 0);\n@@ -4294,6 +4295,7 @@ static int check_unused_refs(const struct string_list *refs)\n static int check_unused_edits(const struct sequence_edits *edits)\n {\n \treturn check_unused_refs(&edits->drop) ||\n+\t\tcheck_unused_refs(&edits->breaks) ||\n \t\tcheck_unused_refs(&edits->edit) ||\n \t\tcheck_unused_refs(&edits->reword);\n }\n@@ -4320,6 +4322,11 @@ static void add_edit_todo_inst(struct strbuf *buf, const struct object_id *oid,\n {\n \tenum todo_command cmd = TODO_PICK;\n\n+\tif (consume_oid(oid, &edits->breaks)) {\n+\t\tadd_todo_cmd(buf, TODO_BREAK, flags);\n+\t\tstrbuf_addstr(buf, \"\\n\");\n+\t}\n+\n \tif (consume_oid(oid, &edits->drop))\n \t\tcmd = TODO_DROP;\n \telse if (consume_oid(oid, &edits->edit))\ndiff --git a/sequencer.h b/sequencer.h\nindex 7887509fea..310829f222 100644\n--- a/sequencer.h\n+++ b/sequencer.h\n@@ -139,6 +139,7 @@ int sequencer_remove_state(struct replay_opts *opts);\n  */\n struct sequence_edits {\n \tstruct commit_list *revs;\n+\tstruct string_list breaks;\n \tstruct string_list drop;\n \tstruct string_list edit;\n \tstruct string_list reword;\n--\n2.20.1\n"},{"id":"374213","messageId":"xmqqk1fm9712.fsf@gitster-ct.c.googlers.com","threadId":"50964","inReplyTo":"20190422000712.13584-1-phil.hord@gmail.com","subject":"Re: [PATCH/RFC 0/2] rebase: add switches to control todo-list setup","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2019-04-22T01:13:13Z","receivedAt":"2019-04-22T01:13:18Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Phil Hord <phil.hord@gmail.com> writes:\n\n> Currently it supports these switches:\n>\n>     usage: git rebase [-i] [options] [--exec <cmd>] ...\n>        :\n>     --break <revision>    stop before the mentioned ref\n>     --drop <revision>     drop the mentioned ref from the todo list\n>     --edit <revision>     edit the mentioned ref instead of picking it\n>     --reword <revision>   reword the mentioned ref instead of picking it\n>\n> I have plans to add these, but I don't like how their \"onto\" will be\n> controlled. More thinking is needed here.\n>\n>     --fixup <revision>    fixup the mentioned ref instead of picking it\n>     --squash <revision>   squash the mentioned ref instead of picking it\n>     --pick <revision>     pick the mentioned ref onto the start of the list\n\nYeah, I can see that it may be very useful to shorten the sequence\nto (1) learn what commits there are and think what you want to do\nwith each of them by looking at \"git log --oneline master..\" output\nand then to (2) look at and edit todo in \"git rebase -i master\".\n\nI personally would be fine without the step (1), as what \"rebase -i\"\ngives me in step (2) essentially is \"log --oneline master..\".  So I\nam not quite getting in what way these command line options would be\nmore useful than without them, though, especially since I do not see\nhow well an option to reorder commits would fit with the way you\nstructured your UI.\n\nHaving already said that, if I were to get in the habit of looking\nat \"log\" first to decide and then running \"rebase -i\" after I made\nup my mind, using a tweaked \"log --oneline\" output that looks\nperhaps like this:\n\n\t$ git log --oneline master.. | tac | cat -n\n\t1 xxxxxx prelim cleanly\n\t2 xxxxxx implement the feature\n\t3 xxxxxx document and test the feature\n\t4 xxxxxx the final step\n\t5 xxxxxx fixup! implement the feature\n\nI think I may appreciate such a feature in \"rebase -i\" even more, if\nthe UI were done a bit differently, e.g.\n\n\t$ git rebase -i --edit=\"1 3 2 b f5 b r4\" master..\n\nto mean \"pick the first (i.e. bottommost) one, pick the third one\nfor testing, pick the second one, then break so that I can test,\nfixup the fifth one, break to test, and finally pick the fourth\none but reword its log message\", to come up with:\n\n\tpick xxxxxx prelim cleanly\n\tpick xxxxxx document and test the feature\n\tpick xxxxxx implement the feature\n\tbreak\n\tfixup xxxxxx oops, the second one needs fixing\n        break\n\treword xxxxxx the final step\n\nI am guessing that the way you did it, the above would be impossible\n(as it requires reordering) but given that you would leave most of\nthe 'pick's intact and only tweak them in-place into drop, edit,\nreword, etc., that may not be too bad, but I suspect that it would\nbecome very verbose.\n\n\t$ git rebase -i \\\n\t\t--pick HEAD~4 --pick HEAD~3 --break --fixup HEAD \\\n\t\t...\n\nThe --edit alternative I threw in in the above would make it\nnecessary for the user to spell out all the picks, and that would be\nmore cumbersome given our assumption that most picks will be left\nintact, but then we could do something like\n\n\t--edit=\"1-4 5e 6 8-\" master..\n\nto say \"pick 1 thru 4, edit 5, pick 6, drop 7 and pick 8 thru the\nend\".\n\nI dunno.\n"},{"id":"374241","messageId":"623d6ebd-60c4-916d-6295-4c648dbf3932@gmail.com","threadId":"50964","inReplyTo":"xmqqk1fm9712.fsf@gitster-ct.c.googlers.com","subject":"Re: [PATCH/RFC 0/2] rebase: add switches to control todo-list setup","fromName":"Phillip Wood","fromEmail":"phillip.wood123@gmail.com","sentAt":"2019-04-22T14:44:00Z","receivedAt":"2019-04-22T14:44:07Z","isPatch":true,"sender":{"key":"phillip.wood@dunelm.org.uk","avatar":null},"body":"On 22/04/2019 02:13, Junio C Hamano wrote:\n> Phil Hord <phil.hord@gmail.com> writes:\n> \n>> Currently it supports these switches:\n>>\n>>      usage: git rebase [-i] [options] [--exec <cmd>] ...\n>>         :\n>>      --break <revision>    stop before the mentioned ref\n>>      --drop <revision>     drop the mentioned ref from the todo list\n>>      --edit <revision>     edit the mentioned ref instead of picking it\n>>      --reword <revision>   reword the mentioned ref instead of picking it\n>>\n>> I have plans to add these, but I don't like how their \"onto\" will be\n>> controlled. More thinking is needed here.\n>>\n>>      --fixup <revision>    fixup the mentioned ref instead of picking it\n>>      --squash <revision>   squash the mentioned ref instead of picking it\n>>      --pick <revision>     pick the mentioned ref onto the start of the list\n> \n> Yeah, I can see that it may be very useful to shorten the sequence\n> to (1) learn what commits there are and think what you want to do\n> with each of them by looking at \"git log --oneline master..\" output\n> and then to (2) look at and edit todo in \"git rebase -i master\".\n >> I personally would be fine without the step (1), as what \"rebase -i\"\n> gives me in step (2) essentially is \"log --oneline master..\".  So I\n> am not quite getting in what way these command line options would be\n> more useful than without them, though, especially since I do not see\n> how well an option to reorder commits would fit with the way you\n> structured your UI.\n\nDoing \"git rebase -i master\" and then editing the todo list has the side \neffect of rebasing the branch. Often I find I want to amend or reword a \ncommit without rebasing (for instance when preparing a re-roll). To do \nthis I use a script that runs something like\n\nGIT_SEQUENCE_EDITOR=\"sed -i s/pick $sha/edit $sha/\" git rebase -i $sha^\n\nand I have my shell set up to interactively select a commit[1] so I \ndon't have to cut and paste the output from git log. I've found this \nreally useful as most of the time I just want to amend or reword a \ncommit or squash fixups rather than rearranging commits. The script \nknows how to rewind a running rebase so I can amend several commits \nwithout having to start a new rebase each time.\n\nSo I can see a use for --edit, --reword & --drop if they selected a \nsuitable upstream to avoid unwanted rebases (I'm not so sure about the \nothers though). If you want to rebase as well then I agree you might as \nwell just edit the todo list.\n\nBest Wishes\n\nPhillip\n\n[1] Something like \nhttps://public-inbox.org/git/87k3xli6mn.fsf@thomas.inf.ethz.ch/\n\n> Having already said that, if I were to get in the habit of looking\n> at \"log\" first to decide and then running \"rebase -i\" after I made\n> up my mind, using a tweaked \"log --oneline\" output that looks\n> perhaps like this:\n> \n> \t$ git log --oneline master.. | tac | cat -n\n> \t1 xxxxxx prelim cleanly\n> \t2 xxxxxx implement the feature\n> \t3 xxxxxx document and test the feature\n> \t4 xxxxxx the final step\n> \t5 xxxxxx fixup! implement the feature\n> \n> I think I may appreciate such a feature in \"rebase -i\" even more, if\n> the UI were done a bit differently, e.g.\n> \n> \t$ git rebase -i --edit=\"1 3 2 b f5 b r4\" master.. >\n> to mean \"pick the first (i.e. bottommost) one, pick the third one\n> for testing, pick the second one, then break so that I can test,\n> fixup the fifth one, break to test, and finally pick the fourth\n> one but reword its log message\", to come up with:\n> \n> \tpick xxxxxx prelim cleanly\n> \tpick xxxxxx document and test the feature\n> \tpick xxxxxx implement the feature\n> \tbreak\n> \tfixup xxxxxx oops, the second one needs fixing\n>          break\n> \treword xxxxxx the final step\n> \n> I am guessing that the way you did it, the above would be impossible\n> (as it requires reordering) but given that you would leave most of\n> the 'pick's intact and only tweak them in-place into drop, edit,\n> reword, etc., that may not be too bad, but I suspect that it would\n> become very verbose.\n> \n> \t$ git rebase -i \\\n> \t\t--pick HEAD~4 --pick HEAD~3 --break --fixup HEAD \\\n> \t\t...\n> \n> The --edit alternative I threw in in the above would make it\n> necessary for the user to spell out all the picks, and that would be\n> more cumbersome given our assumption that most picks will be left\n> intact, but then we could do something like\n> \n> \t--edit=\"1-4 5e 6 8-\" master..\n> \n> to say \"pick 1 thru 4, edit 5, pick 6, drop 7 and pick 8 thru the\n> end\".\n> \n> I dunno.\n> \n"},{"id":"374256","messageId":"CABURp0oViG2VFOU2TbXuM3Q7omUFAtBZACH8teuQgPjBwRPL2A@mail.gmail.com","threadId":"50964","inReplyTo":"xmqqk1fm9712.fsf@gitster-ct.c.googlers.com","subject":"Re: [PATCH/RFC 0/2] rebase: add switches to control todo-list setup","fromName":"Phil Hord","fromEmail":"phil.hord@gmail.com","sentAt":"2019-04-22T17:50:44Z","receivedAt":"2019-04-22T17:51:00Z","isPatch":true,"sender":{"key":"phil.hord@gmail.com","avatar":"https://avatars.githubusercontent.com/u/123908?v=4"},"body":"On Sun, Apr 21, 2019 at 6:13 PM Junio C Hamano <gitster@pobox.com> wrote:\n>\n> Phil Hord <phil.hord@gmail.com> writes:\n>\n> > Currently it supports these switches:\n> >\n> >     usage: git rebase [-i] [options] [--exec <cmd>] ...\n> >        :\n> >     --break <revision>    stop before the mentioned ref\n> >     --drop <revision>     drop the mentioned ref from the todo list\n> >     --edit <revision>     edit the mentioned ref instead of picking it\n> >     --reword <revision>   reword the mentioned ref instead of picking it\n> >\n> > I have plans to add these, but I don't like how their \"onto\" will be\n> > controlled. More thinking is needed here.\n> >\n> >     --fixup <revision>    fixup the mentioned ref instead of picking it\n> >     --squash <revision>   squash the mentioned ref instead of picking it\n> >     --pick <revision>     pick the mentioned ref onto the start of the list\n>\n> Yeah, I can see that it may be very useful to shorten the sequence\n> to (1) learn what commits there are and think what you want to do\n> with each of them by looking at \"git log --oneline master..\" output\n> and then to (2) look at and edit todo in \"git rebase -i master\".\n>\n> I personally would be fine without the step (1), as what \"rebase -i\"\n> gives me in step (2) essentially is \"log --oneline master..\".\n\nMy example of \"drop\" is probably the worst one for simplification, but\nit nicely reduces the operation to one step if --interactive is not\ngiven.  More commonly I discover something I want to improve in commit\nmessage or in the code so I use --edit or --reword to fix it up before\nI submit it for review.\n\n> So I\n> am not quite getting in what way these command line options would be\n> more useful than without them, though, especially since I do not see\n> how well an option to reorder commits would fit with the way you\n> structured your UI.\n\nI thought I might have \"--pick-onto foo bar\" but that requires two\narguments to one switch, which I think is confusing and unprecedented.\nMy current thinking is that --pick could pick some commit onto the\nbeginning of the todo list, thereby picking it onto 'upstream'.  If\nthe same commit appears later in the todo-list, I am inclined to drop\nit; but I might want to pick it anyway and let it evaporate as an\nempty commit, giving me the opportunity to split a commit in two\nplaces.  But this is still more exotic and confusing.\n\nI tried to have --fixup and --squash simply do their actions in-place,\nbut that seems useless.  So I thought I might treat the same as pick,\npicking them onto upstream. But it's meaningless to fixup or squash on\nthe first step in the todo, so it would have to be on the first child\nof the upstream.  This still feels forced and useless.\n\nA compromise that feels nice in practice is to do the fixup and squash\nin-place and then to use --interactive to open the editor.  Since I\nhave syntax highlighting, the fixup and squash lines stand out boldly\nand I find it easier to move these into the right place as needed. But\nI think this mode could be confusing for users trying to understand\nthe utility of these switches.\n\n> Having already said that, if I were to get in the habit of looking\n> at \"log\" first to decide and then running \"rebase -i\" after I made\n> up my mind, using a tweaked \"log --oneline\" output that looks\n> perhaps like this:\n>\n>         $ git log --oneline master.. | tac | cat -n\n>         1 xxxxxx prelim cleanly\n>         2 xxxxxx implement the feature\n>         3 xxxxxx document and test the feature\n>         4 xxxxxx the final step\n>         5 xxxxxx fixup! implement the feature\n>\n> I think I may appreciate such a feature in \"rebase -i\" even more, if\n> the UI were done a bit differently, e.g.\n>\n>         $ git rebase -i --edit=\"1 3 2 b f5 b r4\" master..\n>\n> to mean \"pick the first (i.e. bottommost) one, pick the third one\n> for testing, pick the second one, then break so that I can test,\n> fixup the fifth one, break to test, and finally pick the fourth\n> one but reword its log message\", to come up with:\n>\n>         pick xxxxxx prelim cleanly\n>         pick xxxxxx document and test the feature\n>         pick xxxxxx implement the feature\n>         break\n>         fixup xxxxxx oops, the second one needs fixing\n>         break\n>         reword xxxxxx the final step\n\nThis kind of gui brings more power and flexibility. I don't think I\nwould use it since reordering in the editor feels right to me.  Maybe\nthat's the real problem with reordering at all with these switches,\nand I should leave fixup/squash/pick out for good.\n\n> I am guessing that the way you did it, the above would be impossible\n> (as it requires reordering) but given that you would leave most of\n> the 'pick's intact and only tweak them in-place into drop, edit,\n> reword, etc., that may not be too bad, but I suspect that it would\n> become very verbose.\n>\n>         $ git rebase -i \\\n>                 --pick HEAD~4 --pick HEAD~3 --break --fixup HEAD \\\n>                 ...\n>\n> The --edit alternative I threw in in the above would make it\n> necessary for the user to spell out all the picks, and that would be\n> more cumbersome given our assumption that most picks will be left\n> intact, but then we could do something like\n>\n>         --edit=\"1-4 5e 6 8-\" master..\n>\n> to say \"pick 1 thru 4, edit 5, pick 6, drop 7 and pick 8 thru the\n> end\".\n\nMy own itch is to help the case when I am leaving most of the lines as\npicks.  That is, I don't really want to rebase to some new upstream\ncommit; I don't want to enumerate all the changes that\nrebase--interactive helpfully chooses for me; I only want to fix one\nor two warts.\n\nAs a trivial example, I can say\n\n        $ git commit --amend\n\nto reword my HEAD commit.  But I have no easy way to say that for\nHEAD^.  With this change I can.\n\n        $ git rebase --edit HEAD^ HEAD^^\n\nIdeally I wouldn't need to specify HEAD^^.  I'm thinking of a switch\nto say \"use the mergebase of my mentioned edits\", but that's still a\nwip.\n"},{"id":"374263","messageId":"CABURp0r9DBxoxLjjynNj-px7mFBA5--ZS7SoNniNu7MLPZkqwg@mail.gmail.com","threadId":"50964","inReplyTo":"623d6ebd-60c4-916d-6295-4c648dbf3932@gmail.com","subject":"Re: [PATCH/RFC 0/2] rebase: add switches to control todo-list setup","fromName":"Phil Hord","fromEmail":"phil.hord@gmail.com","sentAt":"2019-04-22T19:16:16Z","receivedAt":"2019-04-22T19:16:32Z","isPatch":true,"sender":{"key":"phil.hord@gmail.com","avatar":"https://avatars.githubusercontent.com/u/123908?v=4"},"body":"On Mon, Apr 22, 2019 at 7:44 AM Phillip Wood <phillip.wood123@gmail.com> wrote:\n> Doing \"git rebase -i master\" and then editing the todo list has the side\n> effect of rebasing the branch. Often I find I want to amend or reword a\n> commit without rebasing (for instance when preparing a re-roll). To do\n> this I use a script that runs something like\n>\n> GIT_SEQUENCE_EDITOR=\"sed -i s/pick $sha/edit $sha/\" git rebase -i $sha^\n>\n> and I have my shell set up to interactively select a commit[1] so I\n> don't have to cut and paste the output from git log. I've found this\n> really useful as most of the time I just want to amend or reword a\n> commit or squash fixups rather than rearranging commits. The script\n> knows how to rewind a running rebase so I can amend several commits\n> without having to start a new rebase each time.\n>\n> So I can see a use for --edit, --reword & --drop if they selected a\n> suitable upstream to avoid unwanted rebases (I'm not so sure about the\n> others though). If you want to rebase as well then I agree you might as\n> well just edit the todo list.\n\nI have the same need.  I plan to have some switch that invokes this\n\"in-place rebase\" behavior so that git can choose the upstream for me\nas `mergebase $sequence-edits`.  In fact, I want to make that the\ndefault for these switches, but that feels too surprising for the\nrebase command. I plan to progress like this:\n\n    # --in-place switch is not supported; manual upstream is given by user\n    git rebase --edit foo foo^\n\n     # --in-place switch is added; now we can say this\n     git rebase --edit foo --in-place\n\n     # prefer in-place edits as default when editing\n     git config --add rebase.in-place-edits true\n     git rebase --edit foo\n\nThis --in-place switch would use `mergebase $sequence-edits` to find\nmy upstream parameter if I didn't give one explicitly.\n\nThis config option set to true would tell git to assume I meant to use\n--in-place whenever I use some sequence-edit switch and I don't\nspecify an upstream.\n\nI have written some of this code, but since I am running into\nconflicts with next and pu, I haven't ironed it out yet.\n\nPhil\n"},{"id":"374264","messageId":"CABURp0pEB-3m=wbWsVc9C82d3Jf2UW4fXnsSZ+GnTHKWRJo0NQ@mail.gmail.com","threadId":"50964","inReplyTo":"CABURp0r9DBxoxLjjynNj-px7mFBA5--ZS7SoNniNu7MLPZkqwg@mail.gmail.com","subject":"Re: [PATCH/RFC 0/2] rebase: add switches to control todo-list setup","fromName":"Phil Hord","fromEmail":"phil.hord@gmail.com","sentAt":"2019-04-22T19:20:29Z","receivedAt":"2019-04-22T19:20:45Z","isPatch":true,"sender":{"key":"phil.hord@gmail.com","avatar":"https://avatars.githubusercontent.com/u/123908?v=4"},"body":"On Mon, Apr 22, 2019 at 12:16 PM Phil Hord <phil.hord@gmail.com> wrote:\n>\n> I have the same need.  I plan to have some switch that invokes this\n> \"in-place rebase\" behavior so that git can choose the upstream for me\n> as `mergebase $sequence-edits`.  In fact, I want to make that the\n> default for these switches, but that feels too surprising for the\n> rebase command. I plan to progress like this:\n>\n>     # --in-place switch is not supported; manual upstream is given by user\n>     git rebase --edit foo foo^\n>\n>      # --in-place switch is added; now we can say this\n>      git rebase --edit foo --in-place\n\nI originally CC'ed Denton on this thread because he recently added\n--keep-base.  I initially hoped it would do something similar to\n--in-place, but on reading the patch discussion, I think it's for\nsomething different altogether.  :-\\   It's similar, though, in the\nsame way that --fork-point is; which may be another way to say \"not\nvery.\"\n"},{"id":"374267","messageId":"20190422194940.GA10592@dev-l","threadId":"50964","inReplyTo":"CABURp0pEB-3m=wbWsVc9C82d3Jf2UW4fXnsSZ+GnTHKWRJo0NQ@mail.gmail.com","subject":"Re: [PATCH/RFC 0/2] rebase: add switches to control todo-list setup","fromName":"Denton Liu","fromEmail":"liu.denton@gmail.com","sentAt":"2019-04-22T19:49:40Z","receivedAt":"2019-04-22T19:54:31Z","isPatch":true,"sender":{"key":"liu.denton@gmail.com","avatar":"https://avatars.githubusercontent.com/u/9620836?v=4"},"body":"Hi Phil,\n\nOn Mon, Apr 22, 2019 at 12:20:29PM -0700, Phil Hord wrote:\n> On Mon, Apr 22, 2019 at 12:16 PM Phil Hord <phil.hord@gmail.com> wrote:\n> >\n> > I have the same need.  I plan to have some switch that invokes this\n> > \"in-place rebase\" behavior so that git can choose the upstream for me\n> > as `mergebase $sequence-edits`.  In fact, I want to make that the\n> > default for these switches, but that feels too surprising for the\n> > rebase command. I plan to progress like this:\n> >\n> >     # --in-place switch is not supported; manual upstream is given by user\n> >     git rebase --edit foo foo^\n> >\n> >      # --in-place switch is added; now we can say this\n> >      git rebase --edit foo --in-place\n> \n> I originally CC'ed Denton on this thread because he recently added\n> --keep-base.  I initially hoped it would do something similar to\n> --in-place, but on reading the patch discussion, I think it's for\n> something different altogether.  :-\\   It's similar, though, in the\n> same way that --fork-point is; which may be another way to say \"not\n> very.\"\n\nYou're correct, --keep-base is a little more explicit than your proposed\n--in-place switch in that the former requires an upstream revision be\nspecified whereas yours implicitly finds the base using the\n$sequence-edits. I suppose until --in-place is implemented, users could\nalways use explicitly specify the upstream branch, such as:\n\n\t$ git rebase --edit foo --keep-base master\n\nAnyway, I've been following along with the discussion and although there\nare kinks to iron out, I like the general idea. Although I use fixup and\nsquash commits + rebase -i --keep-base for major branch polishing,\nsometimes after the branch is mostly polished, there are a few\nlast-minute changes to be made. I think that your proposed solution\nwould also match my use-case nicely.\n\nThanks,\n\nDenton\n"},{"id":"374282","messageId":"xmqq4l6p7bz7.fsf@gitster-ct.c.googlers.com","threadId":"50964","inReplyTo":"623d6ebd-60c4-916d-6295-4c648dbf3932@gmail.com","subject":"Re: [PATCH/RFC 0/2] rebase: add switches to control todo-list setup","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2019-04-23T01:21:32Z","receivedAt":"2019-04-23T01:21:37Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Phillip Wood <phillip.wood123@gmail.com> writes:\n\n> Doing \"git rebase -i master\" and then editing the todo list has the\n> side effect of rebasing the branch. Often I find I want to amend or\n> reword a commit without rebasing (for instance when preparing a\n> re-roll).\n\nI am not sure what you mean by \"not rebasing\".  Are you talking\nabout --keep-base that uses the same --onto as the previous?\n\nI think that is often desired, but I do not think it has much to do\nwith the topic of the proposal these two patches raises.\n\nAnd that (i.e. \"this has nothing to do with the choice of 'onto'\")\nwas why I used the casual \"rebase -i master\" in my illustrations.\n"},{"id":"374287","messageId":"CABURp0rLg=E6MT9Ld5EXpk127PURYMPdP9Mgo7duyerO-yCPOg@mail.gmail.com","threadId":"50964","inReplyTo":"xmqq4l6p7bz7.fsf@gitster-ct.c.googlers.com","subject":"Re: [PATCH/RFC 0/2] rebase: add switches to control todo-list setup","fromName":"Phil Hord","fromEmail":"phil.hord@gmail.com","sentAt":"2019-04-23T02:20:36Z","receivedAt":"2019-04-23T02:20:51Z","isPatch":true,"sender":{"key":"phil.hord@gmail.com","avatar":"https://avatars.githubusercontent.com/u/123908?v=4"},"body":"On Mon, Apr 22, 2019 at 6:21 PM Junio C Hamano <gitster@pobox.com> wrote:\n>\n> Phillip Wood <phillip.wood123@gmail.com> writes:\n>\n> > Doing \"git rebase -i master\" and then editing the todo list has the\n> > side effect of rebasing the branch. Often I find I want to amend or\n> > reword a commit without rebasing (for instance when preparing a\n> > re-roll).\n>\n> I am not sure what you mean by \"not rebasing\".  Are you talking\n> about --keep-base that uses the same --onto as the previous?\n>\n> I think that is often desired, but I do not think it has much to do\n> with the topic of the proposal these two patches raises.\n>\n> And that (i.e. \"this has nothing to do with the choice of 'onto'\")\n> was why I used the casual \"rebase -i master\" in my illustrations.\n\nI know exactly what he means, because it usually is exactly what I\nwant to do here.  In fact, I almost always want `rebase --interactive`\nto do this \"in-place\" editing of the history.  Sure, I may want to\n`rebase @{upstream}` someday, but I seldom use --interactive for that.\n\nRebase invites conflicts.  It's nice to invite as few as possible at once.\n\nP\n"}]}