{"thread":{"id":"38843","subject":"[PATCH/WIP 0/8] Convert git-rebase.sh to C","startedAt":"2015-03-18T09:55:39Z","lastAt":"2015-03-18T09:55:47Z","messageCount":9,"participants":["Nguyễn Thái Ngọc Duy"],"isPatch":true,"patchVersion":1,"patchTotal":8},"messages":[{"id":"257925","messageId":"1426672547-11369-1-git-send-email-pclouds@gmail.com","threadId":"38843","inReplyTo":null,"subject":"[PATCH/WIP 0/8] Convert git-rebase.sh to C","fromName":"Nguyễn Thái Ngọc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2015-03-18T09:55:39Z","receivedAt":"2015-03-18T09:55:39Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"In the spirit of sharing code proactively [1], despite my embarrassment,\nthis is what I got for converting git-rebase.sh to C. Note that this\nis only about git-rebase.sh, not git-rebase--*.sh. Some changes in\ngit-rebase.sh are pushed back to git-rebase--*.sh. The idea is we\nconvert git-rebase.sh first, then the rest later.\n\nAnybody who wants to base their work on this code, feel free to\n--reset-author (and take all the bugs with you, I'm sure there are\nlots of them). This work is from 2013. git-rebase.sh has received lots\nof updates since then, so there's still lots of work to do.\n\n[1] http://article.gmane.org/gmane.comp.version-control.git/265699\n\nNguyễn Thái Ngọc Duy (8):\n  strbuf: add and use strbuf_read_file_or_die()\n  Move reset_tree from builtin/checkout.c to unpack-trees.c\n  rebase: turn rebase--am into a separate program\n  rebase: turn rebase--merge into a separate program\n  rebase: turn rebase--interactive into a separate program\n  rebase: remove unused function\n  rebase: move resolvemsg to rebase--* scripts\n  Build in rebase\n\n Makefile                                |   8 +-\n builtin.h                               |   1 +\n builtin/blame.c                         |   4 +-\n builtin/checkout.c                      |  40 +-\n builtin/commit.c                        |  16 +-\n builtin/merge.c                         |  32 +-\n builtin/notes.c                         |   4 +-\n builtin/rebase.c (new)                  | 752 ++++++++++++++++++++++++++++++++\n builtin/tag.c                           |   7 +-\n commit.c                                |   4 +-\n commit.h                                |   4 +-\n contrib/examples/git-rebase.sh (new +x) | 532 ++++++++++++++++++++++\n git-rebase--am.sh (mode +x)             |  39 ++\n git-rebase--interactive.sh (mode +x)    |  41 +-\n git-rebase--merge.sh (mode +x)          |  39 ++\n git-rebase.sh (gone)                    | 544 -----------------------\n git.c                                   |   1 +\n strbuf.c                                |   8 +\n strbuf.h                                |   1 +\n unpack-trees.c                          |  33 ++\n unpack-trees.h                          |   4 +\n 21 files changed, 1480 insertions(+), 634 deletions(-)\n create mode 100644 builtin/rebase.c\n create mode 100755 contrib/examples/git-rebase.sh\n mode change 100644 => 100755 git-rebase--am.sh\n mode change 100644 => 100755 git-rebase--interactive.sh\n mode change 100644 => 100755 git-rebase--merge.sh\n delete mode 100755 git-rebase.sh\n\n-- \n2.3.0.rc1.137.g477eb31\n"},{"id":"257926","messageId":"1426672547-11369-2-git-send-email-pclouds@gmail.com","threadId":"38843","inReplyTo":"1426672547-11369-1-git-send-email-pclouds@gmail.com","subject":"[PATCH/WIP 1/8] strbuf: add and use strbuf_read_file_or_die()","fromName":"Nguyễn Thái Ngọc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2015-03-18T09:55:40Z","receivedAt":"2015-03-18T09:55:40Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"---\n builtin/blame.c  |  4 ++--\n builtin/commit.c | 16 +++++-----------\n builtin/merge.c  |  3 +--\n builtin/notes.c  |  4 ++--\n builtin/tag.c    |  7 ++-----\n strbuf.c         |  8 ++++++++\n strbuf.h         |  1 +\n 7 files changed, 21 insertions(+), 22 deletions(-)\n\ndiff --git a/builtin/blame.c b/builtin/blame.c\nindex bc6c899..503595c 100644\n--- a/builtin/blame.c\n+++ b/builtin/blame.c\n@@ -2193,8 +2193,8 @@ static struct commit *fake_working_tree_commit(struct diff_options *opt,\n \t\t\tif (DIFF_OPT_TST(opt, ALLOW_TEXTCONV) &&\n \t\t\t    textconv_object(read_from, mode, null_sha1, 0, &buf_ptr, &buf_len))\n \t\t\t\tstrbuf_attach(&buf, buf_ptr, buf_len, buf_len + 1);\n-\t\t\telse if (strbuf_read_file(&buf, read_from, st.st_size) != st.st_size)\n-\t\t\t\tdie_errno(\"cannot open or read '%s'\", read_from);\n+\t\t\telse\n+\t\t\t\tstrbuf_read_file_or_die(&buf, read_from, st.st_size);\n \t\t\tbreak;\n \t\tcase S_IFLNK:\n \t\t\tif (strbuf_readlink(&buf, read_from, st.st_size) < 0)\ndiff --git a/builtin/commit.c b/builtin/commit.c\nindex d6dd3df..dad9acf 100644\n--- a/builtin/commit.c\n+++ b/builtin/commit.c\n@@ -612,9 +612,7 @@ static int prepare_to_commit(const char *index_file, const char *prefix,\n \t\t\tdie_errno(_(\"could not read log from standard input\"));\n \t\thook_arg1 = \"message\";\n \t} else if (logfile) {\n-\t\tif (strbuf_read_file(&sb, logfile, 0) < 0)\n-\t\t\tdie_errno(_(\"could not read log file '%s'\"),\n-\t\t\t\t  logfile);\n+\t\tstrbuf_read_file_or_die(&sb, logfile, 0);\n \t\thook_arg1 = \"message\";\n \t} else if (use_message) {\n \t\tbuffer = strstr(use_message_buffer, \"\\n\\n\");\n@@ -634,16 +632,13 @@ static int prepare_to_commit(const char *index_file, const char *prefix,\n \t\t\t\t      &sb, &ctx);\n \t\thook_arg1 = \"message\";\n \t} else if (!stat(git_path(\"MERGE_MSG\"), &statbuf)) {\n-\t\tif (strbuf_read_file(&sb, git_path(\"MERGE_MSG\"), 0) < 0)\n-\t\t\tdie_errno(_(\"could not read MERGE_MSG\"));\n+\t\tstrbuf_read_file_or_die(&sb, git_path(\"MERGE_MSG\"), 0);\n \t\thook_arg1 = \"merge\";\n \t} else if (!stat(git_path(\"SQUASH_MSG\"), &statbuf)) {\n-\t\tif (strbuf_read_file(&sb, git_path(\"SQUASH_MSG\"), 0) < 0)\n-\t\t\tdie_errno(_(\"could not read SQUASH_MSG\"));\n+\t\tstrbuf_read_file_or_die(&sb, git_path(\"SQUASH_MSG\"), 0);\n \t\thook_arg1 = \"squash\";\n \t} else if (template_file) {\n-\t\tif (strbuf_read_file(&sb, template_file, 0) < 0)\n-\t\t\tdie_errno(_(\"could not read '%s'\"), template_file);\n+\t\tstrbuf_read_file_or_die(&sb, template_file, 0);\n \t\thook_arg1 = \"template\";\n \t\tclean_message_contents = 0;\n \t}\n@@ -1497,8 +1492,7 @@ int cmd_commit(int argc, const char **argv, const char *prefix)\n \t\tfclose(fp);\n \t\tstrbuf_release(&m);\n \t\tif (!stat(git_path(\"MERGE_MODE\"), &statbuf)) {\n-\t\t\tif (strbuf_read_file(&sb, git_path(\"MERGE_MODE\"), 0) < 0)\n-\t\t\t\tdie_errno(_(\"could not read MERGE_MODE\"));\n+\t\t\tstrbuf_read_file_or_die(&sb, git_path(\"MERGE_MODE\"), 0);\n \t\t\tif (!strcmp(sb.buf, \"no-ff\"))\n \t\t\t\tallow_fast_forward = 0;\n \t\t}\ndiff --git a/builtin/merge.c b/builtin/merge.c\nindex 9307e9c..6babf39 100644\n--- a/builtin/merge.c\n+++ b/builtin/merge.c\n@@ -769,8 +769,7 @@ static void read_merge_msg(struct strbuf *msg)\n {\n \tconst char *filename = git_path(\"MERGE_MSG\");\n \tstrbuf_reset(msg);\n-\tif (strbuf_read_file(msg, filename, 0) < 0)\n-\t\tdie_errno(_(\"Could not read from '%s'\"), filename);\n+\tstrbuf_read_file_or_die(msg, filename, 0);\n }\n \n static void write_merge_state(struct commit_list *);\ndiff --git a/builtin/notes.c b/builtin/notes.c\nindex 453457a..3210c7f 100644\n--- a/builtin/notes.c\n+++ b/builtin/notes.c\n@@ -252,8 +252,8 @@ static int parse_file_arg(const struct option *opt, const char *arg, int unset)\n \tif (!strcmp(arg, \"-\")) {\n \t\tif (strbuf_read(&(msg->buf), 0, 1024) < 0)\n \t\t\tdie_errno(_(\"cannot read '%s'\"), arg);\n-\t} else if (strbuf_read_file(&(msg->buf), arg, 1024) < 0)\n-\t\tdie_errno(_(\"could not open or read '%s'\"), arg);\n+\t} else\n+\t\tstrbuf_read_file_or_die(&(msg->buf), arg, 0);\n \tstripspace(&(msg->buf), 0);\n \n \tmsg->given = 1;\ndiff --git a/builtin/tag.c b/builtin/tag.c\nindex 9c3e067..69f4ea3 100644\n--- a/builtin/tag.c\n+++ b/builtin/tag.c\n@@ -540,11 +540,8 @@ int cmd_tag(int argc, const char **argv, const char *prefix)\n \t\t\tif (!strcmp(msgfile, \"-\")) {\n \t\t\t\tif (strbuf_read(&buf, 0, 1024) < 0)\n \t\t\t\t\tdie_errno(_(\"cannot read '%s'\"), msgfile);\n-\t\t\t} else {\n-\t\t\t\tif (strbuf_read_file(&buf, msgfile, 1024) < 0)\n-\t\t\t\t\tdie_errno(_(\"could not open or read '%s'\"),\n-\t\t\t\t\t\tmsgfile);\n-\t\t\t}\n+\t\t\t} else\n+\t\t\t\tstrbuf_read_file_or_die(&buf, msgfile, 0);\n \t\t}\n \t}\n \ndiff --git a/strbuf.c b/strbuf.c\nindex 9a373be..9f50478 100644\n--- a/strbuf.c\n+++ b/strbuf.c\n@@ -411,6 +411,14 @@ int strbuf_read_file(struct strbuf *sb, const char *path, size_t hint)\n \treturn len;\n }\n \n+void strbuf_read_file_or_die(struct strbuf *sb, const char *path, size_t size)\n+{\n+\tint ret;\n+\tret = strbuf_read_file(sb, path, size);\n+\tif (ret < 0 || (size && ret != size))\n+\t\tdie_errno(_(\"could not open or read '%s'\"), path);\n+}\n+\n void strbuf_add_lines(struct strbuf *out, const char *prefix,\n \t\t      const char *buf, size_t size)\n {\ndiff --git a/strbuf.h b/strbuf.h\nindex ecae4e2..c1f012d 100644\n--- a/strbuf.h\n+++ b/strbuf.h\n@@ -152,6 +152,7 @@ extern size_t strbuf_fread(struct strbuf *, size_t, FILE *);\n /* XXX: if read fails, any partial read is undone */\n extern ssize_t strbuf_read(struct strbuf *, int fd, size_t hint);\n extern int strbuf_read_file(struct strbuf *sb, const char *path, size_t hint);\n+extern void strbuf_read_file_or_die(struct strbuf *sb, const char *path, size_t size);\n extern int strbuf_readlink(struct strbuf *sb, const char *path, size_t hint);\n \n extern int strbuf_getwholeline(struct strbuf *, FILE *, int);\n-- \n2.3.0.rc1.137.g477eb31\n"},{"id":"257927","messageId":"1426672547-11369-3-git-send-email-pclouds@gmail.com","threadId":"38843","inReplyTo":"1426672547-11369-1-git-send-email-pclouds@gmail.com","subject":"[PATCH/WIP 2/8] Move reset_tree from builtin/checkout.c to unpack-trees.c","fromName":"Nguyễn Thái Ngọc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2015-03-18T09:55:41Z","receivedAt":"2015-03-18T09:55:41Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"---\n builtin/checkout.c | 40 +++-------------------------------------\n builtin/merge.c    | 29 +++++++----------------------\n unpack-trees.c     | 33 +++++++++++++++++++++++++++++++++\n unpack-trees.h     |  4 ++++\n 4 files changed, 47 insertions(+), 59 deletions(-)\n\ndiff --git a/builtin/checkout.c b/builtin/checkout.c\nindex a9c1b5a..93b18ad 100644\n--- a/builtin/checkout.c\n+++ b/builtin/checkout.c\n@@ -362,40 +362,6 @@ static void describe_detached_head(const char *msg, struct commit *commit)\n \tstrbuf_release(&sb);\n }\n \n-static int reset_tree(struct tree *tree, const struct checkout_opts *o,\n-\t\t      int worktree, int *writeout_error)\n-{\n-\tstruct unpack_trees_options opts;\n-\tstruct tree_desc tree_desc;\n-\n-\tmemset(&opts, 0, sizeof(opts));\n-\topts.head_idx = -1;\n-\topts.update = worktree;\n-\topts.skip_unmerged = !worktree;\n-\topts.reset = 1;\n-\topts.merge = 1;\n-\topts.fn = oneway_merge;\n-\topts.verbose_update = !o->quiet && isatty(2);\n-\topts.src_index = &the_index;\n-\topts.dst_index = &the_index;\n-\tparse_tree(tree);\n-\tinit_tree_desc(&tree_desc, tree->buffer, tree->size);\n-\tswitch (unpack_trees(1, &tree_desc, &opts)) {\n-\tcase -2:\n-\t\t*writeout_error = 1;\n-\t\t/*\n-\t\t * We return 0 nevertheless, as the index is all right\n-\t\t * and more importantly we have made best efforts to\n-\t\t * update paths in the work tree, and we cannot revert\n-\t\t * them.\n-\t\t */\n-\tcase 0:\n-\t\treturn 0;\n-\tdefault:\n-\t\treturn 128;\n-\t}\n-}\n-\n struct branch_info {\n \tconst char *name; /* The short name used */\n \tconst char *path; /* The full name of a real branch */\n@@ -427,7 +393,7 @@ static int merge_working_tree(const struct checkout_opts *opts,\n \n \tresolve_undo_clear();\n \tif (opts->force) {\n-\t\tret = reset_tree(new->commit->tree, opts, 1, writeout_error);\n+\t\tret = reset_tree(new->commit->tree, opts->quiet, 1, writeout_error);\n \t\tif (ret)\n \t\t\treturn ret;\n \t} else {\n@@ -513,7 +479,7 @@ static int merge_working_tree(const struct checkout_opts *opts,\n \t\t\to.verbosity = 0;\n \t\t\twork = write_tree_from_memory(&o);\n \n-\t\t\tret = reset_tree(new->commit->tree, opts, 1,\n+\t\t\tret = reset_tree(new->commit->tree, opts->quiet, 1,\n \t\t\t\t\t writeout_error);\n \t\t\tif (ret)\n \t\t\t\treturn ret;\n@@ -522,7 +488,7 @@ static int merge_working_tree(const struct checkout_opts *opts,\n \t\t\to.branch2 = \"local\";\n \t\t\tmerge_trees(&o, new->commit->tree, work,\n \t\t\t\told->commit->tree, &result);\n-\t\t\tret = reset_tree(new->commit->tree, opts, 0,\n+\t\t\tret = reset_tree(new->commit->tree, opts->quiet, 0,\n \t\t\t\t\t writeout_error);\n \t\t\tif (ret)\n \t\t\t\treturn ret;\ndiff --git a/builtin/merge.c b/builtin/merge.c\nindex 6babf39..c51e4f5 100644\n--- a/builtin/merge.c\n+++ b/builtin/merge.c\n@@ -269,33 +269,18 @@ static void read_empty(unsigned const char *sha1, int verbose)\n \t\tdie(_(\"read-tree failed\"));\n }\n \n-static void reset_hard(unsigned const char *sha1, int verbose)\n-{\n-\tint i = 0;\n-\tconst char *args[6];\n-\n-\targs[i++] = \"read-tree\";\n-\tif (verbose)\n-\t\targs[i++] = \"-v\";\n-\targs[i++] = \"--reset\";\n-\targs[i++] = \"-u\";\n-\targs[i++] = sha1_to_hex(sha1);\n-\targs[i] = NULL;\n-\n-\tif (run_command_v_opt(args, RUN_GIT_CMD))\n-\t\tdie(_(\"read-tree failed\"));\n-}\n-\n-static void restore_state(const unsigned char *head,\n+static void restore_state(struct commit *head_commit,\n \t\t\t  const unsigned char *stash)\n {\n \tstruct strbuf sb = STRBUF_INIT;\n \tconst char *args[] = { \"stash\", \"apply\", NULL, NULL };\n+\tint error = 0;\n \n \tif (is_null_sha1(stash))\n \t\treturn;\n \n-\treset_hard(head, 1);\n+\tif (reset_tree(head_commit->tree, 0, 1, &error) || error)\n+\t\tdie(_(\"read-tree failed\"));\n \n \targs[2] = sha1_to_hex(stash);\n \n@@ -1409,7 +1394,7 @@ int cmd_merge(int argc, const char **argv, const char *prefix)\n \t\tint ret;\n \t\tif (i) {\n \t\t\tprintf(_(\"Rewinding the tree to pristine...\\n\"));\n-\t\t\trestore_state(head_commit->object.sha1, stash);\n+\t\t\trestore_state(head_commit, stash);\n \t\t}\n \t\tif (use_strategies_nr != 1)\n \t\t\tprintf(_(\"Trying merge strategy %s...\\n\"),\n@@ -1475,7 +1460,7 @@ int cmd_merge(int argc, const char **argv, const char *prefix)\n \t * it up.\n \t */\n \tif (!best_strategy) {\n-\t\trestore_state(head_commit->object.sha1, stash);\n+\t\trestore_state(head_commit, stash);\n \t\tif (use_strategies_nr > 1)\n \t\t\tfprintf(stderr,\n \t\t\t\t_(\"No merge strategy handled the merge.\\n\"));\n@@ -1488,7 +1473,7 @@ int cmd_merge(int argc, const char **argv, const char *prefix)\n \t\t; /* We already have its result in the working tree. */\n \telse {\n \t\tprintf(_(\"Rewinding the tree to pristine...\\n\"));\n-\t\trestore_state(head_commit->object.sha1, stash);\n+\t\trestore_state(head_commit, stash);\n \t\tprintf(_(\"Using the %s to prepare resolving by hand.\\n\"),\n \t\t\tbest_strategy);\n \t\ttry_merge_strategy(best_strategy, common, remoteheads,\ndiff --git a/unpack-trees.c b/unpack-trees.c\nindex 0e1a196..3c24a4d 100644\n--- a/unpack-trees.c\n+++ b/unpack-trees.c\n@@ -1847,3 +1847,36 @@ int oneway_merge(struct cache_entry **src, struct unpack_trees_options *o)\n \t}\n \treturn merged_entry(a, old, o);\n }\n+\n+int reset_tree(struct tree *tree, int quiet, int worktree, int *writeout_error)\n+{\n+\tstruct unpack_trees_options opts;\n+\tstruct tree_desc tree_desc;\n+\n+\tmemset(&opts, 0, sizeof(opts));\n+\topts.head_idx = -1;\n+\topts.update = worktree;\n+\topts.skip_unmerged = !worktree;\n+\topts.reset = 1;\n+\topts.merge = 1;\n+\topts.fn = oneway_merge;\n+\topts.verbose_update = !quiet && isatty(2);\n+\topts.src_index = &the_index;\n+\topts.dst_index = &the_index;\n+\tparse_tree(tree);\n+\tinit_tree_desc(&tree_desc, tree->buffer, tree->size);\n+\tswitch (unpack_trees(1, &tree_desc, &opts)) {\n+\tcase -2:\n+\t\t*writeout_error = 1;\n+\t\t/*\n+\t\t * We return 0 nevertheless, as the index is all right\n+\t\t * and more importantly we have made best efforts to\n+\t\t * update paths in the work tree, and we cannot revert\n+\t\t * them.\n+\t\t */\n+\tcase 0:\n+\t\treturn 0;\n+\tdefault:\n+\t\treturn 128;\n+\t}\n+}\ndiff --git a/unpack-trees.h b/unpack-trees.h\nindex ec74a9f..f0850bb 100644\n--- a/unpack-trees.h\n+++ b/unpack-trees.h\n@@ -83,4 +83,8 @@ int twoway_merge(struct cache_entry **src, struct unpack_trees_options *o);\n int bind_merge(struct cache_entry **src, struct unpack_trees_options *o);\n int oneway_merge(struct cache_entry **src, struct unpack_trees_options *o);\n \n+\n+struct tree;\n+extern int reset_tree(struct tree *tree, int quiet,\n+\t\t      int worktree, int *writeout_error);\n #endif\n-- \n2.3.0.rc1.137.g477eb31\n"},{"id":"257929","messageId":"1426672547-11369-4-git-send-email-pclouds@gmail.com","threadId":"38843","inReplyTo":"1426672547-11369-1-git-send-email-pclouds@gmail.com","subject":"[PATCH/WIP 3/8] rebase: turn rebase--am into a separate program","fromName":"Nguyễn Thái Ngọc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2015-03-18T09:55:42Z","receivedAt":"2015-03-18T09:55:42Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"---\n Makefile                    |  2 +-\n git-rebase--am.sh (mode +x) | 34 ++++++++++++++++++++++++++++++++++\n git-rebase.sh               | 11 ++++++++++-\n 3 files changed, 45 insertions(+), 2 deletions(-)\n mode change 100644 => 100755 git-rebase--am.sh\n\ndiff --git a/Makefile b/Makefile\nindex 1b30d7b..93151f4 100644\n--- a/Makefile\n+++ b/Makefile\n@@ -445,6 +445,7 @@ SCRIPT_SH += git-mergetool.sh\n SCRIPT_SH += git-pull.sh\n SCRIPT_SH += git-quiltimport.sh\n SCRIPT_SH += git-rebase.sh\n+SCRIPT_SH += git-rebase--am.sh\n SCRIPT_SH += git-repack.sh\n SCRIPT_SH += git-request-pull.sh\n SCRIPT_SH += git-stash.sh\n@@ -453,7 +454,6 @@ SCRIPT_SH += git-web--browse.sh\n \n SCRIPT_LIB += git-mergetool--lib\n SCRIPT_LIB += git-parse-remote\n-SCRIPT_LIB += git-rebase--am\n SCRIPT_LIB += git-rebase--interactive\n SCRIPT_LIB += git-rebase--merge\n SCRIPT_LIB += git-sh-setup\ndiff --git a/git-rebase--am.sh b/git-rebase--am.sh\nold mode 100644\nnew mode 100755\nindex 97f31dc..ab84330\n--- a/git-rebase--am.sh\n+++ b/git-rebase--am.sh\n@@ -3,6 +3,40 @@\n # Copyright (c) 2010 Junio C Hamano.\n #\n \n+. git-sh-setup\n+. git-sh-i18n\n+set_reflog_action rebase\n+require_work_tree_exists\n+\n+GIT_QUIET=$git_quiet\n+\n+write_basic_state () {\n+\techo \"$head_name\" > \"$state_dir\"/head-name &&\n+\techo \"$onto\" > \"$state_dir\"/onto &&\n+\techo \"$orig_head\" > \"$state_dir\"/orig-head &&\n+\techo \"$GIT_QUIET\" > \"$state_dir\"/quiet &&\n+\ttest t = \"$verbose\" && : > \"$state_dir\"/verbose\n+\ttest -n \"$strategy\" && echo \"$strategy\" > \"$state_dir\"/strategy\n+\ttest -n \"$strategy_opts\" && echo \"$strategy_opts\" > \\\n+\t\t\"$state_dir\"/strategy_opts\n+\ttest -n \"$allow_rerere_autoupdate\" && echo \"$allow_rerere_autoupdate\" > \\\n+\t\t\"$state_dir\"/allow_rerere_autoupdate\n+}\n+\n+move_to_original_branch () {\n+\tcase \"$head_name\" in\n+\trefs/*)\n+\t\tmessage=\"rebase finished: $head_name onto $onto\"\n+\t\tgit update-ref -m \"$message\" \\\n+\t\t\t$head_name $(git rev-parse HEAD) $orig_head &&\n+\t\tgit symbolic-ref \\\n+\t\t\t-m \"rebase finished: returning to $head_name\" \\\n+\t\t\tHEAD $head_name ||\n+\t\tdie \"$(gettext \"Could not move back to $head_name\")\"\n+\t\t;;\n+\tesac\n+}\n+\n case \"$action\" in\n continue)\n \tgit am --resolved --resolvemsg=\"$resolvemsg\" &&\ndiff --git a/git-rebase.sh b/git-rebase.sh\nindex b2f1c76..42e868d 100755\n--- a/git-rebase.sh\n+++ b/git-rebase.sh\n@@ -149,7 +149,16 @@ run_specific_rebase () {\n \t\texport GIT_EDITOR\n \t\tautosquash=\n \tfi\n-\t. git-rebase--$type\n+\tgit_quiet=$GIT_QUIET\n+\texport GIT_PAGER\n+\texport action allow_rerere_autoupdate git_am_opt git_quiet head_name keep_empty\n+\texport onto orig_head rebase_root resolvemsg revisions\n+\texport state_dir verbose strategy strategy_opts\n+\tif [ \"$type\" = am ]; then\n+\t\texec git-rebase--am\n+\telse\n+\t\t. git-rebase--$type\n+\tfi\n }\n \n run_pre_rebase_hook () {\n-- \n2.3.0.rc1.137.g477eb31\n"},{"id":"257928","messageId":"1426672547-11369-5-git-send-email-pclouds@gmail.com","threadId":"38843","inReplyTo":"1426672547-11369-1-git-send-email-pclouds@gmail.com","subject":"[PATCH/WIP 4/8] rebase: turn rebase--merge into a separate program","fromName":"Nguyễn Thái Ngọc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2015-03-18T09:55:43Z","receivedAt":"2015-03-18T09:55:43Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"---\n Makefile                       |  2 +-\n git-rebase--merge.sh (mode +x) | 34 ++++++++++++++++++++++++++++++++++\n git-rebase.sh                  |  2 ++\n 3 files changed, 37 insertions(+), 1 deletion(-)\n mode change 100644 => 100755 git-rebase--merge.sh\n\ndiff --git a/Makefile b/Makefile\nindex 93151f4..7ee8df7 100644\n--- a/Makefile\n+++ b/Makefile\n@@ -446,6 +446,7 @@ SCRIPT_SH += git-pull.sh\n SCRIPT_SH += git-quiltimport.sh\n SCRIPT_SH += git-rebase.sh\n SCRIPT_SH += git-rebase--am.sh\n+SCRIPT_SH += git-rebase--merge.sh\n SCRIPT_SH += git-repack.sh\n SCRIPT_SH += git-request-pull.sh\n SCRIPT_SH += git-stash.sh\n@@ -455,7 +456,6 @@ SCRIPT_SH += git-web--browse.sh\n SCRIPT_LIB += git-mergetool--lib\n SCRIPT_LIB += git-parse-remote\n SCRIPT_LIB += git-rebase--interactive\n-SCRIPT_LIB += git-rebase--merge\n SCRIPT_LIB += git-sh-setup\n SCRIPT_LIB += git-sh-i18n\n \ndiff --git a/git-rebase--merge.sh b/git-rebase--merge.sh\nold mode 100644\nnew mode 100755\nindex b10f2cf..baaef41\n--- a/git-rebase--merge.sh\n+++ b/git-rebase--merge.sh\n@@ -3,8 +3,42 @@\n # Copyright (c) 2010 Junio C Hamano.\n #\n \n+. git-sh-setup\n+. git-sh-i18n\n+set_reflog_action rebase\n+require_work_tree_exists\n+\n+GIT_QUIET=$git_quiet\n+\n prec=4\n \n+write_basic_state () {\n+\techo \"$head_name\" > \"$state_dir\"/head-name &&\n+\techo \"$onto\" > \"$state_dir\"/onto &&\n+\techo \"$orig_head\" > \"$state_dir\"/orig-head &&\n+\techo \"$GIT_QUIET\" > \"$state_dir\"/quiet &&\n+\ttest t = \"$verbose\" && : > \"$state_dir\"/verbose\n+\ttest -n \"$strategy\" && echo \"$strategy\" > \"$state_dir\"/strategy\n+\ttest -n \"$strategy_opts\" && echo \"$strategy_opts\" > \\\n+\t\t\"$state_dir\"/strategy_opts\n+\ttest -n \"$allow_rerere_autoupdate\" && echo \"$allow_rerere_autoupdate\" > \\\n+\t\t\"$state_dir\"/allow_rerere_autoupdate\n+}\n+\n+move_to_original_branch () {\n+\tcase \"$head_name\" in\n+\trefs/*)\n+\t\tmessage=\"rebase finished: $head_name onto $onto\"\n+\t\tgit update-ref -m \"$message\" \\\n+\t\t\t$head_name $(git rev-parse HEAD) $orig_head &&\n+\t\tgit symbolic-ref \\\n+\t\t\t-m \"rebase finished: returning to $head_name\" \\\n+\t\t\tHEAD $head_name ||\n+\t\tdie \"$(gettext \"Could not move back to $head_name\")\"\n+\t\t;;\n+\tesac\n+}\n+\n read_state () {\n \tonto_name=$(cat \"$state_dir\"/onto_name) &&\n \tend=$(cat \"$state_dir\"/end) &&\ndiff --git a/git-rebase.sh b/git-rebase.sh\nindex 42e868d..ff2c2ae 100755\n--- a/git-rebase.sh\n+++ b/git-rebase.sh\n@@ -156,6 +156,8 @@ run_specific_rebase () {\n \texport state_dir verbose strategy strategy_opts\n \tif [ \"$type\" = am ]; then\n \t\texec git-rebase--am\n+\telif [ \"$type\" = merge ]; then\n+\t\texec git-rebase--merge\n \telse\n \t\t. git-rebase--$type\n \tfi\n-- \n2.3.0.rc1.137.g477eb31\n"},{"id":"257930","messageId":"1426672547-11369-6-git-send-email-pclouds@gmail.com","threadId":"38843","inReplyTo":"1426672547-11369-1-git-send-email-pclouds@gmail.com","subject":"[PATCH/WIP 5/8] rebase: turn rebase--interactive into a separate program","fromName":"Nguyễn Thái Ngọc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2015-03-18T09:55:44Z","receivedAt":"2015-03-18T09:55:44Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"---\n Makefile                             |  2 +-\n git-rebase--interactive.sh (mode +x) | 36 +++++++++++++++++++++++++++++++++++-\n git-rebase.sh                        |  9 ++-------\n 3 files changed, 38 insertions(+), 9 deletions(-)\n mode change 100644 => 100755 git-rebase--interactive.sh\n\ndiff --git a/Makefile b/Makefile\nindex 7ee8df7..83972a2 100644\n--- a/Makefile\n+++ b/Makefile\n@@ -446,6 +446,7 @@ SCRIPT_SH += git-pull.sh\n SCRIPT_SH += git-quiltimport.sh\n SCRIPT_SH += git-rebase.sh\n SCRIPT_SH += git-rebase--am.sh\n+SCRIPT_SH += git-rebase--interactive.sh\n SCRIPT_SH += git-rebase--merge.sh\n SCRIPT_SH += git-repack.sh\n SCRIPT_SH += git-request-pull.sh\n@@ -455,7 +456,6 @@ SCRIPT_SH += git-web--browse.sh\n \n SCRIPT_LIB += git-mergetool--lib\n SCRIPT_LIB += git-parse-remote\n-SCRIPT_LIB += git-rebase--interactive\n SCRIPT_LIB += git-sh-setup\n SCRIPT_LIB += git-sh-i18n\n \ndiff --git a/git-rebase--interactive.sh b/git-rebase--interactive.sh\nold mode 100644\nnew mode 100755\nindex 44901d5..b1c71a9\n--- a/git-rebase--interactive.sh\n+++ b/git-rebase--interactive.sh\n@@ -9,7 +9,14 @@\n #\n # The original idea comes from Eric W. Biederman, in\n # http://article.gmane.org/gmane.comp.version-control.git/22407\n-#\n+\n+. git-sh-setup\n+. git-sh-i18n\n+set_reflog_action \"rebase -i ($action)\"\n+require_work_tree_exists\n+\n+GIT_QUIET=$git_quiet\n+\n # The file containing rebase commands, comments, and empty lines.\n # This file is created by \"git rebase -i\" then edited by the user.  As\n # the lines are processed, they are removed from the front of this\n@@ -80,6 +87,33 @@ rewritten_pending=\"$state_dir\"/rewritten-pending\n GIT_CHERRY_PICK_HELP=\"$resolvemsg\"\n export GIT_CHERRY_PICK_HELP\n \n+write_basic_state () {\n+\techo \"$head_name\" > \"$state_dir\"/head-name &&\n+\techo \"$onto\" > \"$state_dir\"/onto &&\n+\techo \"$orig_head\" > \"$state_dir\"/orig-head &&\n+\techo \"$GIT_QUIET\" > \"$state_dir\"/quiet &&\n+\ttest t = \"$verbose\" && : > \"$state_dir\"/verbose\n+\ttest -n \"$strategy\" && echo \"$strategy\" > \"$state_dir\"/strategy\n+\ttest -n \"$strategy_opts\" && echo \"$strategy_opts\" > \\\n+\t\t\"$state_dir\"/strategy_opts\n+\ttest -n \"$allow_rerere_autoupdate\" && echo \"$allow_rerere_autoupdate\" > \\\n+\t\t\"$state_dir\"/allow_rerere_autoupdate\n+}\n+\n+output () {\n+\tcase \"$verbose\" in\n+\t'')\n+\t\toutput=$(\"$@\" 2>&1 )\n+\t\tstatus=$?\n+\t\ttest $status != 0 && printf \"%s\\n\" \"$output\"\n+\t\treturn $status\n+\t\t;;\n+\t*)\n+\t\t\"$@\"\n+\t\t;;\n+\tesac\n+}\n+\n warn () {\n \tprintf '%s\\n' \"$*\" >&2\n }\ndiff --git a/git-rebase.sh b/git-rebase.sh\nindex ff2c2ae..86119e7 100755\n--- a/git-rebase.sh\n+++ b/git-rebase.sh\n@@ -154,13 +154,8 @@ run_specific_rebase () {\n \texport action allow_rerere_autoupdate git_am_opt git_quiet head_name keep_empty\n \texport onto orig_head rebase_root resolvemsg revisions\n \texport state_dir verbose strategy strategy_opts\n-\tif [ \"$type\" = am ]; then\n-\t\texec git-rebase--am\n-\telif [ \"$type\" = merge ]; then\n-\t\texec git-rebase--merge\n-\telse\n-\t\t. git-rebase--$type\n-\tfi\n+\texport autosquash cmd force_rebase preserve_merges squash_onto switch_to upstream\n+\texec git-rebase--$type\n }\n \n run_pre_rebase_hook () {\n-- \n2.3.0.rc1.137.g477eb31\n"},{"id":"257931","messageId":"1426672547-11369-7-git-send-email-pclouds@gmail.com","threadId":"38843","inReplyTo":"1426672547-11369-1-git-send-email-pclouds@gmail.com","subject":"[PATCH/WIP 6/8] rebase: remove unused function","fromName":"Nguyễn Thái Ngọc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2015-03-18T09:55:45Z","receivedAt":"2015-03-18T09:55:45Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"git-rebase.sh is no longer a dependency for rebase subscripts. This\nfunction is only used by subscripts only, which now becomes useless.\n---\n git-rebase.sh | 13 -------------\n 1 file changed, 13 deletions(-)\n\ndiff --git a/git-rebase.sh b/git-rebase.sh\nindex 86119e7..d941239 100755\n--- a/git-rebase.sh\n+++ b/git-rebase.sh\n@@ -102,19 +102,6 @@ read_basic_state () {\n \t\tallow_rerere_autoupdate=\"$(cat \"$state_dir\"/allow_rerere_autoupdate)\"\n }\n \n-write_basic_state () {\n-\techo \"$head_name\" > \"$state_dir\"/head-name &&\n-\techo \"$onto\" > \"$state_dir\"/onto &&\n-\techo \"$orig_head\" > \"$state_dir\"/orig-head &&\n-\techo \"$GIT_QUIET\" > \"$state_dir\"/quiet &&\n-\ttest t = \"$verbose\" && : > \"$state_dir\"/verbose\n-\ttest -n \"$strategy\" && echo \"$strategy\" > \"$state_dir\"/strategy\n-\ttest -n \"$strategy_opts\" && echo \"$strategy_opts\" > \\\n-\t\t\"$state_dir\"/strategy_opts\n-\ttest -n \"$allow_rerere_autoupdate\" && echo \"$allow_rerere_autoupdate\" > \\\n-\t\t\"$state_dir\"/allow_rerere_autoupdate\n-}\n-\n output () {\n \tcase \"$verbose\" in\n \t'')\n-- \n2.3.0.rc1.137.g477eb31\n"},{"id":"257932","messageId":"1426672547-11369-8-git-send-email-pclouds@gmail.com","threadId":"38843","inReplyTo":"1426672547-11369-1-git-send-email-pclouds@gmail.com","subject":"[PATCH/WIP 7/8] rebase: move resolvemsg to rebase--* scripts","fromName":"Nguyễn Thái Ngọc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2015-03-18T09:55:46Z","receivedAt":"2015-03-18T09:55:46Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"---\n git-rebase--am.sh          | 5 +++++\n git-rebase--interactive.sh | 5 +++++\n git-rebase--merge.sh       | 5 +++++\n git-rebase.sh              | 7 +------\n 4 files changed, 16 insertions(+), 6 deletions(-)\n\ndiff --git a/git-rebase--am.sh b/git-rebase--am.sh\nindex ab84330..399956b 100755\n--- a/git-rebase--am.sh\n+++ b/git-rebase--am.sh\n@@ -9,6 +9,11 @@ set_reflog_action rebase\n require_work_tree_exists\n \n GIT_QUIET=$git_quiet\n+resolvemsg=\"\n+$(gettext 'When you have resolved this problem, run \"git rebase --continue\".\n+If you prefer to skip this patch, run \"git rebase --skip\" instead.\n+To check out the original branch and stop rebasing, run \"git rebase --abort\".')\n+\"\n \n write_basic_state () {\n \techo \"$head_name\" > \"$state_dir\"/head-name &&\ndiff --git a/git-rebase--interactive.sh b/git-rebase--interactive.sh\nindex b1c71a9..337dec3 100755\n--- a/git-rebase--interactive.sh\n+++ b/git-rebase--interactive.sh\n@@ -16,6 +16,11 @@ set_reflog_action \"rebase -i ($action)\"\n require_work_tree_exists\n \n GIT_QUIET=$git_quiet\n+resolvemsg=\"\n+$(gettext 'When you have resolved this problem, run \"git rebase --continue\".\n+If you prefer to skip this patch, run \"git rebase --skip\" instead.\n+To check out the original branch and stop rebasing, run \"git rebase --abort\".')\n+\"\n \n # The file containing rebase commands, comments, and empty lines.\n # This file is created by \"git rebase -i\" then edited by the user.  As\ndiff --git a/git-rebase--merge.sh b/git-rebase--merge.sh\nindex baaef41..7e240be 100755\n--- a/git-rebase--merge.sh\n+++ b/git-rebase--merge.sh\n@@ -9,6 +9,11 @@ set_reflog_action rebase\n require_work_tree_exists\n \n GIT_QUIET=$git_quiet\n+resolvemsg=\"\n+$(gettext 'When you have resolved this problem, run \"git rebase --continue\".\n+If you prefer to skip this patch, run \"git rebase --skip\" instead.\n+To check out the original branch and stop rebasing, run \"git rebase --abort\".')\n+\"\n \n prec=4\n \ndiff --git a/git-rebase.sh b/git-rebase.sh\nindex d941239..38530e8 100755\n--- a/git-rebase.sh\n+++ b/git-rebase.sh\n@@ -49,11 +49,6 @@ cd_to_toplevel\n LF='\n '\n ok_to_skip_pre_rebase=\n-resolvemsg=\"\n-$(gettext 'When you have resolved this problem, run \"git rebase --continue\".\n-If you prefer to skip this patch, run \"git rebase --skip\" instead.\n-To check out the original branch and stop rebasing, run \"git rebase --abort\".')\n-\"\n unset onto\n cmd=\n strategy=\n@@ -139,7 +134,7 @@ run_specific_rebase () {\n \tgit_quiet=$GIT_QUIET\n \texport GIT_PAGER\n \texport action allow_rerere_autoupdate git_am_opt git_quiet head_name keep_empty\n-\texport onto orig_head rebase_root resolvemsg revisions\n+\texport onto orig_head rebase_root revisions\n \texport state_dir verbose strategy strategy_opts\n \texport autosquash cmd force_rebase preserve_merges squash_onto switch_to upstream\n \texec git-rebase--$type\n-- \n2.3.0.rc1.137.g477eb31\n"},{"id":"257933","messageId":"1426672547-11369-9-git-send-email-pclouds@gmail.com","threadId":"38843","inReplyTo":"1426672547-11369-1-git-send-email-pclouds@gmail.com","subject":"[PATCH/WIP 8/8] Build in rebase","fromName":"Nguyễn Thái Ngọc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2015-03-18T09:55:47Z","receivedAt":"2015-03-18T09:55:47Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"---\n Makefile                                |   2 +-\n builtin.h                               |   1 +\n builtin/rebase.c (new)                  | 752 ++++++++++++++++++++++++++++++++\n commit.c                                |   4 +-\n commit.h                                |   4 +-\n contrib/examples/git-rebase.sh (new +x) | 532 ++++++++++++++++++++++\n git-rebase.sh (gone)                    | 532 ----------------------\n git.c                                   |   1 +\n 8 files changed, 1291 insertions(+), 537 deletions(-)\n create mode 100644 builtin/rebase.c\n create mode 100755 contrib/examples/git-rebase.sh\n delete mode 100755 git-rebase.sh\n\ndiff --git a/Makefile b/Makefile\nindex 83972a2..223d50b 100644\n--- a/Makefile\n+++ b/Makefile\n@@ -444,7 +444,6 @@ SCRIPT_SH += git-merge-resolve.sh\n SCRIPT_SH += git-mergetool.sh\n SCRIPT_SH += git-pull.sh\n SCRIPT_SH += git-quiltimport.sh\n-SCRIPT_SH += git-rebase.sh\n SCRIPT_SH += git-rebase--am.sh\n SCRIPT_SH += git-rebase--interactive.sh\n SCRIPT_SH += git-rebase--merge.sh\n@@ -903,6 +902,7 @@ BUILTIN_OBJS += builtin/prune-packed.o\n BUILTIN_OBJS += builtin/prune.o\n BUILTIN_OBJS += builtin/push.o\n BUILTIN_OBJS += builtin/read-tree.o\n+BUILTIN_OBJS += builtin/rebase.o\n BUILTIN_OBJS += builtin/receive-pack.o\n BUILTIN_OBJS += builtin/reflog.o\n BUILTIN_OBJS += builtin/remote.o\ndiff --git a/builtin.h b/builtin.h\nindex 7e7bbd6..431bbbf 100644\n--- a/builtin.h\n+++ b/builtin.h\n@@ -108,6 +108,7 @@ extern int cmd_prune(int argc, const char **argv, const char *prefix);\n extern int cmd_prune_packed(int argc, const char **argv, const char *prefix);\n extern int cmd_push(int argc, const char **argv, const char *prefix);\n extern int cmd_read_tree(int argc, const char **argv, const char *prefix);\n+extern int cmd_rebase(int argc, const char **argv, const char *prefix);\n extern int cmd_receive_pack(int argc, const char **argv, const char *prefix);\n extern int cmd_reflog(int argc, const char **argv, const char *prefix);\n extern int cmd_remote(int argc, const char **argv, const char *prefix);\ndiff --git a/builtin/rebase.c b/builtin/rebase.c\nnew file mode 100644\nindex 0000000..29eff0e\n--- /dev/null\n+++ b/builtin/rebase.c\n@@ -0,0 +1,752 @@\n+#include \"cache.h\"\n+#include \"parse-options.h\"\n+#include \"argv-array.h\"\n+#include \"run-command.h\"\n+#include \"tree-walk.h\"\n+#include \"unpack-trees.h\"\n+#include \"diff.h\"\n+#include \"commit.h\"\n+#include \"revision.h\"\n+#include \"submodule.h\"\n+#include \"commit.h\"\n+#include \"dir.h\"\n+\n+#define REBASE_AM\t\t1\n+#define REBASE_MERGE\t\t2\n+#define REBASE_INTERACTIVE\t3\n+\n+static const char * const builtin_rebase_usage[] = {\n+\tN_(\"git rebase [-i] [options] [--exec <cmd>] [--onto <newbase>] [<upstream>] [<branch>]\"),\n+\tN_(\"git rebase [-i] [options] [--exec <cmd>] [--onto <newbase>] --root [<branch>]\"),\n+\tN_(\"git rebase --continue | --abort | --skip | --edit-todo\"),\n+\tNULL\n+};\n+\n+/* These are exported as environment variables for git-rebase--*.sh */\n+static int action_abort;\n+static int action_continue;\n+static int action_skip;\n+static int autosquash;\n+static int force_rebase;\n+static int keep_empty;\n+static int preserve_merges;\n+static int quiet;\n+static int rerere_autoupdate;\n+static int root;\n+static int verbose;\n+static const char *exec_cmd;\n+static const char *head_name;\n+static const char *onto;\n+static const char *orig_head;\n+static struct strbuf revisions = STRBUF_INIT;\n+static const char *state_basedir;\n+static const char *strategy;\n+static const char *strategy_opts;\n+static const char *switch_to;\n+static const char *squash_onto;\n+\n+static int do_merge;\n+static int edit_todo;\n+static int interactive_rebase;\n+static int rebase_type;\n+static int show_stat;\n+\n+static char *read_file(const char *name)\n+{\n+\tstruct strbuf sb = STRBUF_INIT;\n+\tif (strbuf_read_file(&sb,\n+\t\t\t     git_path(\"%s/%s\", state_basedir, name),\n+\t\t\t     0) >= 0)\n+\t\treturn strbuf_detach(&sb, NULL);\n+\telse\n+\t\treturn NULL;\n+}\n+\n+static char *read_file_or_die(const char *name)\n+{\n+\tstruct strbuf sb = STRBUF_INIT;\n+\tstrbuf_read_file_or_die(&sb,\n+\t\t\t\tgit_path(\"%s/%s\", state_basedir, name),\n+\t\t\t\t0);\n+\treturn strbuf_detach(&sb, NULL);\n+}\n+\n+static void read_bool(const char *name, int *var)\n+{\n+\tchar *buf = read_file(name);\n+\tif (buf) {\n+\t\t*var = buf[0] && !isspace(buf[0]);\n+\t\tfree(buf);\n+\t}\n+}\n+\n+static int read_bool_or_die(const char *name)\n+{\n+\tchar *buf = read_file_or_die(name);\n+\tint ret = buf[0] && !isspace(buf[0]);\n+\tfree(buf);\n+\treturn ret;\n+}\n+\n+/*\n+ * Note:\n+ *\n+ * After git-rebase--*.sh are integrated, we should probably adopt\n+ * git-config format and store everything in one file instead of so\n+ * many like this. state_dir will be something different to avoid\n+ * misuse by old rebase versions. This code will stay for a few major\n+ * releases before being phased out.\n+ */\n+static void read_basic_state()\n+{\n+\thead_name = read_file_or_die(\"head-name\");\n+\tonto = read_file_or_die(\"onto\");\n+\t/*\n+\t * We always write to orig-head, but interactive rebase used\n+\t * to write to head. Fall back to reading from head to cover\n+\t * for the case that the user upgraded git with an ongoing\n+\t * interactive rebase.\n+\t */\n+\tif ((orig_head = read_file(\"orig-head\")) == NULL)\n+\t\torig_head = read_file_or_die(\"head\");\n+\tquiet = read_bool_or_die(\"quiet\");\n+\tread_bool(\"verbose\", &verbose);\n+\tstrategy = read_file(\"strategy\");\n+\tstrategy_opts = read_file(\"strategy_opts\");\n+\tread_bool(\"allow_rerere_autoupdate\", &rerere_autoupdate);\n+}\n+\n+static void push_env_string(struct argv_array *argv,\n+\t\t\t    const char *name,\n+\t\t\t    const char *value)\n+{\n+\tstruct strbuf sb = STRBUF_INIT;\n+\tstrbuf_addf(&sb, \"%s=%s\", name, value);\n+\targv_array_push(argv, sb.buf);\n+\tstrbuf_release(&sb);\n+}\n+\n+static void push_env_bool(struct argv_array *argv,\n+\t\t\t  const char *name,\n+\t\t\t  int value)\n+{\n+\tstruct strbuf sb = STRBUF_INIT;\n+\tstrbuf_addf(&sb, \"%s=%s\", name, value ? \"t\" : \"\");\n+\targv_array_push(argv, sb.buf);\n+\tstrbuf_release(&sb);\n+}\n+\n+static int run_specific_rebase()\n+{\n+\tstruct child_process cmd;\n+\tstruct argv_array env = ARGV_ARRAY_INIT;\n+\tconst char *argv[2];\n+\tint ret;\n+\n+\tif (interactive_rebase == -1) {\n+\t\targv_array_push(&env, \"GIT_EDITOR=:\");\n+\t\tautosquash = 0;\n+\t}\n+\tpush_env_bool(&env, \"git_quiet\", quiet);\n+\tif (action_continue)\n+\t\targv_array_push(&env, \"action=continue\");\n+\telse if (action_skip)\n+\t\targv_array_push(&env, \"action=skip\");\n+\telse if (action_abort)\n+\t\targv_array_push(&env, \"action=abort\");\n+\telse if (edit_todo)\n+\t\targv_array_push(&env, \"action=edit-todo\");\n+\telse\n+\t\targv_array_push(&env, \"action=\");\n+\tpush_env_bool(&env,   \"allow_rerere_autoupdate\", rerere_autoupdate);\n+\tpush_env_bool(&env,   \"autosquash\",              autosquash);\n+\tpush_env_string(&env, \"cmd\",                     exec_cmd);\n+\tpush_env_bool(&env,   \"force_rebase\",            force_rebase);\n+\tpush_env_string(&env, \"git_am_opt\", \"\"/* git_am_opt */);\n+\tpush_env_string(&env, \"head_name\",               head_name);\n+\tpush_env_bool(&env,   \"keep_empty\",              keep_empty);\n+\tpush_env_string(&env, \"onto\",                    onto);\n+\tpush_env_string(&env, \"orig_head\",               orig_head);\n+\tpush_env_bool(&env,   \"preserve_merges\",         preserve_merges);\n+\tpush_env_bool(&env,   \"rebase_root\",             root);\n+\tpush_env_string(&env, \"revisions\",               revisions.buf);\n+\tpush_env_string(&env, \"squash_onto\",             squash_onto);\n+\tpush_env_string(&env, \"state_dir\", git_path(\"%s\", state_basedir));\n+\tpush_env_string(&env, \"strategy\", strategy);\n+\tpush_env_string(&env, \"strategy_opts\", strategy_opts);\n+\tpush_env_string(&env, \"switch_to\", switch_to);\n+\t/* upstream */\n+\tpush_env_bool(&env, \"verbose\", verbose);\n+\n+\tswitch (rebase_type) {\n+\tcase REBASE_INTERACTIVE: argv[0] = \"rebase--interactive\"; break;\n+\tcase REBASE_AM:\t\t argv[0] = \"rebase--am\";\t  break;\n+\tcase REBASE_MERGE:\t argv[0] = \"rebase--merge\";\t  break;\n+\tdefault:\n+\t\tdie(\"BUG: unsupported rebase type %d\", rebase_type);\n+\t}\n+\targv[1] = NULL;\n+\n+\tmemset(&cmd, 0, sizeof(cmd));\n+\tcmd.in  = 0;\n+\tcmd.out = 1;\n+\tcmd.err = 2;\n+\tcmd.git_cmd = 1;\n+\tcmd.env = env.argv;\n+\tcmd.argv = argv;\n+\tret = run_command(&cmd);\n+\tif (ret)\n+\t\tdie_errno(\"failed to run %s\", argv[0]);\n+\n+\targv_array_clear(&env);\n+\treturn ret;\n+}\n+\n+static int do_continue()\n+{\n+\tunsigned char sha1[20];\n+\tif (get_sha1(\"HEAD\", sha1))\n+\t\tdie(_(\"Cannot read HEAD\"));\n+\tif (read_cache_unmerged()) {\n+\t\tprintf(_(\"You must edit all merge conflicts and then\\n\"\n+\t\t\t \"mark them as resolved using 'git add'\\n\"));\n+\t\treturn 1;\n+\t}\n+\tread_basic_state();\n+\treturn run_specific_rebase();\n+}\n+\n+static int do_skip()\n+{\n+\tint ret, error = 0;\n+\tunsigned char sha1[20];\n+\tif (get_sha1(\"HEAD\", sha1))\n+\t\tdie(_(\"Cannot read HEAD\"));\n+\n+\tret = reset_tree(lookup_commit(sha1)->tree, quiet, 1, &error);\n+\tif (ret)\n+\t\treturn ret;\n+\tread_basic_state();\n+\treturn run_specific_rebase();\n+}\n+\n+static int do_abort()\n+{\n+\tint ret, error = 0;\n+\tunsigned char sha1[20];\n+\tconst char *rerere[] = { \"rerere\", \"clear\", NULL };\n+\tstruct strbuf path = STRBUF_INIT;\n+\n+\tret = run_command_v_opt(rerere, RUN_GIT_CMD);\n+\tif (ret)\n+\t\treturn ret;\n+\tread_basic_state();\n+\tif (!prefixcmp(head_name, \"refs/\"))\n+\t\tcreate_symref(\"HEAD\", head_name, \"rebase: aborting\");\n+\n+\tif (get_sha1(orig_head, sha1))\n+\t\tdie(_(\"Cannot read %s\"), orig_head);\n+\n+\tret = reset_tree(lookup_commit(sha1)->tree, quiet, 1, &error);\n+\tif (ret)\n+\t\treturn ret;\n+\n+\tstrbuf_addstr(&path, git_path(\"%s\", state_basedir));\n+\tremove_dir_recursively(&path, 0);\n+\tstrbuf_release(&path);\n+\treturn 0;\n+}\n+\n+static int do_edit_todo()\n+{\n+\tif (rebase_type != REBASE_INTERACTIVE)\n+\t\tdie(_(\"The --edit-todo action can only be \"\n+\t\t      \"used during interactive rebase.\"));\n+\treturn run_specific_rebase();\n+}\n+\n+static void error_on_missing_default_upstream()\n+{\n+\tunsigned char sha1[20];\n+\tconst char *head = resolve_ref_unsafe(\"HEAD\", sha1, 0, NULL);\n+\tif (!head)\n+\t\tdie(_(\"Failed to resolve HEAD as a valid ref.\"));\n+\tif (!strcmp(head, \"HEAD\")) {\n+\t\tprintf(_(\"You are not currently on a branch. Please specify which\\n\"\n+\t\t\t \"branch you want to rebase against. See git-rebase(1) for details.\\n\"\n+\t\t\t \"\\n\"\n+\t\t\t \"    git rebase <branch>\\n\"));\n+\t\treturn;\n+\t}\n+\n+\tif (!prefixcmp(head, \"refs/heads/\"))\n+\t\thead += strlen(\"refs/heads/\");\n+\tprintf(_(\"There is no tracking information for the current branch.\\n\"\n+\t\t \"Please specify which branch you want to rebase against.\\n\"\n+\t\t \"See git-rebase(1) for details\\n\"\n+\t\t \"\\n\"\n+\t\t \"    git rebase <branch>\\n\"\n+\t\t \"\\n\"\n+\t\t \"If you wish to set tracking information for this branch you can do so with:\\n\"\n+\t\t \"\\n\"\n+\t\t \"    git branch --set-upstream-to=$remote/<branch> %s\\n\"),\n+\t       head);\n+}\n+\n+static int determine_upstream(int argc, const char **argv,\n+\t\t\t      const struct option *options,\n+\t\t\t      const char **upstream_name,\n+\t\t\t      const char **upstream_arg)\n+{\n+\tint consumed = 0;\n+\tif (!root) {\n+\t\tunsigned char sha1[20];\n+\t\tif (argc) {\n+\t\t\t*upstream_name = argv[0];\n+\t\t\targv++;\n+\t\t\targc--;\n+\t\t\tconsumed++;\n+\t\t} else {\n+\t\t\t*upstream_name = \"@{upstream}\";\n+\t\t\tif (get_sha1(*upstream_name, sha1)) {\n+\t\t\t\terror_on_missing_default_upstream();\n+\t\t\t\texit(1);\n+\t\t\t}\n+\t\t}\n+\t\tif (get_sha1(*upstream_name, sha1))\n+\t\t\tdie(_(\"Failed to resolve %s.\"), *upstream_name);\n+\t\tlookup_commit_or_die(sha1, *upstream_name);\n+\t\t*upstream_arg = *upstream_name;\n+\t\treturn consumed;\n+\t}\n+\n+\tif (!onto) {\n+\t\tunsigned char sha1[20];\n+\t\tstruct strbuf sb = STRBUF_INIT;\n+\t\tif (commit_tree(&sb, EMPTY_TREE_SHA1_BIN, NULL, sha1, NULL, NULL))\n+\t\t\tdie(_(\"failed to create empty-tree commit\"));\n+\t\tonto = xstrdup(sha1_to_hex(sha1));\n+\t\tsquash_onto = onto;\n+\t}\n+\tif (argc > 1)\n+\t\tusage_with_options(builtin_rebase_usage,\n+\t\t\t\t   options);\n+\t*upstream_arg = \"--root\";\n+\treturn consumed;\n+}\n+\n+static void require_clean_work_tree()\n+{\n+\tstruct rev_info rev;\n+\tunsigned char sha1[20];\n+\tint err = 0;\n+\n+\tif (get_sha1(\"HEAD\", sha1))\n+\t\tdie(\"HEAD is not a valid ref\");\n+\n+\tif (read_cache() < 0)\n+\t\tdie(_(\"unable to read index file\"));\n+\trefresh_cache(REFRESH_QUIET | REFRESH_IGNORE_SUBMODULES);\n+\n+\tinit_revisions(&rev, NULL);\n+\tDIFF_OPT_SET(&rev.diffopt, QUICK);\n+\tDIFF_OPT_SET(&rev.diffopt, OVERRIDE_SUBMODULE_CONFIG);\n+\thandle_ignore_submodules_arg(&rev.diffopt, \"all\");\n+\tdiff_setup_done(&rev.diffopt);\n+\trun_diff_files(&rev, 0);\n+\tif (DIFF_OPT_TST(&rev.diffopt, HAS_CHANGES)) {\n+\t\tfputs(_(\"Cannot rebase: You have unstaged changes.\\n\"), stderr);\n+\t\terr = 1;\n+\t}\n+\n+\tinit_revisions(&rev, NULL);\n+\tDIFF_OPT_SET(&rev.diffopt, QUICK);\n+\tDIFF_OPT_SET(&rev.diffopt, OVERRIDE_SUBMODULE_CONFIG);\n+\thandle_ignore_submodules_arg(&rev.diffopt, \"all\");\n+\tdiff_setup_done(&rev.diffopt);\n+\tadd_head_to_pending(&rev);\n+\trun_diff_index(&rev, 1);\n+\tif (DIFF_OPT_TST(&rev.diffopt, HAS_CHANGES)) {\n+\t\tconst char *msg = err ?\n+\t\t\t_(\"Additionally, your index contains uncommitted changes.\\n\") :\n+\t\t\t_(\"Cannot rebase: Your index contains uncommitted changes.\\n\");\n+\t\tfputs(msg, stderr);\n+\t\terr = 1;\n+\t}\n+\n+\tif (err) {\n+\t\tfputs(_(\"Please commit or stash them.\\n\"), stderr);\n+\t\texit(1);\n+\t}\n+}\n+\n+static void run_pre_rebase_hook(int argc, const char **argv,\n+\t\t\t\tconst char *upstream_arg)\n+{\n+\t/*\n+\tif test -z \"$ok_to_skip_pre_rebase\" &&\n+\t   test -x \"$GIT_DIR/hooks/pre-rebase\"\n+\tthen\n+\t\t\"$GIT_DIR/hooks/pre-rebase\" ${1+\"$@\"} ||\n+\t\tdie \"$(gettext \"The pre-rebase hook refused to rebase.\")\"\n+\tfi\n+\t */\n+}\n+\n+static int do_rebase(int argc, const char **argv,\n+\t\t     const struct option *options)\n+{\n+\tconst char *upstream_name = NULL;\n+\tconst char *upstream_arg = NULL;\n+\tconst char *branch_name;\n+\tconst char *onto_name;\n+\tunsigned char onto_sha1[20];\n+\n+\tint n;\n+\tif (root && !onto && !interactive_rebase)\n+\t\tinteractive_rebase = -1; /* implied */\n+\n+\tif (interactive_rebase) {\n+\t\trebase_type = REBASE_INTERACTIVE;\n+\t\tstate_basedir = \"rebase-merge\";\n+\t} else if (do_merge) {\n+\t\trebase_type = REBASE_MERGE;\n+\t\tstate_basedir = \"rebase-merge\";\n+\t} else {\n+\t\trebase_type = REBASE_AM;\n+\t\tstate_basedir = \"rebase-apply\";\n+\t}\n+\n+\tn = determine_upstream(argc, argv, options,\n+\t\t\t       &upstream_name, &upstream_arg);\n+\targc += n;\n+\targv += n;\n+\n+\tif (root)\n+\t\tupstream_arg = \"--root\";\n+\n+\t/* Make sure the branch to rebase onto is valid. */\n+\tonto_name = onto ? onto : upstream_name;\n+\tif (strstr(onto, \"...\")) {\n+\t\t/*\n+case \"$onto_name\" in\n+*...*)\n+\tif\tleft=${onto_name%...*} right=${onto_name#*...} &&\n+\t\tonto=$(git merge-base --all ${left:-HEAD} ${right:-HEAD})\n+\tthen\n+\t\tcase \"$onto\" in\n+\t\t?*\"$LF\"?*)\n+\t\t\tdie \"$(eval_gettext \"\\$onto_name: there are more than one merge bases\")\"\n+\t\t\t;;\n+\t\t'')\n+\t\t\tdie \"$(eval_gettext \"\\$onto_name: there is no merge base\")\"\n+\t\t\t;;\n+\t\tesac\n+\telse\n+\t\tdie \"$(eval_gettext \"\\$onto_name: there is no merge base\")\"\n+\tfi\n+\t;;\n+\t\t*/\n+\t} else {\n+\t\tif (get_sha1(onto_name, onto_sha1) || !lookup_commit(onto_sha1))\n+\t\t\tdie(_(\"Does not point to a valid commit: %s\"), onto_name);\n+\t}\n+\n+\t/*\n+\t * If the branch to rebase is given, that is the branch we\n+\t * will rebase\n+\t *\n+\t * $branch_name -- branch being rebased, or HEAD (already\n+\t * detached)\n+\t *\n+\t * $orig_head -- commit object name of tip of the branch\n+\t * before rebasing\n+\t *\n+\t * $head_name -- refs/heads/<that-branch> or \"detached HEAD\"\n+\t */\n+\tswitch (argc) {\n+\tcase 1:\n+\t\t/* Is it \"rebase other $branchname\" or \"rebase other $commit\"? */\n+\t\tbranch_name = argv[0];\n+\t\tswitch_to = argv[0];\n+\t\t/*\n+\tif git show-ref --verify --quiet -- \"refs/heads/$1\" &&\n+\t   orig_head=$(git rev-parse -q --verify \"refs/heads/$1\")\n+\tthen\n+\t\thead_name=\"refs/heads/$1\"\n+\telif orig_head=$(git rev-parse -q --verify \"$1\")\n+\tthen\n+\t\thead_name=\"detached HEAD\"\n+\telse\n+\t\tdie \"$(eval_gettext \"fatal: no such branch: \\$branch_name\")\"\n+\tfi\n+\t */\n+\t\tbreak;\n+\n+\tcase 0:\n+\t\t/*\n+\t# Do not need to switch branches, we are already on it.\n+\tif branch_name=`git symbolic-ref -q HEAD`\n+\tthen\n+\t\thead_name=$branch_name\n+\t\tbranch_name=`expr \"z$branch_name\" : 'zrefs/heads/\\(.*\\)'`\n+\telse\n+\t\thead_name=\"detached HEAD\"\n+\t\tbranch_name=HEAD ;# detached\n+\tfi\n+\torig_head=$(git rev-parse --verify \"${branch_name}^0\") || exit\n+\t\t */\n+\t\tbreak;\n+\tdefault:\n+\t\tdie(\"BUG: unexpected number of arguments left to parse\");\n+\t}\n+\n+\trequire_clean_work_tree();\n+\n+\t/*\n+\t * Now we are rebasing commits $upstream..$orig_head (or with\n+\t * --root, everything leading up to $orig_head) on top of\n+\t * $onto\n+\t */\n+\n+\t/*\n+\t * Check if we are already based on $onto with linear history,\n+\t * but this should be done only when upstream and onto are the\n+\t * same and if this is not an interactive rebase.\n+\t */\n+\n+\t/*\n+mb=$(git merge-base \"$onto\" \"$orig_head\")\n+if test \"$type\" != interactive && test \"$upstream\" = \"$onto\" &&\n+\ttest \"$mb\" = \"$onto\" &&\n+\t# linear history?\n+\t! (git rev-list --parents \"$onto\"..\"$orig_head\" | sane_grep \" .* \") > /dev/null\n+then\n+\tif test -z \"$force_rebase\"\n+\tthen\n+\t\t# Lazily switch to the target branch if needed...\n+\t\ttest -z \"$switch_to\" || git checkout \"$switch_to\" --\n+\t\tsay \"$(eval_gettext \"Current branch \\$branch_name is up to date.\")\"\n+\t\texit 0\n+\telse\n+\t\tsay \"$(eval_gettext \"Current branch \\$branch_name is up to date, rebase forced.\")\"\n+\tfi\n+fi\n+\t*/\n+\n+\t/* If a hook exists, give it a chance to interrupt */\n+\trun_pre_rebase_hook(argc, argv, upstream_arg);\n+\n+\t/*\n+if test -n \"$diffstat\"\n+then\n+\tif test -n \"$verbose\"\n+\tthen\n+\t\techo \"$(eval_gettext \"Changes from \\$mb to \\$onto:\")\"\n+\tfi\n+\t# We want color (if set), but no pager\n+\tGIT_PAGER='' git diff --stat --summary \"$mb\" \"$onto\"\n+fi\n+\t*/\n+\n+\tif (rebase_type == REBASE_INTERACTIVE)\n+\t\treturn run_specific_rebase();\n+\n+\t/* Detach HEAD and reset the tree */\n+\t/*\n+say \"$(gettext \"First, rewinding head to replay your work on top of it...\")\"\n+git checkout -q \"$onto^0\" || die \"could not detach HEAD\"\n+git update-ref ORIG_HEAD $orig_head\n+\t*/\n+\n+\t/*\n+\t * If the $onto is a proper descendant of the tip of the\n+\t * branch, then we just fast-forwarded.\n+\t */\n+\tif (!hashcmp(mb, orig_head)) {\n+\t\tprintf(_(\"Fast-forwarded %s to %s.\"), branch_name, onto_name);\n+\t\tmove_to_original_branch();\n+\t\treturn 0;\n+\t}\n+\n+\tif (root)\n+\t\tstrbuf_addf(&revisions, \"%s..%s\", onto, orig_head);\n+\telse\n+\t\tstrbuf_addf(&revisions, \"%s..%s\", upstream, orig_head);\n+\n+\treturn run_specific_rebase();\n+}\n+\n+static int git_rebase_config(const char *name, const char *value, void *data)\n+{\n+\tif (!strcmp(name, \"rebase.stat\")) {\n+\t\tshow_stat = git_config_bool(name, value);\n+\t\treturn 0;\n+\t} else if (!strcmp(name, \"rebase.autosquash\")) {\n+\t\tautosquash = git_config_bool(name, value);\n+\t\treturn 0;\n+\t}\n+\treturn git_default_config(name, value, data);\n+}\n+\n+int cmd_rebase(int argc, const char **argv, const char *prefix)\n+{\n+\tconst char *whitespace_opt = NULL;\n+\tint committer_date_is_author_date = 0;\n+\tint context_opt = 0;\n+\tint ignore_date = 0;\n+\tint ignore_whitespace = 0;\n+\tint no_ff = 0;\n+\tint pre_rebase = 1;\n+\tstruct option options[] = {\n+\t\tOPT__VERBOSE(&verbose,\n+\t\t\t     N_(\"display a diffstat of what changed upstream\")),\n+\t\tOPT__QUIET(&quiet,\n+\t\t\t   N_(\"be quiet. implies --no-stat\")),\n+\t\tOPT_STRING(0, \"onto\", &onto, \"ref\",\n+\t\t\t   N_(\"rebase onto given branch instead of upstream\")),\n+\t\tOPT_BOOL('p', \"preserve-merges\", &preserve_merges,\n+\t\t\t N_(\"try to recreate merges instead of ignoring them\")),\n+\t\tOPT_STRING('s', \"stragegy\", &strategy, \"strategy\",\n+\t\t\t   N_(\"use the given merge strategy\")),\n+\t\t{ OPTION_SET_INT, 0, \"no-ff\", &no_ff, NULL,\n+\t\t  N_(\"cherry-pick all commits, even if unchanged\"),\n+\t\t  PARSE_OPT_NOARG | PARSE_OPT_NONEG, NULL, 1 },\n+\t\tOPT_BOOL('m', \"merge\", &do_merge,\n+\t\t\t N_(\"use merging strategies to rebase\")),\n+\t\tOPT_BOOL('i', \"interactive\", &interactive_rebase,\n+\t\t\t N_(\"let the user edit the list of commits to rebase\")),\n+\t\tOPT_STRING('x', \"exec\", &exec_cmd, \"command\",\n+\t\t\t   N_(\"add exec lines after each commit of the editable list\")),\n+\t\tOPT_BOOL('k', \"keep-empty\", &keep_empty,\n+\t\t\t N_(\"preserve empty commits during rebase\")),\n+\t\tOPT_BOOL('f', \"force-rebase\", &force_rebase,\n+\t\t\t N_(\"force rebase even if branch is up to date\")),\n+\t\tOPT_STRING('X', \"strategy-options\", &strategy_opts, \"options\",\n+\t\t\t   N_(\"pass the argument through to the merge strategy\")),\n+\t\t{ OPTION_SET_INT, 0, \"stat\", &show_stat, NULL,\n+\t\t  N_(\"display a diffstat of what changed upstream\"),\n+\t\t  PARSE_OPT_NOARG | PARSE_OPT_NONEG, NULL, 1 },\n+\t\tOPT_SET_INT('n', \"no-stat\", &show_stat,\n+\t\t\t    N_(\"do not show diffstat of what changed upstream\"), 0),\n+\t\tOPT_BOOL(0, \"verify\", &pre_rebase,\n+\t\t\t N_(\"allow pre-rebase hook to run\")),\n+\t\tOPT_BOOL(0, \"rerere-autoupdate\", &rerere_autoupdate,\n+\t\t\t N_(\"allow rerere to update index with resolved conflicts\")),\n+\t\tOPT_BOOL(0, \"root\", &root,\n+\t\t\t N_(\"rebase all reachable commits up to the root(s)\")),\n+\t\tOPT_BOOL(0, \"autosquash\", &autosquash,\n+\t\t\t N_(\"move commits that begin with squash!/fixup! under -i\")),\n+\t\tOPT_BOOL(0, \"committer-date-is-author-date\", &committer_date_is_author_date,\n+\t\t\t N_(\"lie about committer date\")),\n+\t\tOPT_BOOL(0, \"ignore-date\", &ignore_date,\n+\t\t\t N_(\"use current timestamp for author date\")),\n+\t\tOPT_STRING(0, \"whitespace\", &whitespace_opt, \"mode\",\n+\t\t\t   N_(\"detect new or modified lines that have whitespace errors\")),\n+\t\tOPT_INTEGER('C', NULL, &context_opt,\n+\t\t\t    N_(\"ensure at least <n> lines of context match by 'git apply'\")),\n+\t\tOPT_BOOL(0, \"ignore-whitespace\", &ignore_whitespace,\n+\t\t\t N_(\"ignore changes in whitespace when finding context\")),\n+\n+\t\tOPT_GROUP(\"Actions\"),\n+\t\tOPT_BOOL(0, \"continue\", &action_continue,\n+\t\t\t N_(\"continue\")),\n+\t\tOPT_BOOL(0, \"abort\", &action_abort,\n+\t\t\t N_(\"abort and check out the original branch\")),\n+\t\tOPT_BOOL(0, \"skip\", &action_skip,\n+\t\t\t N_(\"skip current patch and continue\")),\n+\t\tOPT_BOOL(0, \"edit-todo\", &edit_todo,\n+\t\t\t N_(\"edit the todo list during an interactive rebase\")),\n+\t\tOPT_END()\n+\t};\n+\tstruct stat st;\n+\tint action_nr, in_progress;\n+\n+\tif (!stat(git_path(\"rebase-apply\"), &st) && S_ISDIR(st.st_mode)) {\n+\t\tif (!access(git_path(\"rebase-apply/applying\"), F_OK))\n+\t\t\tdie(_(\"It looks like git-am is in progress. Cannot rebase.\"));\n+\t\trebase_type = REBASE_AM;\n+\t\tstate_basedir = \"rebase-apply\";\n+\t\tin_progress = 1;\n+\t} else if (!stat(git_path(\"rebase-merge\"), &st) &&\n+\t\t   S_ISDIR(st.st_mode)) {\n+\t\tif (!access(git_path(\"rebase-merge/interactive\"), F_OK)) {\n+\t\t\trebase_type = REBASE_INTERACTIVE;\n+\t\t\tinteractive_rebase = 1; /* explicit */\n+\t\t} else\n+\t\t\trebase_type = REBASE_MERGE;\n+\t\tstate_basedir = \"rebase-merge\";\n+\t\tin_progress = 1;\n+\t} else\n+\t\tin_progress = 0;\n+\n+\tgit_config(git_rebase_config, NULL);\n+\tgitmodules_config();\n+\n+\targc = parse_options(argc, argv, prefix, options,\n+\t\t\t     builtin_rebase_usage, 0);\n+\n+\taction_nr = action_continue + action_skip + action_abort + edit_todo;\n+\tif ((action_nr != 1 && action_nr != 0) || argc > 2)\n+\t\tusage_with_options(builtin_rebase_usage, options);\n+\n+\tif (verbose && quiet)\n+\t\tdie(_(\"--quiet and --verbose are incompatible\"));\n+\telse if (verbose)\n+\t\tshow_stat = 1;\n+\telse if (quiet)\n+\t\tshow_stat = 0;\n+\n+\tif (preserve_merges && !interactive_rebase)\n+\t\tinteractive_rebase = -1; /* implied */\n+\n+\tif (strategy_opts) {\n+\t\tif (!strategy)\n+\t\t\tstrategy = \"recursive\";\n+\t\t/* validate strategy options */\n+\t}\n+\n+\tif (strategy)\n+\t\tdo_merge = 1;\n+\n+\tif (!strcmp(whitespace_opt, \"fix\") ||\n+\t    !strcmp(whitespace_opt, \"strip\") ||\n+\t    committer_date_is_author_date ||\n+\t    no_ff)\n+\t\tforce_rebase = 1;\n+\n+\tif (exec_cmd && interactive_rebase != 1)\n+\t\tdie(_(\"The --exec option must be used with the --interactive option\"));\n+\n+\tif (action_nr) {\n+\t\tif (!in_progress)\n+\t\t\tdie(_(\"No rebase in progress?\"));\n+\t\tif (rebase_type == REBASE_INTERACTIVE)\n+\t\t\t; /* GIT_REFLOG_ACTION = \"rebase -i ($action)\" */\n+\n+\t\tif (action_continue)\n+\t\t\treturn do_continue();\n+\t\telse if (action_skip)\n+\t\t\treturn do_skip();\n+\t\telse if (action_abort)\n+\t\t\treturn do_abort();\n+\t\telse if (edit_todo)\n+\t\t\treturn do_edit_todo();\n+\t\telse\n+\t\t\tdie(\"BUG: how do you get here?\");\n+\t}\n+\n+\tif (in_progress)\n+\t\tdie(_(\"It seems that there is already a %s directory, and\\n\"\n+\t\t      \"I wonder if you are in the middle of another rebase. If that is the\\n\"\n+\t\t      \"case, please try\\n\"\n+\t\t      \"\\tgit rebase (--continue | --abort | --skip)\\n\"\n+\t\t      \"If that is not the case, please\\n\"\n+\t\t      \"\\trm -rf \\\"%s/%s\\\"\"\n+\t\t      \"and run me again. I am stopping in case you still have something\\n\"\n+\t\t      \"valuable there.\"),\n+\t\t    state_basedir,\n+\t\t    get_git_dir(), state_basedir);\n+\n+\treturn do_rebase(argc, argv, options);\n+}\ndiff --git a/commit.c b/commit.c\nindex e8eb0ae..395a860 100644\n--- a/commit.c\n+++ b/commit.c\n@@ -1135,7 +1135,7 @@ void free_commit_extra_headers(struct commit_extra_header *extra)\n \t}\n }\n \n-int commit_tree(const struct strbuf *msg, unsigned char *tree,\n+int commit_tree(const struct strbuf *msg, const unsigned char *tree,\n \t\tstruct commit_list *parents, unsigned char *ret,\n \t\tconst char *author, const char *sign_commit)\n {\n@@ -1238,7 +1238,7 @@ static const char commit_utf8_warn[] =\n \"You may want to amend it after fixing the message, or set the config\\n\"\n \"variable i18n.commitencoding to the encoding your project uses.\\n\";\n \n-int commit_tree_extended(const struct strbuf *msg, unsigned char *tree,\n+int commit_tree_extended(const struct strbuf *msg, const unsigned char *tree,\n \t\t\t struct commit_list *parents, unsigned char *ret,\n \t\t\t const char *author, const char *sign_commit,\n \t\t\t struct commit_extra_header *extra)\ndiff --git a/commit.h b/commit.h\nindex 0f469e5..058886f 100644\n--- a/commit.h\n+++ b/commit.h\n@@ -193,11 +193,11 @@ struct commit_extra_header {\n extern void append_merge_tag_headers(struct commit_list *parents,\n \t\t\t\t     struct commit_extra_header ***tail);\n \n-extern int commit_tree(const struct strbuf *msg, unsigned char *tree,\n+extern int commit_tree(const struct strbuf *msg, const unsigned char *tree,\n \t\t       struct commit_list *parents, unsigned char *ret,\n \t\t       const char *author, const char *sign_commit);\n \n-extern int commit_tree_extended(const struct strbuf *msg, unsigned char *tree,\n+extern int commit_tree_extended(const struct strbuf *msg, const unsigned char *tree,\n \t\t\t\tstruct commit_list *parents, unsigned char *ret,\n \t\t\t\tconst char *author, const char *sign_commit,\n \t\t\t\tstruct commit_extra_header *);\ndiff --git a/contrib/examples/git-rebase.sh b/contrib/examples/git-rebase.sh\nnew file mode 100755\nindex 0000000..38530e8\n--- /dev/null\n+++ b/contrib/examples/git-rebase.sh\n@@ -0,0 +1,532 @@\n+#!/bin/sh\n+#\n+# Copyright (c) 2005 Junio C Hamano.\n+#\n+\n+SUBDIRECTORY_OK=Yes\n+OPTIONS_KEEPDASHDASH=\n+OPTIONS_SPEC=\"\\\n+git rebase [-i] [options] [--exec <cmd>] [--onto <newbase>] [<upstream>] [<branch>]\n+git rebase [-i] [options] [--exec <cmd>] [--onto <newbase>] --root [<branch>]\n+git-rebase --continue | --abort | --skip | --edit-todo\n+--\n+ Available options are\n+v,verbose!         display a diffstat of what changed upstream\n+q,quiet!           be quiet. implies --no-stat\n+onto=!             rebase onto given branch instead of upstream\n+p,preserve-merges! try to recreate merges instead of ignoring them\n+s,strategy=!       use the given merge strategy\n+no-ff!             cherry-pick all commits, even if unchanged\n+m,merge!           use merging strategies to rebase\n+i,interactive!     let the user edit the list of commits to rebase\n+x,exec=!           add exec lines after each commit of the editable list\n+k,keep-empty\t   preserve empty commits during rebase\n+f,force-rebase!    force rebase even if branch is up to date\n+X,strategy-option=! pass the argument through to the merge strategy\n+stat!              display a diffstat of what changed upstream\n+n,no-stat!         do not show diffstat of what changed upstream\n+verify             allow pre-rebase hook to run\n+rerere-autoupdate  allow rerere to update index with resolved conflicts\n+root!              rebase all reachable commits up to the root(s)\n+autosquash         move commits that begin with squash!/fixup! under -i\n+committer-date-is-author-date! passed to 'git am'\n+ignore-date!       passed to 'git am'\n+whitespace=!       passed to 'git apply'\n+ignore-whitespace! passed to 'git apply'\n+C=!                passed to 'git apply'\n+ Actions:\n+continue!          continue\n+abort!             abort and check out the original branch\n+skip!              skip current patch and continue\n+edit-todo!         edit the todo list during an interactive rebase\n+\"\n+. git-sh-setup\n+. git-sh-i18n\n+set_reflog_action rebase\n+require_work_tree_exists\n+cd_to_toplevel\n+\n+LF='\n+'\n+ok_to_skip_pre_rebase=\n+unset onto\n+cmd=\n+strategy=\n+strategy_opts=\n+do_merge=\n+merge_dir=\"$GIT_DIR\"/rebase-merge\n+apply_dir=\"$GIT_DIR\"/rebase-apply\n+verbose=\n+diffstat=\n+test \"$(git config --bool rebase.stat)\" = true && diffstat=t\n+git_am_opt=\n+rebase_root=\n+force_rebase=\n+allow_rerere_autoupdate=\n+# Non-empty if a rebase was in progress when 'git rebase' was invoked\n+in_progress=\n+# One of {am, merge, interactive}\n+type=\n+# One of {\"$GIT_DIR\"/rebase-apply, \"$GIT_DIR\"/rebase-merge}\n+state_dir=\n+# One of {'', continue, skip, abort}, as parsed from command line\n+action=\n+preserve_merges=\n+autosquash=\n+keep_empty=\n+test \"$(git config --bool rebase.autosquash)\" = \"true\" && autosquash=t\n+\n+read_basic_state () {\n+\thead_name=$(cat \"$state_dir\"/head-name) &&\n+\tonto=$(cat \"$state_dir\"/onto) &&\n+\t# We always write to orig-head, but interactive rebase used to write to\n+\t# head. Fall back to reading from head to cover for the case that the\n+\t# user upgraded git with an ongoing interactive rebase.\n+\tif test -f \"$state_dir\"/orig-head\n+\tthen\n+\t\torig_head=$(cat \"$state_dir\"/orig-head)\n+\telse\n+\t\torig_head=$(cat \"$state_dir\"/head)\n+\tfi &&\n+\tGIT_QUIET=$(cat \"$state_dir\"/quiet) &&\n+\ttest -f \"$state_dir\"/verbose && verbose=t\n+\ttest -f \"$state_dir\"/strategy && strategy=\"$(cat \"$state_dir\"/strategy)\"\n+\ttest -f \"$state_dir\"/strategy_opts &&\n+\t\tstrategy_opts=\"$(cat \"$state_dir\"/strategy_opts)\"\n+\ttest -f \"$state_dir\"/allow_rerere_autoupdate &&\n+\t\tallow_rerere_autoupdate=\"$(cat \"$state_dir\"/allow_rerere_autoupdate)\"\n+}\n+\n+output () {\n+\tcase \"$verbose\" in\n+\t'')\n+\t\toutput=$(\"$@\" 2>&1 )\n+\t\tstatus=$?\n+\t\ttest $status != 0 && printf \"%s\\n\" \"$output\"\n+\t\treturn $status\n+\t\t;;\n+\t*)\n+\t\t\"$@\"\n+\t\t;;\n+\tesac\n+}\n+\n+move_to_original_branch () {\n+\tcase \"$head_name\" in\n+\trefs/*)\n+\t\tmessage=\"rebase finished: $head_name onto $onto\"\n+\t\tgit update-ref -m \"$message\" \\\n+\t\t\t$head_name $(git rev-parse HEAD) $orig_head &&\n+\t\tgit symbolic-ref \\\n+\t\t\t-m \"rebase finished: returning to $head_name\" \\\n+\t\t\tHEAD $head_name ||\n+\t\tdie \"$(gettext \"Could not move back to $head_name\")\"\n+\t\t;;\n+\tesac\n+}\n+\n+run_specific_rebase () {\n+\tif [ \"$interactive_rebase\" = implied ]; then\n+\t\tGIT_EDITOR=:\n+\t\texport GIT_EDITOR\n+\t\tautosquash=\n+\tfi\n+\tgit_quiet=$GIT_QUIET\n+\texport GIT_PAGER\n+\texport action allow_rerere_autoupdate git_am_opt git_quiet head_name keep_empty\n+\texport onto orig_head rebase_root revisions\n+\texport state_dir verbose strategy strategy_opts\n+\texport autosquash cmd force_rebase preserve_merges squash_onto switch_to upstream\n+\texec git-rebase--$type\n+}\n+\n+run_pre_rebase_hook () {\n+\tif test -z \"$ok_to_skip_pre_rebase\" &&\n+\t   test -x \"$GIT_DIR/hooks/pre-rebase\"\n+\tthen\n+\t\t\"$GIT_DIR/hooks/pre-rebase\" ${1+\"$@\"} ||\n+\t\tdie \"$(gettext \"The pre-rebase hook refused to rebase.\")\"\n+\tfi\n+}\n+\n+test -f \"$apply_dir\"/applying &&\n+\tdie \"$(gettext \"It looks like git-am is in progress. Cannot rebase.\")\"\n+\n+if test -d \"$apply_dir\"\n+then\n+\ttype=am\n+\tstate_dir=\"$apply_dir\"\n+elif test -d \"$merge_dir\"\n+then\n+\tif test -f \"$merge_dir\"/interactive\n+\tthen\n+\t\ttype=interactive\n+\t\tinteractive_rebase=explicit\n+\telse\n+\t\ttype=merge\n+\tfi\n+\tstate_dir=\"$merge_dir\"\n+fi\n+test -n \"$type\" && in_progress=t\n+\n+total_argc=$#\n+while test $# != 0\n+do\n+\tcase \"$1\" in\n+\t--no-verify)\n+\t\tok_to_skip_pre_rebase=yes\n+\t\t;;\n+\t--verify)\n+\t\tok_to_skip_pre_rebase=\n+\t\t;;\n+\t--continue|--skip|--abort|--edit-todo)\n+\t\ttest $total_argc -eq 2 || usage\n+\t\taction=${1##--}\n+\t\t;;\n+\t--onto)\n+\t\ttest 2 -le \"$#\" || usage\n+\t\tonto=\"$2\"\n+\t\tshift\n+\t\t;;\n+\t-x)\n+\t\ttest 2 -le \"$#\" || usage\n+\t\tcmd=\"${cmd}exec $2${LF}\"\n+\t\tshift\n+\t\t;;\n+\t-i)\n+\t\tinteractive_rebase=explicit\n+\t\t;;\n+\t-k)\n+\t\tkeep_empty=yes\n+\t\t;;\n+\t-p)\n+\t\tpreserve_merges=t\n+\t\ttest -z \"$interactive_rebase\" && interactive_rebase=implied\n+\t\t;;\n+\t--autosquash)\n+\t\tautosquash=t\n+\t\t;;\n+\t--no-autosquash)\n+\t\tautosquash=\n+\t\t;;\n+\t-M|-m)\n+\t\tdo_merge=t\n+\t\t;;\n+\t-X)\n+\t\tshift\n+\t\tstrategy_opts=\"$strategy_opts $(git rev-parse --sq-quote \"--$1\")\"\n+\t\tdo_merge=t\n+\t\ttest -z \"$strategy\" && strategy=recursive\n+\t\t;;\n+\t-s)\n+\t\tshift\n+\t\tstrategy=\"$1\"\n+\t\tdo_merge=t\n+\t\t;;\n+\t-n)\n+\t\tdiffstat=\n+\t\t;;\n+\t--stat)\n+\t\tdiffstat=t\n+\t\t;;\n+\t-v)\n+\t\tverbose=t\n+\t\tdiffstat=t\n+\t\tGIT_QUIET=\n+\t\t;;\n+\t-q)\n+\t\tGIT_QUIET=t\n+\t\tgit_am_opt=\"$git_am_opt -q\"\n+\t\tverbose=\n+\t\tdiffstat=\n+\t\t;;\n+\t--whitespace)\n+\t\tshift\n+\t\tgit_am_opt=\"$git_am_opt --whitespace=$1\"\n+\t\tcase \"$1\" in\n+\t\tfix|strip)\n+\t\t\tforce_rebase=t\n+\t\t\t;;\n+\t\tesac\n+\t\t;;\n+\t--ignore-whitespace)\n+\t\tgit_am_opt=\"$git_am_opt $1\"\n+\t\t;;\n+\t--committer-date-is-author-date|--ignore-date)\n+\t\tgit_am_opt=\"$git_am_opt $1\"\n+\t\tforce_rebase=t\n+\t\t;;\n+\t-C)\n+\t\tshift\n+\t\tgit_am_opt=\"$git_am_opt -C$1\"\n+\t\t;;\n+\t--root)\n+\t\trebase_root=t\n+\t\t;;\n+\t-f|--no-ff)\n+\t\tforce_rebase=t\n+\t\t;;\n+\t--rerere-autoupdate|--no-rerere-autoupdate)\n+\t\tallow_rerere_autoupdate=\"$1\"\n+\t\t;;\n+\t--)\n+\t\tshift\n+\t\tbreak\n+\t\t;;\n+\tesac\n+\tshift\n+done\n+test $# -gt 2 && usage\n+\n+if test -n \"$cmd\" &&\n+   test \"$interactive_rebase\" != explicit\n+then\n+\tdie \"$(gettext \"The --exec option must be used with the --interactive option\")\"\n+fi\n+\n+if test -n \"$action\"\n+then\n+\ttest -z \"$in_progress\" && die \"$(gettext \"No rebase in progress?\")\"\n+\t# Only interactive rebase uses detailed reflog messages\n+\tif test \"$type\" = interactive && test \"$GIT_REFLOG_ACTION\" = rebase\n+\tthen\n+\t\tGIT_REFLOG_ACTION=\"rebase -i ($action)\"\n+\t\texport GIT_REFLOG_ACTION\n+\tfi\n+fi\n+\n+if test \"$action\" = \"edit-todo\" && test \"$type\" != \"interactive\"\n+then\n+\tdie \"$(gettext \"The --edit-todo action can only be used during interactive rebase.\")\"\n+fi\n+\n+case \"$action\" in\n+continue)\n+\t# Sanity check\n+\tgit rev-parse --verify HEAD >/dev/null ||\n+\t\tdie \"$(gettext \"Cannot read HEAD\")\"\n+\tgit update-index --ignore-submodules --refresh &&\n+\tgit diff-files --quiet --ignore-submodules || {\n+\t\techo \"$(gettext \"You must edit all merge conflicts and then\n+mark them as resolved using git add\")\"\n+\t\texit 1\n+\t}\n+\tread_basic_state\n+\trun_specific_rebase\n+\t;;\n+skip)\n+\toutput git reset --hard HEAD || exit $?\n+\tread_basic_state\n+\trun_specific_rebase\n+\t;;\n+abort)\n+\tgit rerere clear\n+\tread_basic_state\n+\tcase \"$head_name\" in\n+\trefs/*)\n+\t\tgit symbolic-ref -m \"rebase: aborting\" HEAD $head_name ||\n+\t\tdie \"$(eval_gettext \"Could not move back to \\$head_name\")\"\n+\t\t;;\n+\tesac\n+\toutput git reset --hard $orig_head\n+\trm -r \"$state_dir\"\n+\texit\n+\t;;\n+edit-todo)\n+\trun_specific_rebase\n+\t;;\n+esac\n+\n+# Make sure no rebase is in progress\n+if test -n \"$in_progress\"\n+then\n+\tstate_dir_base=${state_dir##*/}\n+\tcmd_live_rebase=\"git rebase (--continue | --abort | --skip)\"\n+\tcmd_clear_stale_rebase=\"rm -fr \\\"$state_dir\\\"\"\n+\tdie \"\n+$(eval_gettext 'It seems that there is already a $state_dir_base directory, and\n+I wonder if you are in the middle of another rebase.  If that is the\n+case, please try\n+\t$cmd_live_rebase\n+If that is not the case, please\n+\t$cmd_clear_stale_rebase\n+and run me again.  I am stopping in case you still have something\n+valuable there.')\"\n+fi\n+\n+if test -n \"$rebase_root\" && test -z \"$onto\"\n+then\n+\ttest -z \"$interactive_rebase\" && interactive_rebase=implied\n+fi\n+\n+if test -n \"$interactive_rebase\"\n+then\n+\ttype=interactive\n+\tstate_dir=\"$merge_dir\"\n+elif test -n \"$do_merge\"\n+then\n+\ttype=merge\n+\tstate_dir=\"$merge_dir\"\n+else\n+\ttype=am\n+\tstate_dir=\"$apply_dir\"\n+fi\n+\n+if test -z \"$rebase_root\"\n+then\n+\tcase \"$#\" in\n+\t0)\n+\t\tif ! upstream_name=$(git rev-parse --symbolic-full-name \\\n+\t\t\t--verify -q @{upstream} 2>/dev/null)\n+\t\tthen\n+\t\t\t. git-parse-remote\n+\t\t\terror_on_missing_default_upstream \"rebase\" \"rebase\" \\\n+\t\t\t\t\"against\" \"git rebase <branch>\"\n+\t\tfi\n+\t\t;;\n+\t*)\tupstream_name=\"$1\"\n+\t\tshift\n+\t\t;;\n+\tesac\n+\tupstream=`git rev-parse --verify \"${upstream_name}^0\"` ||\n+\tdie \"$(eval_gettext \"invalid upstream \\$upstream_name\")\"\n+\tupstream_arg=\"$upstream_name\"\n+else\n+\tif test -z \"$onto\"\n+\tthen\n+\t\tempty_tree=`git hash-object -t tree /dev/null`\n+\t\tonto=`git commit-tree $empty_tree </dev/null`\n+\t\tsquash_onto=\"$onto\"\n+\tfi\n+\tunset upstream_name\n+\tunset upstream\n+\ttest $# -gt 1 && usage\n+\tupstream_arg=--root\n+fi\n+\n+# Make sure the branch to rebase onto is valid.\n+onto_name=${onto-\"$upstream_name\"}\n+case \"$onto_name\" in\n+*...*)\n+\tif\tleft=${onto_name%...*} right=${onto_name#*...} &&\n+\t\tonto=$(git merge-base --all ${left:-HEAD} ${right:-HEAD})\n+\tthen\n+\t\tcase \"$onto\" in\n+\t\t?*\"$LF\"?*)\n+\t\t\tdie \"$(eval_gettext \"\\$onto_name: there are more than one merge bases\")\"\n+\t\t\t;;\n+\t\t'')\n+\t\t\tdie \"$(eval_gettext \"\\$onto_name: there is no merge base\")\"\n+\t\t\t;;\n+\t\tesac\n+\telse\n+\t\tdie \"$(eval_gettext \"\\$onto_name: there is no merge base\")\"\n+\tfi\n+\t;;\n+*)\n+\tonto=$(git rev-parse --verify \"${onto_name}^0\") ||\n+\tdie \"$(eval_gettext \"Does not point to a valid commit: \\$onto_name\")\"\n+\t;;\n+esac\n+\n+# If the branch to rebase is given, that is the branch we will rebase\n+# $branch_name -- branch being rebased, or HEAD (already detached)\n+# $orig_head -- commit object name of tip of the branch before rebasing\n+# $head_name -- refs/heads/<that-branch> or \"detached HEAD\"\n+switch_to=\n+case \"$#\" in\n+1)\n+\t# Is it \"rebase other $branchname\" or \"rebase other $commit\"?\n+\tbranch_name=\"$1\"\n+\tswitch_to=\"$1\"\n+\n+\tif git show-ref --verify --quiet -- \"refs/heads/$1\" &&\n+\t   orig_head=$(git rev-parse -q --verify \"refs/heads/$1\")\n+\tthen\n+\t\thead_name=\"refs/heads/$1\"\n+\telif orig_head=$(git rev-parse -q --verify \"$1\")\n+\tthen\n+\t\thead_name=\"detached HEAD\"\n+\telse\n+\t\tdie \"$(eval_gettext \"fatal: no such branch: \\$branch_name\")\"\n+\tfi\n+\t;;\n+0)\n+\t# Do not need to switch branches, we are already on it.\n+\tif branch_name=`git symbolic-ref -q HEAD`\n+\tthen\n+\t\thead_name=$branch_name\n+\t\tbranch_name=`expr \"z$branch_name\" : 'zrefs/heads/\\(.*\\)'`\n+\telse\n+\t\thead_name=\"detached HEAD\"\n+\t\tbranch_name=HEAD ;# detached\n+\tfi\n+\torig_head=$(git rev-parse --verify \"${branch_name}^0\") || exit\n+\t;;\n+*)\n+\tdie \"BUG: unexpected number of arguments left to parse\"\n+\t;;\n+esac\n+\n+require_clean_work_tree \"rebase\" \"$(gettext \"Please commit or stash them.\")\"\n+\n+# Now we are rebasing commits $upstream..$orig_head (or with --root,\n+# everything leading up to $orig_head) on top of $onto\n+\n+# Check if we are already based on $onto with linear history,\n+# but this should be done only when upstream and onto are the same\n+# and if this is not an interactive rebase.\n+mb=$(git merge-base \"$onto\" \"$orig_head\")\n+if test \"$type\" != interactive && test \"$upstream\" = \"$onto\" &&\n+\ttest \"$mb\" = \"$onto\" &&\n+\t# linear history?\n+\t! (git rev-list --parents \"$onto\"..\"$orig_head\" | sane_grep \" .* \") > /dev/null\n+then\n+\tif test -z \"$force_rebase\"\n+\tthen\n+\t\t# Lazily switch to the target branch if needed...\n+\t\ttest -z \"$switch_to\" || git checkout \"$switch_to\" --\n+\t\tsay \"$(eval_gettext \"Current branch \\$branch_name is up to date.\")\"\n+\t\texit 0\n+\telse\n+\t\tsay \"$(eval_gettext \"Current branch \\$branch_name is up to date, rebase forced.\")\"\n+\tfi\n+fi\n+\n+# If a hook exists, give it a chance to interrupt\n+run_pre_rebase_hook \"$upstream_arg\" \"$@\"\n+\n+if test -n \"$diffstat\"\n+then\n+\tif test -n \"$verbose\"\n+\tthen\n+\t\techo \"$(eval_gettext \"Changes from \\$mb to \\$onto:\")\"\n+\tfi\n+\t# We want color (if set), but no pager\n+\tGIT_PAGER='' git diff --stat --summary \"$mb\" \"$onto\"\n+fi\n+\n+test \"$type\" = interactive && run_specific_rebase\n+\n+# Detach HEAD and reset the tree\n+say \"$(gettext \"First, rewinding head to replay your work on top of it...\")\"\n+git checkout -q \"$onto^0\" || die \"could not detach HEAD\"\n+git update-ref ORIG_HEAD $orig_head\n+\n+# If the $onto is a proper descendant of the tip of the branch, then\n+# we just fast-forwarded.\n+if test \"$mb\" = \"$orig_head\"\n+then\n+\tsay \"$(eval_gettext \"Fast-forwarded \\$branch_name to \\$onto_name.\")\"\n+\tmove_to_original_branch\n+\texit 0\n+fi\n+\n+if test -n \"$rebase_root\"\n+then\n+\trevisions=\"$onto..$orig_head\"\n+else\n+\trevisions=\"$upstream..$orig_head\"\n+fi\n+\n+run_specific_rebase\ndiff --git a/git-rebase.sh b/git-rebase.sh\ndeleted file mode 100755\nindex 38530e8..0000000\n--- a/git-rebase.sh\n+++ /dev/null\n@@ -1,532 +0,0 @@\n-#!/bin/sh\n-#\n-# Copyright (c) 2005 Junio C Hamano.\n-#\n-\n-SUBDIRECTORY_OK=Yes\n-OPTIONS_KEEPDASHDASH=\n-OPTIONS_SPEC=\"\\\n-git rebase [-i] [options] [--exec <cmd>] [--onto <newbase>] [<upstream>] [<branch>]\n-git rebase [-i] [options] [--exec <cmd>] [--onto <newbase>] --root [<branch>]\n-git-rebase --continue | --abort | --skip | --edit-todo\n---\n- Available options are\n-v,verbose!         display a diffstat of what changed upstream\n-q,quiet!           be quiet. implies --no-stat\n-onto=!             rebase onto given branch instead of upstream\n-p,preserve-merges! try to recreate merges instead of ignoring them\n-s,strategy=!       use the given merge strategy\n-no-ff!             cherry-pick all commits, even if unchanged\n-m,merge!           use merging strategies to rebase\n-i,interactive!     let the user edit the list of commits to rebase\n-x,exec=!           add exec lines after each commit of the editable list\n-k,keep-empty\t   preserve empty commits during rebase\n-f,force-rebase!    force rebase even if branch is up to date\n-X,strategy-option=! pass the argument through to the merge strategy\n-stat!              display a diffstat of what changed upstream\n-n,no-stat!         do not show diffstat of what changed upstream\n-verify             allow pre-rebase hook to run\n-rerere-autoupdate  allow rerere to update index with resolved conflicts\n-root!              rebase all reachable commits up to the root(s)\n-autosquash         move commits that begin with squash!/fixup! under -i\n-committer-date-is-author-date! passed to 'git am'\n-ignore-date!       passed to 'git am'\n-whitespace=!       passed to 'git apply'\n-ignore-whitespace! passed to 'git apply'\n-C=!                passed to 'git apply'\n- Actions:\n-continue!          continue\n-abort!             abort and check out the original branch\n-skip!              skip current patch and continue\n-edit-todo!         edit the todo list during an interactive rebase\n-\"\n-. git-sh-setup\n-. git-sh-i18n\n-set_reflog_action rebase\n-require_work_tree_exists\n-cd_to_toplevel\n-\n-LF='\n-'\n-ok_to_skip_pre_rebase=\n-unset onto\n-cmd=\n-strategy=\n-strategy_opts=\n-do_merge=\n-merge_dir=\"$GIT_DIR\"/rebase-merge\n-apply_dir=\"$GIT_DIR\"/rebase-apply\n-verbose=\n-diffstat=\n-test \"$(git config --bool rebase.stat)\" = true && diffstat=t\n-git_am_opt=\n-rebase_root=\n-force_rebase=\n-allow_rerere_autoupdate=\n-# Non-empty if a rebase was in progress when 'git rebase' was invoked\n-in_progress=\n-# One of {am, merge, interactive}\n-type=\n-# One of {\"$GIT_DIR\"/rebase-apply, \"$GIT_DIR\"/rebase-merge}\n-state_dir=\n-# One of {'', continue, skip, abort}, as parsed from command line\n-action=\n-preserve_merges=\n-autosquash=\n-keep_empty=\n-test \"$(git config --bool rebase.autosquash)\" = \"true\" && autosquash=t\n-\n-read_basic_state () {\n-\thead_name=$(cat \"$state_dir\"/head-name) &&\n-\tonto=$(cat \"$state_dir\"/onto) &&\n-\t# We always write to orig-head, but interactive rebase used to write to\n-\t# head. Fall back to reading from head to cover for the case that the\n-\t# user upgraded git with an ongoing interactive rebase.\n-\tif test -f \"$state_dir\"/orig-head\n-\tthen\n-\t\torig_head=$(cat \"$state_dir\"/orig-head)\n-\telse\n-\t\torig_head=$(cat \"$state_dir\"/head)\n-\tfi &&\n-\tGIT_QUIET=$(cat \"$state_dir\"/quiet) &&\n-\ttest -f \"$state_dir\"/verbose && verbose=t\n-\ttest -f \"$state_dir\"/strategy && strategy=\"$(cat \"$state_dir\"/strategy)\"\n-\ttest -f \"$state_dir\"/strategy_opts &&\n-\t\tstrategy_opts=\"$(cat \"$state_dir\"/strategy_opts)\"\n-\ttest -f \"$state_dir\"/allow_rerere_autoupdate &&\n-\t\tallow_rerere_autoupdate=\"$(cat \"$state_dir\"/allow_rerere_autoupdate)\"\n-}\n-\n-output () {\n-\tcase \"$verbose\" in\n-\t'')\n-\t\toutput=$(\"$@\" 2>&1 )\n-\t\tstatus=$?\n-\t\ttest $status != 0 && printf \"%s\\n\" \"$output\"\n-\t\treturn $status\n-\t\t;;\n-\t*)\n-\t\t\"$@\"\n-\t\t;;\n-\tesac\n-}\n-\n-move_to_original_branch () {\n-\tcase \"$head_name\" in\n-\trefs/*)\n-\t\tmessage=\"rebase finished: $head_name onto $onto\"\n-\t\tgit update-ref -m \"$message\" \\\n-\t\t\t$head_name $(git rev-parse HEAD) $orig_head &&\n-\t\tgit symbolic-ref \\\n-\t\t\t-m \"rebase finished: returning to $head_name\" \\\n-\t\t\tHEAD $head_name ||\n-\t\tdie \"$(gettext \"Could not move back to $head_name\")\"\n-\t\t;;\n-\tesac\n-}\n-\n-run_specific_rebase () {\n-\tif [ \"$interactive_rebase\" = implied ]; then\n-\t\tGIT_EDITOR=:\n-\t\texport GIT_EDITOR\n-\t\tautosquash=\n-\tfi\n-\tgit_quiet=$GIT_QUIET\n-\texport GIT_PAGER\n-\texport action allow_rerere_autoupdate git_am_opt git_quiet head_name keep_empty\n-\texport onto orig_head rebase_root revisions\n-\texport state_dir verbose strategy strategy_opts\n-\texport autosquash cmd force_rebase preserve_merges squash_onto switch_to upstream\n-\texec git-rebase--$type\n-}\n-\n-run_pre_rebase_hook () {\n-\tif test -z \"$ok_to_skip_pre_rebase\" &&\n-\t   test -x \"$GIT_DIR/hooks/pre-rebase\"\n-\tthen\n-\t\t\"$GIT_DIR/hooks/pre-rebase\" ${1+\"$@\"} ||\n-\t\tdie \"$(gettext \"The pre-rebase hook refused to rebase.\")\"\n-\tfi\n-}\n-\n-test -f \"$apply_dir\"/applying &&\n-\tdie \"$(gettext \"It looks like git-am is in progress. Cannot rebase.\")\"\n-\n-if test -d \"$apply_dir\"\n-then\n-\ttype=am\n-\tstate_dir=\"$apply_dir\"\n-elif test -d \"$merge_dir\"\n-then\n-\tif test -f \"$merge_dir\"/interactive\n-\tthen\n-\t\ttype=interactive\n-\t\tinteractive_rebase=explicit\n-\telse\n-\t\ttype=merge\n-\tfi\n-\tstate_dir=\"$merge_dir\"\n-fi\n-test -n \"$type\" && in_progress=t\n-\n-total_argc=$#\n-while test $# != 0\n-do\n-\tcase \"$1\" in\n-\t--no-verify)\n-\t\tok_to_skip_pre_rebase=yes\n-\t\t;;\n-\t--verify)\n-\t\tok_to_skip_pre_rebase=\n-\t\t;;\n-\t--continue|--skip|--abort|--edit-todo)\n-\t\ttest $total_argc -eq 2 || usage\n-\t\taction=${1##--}\n-\t\t;;\n-\t--onto)\n-\t\ttest 2 -le \"$#\" || usage\n-\t\tonto=\"$2\"\n-\t\tshift\n-\t\t;;\n-\t-x)\n-\t\ttest 2 -le \"$#\" || usage\n-\t\tcmd=\"${cmd}exec $2${LF}\"\n-\t\tshift\n-\t\t;;\n-\t-i)\n-\t\tinteractive_rebase=explicit\n-\t\t;;\n-\t-k)\n-\t\tkeep_empty=yes\n-\t\t;;\n-\t-p)\n-\t\tpreserve_merges=t\n-\t\ttest -z \"$interactive_rebase\" && interactive_rebase=implied\n-\t\t;;\n-\t--autosquash)\n-\t\tautosquash=t\n-\t\t;;\n-\t--no-autosquash)\n-\t\tautosquash=\n-\t\t;;\n-\t-M|-m)\n-\t\tdo_merge=t\n-\t\t;;\n-\t-X)\n-\t\tshift\n-\t\tstrategy_opts=\"$strategy_opts $(git rev-parse --sq-quote \"--$1\")\"\n-\t\tdo_merge=t\n-\t\ttest -z \"$strategy\" && strategy=recursive\n-\t\t;;\n-\t-s)\n-\t\tshift\n-\t\tstrategy=\"$1\"\n-\t\tdo_merge=t\n-\t\t;;\n-\t-n)\n-\t\tdiffstat=\n-\t\t;;\n-\t--stat)\n-\t\tdiffstat=t\n-\t\t;;\n-\t-v)\n-\t\tverbose=t\n-\t\tdiffstat=t\n-\t\tGIT_QUIET=\n-\t\t;;\n-\t-q)\n-\t\tGIT_QUIET=t\n-\t\tgit_am_opt=\"$git_am_opt -q\"\n-\t\tverbose=\n-\t\tdiffstat=\n-\t\t;;\n-\t--whitespace)\n-\t\tshift\n-\t\tgit_am_opt=\"$git_am_opt --whitespace=$1\"\n-\t\tcase \"$1\" in\n-\t\tfix|strip)\n-\t\t\tforce_rebase=t\n-\t\t\t;;\n-\t\tesac\n-\t\t;;\n-\t--ignore-whitespace)\n-\t\tgit_am_opt=\"$git_am_opt $1\"\n-\t\t;;\n-\t--committer-date-is-author-date|--ignore-date)\n-\t\tgit_am_opt=\"$git_am_opt $1\"\n-\t\tforce_rebase=t\n-\t\t;;\n-\t-C)\n-\t\tshift\n-\t\tgit_am_opt=\"$git_am_opt -C$1\"\n-\t\t;;\n-\t--root)\n-\t\trebase_root=t\n-\t\t;;\n-\t-f|--no-ff)\n-\t\tforce_rebase=t\n-\t\t;;\n-\t--rerere-autoupdate|--no-rerere-autoupdate)\n-\t\tallow_rerere_autoupdate=\"$1\"\n-\t\t;;\n-\t--)\n-\t\tshift\n-\t\tbreak\n-\t\t;;\n-\tesac\n-\tshift\n-done\n-test $# -gt 2 && usage\n-\n-if test -n \"$cmd\" &&\n-   test \"$interactive_rebase\" != explicit\n-then\n-\tdie \"$(gettext \"The --exec option must be used with the --interactive option\")\"\n-fi\n-\n-if test -n \"$action\"\n-then\n-\ttest -z \"$in_progress\" && die \"$(gettext \"No rebase in progress?\")\"\n-\t# Only interactive rebase uses detailed reflog messages\n-\tif test \"$type\" = interactive && test \"$GIT_REFLOG_ACTION\" = rebase\n-\tthen\n-\t\tGIT_REFLOG_ACTION=\"rebase -i ($action)\"\n-\t\texport GIT_REFLOG_ACTION\n-\tfi\n-fi\n-\n-if test \"$action\" = \"edit-todo\" && test \"$type\" != \"interactive\"\n-then\n-\tdie \"$(gettext \"The --edit-todo action can only be used during interactive rebase.\")\"\n-fi\n-\n-case \"$action\" in\n-continue)\n-\t# Sanity check\n-\tgit rev-parse --verify HEAD >/dev/null ||\n-\t\tdie \"$(gettext \"Cannot read HEAD\")\"\n-\tgit update-index --ignore-submodules --refresh &&\n-\tgit diff-files --quiet --ignore-submodules || {\n-\t\techo \"$(gettext \"You must edit all merge conflicts and then\n-mark them as resolved using git add\")\"\n-\t\texit 1\n-\t}\n-\tread_basic_state\n-\trun_specific_rebase\n-\t;;\n-skip)\n-\toutput git reset --hard HEAD || exit $?\n-\tread_basic_state\n-\trun_specific_rebase\n-\t;;\n-abort)\n-\tgit rerere clear\n-\tread_basic_state\n-\tcase \"$head_name\" in\n-\trefs/*)\n-\t\tgit symbolic-ref -m \"rebase: aborting\" HEAD $head_name ||\n-\t\tdie \"$(eval_gettext \"Could not move back to \\$head_name\")\"\n-\t\t;;\n-\tesac\n-\toutput git reset --hard $orig_head\n-\trm -r \"$state_dir\"\n-\texit\n-\t;;\n-edit-todo)\n-\trun_specific_rebase\n-\t;;\n-esac\n-\n-# Make sure no rebase is in progress\n-if test -n \"$in_progress\"\n-then\n-\tstate_dir_base=${state_dir##*/}\n-\tcmd_live_rebase=\"git rebase (--continue | --abort | --skip)\"\n-\tcmd_clear_stale_rebase=\"rm -fr \\\"$state_dir\\\"\"\n-\tdie \"\n-$(eval_gettext 'It seems that there is already a $state_dir_base directory, and\n-I wonder if you are in the middle of another rebase.  If that is the\n-case, please try\n-\t$cmd_live_rebase\n-If that is not the case, please\n-\t$cmd_clear_stale_rebase\n-and run me again.  I am stopping in case you still have something\n-valuable there.')\"\n-fi\n-\n-if test -n \"$rebase_root\" && test -z \"$onto\"\n-then\n-\ttest -z \"$interactive_rebase\" && interactive_rebase=implied\n-fi\n-\n-if test -n \"$interactive_rebase\"\n-then\n-\ttype=interactive\n-\tstate_dir=\"$merge_dir\"\n-elif test -n \"$do_merge\"\n-then\n-\ttype=merge\n-\tstate_dir=\"$merge_dir\"\n-else\n-\ttype=am\n-\tstate_dir=\"$apply_dir\"\n-fi\n-\n-if test -z \"$rebase_root\"\n-then\n-\tcase \"$#\" in\n-\t0)\n-\t\tif ! upstream_name=$(git rev-parse --symbolic-full-name \\\n-\t\t\t--verify -q @{upstream} 2>/dev/null)\n-\t\tthen\n-\t\t\t. git-parse-remote\n-\t\t\terror_on_missing_default_upstream \"rebase\" \"rebase\" \\\n-\t\t\t\t\"against\" \"git rebase <branch>\"\n-\t\tfi\n-\t\t;;\n-\t*)\tupstream_name=\"$1\"\n-\t\tshift\n-\t\t;;\n-\tesac\n-\tupstream=`git rev-parse --verify \"${upstream_name}^0\"` ||\n-\tdie \"$(eval_gettext \"invalid upstream \\$upstream_name\")\"\n-\tupstream_arg=\"$upstream_name\"\n-else\n-\tif test -z \"$onto\"\n-\tthen\n-\t\tempty_tree=`git hash-object -t tree /dev/null`\n-\t\tonto=`git commit-tree $empty_tree </dev/null`\n-\t\tsquash_onto=\"$onto\"\n-\tfi\n-\tunset upstream_name\n-\tunset upstream\n-\ttest $# -gt 1 && usage\n-\tupstream_arg=--root\n-fi\n-\n-# Make sure the branch to rebase onto is valid.\n-onto_name=${onto-\"$upstream_name\"}\n-case \"$onto_name\" in\n-*...*)\n-\tif\tleft=${onto_name%...*} right=${onto_name#*...} &&\n-\t\tonto=$(git merge-base --all ${left:-HEAD} ${right:-HEAD})\n-\tthen\n-\t\tcase \"$onto\" in\n-\t\t?*\"$LF\"?*)\n-\t\t\tdie \"$(eval_gettext \"\\$onto_name: there are more than one merge bases\")\"\n-\t\t\t;;\n-\t\t'')\n-\t\t\tdie \"$(eval_gettext \"\\$onto_name: there is no merge base\")\"\n-\t\t\t;;\n-\t\tesac\n-\telse\n-\t\tdie \"$(eval_gettext \"\\$onto_name: there is no merge base\")\"\n-\tfi\n-\t;;\n-*)\n-\tonto=$(git rev-parse --verify \"${onto_name}^0\") ||\n-\tdie \"$(eval_gettext \"Does not point to a valid commit: \\$onto_name\")\"\n-\t;;\n-esac\n-\n-# If the branch to rebase is given, that is the branch we will rebase\n-# $branch_name -- branch being rebased, or HEAD (already detached)\n-# $orig_head -- commit object name of tip of the branch before rebasing\n-# $head_name -- refs/heads/<that-branch> or \"detached HEAD\"\n-switch_to=\n-case \"$#\" in\n-1)\n-\t# Is it \"rebase other $branchname\" or \"rebase other $commit\"?\n-\tbranch_name=\"$1\"\n-\tswitch_to=\"$1\"\n-\n-\tif git show-ref --verify --quiet -- \"refs/heads/$1\" &&\n-\t   orig_head=$(git rev-parse -q --verify \"refs/heads/$1\")\n-\tthen\n-\t\thead_name=\"refs/heads/$1\"\n-\telif orig_head=$(git rev-parse -q --verify \"$1\")\n-\tthen\n-\t\thead_name=\"detached HEAD\"\n-\telse\n-\t\tdie \"$(eval_gettext \"fatal: no such branch: \\$branch_name\")\"\n-\tfi\n-\t;;\n-0)\n-\t# Do not need to switch branches, we are already on it.\n-\tif branch_name=`git symbolic-ref -q HEAD`\n-\tthen\n-\t\thead_name=$branch_name\n-\t\tbranch_name=`expr \"z$branch_name\" : 'zrefs/heads/\\(.*\\)'`\n-\telse\n-\t\thead_name=\"detached HEAD\"\n-\t\tbranch_name=HEAD ;# detached\n-\tfi\n-\torig_head=$(git rev-parse --verify \"${branch_name}^0\") || exit\n-\t;;\n-*)\n-\tdie \"BUG: unexpected number of arguments left to parse\"\n-\t;;\n-esac\n-\n-require_clean_work_tree \"rebase\" \"$(gettext \"Please commit or stash them.\")\"\n-\n-# Now we are rebasing commits $upstream..$orig_head (or with --root,\n-# everything leading up to $orig_head) on top of $onto\n-\n-# Check if we are already based on $onto with linear history,\n-# but this should be done only when upstream and onto are the same\n-# and if this is not an interactive rebase.\n-mb=$(git merge-base \"$onto\" \"$orig_head\")\n-if test \"$type\" != interactive && test \"$upstream\" = \"$onto\" &&\n-\ttest \"$mb\" = \"$onto\" &&\n-\t# linear history?\n-\t! (git rev-list --parents \"$onto\"..\"$orig_head\" | sane_grep \" .* \") > /dev/null\n-then\n-\tif test -z \"$force_rebase\"\n-\tthen\n-\t\t# Lazily switch to the target branch if needed...\n-\t\ttest -z \"$switch_to\" || git checkout \"$switch_to\" --\n-\t\tsay \"$(eval_gettext \"Current branch \\$branch_name is up to date.\")\"\n-\t\texit 0\n-\telse\n-\t\tsay \"$(eval_gettext \"Current branch \\$branch_name is up to date, rebase forced.\")\"\n-\tfi\n-fi\n-\n-# If a hook exists, give it a chance to interrupt\n-run_pre_rebase_hook \"$upstream_arg\" \"$@\"\n-\n-if test -n \"$diffstat\"\n-then\n-\tif test -n \"$verbose\"\n-\tthen\n-\t\techo \"$(eval_gettext \"Changes from \\$mb to \\$onto:\")\"\n-\tfi\n-\t# We want color (if set), but no pager\n-\tGIT_PAGER='' git diff --stat --summary \"$mb\" \"$onto\"\n-fi\n-\n-test \"$type\" = interactive && run_specific_rebase\n-\n-# Detach HEAD and reset the tree\n-say \"$(gettext \"First, rewinding head to replay your work on top of it...\")\"\n-git checkout -q \"$onto^0\" || die \"could not detach HEAD\"\n-git update-ref ORIG_HEAD $orig_head\n-\n-# If the $onto is a proper descendant of the tip of the branch, then\n-# we just fast-forwarded.\n-if test \"$mb\" = \"$orig_head\"\n-then\n-\tsay \"$(eval_gettext \"Fast-forwarded \\$branch_name to \\$onto_name.\")\"\n-\tmove_to_original_branch\n-\texit 0\n-fi\n-\n-if test -n \"$rebase_root\"\n-then\n-\trevisions=\"$onto..$orig_head\"\n-else\n-\trevisions=\"$upstream..$orig_head\"\n-fi\n-\n-run_specific_rebase\ndiff --git a/git.c b/git.c\nindex ed66c66..a4cb4a8 100644\n--- a/git.c\n+++ b/git.c\n@@ -379,6 +379,7 @@ static void handle_internal_command(int argc, const char **argv)\n \t\t{ \"prune-packed\", cmd_prune_packed, RUN_SETUP },\n \t\t{ \"push\", cmd_push, RUN_SETUP },\n \t\t{ \"read-tree\", cmd_read_tree, RUN_SETUP },\n+\t\t{ \"rebase\", cmd_rebase, RUN_SETUP | NEED_WORK_TREE },\n \t\t{ \"receive-pack\", cmd_receive_pack },\n \t\t{ \"reflog\", cmd_reflog, RUN_SETUP },\n \t\t{ \"remote\", cmd_remote, RUN_SETUP },\n-- \n2.3.0.rc1.137.g477eb31\n"}]}