git/list[1] front-page[2] threads[3] people[4] search[5] about
 

[PATCH v2 00/34] Teach the sequencer to act as rebase -i's backend

From
Johannes Schindelin <johannes.schindelin@gmx.de>
Date
Dec 13, 2016, 15:29 UTC
Message-ID
<cover.1481642927.git.johannes.schindelin@gmx.de>
In-Reply-To
<cover.1472633606.git.johannes.schindelin@gmx.de>

This marks the count down to '3': two more patch series after this (really tiny ones) and we have a faster rebase -i.

The idea of this patch series is to teach the sequencer to understand all of the commands in `git-rebase-todo` scripts, to execute them and to behave pretty much very the same as `git rebase -i --continue` when called with the newly-introduced REPLAY_INTERACTIVE_REBASE mode.

Most of these patches should be pretty much straight-forward. When not, I tried to make a point of describing enough background in the commit message. Please feel free to point out where my explanations fall short.

Note that even after this patch series is applied, rebase -i is still unaffected. It will require the next patch series which introduces the rebase--helper that essentially implements `git rebase -i --continue` by calling the sequencer with the appropriate options.

The final patch series will move a couple of pre- and post-processing steps into the rebase--helper/sequencer (such as expanding/shrinking the SHA-1s, reordering the fixup!/squash! lines, etc). This might sound like a mere add-on, but it is essential for the speed improvements: those stupid little processing steps really dominated the execution time in my tests.

Apart from mostly cosmetic patches (and the occasional odd bug that I fixed promptly), I used these patches since mid May to perform all of my interactive rebases. In mid June, I had the idea to teach rebase -i to run *both* scripted rebase and rebase--helper and to cross-validate the results. This slowed down all my interactive rebases since, but helped me catch three rather obscure bugs (e.g. that git commit --fixup unfolds long onelines and rebase -i still finds the correct original commit).

This is all only to say that I am rather confident that the current code does the job.

Since sending out v1, I integrated all of these patch series into Git for Windows v2.10.0, where they have been live ever since, and used by myself (also in a Linux VM, as Git for Windows' master branch always builds also on Linux and passes the test suite, too).

Just to reiterate why I do all this: it speeds up the interactive rebase substantially. Even with a not yet fully builtin rebase -i, but just the part after the user edited the `git-rebase-todo` script.

The performance test I introduced to demonstrate this (p3404) shows a speed-up of +380% here (i.e. roughly 5x), from ~8.8 seconds to ~1.8 seconds. This is on Windows, where the performance impact of avoiding shell scripting is most noticable.

On MacOSX and on Linux, the speed-up is less pronounced, but still noticable, at least if you trust Travis CI, which I abused to perform that test for me. Check for yourself (searching for "3404.2") here: https://travis-ci.org/git/git/builds/156295227. According to those logs, p3404 is speeded up from ~0.45 seconds to ~0.12 seconds on Linux (read: about 3.5x) and from ~1.7 seconds to ~0.5 seconds on MacOSX (read: almost 4x).

Please note that the interdiff vs v1 is only of limited use: too many things changed in the meantime, in particular the prepare-sequencer branch that went through a couple of iterations before it found its way into git.git's master branch. So please take the interdiff with a mountain range of salt.

Changes since v1:
- some grammar touch-ups.
- simplified determining the command string in
  walk_revs_populate_todo().
- removed the beautiful ordinal logic (to print out "1st", "2nd", "3rd"
  etc) and made things consistent with the current `rebase -i`.
- while at it, marked more messages for translation.
- added code-comments to clarify the order, and the sections, of the
  todo_command enum.
- replaced one error(..., strerror(...)) to an error_errno(...).
- downcased error messages
- marked error messages for translation
- adjusted the patches to account for sequencer_entrust() having been
  removed from the prepare-sequencer patch series by request of Junio.
- moved the introduction of write_message_gently() into the patch
  introducing its first usage, i.e. the support for the 'edit' command.
- adjusted some indentations
- prevented an write_in_full() from being called after a failed open()
- inserted a few forgotten strbuf_release() calls
Johannes Schindelin (34):
  sequencer: support a new action: 'interactive rebase'
  sequencer (rebase -i): implement the 'noop' command
  sequencer (rebase -i): implement the 'edit' command
  sequencer (rebase -i): implement the 'exec' command
  sequencer (rebase -i): learn about the 'verbose' mode
  sequencer (rebase -i): write the 'done' file
  sequencer (rebase -i): add support for the 'fixup' and 'squash'
    commands
  sequencer (rebase -i): implement the short commands
  sequencer (rebase -i): write an author-script file
  sequencer (rebase -i): allow continuing with staged changes
  sequencer (rebase -i): remove CHERRY_PICK_HEAD when no longer needed
  sequencer (rebase -i): skip some revert/cherry-pick specific code path
  sequencer (rebase -i): the todo can be empty when continuing
  sequencer (rebase -i): update refs after a successful rebase
  sequencer (rebase -i): leave a patch upon error
  sequencer (rebase -i): implement the 'reword' command
  sequencer (rebase -i): allow fast-forwarding for edit/reword
  sequencer (rebase -i): refactor setting the reflog message
  sequencer (rebase -i): set the reflog message consistently
  sequencer (rebase -i): copy commit notes at end
  sequencer (rebase -i): record interrupted commits in rewritten, too
  sequencer (rebase -i): run the post-rewrite hook, if needed
  sequencer (rebase -i): respect the rebase.autostash setting
  sequencer (rebase -i): respect strategy/strategy_opts settings
  sequencer (rebase -i): allow rescheduling commands
  sequencer (rebase -i): implement the 'drop' command
  sequencer (rebase -i): differentiate between comments and 'noop'
  run_command_opt(): optionally hide stderr when the command succeeds
  sequencer (rebase -i): show only failed `git commit`'s output
  sequencer (rebase -i): show only failed cherry-picks' output
  sequencer (rebase -i): suggest --edit-todo upon unknown command
  sequencer (rebase -i): show the progress
  sequencer (rebase -i): write the progress into files
  sequencer (rebase -i): write out the final message
 run-command.c |   23 ++
 run-command.h |    1 +
 sequencer.c   | 1003 ++++++++++++++++++++++++++++++++++++++++++++++++++++++---
 sequencer.h   |    4 +-
 4 files changed, 983 insertions(+), 48 deletions(-)
base-commit: 8d7a455ed52e2a96debc080dfc011b6bb00db5d2
Published-As: https://github.com/dscho/git/releases/tag/sequencer-i-v2
Fetch-It-Via: git fetch https://github.com/dscho/git sequencer-i-v2
Interdiff vs v1:
 diff --git a/sequencer.c b/sequencer.c
 index 6ca9d1e09d..41be4cde16 100644
 --- a/sequencer.c
 +++ b/sequencer.c
 @@ -125,7 +125,6 @@ static GIT_PATH_FUNC(rebase_path_autostash, "rebase-merge/autostash")
  static GIT_PATH_FUNC(rebase_path_strategy, "rebase-merge/strategy")
  static GIT_PATH_FUNC(rebase_path_strategy_opts, "rebase-merge/strategy_opts")
  
 -/* We will introduce the 'interactive rebase' mode later */
  static inline int is_rebase_i(const struct replay_opts *opts)
  {
  	return opts->action == REPLAY_INTERACTIVE_REBASE;
 @@ -259,13 +258,13 @@ static const char *action_name(const struct replay_opts *opts)
  {
  	switch (opts->action) {
  	case REPLAY_REVERT:
 -		return "revert";
 +		return N_("revert");
  	case REPLAY_PICK:
 -		return "cherry-pick";
 +		return N_("cherry-pick");
  	case REPLAY_INTERACTIVE_REBASE:
 -		return "rebase -i";
 +		return N_("rebase -i");
  	}
 -	die("Unknown action: %d", opts->action);
 +	die(_("Unknown action: %d"), opts->action);
  }
  
  struct commit_message {
 @@ -548,6 +547,7 @@ static int write_author_script(const char *message)
  {
  	struct strbuf buf = STRBUF_INIT;
  	const char *eol;
 +	int res;
  
  	for (;;)
  		if (!*message || starts_with(message, "\n")) {
 @@ -585,8 +585,9 @@ static int write_author_script(const char *message)
  			strbuf_addch(&buf, *(message++));
  		else
  			strbuf_addf(&buf, "'\\\\%c'", *(message++));
 -	strbuf_addstr(&buf, "'\n");
 -	return write_message(&buf, rebase_path_author_script());
 +	res = write_message(buf.buf, buf.len, rebase_path_author_script(), 1);
 +	strbuf_release(&buf);
 +	return res;
  }
  
  /*
 @@ -771,16 +772,25 @@ static int allow_empty(struct replay_opts *opts, struct commit *commit)
  		return 1;
  }
  
 +/*
 + * Note that ordering matters in this enum. Not only must it match the mapping
 + * below, it is also divided into several sections that matter.  When adding
 + * new commands, make sure you add it in the right section.
 + */
  enum todo_command {
 +	/* commands that handle commits */
  	TODO_PICK = 0,
  	TODO_REVERT,
  	TODO_EDIT,
  	TODO_REWORD,
  	TODO_FIXUP,
  	TODO_SQUASH,
 +	/* commands that do something else than handling a single commit */
  	TODO_EXEC,
 +	/* commands that do nothing but are counted for reporting progress */
  	TODO_NOOP,
  	TODO_DROP,
 +	/* comments (not counted for reporting progress) */
  	TODO_COMMENT
  };
  
 @@ -812,47 +822,34 @@ static int is_fixup(enum todo_command command)
  	return command == TODO_FIXUP || command == TODO_SQUASH;
  }
  
 -static const char *nth_for_number(int n)
 -{
 -	int n1 = n % 10, n10 = n % 100;
 -
 -	if (n1 == 1 && n10 != 11)
 -		return "st";
 -	if (n1 == 2 && n10 != 12)
 -		return "nd";
 -	if (n1 == 3 && n10 != 13)
 -		return "rd";
 -	return "th";
 -}
 -
  static int update_squash_messages(enum todo_command command,
  		struct commit *commit, struct replay_opts *opts)
  {
  	struct strbuf buf = STRBUF_INIT;
 -	int count;
 +	int count, res;
  	const char *message, *body;
  
  	if (file_exists(rebase_path_squash_msg())) {
  		char *p, *p2;
  
  		if (strbuf_read_file(&buf, rebase_path_squash_msg(), 2048) <= 0)
 -			return error("Could not read %s",
 +			return error(_("could not read '%s'"),
  				rebase_path_squash_msg());
  
 -		if (buf.buf[0] == '\n' || !skip_prefix(buf.buf + 1,
 -				" This is a combination of ",
 -				(const char **)&p))
 -			return error("Unexpected 1st line of squash message:\n"
 -				"\n\t%.*s",
 -				(int)(strchrnul(buf.buf, '\n') - buf.buf),
 -				buf.buf);
 +		if (buf.buf[0] != comment_line_char ||
 +		    !skip_prefix(buf.buf + 1, " This is a combination of ",
 +				 (const char **)&p))
 +			return error(_("unexpected 1st line of squash message:"
 +				       "\n\n\t%.*s"),
 +				     (int)(strchrnul(buf.buf, '\n') - buf.buf),
 +				     buf.buf);
  		count = strtol(p, &p2, 10);
  
  		if (count < 1 || *p2 != ' ')
 -			return error("Invalid 1st line of squash message:\n"
 -				"\n\t%.*s",
 -				(int)(strchrnul(buf.buf, '\n') - buf.buf),
 -				buf.buf);
 +			return error(_("invalid 1st line of squash message:\n"
 +				       "\n\t%.*s"),
 +				     (int)(strchrnul(buf.buf, '\n') - buf.buf),
 +				     buf.buf);
  
  		sprintf((char *)p, "%d", ++count);
  		if (!*p2)
 @@ -868,32 +865,33 @@ static int update_squash_messages(enum todo_command command,
  		const char *head_message, *body;
  
  		if (get_sha1("HEAD", head))
 -			return error("Need a HEAD to fixup");
 +			return error(_("need a HEAD to fixup"));
  		if (!(head_commit = lookup_commit_reference(head)))
 -			return error("Could not read HEAD");
 +			return error(_("could not read HEAD"));
  		if (!(head_message = get_commit_buffer(head_commit, NULL)))
 -			return error("Could not read HEAD's commit message");
 +			return error(_("could not read HEAD's commit message"));
  
  		body = strstr(head_message, "\n\n");
  		if (!body)
  			body = "";
  		else
  			body = skip_blank_lines(body + 2);
 -		if (write_file_gently(rebase_path_fixup_msg(), body, 0))
 -			return error("Cannot write %s",
 -				rebase_path_fixup_msg());
 +		if (write_message(body, strlen(body),
 +				  rebase_path_fixup_msg(), 0))
 +			return error(_("cannot write '%s'"),
 +				     rebase_path_fixup_msg());
  
  		count = 2;
 -		strbuf_addf(&buf, "%c This is a combination of 2 commits.\n"
 -			"%c The first commit's message is:\n\n%s",
 -			comment_line_char, comment_line_char, body);
 +		strbuf_addf(&buf, _("%c This is a combination of 2 commits.\n"
 +				    "%c The first commit's message is:\n\n%s"),
 +			    comment_line_char, comment_line_char, body);
  
  		unuse_commit_buffer(head_commit, head_message);
  	}
  
  	if (!(message = get_commit_buffer(commit, NULL)))
 -		return error("Could not read commit message of %s",
 -			oid_to_hex(&commit->object.oid));
 +		return error(_("could not read commit message of %s"),
 +			     oid_to_hex(&commit->object.oid));
  	body = strstr(message, "\n\n");
  	if (!body)
  		body = "";
 @@ -902,21 +900,23 @@ static int update_squash_messages(enum todo_command command,
  
  	if (command == TODO_SQUASH) {
  		unlink(rebase_path_fixup_msg());
 -		strbuf_addf(&buf, "\n%c This is the %d%s commit message:\n\n%s",
 -			comment_line_char,
 -			count, nth_for_number(count), body);
 +		strbuf_addf(&buf, _("\n%c This is the commit message #%d:\n"
 +				    "\n%s"),
 +			    comment_line_char, count, body);
  	}
  	else if (command == TODO_FIXUP) {
 -		strbuf_addf(&buf,
 -			"\n%c The %d%s commit message will be skipped:\n\n",
 -			comment_line_char, count, nth_for_number(count));
 +		strbuf_addf(&buf, _("\n%c The commit message #%d "
 +				    "will be skipped:\n\n"),
 +			    comment_line_char, count);
  		strbuf_add_commented_lines(&buf, body, strlen(body));
  	}
  	else
 -		return error("Unknown command: %d", command);
 +		return error(_("unknown command: %d"), command);
  	unuse_commit_buffer(commit, message);
  
 -	return write_message(&buf, rebase_path_squash_msg());
 +	res = write_message(buf.buf, buf.len, rebase_path_squash_msg(), 0);
 +	strbuf_release(&buf);
 +	return res;
  }
  
  static void flush_rewritten_pending(void) {
 @@ -940,6 +940,7 @@ static void flush_rewritten_pending(void) {
  		fclose(out);
  		unlink(rebase_path_rewritten_pending());
  	}
 +	strbuf_release(&buf);
  }
  
  static void record_in_rewritten(struct object_id *oid,
 @@ -1013,7 +1014,7 @@ static int do_pick_commit(enum todo_command command, struct commit *commit,
  		parent = commit->parents->item;
  
  	if (get_message(commit, &msg) != 0)
 -		return error(_("Cannot get commit message for %s"),
 +		return error(_("cannot get commit message for %s"),
  			oid_to_hex(&commit->object.oid));
  
  	if (opts->allow_ff && !is_fixup(command) &&
 @@ -1021,7 +1022,7 @@ static int do_pick_commit(enum todo_command command, struct commit *commit,
  	     (!parent && unborn))) {
  		if (is_rebase_i(opts))
  			write_author_script(msg.message);
 -		res |= fast_forward_to(commit->object.oid.hash, head, unborn,
 +		res = fast_forward_to(commit->object.oid.hash, head, unborn,
  			opts);
  		if (res || command != TODO_REWORD)
  			goto leave;
 @@ -1100,8 +1101,8 @@ static int do_pick_commit(enum todo_command command, struct commit *commit,
  			const char *dest = git_path("SQUASH_MSG");
  			unlink(dest);
  			if (copy_file(dest, rebase_path_squash_msg(), 0666))
 -				return error("Could not rename %s to "
 -					"%s", rebase_path_squash_msg(), dest);
 +				return error(_("could not rename '%s' to '%s'"),
 +					     rebase_path_squash_msg(), dest);
  			unlink(git_path("MERGE_MSG"));
  			msg_file = dest;
  			edit = 1;
 @@ -1109,7 +1110,7 @@ static int do_pick_commit(enum todo_command command, struct commit *commit,
  	}
  
  	if (is_rebase_i(opts) && write_author_script(msg.message) < 0)
 -		res |= -1;
 +		res = -1;
  	else if (!opts->strategy || !strcmp(opts->strategy, "recursive") || command == TODO_REVERT) {
  		res = do_recursive_merge(base, next, base_label, next_label,
  					 head, &msgbuf, opts);
 @@ -1166,8 +1167,8 @@ static int do_pick_commit(enum todo_command command, struct commit *commit,
  	}
  	if (!opts->no_commit)
  fast_forward_edit:
 -		res |= sequencer_commit(msg_file, opts, allow, edit, amend,
 -			cleanup_commit_message);
 +		res = run_git_commit(msg_file, opts, allow, edit, amend,
 +				     cleanup_commit_message);
  
  	if (!res && final_fixup) {
  		unlink(rebase_path_fixup_msg());
 @@ -1317,7 +1318,7 @@ static int parse_insn_line(struct todo_item *item, const char *bol, char *eol)
  static int parse_insn_buffer(char *buf, struct todo_list *todo_list)
  {
  	struct todo_item *item;
 -	char *p = buf;
 +	char *p = buf, *next_p;
  	int i, res = 0, fixup_okay = file_exists(rebase_path_done());
  
  	for (i = 1; *p; i++, p = next_p) {
 @@ -1335,15 +1336,16 @@ static int parse_insn_buffer(char *buf, struct todo_list *todo_list)
  				i, (int)(eol - p), p);
  			item->command = TODO_NOOP;
  		}
 +
  		if (fixup_okay)
  			; /* do nothing */
  		else if (is_fixup(item->command))
 -			return error("Cannot '%s' without a previous commit",
 +			return error(_("cannot '%s' without a previous commit"),
  				command_to_string(item->command));
  		else if (item->command < TODO_NOOP)
  			fixup_okay = 1;
 -		p = *eol ? eol + 1 : eol;
  	}
 +
  	return res;
  }
  
 @@ -1377,13 +1379,14 @@ static int read_populate_todo(struct todo_list *todo_list,
  	res = parse_insn_buffer(todo_list->buf.buf, todo_list);
  	if (res) {
  		if (is_rebase_i(opts))
 -			return error("Please fix this using "
 -				"'git rebase --edit-todo'.");
 -		return error(_("Unusable instruction sheet: %s"), todo_file);
 +			return error(_("please fix this using "
 +				       "'git rebase --edit-todo'."));
 +		return error(_("unusable instruction sheet: '%s'"), todo_file);
  	}
 +
  	if (!todo_list->nr &&
  	    (!is_rebase_i(opts) || !file_exists(rebase_path_done())))
 -		return error(_("No commits parsed."));
 +		return error(_("no commits parsed."));
  
  	if (!is_rebase_i(opts)) {
  		enum todo_command valid =
 @@ -1408,10 +1411,10 @@ static int read_populate_todo(struct todo_list *todo_list,
  			todo_list->done_nr = count_commands(&done);
  		else
  			todo_list->done_nr = 0;
 -		todo_list_release(&done);
  
  		todo_list->total_nr = todo_list->done_nr
  			+ count_commands(todo_list);
 +		todo_list_release(&done);
  
  		if (f) {
  			fprintf(f, "%d\n", todo_list->total_nr);
 @@ -1467,6 +1470,26 @@ static int populate_opts_cb(const char *key, const char *value, void *data)
  	return 0;
  }
  
 +static void read_strategy_opts(struct replay_opts *opts, struct strbuf *buf)
 +{
 +	int i;
 +
 +	strbuf_reset(buf);
 +	if (!read_oneliner(buf, rebase_path_strategy(), 0))
 +		return;
 +	opts->strategy = strbuf_detach(buf, NULL);
 +	if (!read_oneliner(buf, rebase_path_strategy_opts(), 0))
 +		return;
 +
 +	opts->xopts_nr = split_cmdline(buf->buf, (const char ***)&opts->xopts);
 +	for (i = 0; i < opts->xopts_nr; i++) {
 +		const char *arg = opts->xopts[i];
 +
 +		skip_prefix(arg, "--", &arg);
 +		opts->xopts[i] = xstrdup(arg);
 +	}
 +}
 +
  static int read_populate_opts(struct replay_opts *opts)
  {
  	if (is_rebase_i(opts)) {
 @@ -1480,30 +1503,12 @@ static int read_populate_opts(struct replay_opts *opts)
  				opts->gpg_sign = xstrdup(buf.buf + 2);
  			}
  		}
 -		strbuf_release(&buf);
  
  		if (file_exists(rebase_path_verbose()))
  			opts->verbose = 1;
  
 -		if (read_oneliner(&buf, rebase_path_strategy(), 0)) {
 -			opts->strategy =
 -				sequencer_entrust(opts,
 -						  strbuf_detach(&buf, NULL));
 -			if (read_oneliner(&buf,
 -					  rebase_path_strategy_opts(), 0)) {
 -				int i;
 -				opts->xopts_nr = split_cmdline(buf.buf,
 -					&opts->xopts);
 -				for (i = 0; i < opts->xopts_nr; i++)
 -					skip_prefix(opts->xopts[i], "--",
 -						    &opts->xopts[i]);
 -				if (opts->xopts_nr)
 -					sequencer_entrust(opts,
 -						strbuf_detach(&buf, NULL));
 -				else
 -					strbuf_release(&buf);
 -			}
 -		}
 +		read_strategy_opts(opts, &buf);
 +		strbuf_release(&buf);
  
  		return 0;
  	}
 @@ -1527,7 +1532,7 @@ static int walk_revs_populate_todo(struct todo_list *todo_list,
  {
  	enum todo_command command = opts->action == REPLAY_PICK ?
  		TODO_PICK : TODO_REVERT;
 -	const char *command_string = todo_command_strings[command];
 +	const char *command_string = todo_command_info[command].str;
  	struct commit *commit;
  
  	if (prepare_revs(opts))
 @@ -1681,12 +1686,15 @@ static int save_todo(struct todo_list *todo_list, struct replay_opts *opts)
  		int prev_offset = !next ? 0 :
  			todo_list->items[next - 1].offset_in_buf;
  
 -		if (offset > prev_offset && write_in_full(fd,
 -				todo_list->buf.buf + prev_offset,
 -				offset - prev_offset) < 0)
 -			return error(_("Could not write to %s (%s)"),
 -				done_path, strerror(errno));
 -		close(fd);
 +		if (fd >= 0 && offset > prev_offset &&
 +		    write_in_full(fd, todo_list->buf.buf + prev_offset,
 +				  offset - prev_offset) < 0) {
 +			close(fd);
 +			return error_errno(_("could not write to '%s'"),
 +					   done_path);
 +		}
 +		if (fd >= 0)
 +			close(fd);
  	}
  	return 0;
  }
 @@ -1730,11 +1738,11 @@ static int make_patch(struct commit *commit, struct replay_opts *opts)
  {
  	struct strbuf buf = STRBUF_INIT;
  	struct rev_info log_tree_opt;
 -	const char *commit_buffer = get_commit_buffer(commit, NULL), *subject;
 +	const char *commit_buffer = get_commit_buffer(commit, NULL), *subject, *p;
  	int res = 0;
  
 -	if (write_file_gently(rebase_path_stopped_sha(),
 -			      short_commit_name(commit), 1) < 0)
 +	p = short_commit_name(commit);
 +	if (write_message(p, strlen(p), rebase_path_stopped_sha(), 1) < 0)
  		return -1;
  
  	strbuf_addf(&buf, "%s/patch", get_dir(opts));
 @@ -1748,7 +1756,7 @@ static int make_patch(struct commit *commit, struct replay_opts *opts)
  	log_tree_opt.diffopt.file = fopen(buf.buf, "w");
  	log_tree_opt.diffopt.use_color = GIT_COLOR_NEVER;
  	if (!log_tree_opt.diffopt.file)
 -		res |= error_errno("could not open '%s'", buf.buf);
 +		res |= error_errno(_("could not open '%s'"), buf.buf);
  	else {
  		res |= log_tree_commit(&log_tree_opt, commit);
  		fclose(log_tree_opt.diffopt.file);
 @@ -1758,7 +1766,7 @@ static int make_patch(struct commit *commit, struct replay_opts *opts)
  	strbuf_addf(&buf, "%s/message", get_dir(opts));
  	if (!file_exists(buf.buf)) {
  		find_commit_subject(commit_buffer, &subject);
 -		res |= write_file_gently(buf.buf, subject, 1);
 +		res |= write_message(subject, strlen(subject), buf.buf, 1);
  		unuse_commit_buffer(commit, commit_buffer);
  	}
  	strbuf_release(&buf);
 @@ -1769,11 +1777,13 @@ static int make_patch(struct commit *commit, struct replay_opts *opts)
  static int intend_to_amend(void)
  {
  	unsigned char head[20];
 +	char *p;
  
  	if (get_sha1("HEAD", head))
 -		return error("Cannot read HEAD");
 +		return error(_("cannot read HEAD"));
  
 -	return write_file_gently(rebase_path_amend(), sha1_to_hex(head), 1);
 +	p = sha1_to_hex(head);
 +	return write_message(p, strlen(p), rebase_path_amend(), 1);
  }
  
  static int error_with_patch(struct commit *commit,
 @@ -1806,13 +1816,13 @@ static int error_failed_squash(struct commit *commit,
  	struct replay_opts *opts, int subject_len, const char *subject)
  {
  	if (rename(rebase_path_squash_msg(), rebase_path_message()))
 -		return error("Could not rename %s to %s",
 +		return error(_("could not rename '%s' to '%s'"),
  			rebase_path_squash_msg(), rebase_path_message());
  	unlink(rebase_path_fixup_msg());
  	unlink(git_path("MERGE_MSG"));
  	if (copy_file(git_path("MERGE_MSG"), rebase_path_message(), 0666))
 -		return error("Could not copy %s to %s", rebase_path_message(),
 -			git_path("MERGE_MSG"));
 +		return error(_("could not copy '%s' to '%s'"),
 +			     rebase_path_message(), git_path("MERGE_MSG"));
  	return error_with_patch(commit, subject, subject_len, opts, 1, 0);
  }
  
 @@ -1827,30 +1837,30 @@ static int do_exec(const char *command_line)
  
  	/* force re-reading of the cache */
  	if (discard_cache() < 0 || read_cache() < 0)
 -		return error(_("Could not read index"));
 +		return error(_("could not read index"));
  
  	dirty = require_clean_work_tree("rebase", NULL, 1, 1);
  
  	if (status) {
 -		warning("Execution failed: %s\n%s"
 -			"You can fix the problem, and then run\n"
 -			"\n"
 -			"  git rebase --continue\n"
 -			"\n",
 +		warning(_("execution failed: %s\n%s"
 +			  "You can fix the problem, and then run\n"
 +			  "\n"
 +			  "  git rebase --continue\n"
 +			  "\n"),
  			command_line,
 -			dirty ? "and made changes to the index and/or the "
 -				"working tree\n" : "");
 +			dirty ? N_("and made changes to the index and/or the "
 +				"working tree\n") : "");
  		if (status == 127)
  			/* command not found */
  			status = 1;
  	}
  	else if (dirty) {
 -		warning("Execution succeeded: %s\nbut "
 -			"left changes to the index and/or the working tree\n"
 -			"Commit or stash your changes, and then run\n"
 -			"\n"
 -			"  git rebase --continue\n"
 -			"\n", command_line);
 +		warning(_("execution succeeded: %s\nbut "
 +			  "left changes to the index and/or the working tree\n"
 +			  "Commit or stash your changes, and then run\n"
 +			  "\n"
 +			  "  git rebase --continue\n"
 +			  "\n"), command_line);
  		status = 1;
  	}
  
 @@ -1912,7 +1922,7 @@ static int apply_autostash(struct replay_opts *opts)
  		argv_array_push(&store.args, "-q");
  		argv_array_push(&store.args, stash_sha1.buf);
  		if (run_command(&store))
 -			ret = error(_("Cannot store %s"), stash_sha1.buf);
 +			ret = error(_("cannot store %s"), stash_sha1.buf);
  		else
  			printf(_("Applying autostash resulted in conflicts.\n"
  				"Your changes are safe in the stash.\n"
 @@ -1995,7 +2005,7 @@ static int pick_commits(struct todo_list *todo_list, struct replay_opts *opts)
  			if (item->command == TODO_EDIT) {
  				struct commit *commit = item->commit;
  				if (!res)
 -					warning("Stopped at %s... %.*s",
 +					warning(_("stopped at %s... %.*s"),
  						short_commit_name(commit),
  						item->arg_len, item->arg);
  				return error_with_patch(commit,
 @@ -2025,7 +2035,7 @@ static int pick_commits(struct todo_list *todo_list, struct replay_opts *opts)
  			*end_of_arg = saved;
  		}
  		else if (item->command < TODO_NOOP)
 -			return error("Unknown command %d", item->command);
 +			return error(_("unknown command %d"), item->command);
  
  		todo_list->current++;
  		if (res)
 @@ -2046,22 +2056,22 @@ static int pick_commits(struct todo_list *todo_list, struct replay_opts *opts)
  			unsigned char head[20], orig[20];
  
  			if (get_sha1("HEAD", head))
 -				return error("Cannot read HEAD");
 +				return error(_("cannot read HEAD"));
  			if (!read_oneliner(&buf, rebase_path_orig_head(), 0) ||
  					get_sha1_hex(buf.buf, orig))
 -				return error("Could not read orig-head");
 +				return error(_("could not read orig-head"));
  			if (!read_oneliner(&buf, rebase_path_onto(), 0))
 -				return error("Could not read 'onto'");
 +				return error(_("could not read 'onto'"));
  			msg = reflog_message(opts, "finish", "%s onto %s",
  				head_ref.buf, buf.buf);
  			if (update_ref(msg, head_ref.buf, head, orig,
  					REF_NODEREF, UPDATE_REFS_MSG_ON_ERR))
 -				return error("Could not update %s",
 +				return error(_("could not update %s"),
  					head_ref.buf);
  			msg = reflog_message(opts, "finish", "returning to %s",
  				head_ref.buf);
  			if (create_symref("HEAD", head_ref.buf, msg))
 -				return error("Could not update HEAD to %s",
 +				return error(_("could not update HEAD to %s"),
  					head_ref.buf);
  			strbuf_reset(&buf);
  		}
 @@ -2072,7 +2082,7 @@ static int pick_commits(struct todo_list *todo_list, struct replay_opts *opts)
  			};
  
  			if (!read_oneliner(&buf, rebase_path_orig_head(), 0))
 -				return error("Could not read %s",
 +				return error(_("could not read '%s'"),
  					rebase_path_orig_head());
  			strbuf_addstr(&buf, "..HEAD");
  			argv[2] = buf.buf;
 @@ -2099,6 +2109,7 @@ static int pick_commits(struct todo_list *todo_list, struct replay_opts *opts)
  
  				hook.in = open(rebase_path_rewritten_list(),
  					O_RDONLY);
 +				hook.stdout_to_stderr = 1;
  				argv_array_push(&hook.args, post_rewrite_hook);
  				argv_array_push(&hook.args, "rebase");
  				/* we don't care if this hook failed */
 @@ -2136,12 +2147,12 @@ static int commit_staged_changes(struct replay_opts *opts)
  	int amend = 0;
  
  	if (has_unstaged_changes(1))
 -		return error(_("Cannot rebase: You have unstaged changes."));
 +		return error(_("cannot rebase: You have unstaged changes."));
  	if (!has_uncommitted_changes(0)) {
  		const char *cherry_pick_head = git_path("CHERRY_PICK_HEAD");
  
  		if (file_exists(cherry_pick_head) && unlink(cherry_pick_head))
 -			return error("Could not remove CHERRY_PICK_HEAD");
 +			return error(_("could not remove CHERRY_PICK_HEAD"));
  		return 0;
  	}
  
 @@ -2150,23 +2161,24 @@ static int commit_staged_changes(struct replay_opts *opts)
  		unsigned char head[20], to_amend[20];
  
  		if (get_sha1("HEAD", head))
 -			return error("Cannot amend non-existing commit");
 +			return error(_("cannot amend non-existing commit"));
  		if (!read_oneliner(&rev, rebase_path_amend(), 0))
 -			return error("Invalid file: %s", rebase_path_amend());
 +			return error(_("invalid file: '%s'"), rebase_path_amend());
  		if (get_sha1_hex(rev.buf, to_amend))
 -			return error("Invalid contents: %s",
 +			return error(_("invalid contents: '%s'"),
  				rebase_path_amend());
  		if (hashcmp(head, to_amend))
 -			return error("\nYou have uncommitted changes in your "
 -				"working tree. Please, commit them\nfirst and "
 -				"then run 'git rebase --continue' again.");
 +			return error(_("\nYou have uncommitted changes in your "
 +				       "working tree. Please, commit them\n"
 +				       "first and then run 'git rebase "
 +				       "--continue' again."));
  
  		strbuf_release(&rev);
  		amend = 1;
  	}
  
 -	if (sequencer_commit(rebase_path_message(), opts, 1, 1, amend, 0))
 -		return error("Could not commit staged changes.");
 +	if (run_git_commit(rebase_path_message(), opts, 1, 1, amend, 0))
 +		return error(_("could not commit staged changes."));
  	unlink(rebase_path_amend());
  	return 0;
  }
 @@ -2194,23 +2206,23 @@ int sequencer_continue(struct replay_opts *opts)
  		/* Verify that the conflict has been resolved */
  		if (file_exists(git_path_cherry_pick_head()) ||
  		    file_exists(git_path_revert_head())) {
 -			int ret = continue_single_pick();
 -			if (ret)
 -				return ret;
 +			res = continue_single_pick();
 +			if (res)
 +				goto release_todo_list;
 +		}
 +		if (index_differs_from("HEAD", 0, 0)) {
 +			res = error_dirty_index(opts);
 +			goto release_todo_list;
  		}
 -		if (index_differs_from("HEAD", 0))
 -			return error_dirty_index(opts);
  		todo_list.current++;
  	}
  	else if (file_exists(rebase_path_stopped_sha())) {
  		struct strbuf buf = STRBUF_INIT;
  		struct object_id oid;
  
 -		if (read_oneliner(&buf, rebase_path_stopped_sha(), 1)) {
 -			if (!get_sha1_committish(buf.buf, oid.hash))
 -				record_in_rewritten(&oid,
 -						peek_command(&todo_list, 0));
 -		}
 +		if (read_oneliner(&buf, rebase_path_stopped_sha(), 1) &&
 +		    !get_sha1_committish(buf.buf, oid.hash))
 +			record_in_rewritten(&oid, peek_command(&todo_list, 0));
  		strbuf_release(&buf);
  	}
  
-- 
2.11.0.rc3.windows.1
Previous: Johannes SchindelinNext: Johannes Schindelin
Message 63 of 212 in “Teach the sequencer to act as rebase -i's backend”
  1. 00/34 Teach the sequencer to act as rebase -i's backendJohannes Schindelin, Aug 31, 2016
  2. 07/34 sequencer (rebase -i): add support for the 'fixup' and 'squash' commandsJohannes Schindelin, Aug 31, 2016
  3. Dennis KaarsemakerSep 1, 2016
  4. Johannes SchindelinSep 1, 2016
  5. Dennis KaarsemakerSep 1, 2016
  6. Johannes SchindelinSep 2, 2016
  7. Dennis KaarsemakerSep 2, 2016
  8. Johannes SchindelinSep 2, 2016
  9. Dennis KaarsemakerSep 2, 2016
  10. Junio C HamanoSep 1, 2016
  11. Johannes SchindelinSep 2, 2016
  12. 05/34 sequencer (rebase -i): learn about the 'verbose' modeJohannes Schindelin, Aug 31, 2016
  13. Dennis KaarsemakerAug 31, 2016
  14. Johannes SchindelinAug 31, 2016
  15. 04/34 sequencer (rebase -i): implement the 'exec' commandJohannes Schindelin, Aug 31, 2016
  16. 03/34 sequencer (rebase -i): implement the 'edit' commandJohannes Schindelin, Aug 31, 2016
  17. 02/34 sequencer (rebase -i): implement the 'noop' commandJohannes Schindelin, Aug 31, 2016
  18. 01/34 sequencer: support a new action: 'interactive rebase'Johannes Schindelin, Aug 31, 2016
  19. Kevin DaudtSep 2, 2016
  20. Johannes SchindelinSep 3, 2016
  21. 08/34 sequencer (rebase -i): implement the short commandsJohannes Schindelin, Aug 31, 2016
  22. 09/34 sequencer (rebase -i): write an author-script fileJohannes Schindelin, Aug 31, 2016
  23. 12/34 sequencer (rebase -i): skip some revert/cherry-pick specific code pathJohannes Schindelin, Aug 31, 2016
  24. 11/34 sequencer (rebase -i): remove CHERRY_PICK_HEAD when no longer neededJohannes Schindelin, Aug 31, 2016
  25. 13/34 sequencer (rebase -i): the todo can be empty when continuingJohannes Schindelin, Aug 31, 2016
  26. 10/34 sequencer (rebase -i): allow continuing with staged changesJohannes Schindelin, Aug 31, 2016
  27. 16/34 sequencer (rebase -i): implement the 'reword' commandJohannes Schindelin, Aug 31, 2016
  28. 19/34 sequencer (rebase -i): set the reflog message consistentlyJohannes Schindelin, Aug 31, 2016
  29. 18/34 sequencer (rebase -i): refactor setting the reflog messageJohannes Schindelin, Aug 31, 2016
  30. 21/34 sequencer (rebase -i): record interrupted commits in rewritten, tooJohannes Schindelin, Aug 31, 2016
  31. 20/34 sequencer (rebase -i): copy commit notes at endJohannes Schindelin, Aug 31, 2016
  32. Dennis KaarsemakerSep 1, 2016
  33. Johannes SchindelinSep 1, 2016
  34. 22/34 sequencer (rebase -i): run the post-rewrite hook, if neededJohannes Schindelin, Aug 31, 2016
  35. 26/34 sequencer (rebase -i): implement the 'drop' commandJohannes Schindelin, Aug 31, 2016
  36. 23/34 sequencer (rebase -i): respect the rebase.autostash settingJohannes Schindelin, Aug 31, 2016
  37. 27/34 sequencer (rebase -i): differentiate between comments and 'noop'Johannes Schindelin, Aug 31, 2016
  38. Dennis KaarsemakerSep 1, 2016
  39. Johannes SchindelinSep 1, 2016
  40. Dennis KaarsemakerSep 1, 2016
  41. Johannes SchindelinSep 2, 2016
  42. 24/34 sequencer (rebase -i): respect strategy/strategy_opts settingsJohannes Schindelin, Aug 31, 2016
  43. 25/34 sequencer (rebase -i): allow rescheduling commandsJohannes Schindelin, Aug 31, 2016
  44. 17/34 sequencer (rebase -i): allow fast-forwarding for edit/rewordJohannes Schindelin, Aug 31, 2016
  45. 28/34 run_command_opt(): optionally hide stderr when the command succeedsJohannes Schindelin, Aug 31, 2016
  46. 29/34 sequencer (rebase -i): show only failed `git commit`'s outputJohannes Schindelin, Aug 31, 2016
  47. 31/34 sequencer (rebase -i): suggest --edit-todo upon unknown commandJohannes Schindelin, Aug 31, 2016
  48. 32/34 sequencer (rebase -i): show the progressJohannes Schindelin, Aug 31, 2016
  49. Dennis KaarsemakerSep 1, 2016
  50. Johannes SchindelinSep 1, 2016
  51. 33/34 sequencer (rebase -i): write the progress into filesJohannes Schindelin, Aug 31, 2016
  52. 30/34 sequencer (rebase -i): show only failed cherry-picks' outputJohannes Schindelin, Aug 31, 2016
  53. 34/34 sequencer (rebase -i): write out the final messageJohannes Schindelin, Aug 31, 2016
  54. 15/34 sequencer (rebase -i): leave a patch upon errorJohannes Schindelin, Aug 31, 2016
  55. Dennis KaarsemakerAug 31, 2016
  56. Johannes SchindelinSep 1, 2016
  57. 06/34 sequencer (rebase -i): write the 'done' fileJohannes Schindelin, Aug 31, 2016
  58. Dennis KaarsemakerAug 31, 2016
  59. Johannes SchindelinSep 1, 2016
  60. 14/34 sequencer (rebase -i): update refs after a successful rebaseJohannes Schindelin, Aug 31, 2016
  61. Dennis KaarsemakerAug 31, 2016
  62. Johannes SchindelinSep 1, 2016
  63. 00/34 Teach the sequencer to act as rebase -i's backendJohannes Schindelin, Dec 13, 2016
  64. 04/34 sequencer (rebase -i): implement the 'exec' commandJohannes Schindelin, Dec 13, 2016
  65. Junio C HamanoDec 13, 2016
  66. Johannes SchindelinDec 19, 2016
  67. 03/34 sequencer (rebase -i): implement the 'edit' commandJohannes Schindelin, Dec 13, 2016
  68. Junio C HamanoDec 13, 2016
  69. Johannes SchindelinDec 19, 2016
  70. Junio C HamanoDec 19, 2016
  71. Junio C HamanoDec 19, 2016
  72. 12/34 sequencer (rebase -i): skip some revert/cherry-pick specific code pathJohannes Schindelin, Dec 13, 2016
  73. 14/34 sequencer (rebase -i): update refs after a successful rebaseJohannes Schindelin, Dec 13, 2016
  74. Junio C HamanoDec 16, 2016
  75. Johannes SchindelinDec 19, 2016
  76. 27/34 sequencer (rebase -i): differentiate between comments and 'noop'Johannes Schindelin, Dec 13, 2016
  77. Junio C HamanoDec 19, 2016
  78. 06/34 sequencer (rebase -i): write the 'done' fileJohannes Schindelin, Dec 13, 2016
  79. Junio C HamanoDec 13, 2016
  80. 05/34 sequencer (rebase -i): learn about the 'verbose' modeJohannes Schindelin, Dec 13, 2016
  81. Junio C HamanoDec 13, 2016
  82. Junio C HamanoDec 14, 2016
  83. Johannes SchindelinJan 2, 2017
  84. Junio C HamanoJan 7, 2017
  85. Junio C HamanoJan 8, 2017
  86. 07/34 sequencer (rebase -i): add support for the 'fixup' and 'squash' commandsJohannes Schindelin, Dec 13, 2016
  87. Junio C HamanoDec 15, 2016
  88. Jeff KingDec 15, 2016
  89. Johannes SchindelinDec 19, 2016
  90. Jeff KingDec 19, 2016
  91. Johannes SchindelinDec 19, 2016
  92. Jeff KingDec 15, 2016
  93. Stefan BellerDec 15, 2016
  94. Jeff KingDec 15, 2016
  95. Stefan BellerDec 15, 2016
  96. Johannes SchindelinDec 19, 2016
  97. 13/34 sequencer (rebase -i): the todo can be empty when continuingJohannes Schindelin, Dec 13, 2016
  98. 28/34 run_command_opt(): optionally hide stderr when the command succeedsJohannes Schindelin, Dec 13, 2016
  99. Johannes SixtDec 14, 2016
  100. Jeff KingDec 14, 2016
  101. Jeff KingDec 14, 2016
  102. Johannes SixtDec 14, 2016
  103. Johannes SchindelinJan 2, 2017
  104. 26/34 sequencer (rebase -i): implement the 'drop' commandJohannes Schindelin, Dec 13, 2016
  105. 15/34 sequencer (rebase -i): leave a patch upon errorJohannes Schindelin, Dec 13, 2016
  106. Junio C HamanoDec 16, 2016
  107. 25/34 sequencer (rebase -i): allow rescheduling commandsJohannes Schindelin, Dec 13, 2016
  108. 24/34 sequencer (rebase -i): respect strategy/strategy_opts settingsJohannes Schindelin, Dec 13, 2016
  109. Junio C HamanoDec 19, 2016
  110. 20/34 sequencer (rebase -i): copy commit notes at endJohannes Schindelin, Dec 13, 2016
  111. Junio C HamanoDec 16, 2016
  112. Johannes SchindelinJan 2, 2017
  113. 23/34 sequencer (rebase -i): respect the rebase.autostash settingJohannes Schindelin, Dec 13, 2016
  114. 22/34 sequencer (rebase -i): run the post-rewrite hook, if neededJohannes Schindelin, Dec 13, 2016
  115. 19/34 sequencer (rebase -i): set the reflog message consistentlyJohannes Schindelin, Dec 13, 2016
  116. 21/34 sequencer (rebase -i): record interrupted commits in rewritten, tooJohannes Schindelin, Dec 13, 2016
  117. 18/34 sequencer (rebase -i): refactor setting the reflog messageJohannes Schindelin, Dec 13, 2016
  118. Junio C HamanoDec 16, 2016
  119. 17/34 sequencer (rebase -i): allow fast-forwarding for edit/rewordJohannes Schindelin, Dec 13, 2016
  120. 16/34 sequencer (rebase -i): implement the 'reword' commandJohannes Schindelin, Dec 13, 2016
  121. 32/34 sequencer (rebase -i): show the progressJohannes Schindelin, Dec 13, 2016
  122. Junio C HamanoDec 19, 2016
  123. 33/34 sequencer (rebase -i): write the progress into filesJohannes Schindelin, Dec 13, 2016
  124. 34/34 sequencer (rebase -i): write out the final messageJohannes Schindelin, Dec 13, 2016
  125. 31/34 sequencer (rebase -i): suggest --edit-todo upon unknown commandJohannes Schindelin, Dec 13, 2016
  126. 01/34 sequencer: support a new action: 'interactive rebase'Johannes Schindelin, Dec 13, 2016
  127. Junio C HamanoDec 13, 2016
  128. Johannes SchindelinDec 19, 2016
  129. Junio C HamanoDec 14, 2016
  130. Stephan BeyerDec 17, 2016
  131. Johannes SchindelinDec 19, 2016
  132. Stephan BeyerDec 19, 2016
  133. 02/34 sequencer (rebase -i): implement the 'noop' commandJohannes Schindelin, Dec 13, 2016
  134. Junio C HamanoDec 13, 2016
  135. Linus TorvaldsDec 13, 2016
  136. Junio C HamanoDec 13, 2016
  137. Johannes SchindelinDec 19, 2016
  138. Junio C HamanoDec 19, 2016
  139. Johannes SchindelinDec 19, 2016
  140. 08/34 sequencer (rebase -i): implement the short commandsJohannes Schindelin, Dec 13, 2016
  141. Junio C HamanoDec 15, 2016
  142. 09/34 sequencer (rebase -i): write an author-script fileJohannes Schindelin, Dec 13, 2016
  143. Junio C HamanoDec 15, 2016
  144. Johannes SchindelinDec 19, 2016
  145. Junio C HamanoDec 20, 2016
  146. Junio C HamanoDec 20, 2016
  147. 10/34 sequencer (rebase -i): allow continuing with staged changesJohannes Schindelin, Dec 13, 2016
  148. Junio C HamanoDec 15, 2016
  149. 11/34 sequencer (rebase -i): remove CHERRY_PICK_HEAD when no longer neededJohannes Schindelin, Dec 13, 2016
  150. Junio C HamanoDec 16, 2016
  151. Johannes SchindelinDec 19, 2016
  152. 30/34 sequencer (rebase -i): show only failed cherry-picks' outputJohannes Schindelin, Dec 13, 2016
  153. 29/34 sequencer (rebase -i): show only failed `git commit`'s outputJohannes Schindelin, Dec 13, 2016
  154. Junio C HamanoDec 13, 2016
  155. Johannes SchindelinDec 19, 2016
  156. Johannes SixtDec 14, 2016
  157. Johannes SchindelinDec 19, 2016
  158. 00/38 Teach the sequencer to act as rebase -i's backendJohannes Schindelin, Jan 2, 2017
  159. 02/38 sequencer: move "else" keyword onto the same line as preceding braceJohannes Schindelin, Jan 2, 2017
  160. Junio C HamanoJan 12, 2017
  161. 01/38 sequencer: avoid unnecessary curly bracesJohannes Schindelin, Jan 2, 2017
  162. Junio C HamanoJan 12, 2017
  163. Johannes SchindelinJan 14, 2017
  164. Jeff KingJan 14, 2017
  165. Jacob KellerJan 16, 2017
  166. 03/38 sequencer: use a helper to find the commit messageJohannes Schindelin, Jan 2, 2017
  167. Junio C HamanoJan 12, 2017
  168. 04/38 sequencer: support a new action: 'interactive rebase'Johannes Schindelin, Jan 2, 2017
  169. 05/38 sequencer (rebase -i): implement the 'noop' commandJohannes Schindelin, Jan 2, 2017
  170. 06/38 sequencer (rebase -i): implement the 'edit' commandJohannes Schindelin, Jan 2, 2017
  171. Junio C HamanoJan 12, 2017
  172. Johannes SchindelinJan 14, 2017
  173. 07/38 sequencer (rebase -i): implement the 'exec' commandJohannes Schindelin, Jan 2, 2017
  174. 08/38 sequencer (rebase -i): learn about the 'verbose' modeJohannes Schindelin, Jan 2, 2017
  175. 09/38 sequencer (rebase -i): write the 'done' fileJohannes Schindelin, Jan 2, 2017
  176. 11/38 sequencer (rebase -i): implement the short commandsJohannes Schindelin, Jan 2, 2017
  177. 10/38 sequencer (rebase -i): add support for the 'fixup' and 'squash' commandsJohannes Schindelin, Jan 2, 2017
  178. 12/38 sequencer (rebase -i): write an author-script fileJohannes Schindelin, Jan 2, 2017
  179. 15/38 sequencer (rebase -i): skip some revert/cherry-pick specific code pathJohannes Schindelin, Jan 2, 2017
  180. 14/38 sequencer (rebase -i): remove CHERRY_PICK_HEAD when no longer neededJohannes Schindelin, Jan 2, 2017
  181. 13/38 sequencer (rebase -i): allow continuing with staged changesJohannes Schindelin, Jan 2, 2017
  182. 16/38 sequencer (rebase -i): the todo can be empty when continuingJohannes Schindelin, Jan 2, 2017
  183. 18/38 sequencer (rebase -i): leave a patch upon errorJohannes Schindelin, Jan 2, 2017
  184. 17/38 sequencer (rebase -i): update refs after a successful rebaseJohannes Schindelin, Jan 2, 2017
  185. 19/38 sequencer (rebase -i): implement the 'reword' commandJohannes Schindelin, Jan 2, 2017
  186. 21/38 sequencer (rebase -i): refactor setting the reflog messageJohannes Schindelin, Jan 2, 2017
  187. 23/38 sequencer (rebase -i): copy commit notes at endJohannes Schindelin, Jan 2, 2017
  188. 20/38 sequencer (rebase -i): allow fast-forwarding for edit/rewordJohannes Schindelin, Jan 2, 2017
  189. 24/38 sequencer (rebase -i): record interrupted commits in rewritten, tooJohannes Schindelin, Jan 2, 2017
  190. 25/38 sequencer (rebase -i): run the post-rewrite hook, if neededJohannes Schindelin, Jan 2, 2017
  191. 22/38 sequencer (rebase -i): set the reflog message consistentlyJohannes Schindelin, Jan 2, 2017
  192. 26/38 sequencer (rebase -i): respect the rebase.autostash settingJohannes Schindelin, Jan 2, 2017
  193. 27/38 sequencer (rebase -i): respect strategy/strategy_opts settingsJohannes Schindelin, Jan 2, 2017
  194. 28/38 sequencer (rebase -i): allow rescheduling commandsJohannes Schindelin, Jan 2, 2017
  195. 29/38 sequencer (rebase -i): implement the 'drop' commandJohannes Schindelin, Jan 2, 2017
  196. 30/38 sequencer (rebase -i): differentiate between comments and 'noop'Johannes Schindelin, Jan 2, 2017
  197. 32/38 sequencer: use run_command() directlyJohannes Schindelin, Jan 2, 2017
  198. 33/38 sequencer (rebase -i): show only failed `git commit`'s outputJohannes Schindelin, Jan 2, 2017
  199. 31/38 sequencer: make reading author-script more elegantJohannes Schindelin, Jan 2, 2017
  200. 34/38 sequencer (rebase -i): show only failed cherry-picks' outputJohannes Schindelin, Jan 2, 2017
  201. 35/38 sequencer (rebase -i): suggest --edit-todo upon unknown commandJohannes Schindelin, Jan 2, 2017
  202. 36/38 sequencer (rebase -i): show the progressJohannes Schindelin, Jan 2, 2017
  203. 37/38 sequencer (rebase -i): write the progress into filesJohannes Schindelin, Jan 2, 2017
  204. 38/38 sequencer (rebase -i): write out the final messageJohannes Schindelin, Jan 2, 2017
  205. Junio C HamanoJan 9, 2017
  206. Junio C HamanoJan 9, 2017
  207. Johannes SchindelinJan 14, 2017
  208. Junio C HamanoJan 15, 2017
  209. Johannes SchindelinJan 14, 2017
  210. Junio C HamanoJan 15, 2017
  211. Johannes SchindelinJan 16, 2017
  212. Junio C HamanoJan 17, 2017

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.