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

[PATCH v4 0/4] rebase -i: avoid stale "# This is a combination of" in commit messages

From
Johannes Schindelin <johannes.schindelin@gmx.de>
Date
Apr 27, 2018, 20:48 UTC
Message-ID
<cover.1524862093.git.johannes.schindelin@gmx.de>
In-Reply-To
<CAPig+cRrS0_nYJJY=O6cboV630sNQHPV5QGrQdD8MW-sYzNFGQ@mail.gmail.com>

Eric Sunshine pointed out that I had such a commit message in https://public-inbox.org/git/CAPig+cRrS0_nYJJY=O6cboV630sNQHPV5QGrQdD8MW-sYzNFGQ@mail.gmail.com/ and I went on a hunt to figure out how the heck this happened.

Turns out that if there is a fixup/squash chain where the *last* command fails with merge conflicts, and we either --skip ahead or resolve the conflict to a clean tree and then --continue, our code does not do a final cleanup.

Contrary to my initial gut feeling, this bug was not introduced by my rewrite in C of the core parts of rebase -i, but it looks to me as if that bug was with us for a very long time (at least the --skip part).

The developer (read: user of rebase -i) in me says that we would want to fast-track this, but the author of rebase -i in me says that we should be cautious and cook this in `next` for a while.

Fixes since v3 (thanks, Phillip, for the really fruitful discussion!):
- We now avoid using the commit message prepared for the skipped
  fixup/squash.
- Replaced the "rebase -i: Handle "combination of <n> commits" with
  GETTEXT_POISON" patch by a *real* fix instead of a work-around: Instead
  of parsing the first line of the commit message and punting when it is
  missing an ASCII-encoded number, we determine <n> separately
  (independent from any localized text).
- Fixed quite a couple more corner cases, using the `current-fixups`
  file introduced for the GETTEXT_POISON fix:
  * we only need to re-commit if this was the final fixup/squash in the
    fixup/squash chain,
  * we only need to commit interactively if there was *any* non-skipped
    squash,
  * if the fixup/squash chain continues, the <N> was incorrect in the
    "This is a combination of <N> commits" comment in the intermediate
    commit message (it included the now-skipped commits), and
  * even if a filed fixup/squash in the middle of a fixup/squash chain
    failed, and its merge conflicts were resolved and committed, the
    "This is a combination of <N> commits" comment was incorrect: we
    had already deleted message-fixup and message-squash, so the next
    update_squash_message() would mistakenly assume that we were
    starting afresh. Worse: if only fixup commands were remaining, but
    there had been a squash command, we would retain the "squash!" line
    in the commit message and not give the user a chance to clean things
    up in the final fixup!
Johannes Schindelin (4):
  rebase -i: demonstrate bugs with fixup!/squash! commit messages
  rebase -i: Handle "combination of <n> commits" with GETTEXT_POISON
  sequencer: always commit without editing when asked for
  rebase --skip: clean up commit message after a failed fixup/squash
 sequencer.c                | 193 ++++++++++++++++++++++++++++---------
 sequencer.h                |   6 +-
 t/t3418-rebase-continue.sh |  49 ++++++++++
 3 files changed, 200 insertions(+), 48 deletions(-)
base-commit: 1f1cddd558b54bb0ce19c8ace353fd07b758510d
Published-As: https://github.com/dscho/git/releases/tag/clean-msg-after-fixup-continue-v4
Fetch-It-Via: git fetch https://github.com/dscho/git clean-msg-after-fixup-continue-v4
Interdiff vs v3:
 diff --git a/sequencer.c b/sequencer.c
 index e1efb0ebf31..cec180714ef 100644
 --- a/sequencer.c
 +++ b/sequencer.c
 @@ -74,13 +74,6 @@ static GIT_PATH_FUNC(rebase_path_message, "rebase-merge/message")
   * previous commit and from the first squash/fixup commit are written
   * to it. The commit message for each subsequent squash/fixup commit
   * is appended to the file as it is processed.
 - *
 - * The first line of the file is of the form
 - *     # This is a combination of $count commits.
 - * where $count is the number of commits whose messages have been
 - * written to the file so far (including the initial "pick" commit).
 - * Each time that a commit message is processed, this line is read and
 - * updated. It is deleted just before the combined commit is made.
   */
  static GIT_PATH_FUNC(rebase_path_squash_msg, "rebase-merge/message-squash")
  /*
 @@ -91,6 +84,11 @@ static GIT_PATH_FUNC(rebase_path_squash_msg, "rebase-merge/message-squash")
   * commit without opening the editor.)
   */
  static GIT_PATH_FUNC(rebase_path_fixup_msg, "rebase-merge/message-fixup")
 +/*
 + * This file contains the list fixup/squash commands that have been
 + * accumulated into message-fixup or message-squash so far.
 + */
 +static GIT_PATH_FUNC(rebase_path_current_fixups, "rebase-merge/current-fixups")
  /*
   * A script to set the GIT_AUTHOR_NAME, GIT_AUTHOR_EMAIL, and
   * GIT_AUTHOR_DATE that will be used for the commit that is currently
 @@ -106,13 +104,6 @@ static GIT_PATH_FUNC(rebase_path_author_script, "rebase-merge/author-script")
   * command is processed, this file is deleted.
   */
  static GIT_PATH_FUNC(rebase_path_amend, "rebase-merge/amend")
 -/*
 - * If there was a merge conflict in a fixup/squash series, we need to
 - * record the type so that a `git rebase --skip` can clean up the commit
 - * message as appropriate. This file will contain that type (`fixup` or
 - * `squash`), and not exist otherwise.
 - */
 -static GIT_PATH_FUNC(rebase_path_amend_type, "rebase-merge/amend-type")
  /*
   * When we stop at a given patch via the "edit" command, this file contains
   * the abbreviated commit name of the corresponding patch.
 @@ -260,6 +251,7 @@ int sequencer_remove_state(struct replay_opts *opts)
  	for (i = 0; i < opts->xopts_nr; i++)
  		free(opts->xopts[i]);
  	free(opts->xopts);
 +	strbuf_release(&opts->current_fixups);
  
  	strbuf_addstr(&dir, get_dir(opts));
  	remove_dir_recursively(&dir, 0);
 @@ -725,6 +717,8 @@ static int run_git_commit(const char *defmsg, struct replay_opts *opts,
  		argv_array_pushf(&cmd.args, "-S%s", opts->gpg_sign);
  	if (defmsg)
  		argv_array_pushl(&cmd.args, "-F", defmsg, NULL);
 +	else if (!(flags & EDIT_MSG))
 +		argv_array_pushl(&cmd.args, "-C", "HEAD", NULL);
  	if ((flags & CLEANUP_MSG))
  		argv_array_push(&cmd.args, "--cleanup=strip");
  	if ((flags & EDIT_MSG))
 @@ -1336,33 +1330,23 @@ static int update_squash_messages(enum todo_command command,
  		struct commit *commit, struct replay_opts *opts)
  {
  	struct strbuf buf = STRBUF_INIT;
 -	int count, res;
 +	int res;
  	const char *message, *body;
  
 -	if (file_exists(rebase_path_squash_msg())) {
 +	if (opts->current_fixup_count > 0) {
  		struct strbuf header = STRBUF_INIT;
 -		char *eol, *p;
 +		char *eol;
  
 -		if (strbuf_read_file(&buf, rebase_path_squash_msg(), 2048) <= 0)
 +		if (strbuf_read_file(&buf, rebase_path_squash_msg(), 9) <= 0)
  			return error(_("could not read '%s'"),
  				rebase_path_squash_msg());
  
 -		p = buf.buf + 1;
 -		eol = strchrnul(buf.buf, '\n');
 -		if (buf.buf[0] != comment_line_char ||
 -		    (p += strcspn(p, "0123456789\n")) == eol)
 -			count = -1;
 -		else
 -			count = strtol(p, NULL, 10);
 +		eol = buf.buf[0] != comment_line_char ?
 +			buf.buf : strchrnul(buf.buf, '\n');
  
  		strbuf_addf(&header, "%c ", comment_line_char);
 -		if (count < 1)
 -			strbuf_addf(&header, _("This is a combination of "
 -					       "several commits."));
 -		else
 -			strbuf_addf(&header,
 -				    _("This is a combination of %d commits."),
 -				    ++count);
 +		strbuf_addf(&header, _("This is a combination of %d commits."),
 +			    opts->current_fixup_count + 2);
  		strbuf_splice(&buf, 0, eol - buf.buf, header.buf, header.len);
  		strbuf_release(&header);
  	} else {
 @@ -1385,10 +1369,8 @@ static int update_squash_messages(enum todo_command command,
  				     rebase_path_fixup_msg());
  		}
  
 -		count = 2;
  		strbuf_addf(&buf, "%c ", comment_line_char);
 -		strbuf_addf(&buf, _("This is a combination of %d commits."),
 -			    count);
 +		strbuf_addf(&buf, _("This is a combination of %d commits."), 2);
  		strbuf_addf(&buf, "\n%c ", comment_line_char);
  		strbuf_addstr(&buf, _("This is the 1st commit message:"));
  		strbuf_addstr(&buf, "\n\n");
 @@ -1405,22 +1387,14 @@ static int update_squash_messages(enum todo_command command,
  	if (command == TODO_SQUASH) {
  		unlink(rebase_path_fixup_msg());
  		strbuf_addf(&buf, "\n%c ", comment_line_char);
 -		if (count < 2)
 -			strbuf_addf(&buf, _("This is the next commit "
 -					    "message:"));
 -		else
 -			strbuf_addf(&buf, _("This is the commit message #%d:"),
 -				    count);
 +		strbuf_addf(&buf, _("This is the commit message #%d:"),
 +			    ++opts->current_fixup_count);
  		strbuf_addstr(&buf, "\n\n");
  		strbuf_addstr(&buf, body);
  	} else if (command == TODO_FIXUP) {
  		strbuf_addf(&buf, "\n%c ", comment_line_char);
 -		if (count < 2)
 -			strbuf_addf(&buf, _("The next commit message will be "
 -					    "skipped:"));
 -		else
 -			strbuf_addf(&buf, _("The commit message #%d will be "
 -					    "skipped:"), count);
 +		strbuf_addf(&buf, _("The commit message #%d will be skipped:"),
 +			    ++opts->current_fixup_count);
  		strbuf_addstr(&buf, "\n\n");
  		strbuf_add_commented_lines(&buf, body, strlen(body));
  	} else
 @@ -1429,6 +1403,17 @@ static int update_squash_messages(enum todo_command command,
  
  	res = write_message(buf.buf, buf.len, rebase_path_squash_msg(), 0);
  	strbuf_release(&buf);
 +
 +	if (!res) {
 +		strbuf_addf(&opts->current_fixups, "%s%s %s",
 +			    opts->current_fixups.len ? "\n" : "",
 +			    command_to_string(command),
 +			    oid_to_hex(&commit->object.oid));
 +		res = write_message(opts->current_fixups.buf,
 +				    opts->current_fixups.len,
 +				    rebase_path_current_fixups(), 0);
 +	}
 +
  	return res;
  }
  
 @@ -1691,6 +1676,9 @@ static int do_pick_commit(enum todo_command command, struct commit *commit,
  	if (!res && final_fixup) {
  		unlink(rebase_path_fixup_msg());
  		unlink(rebase_path_squash_msg());
 +		unlink(rebase_path_current_fixups());
 +		strbuf_reset(&opts->current_fixups);
 +		opts->current_fixup_count = 0;
  	}
  
  leave:
 @@ -2067,6 +2055,16 @@ static int read_populate_opts(struct replay_opts *opts)
  		read_strategy_opts(opts, &buf);
  		strbuf_release(&buf);
  
 +		if (read_oneliner(&opts->current_fixups,
 +				  rebase_path_current_fixups(), 1)) {
 +			const char *p = opts->current_fixups.buf;
 +			opts->current_fixup_count = 1;
 +			while ((p = strchr(p, '\n'))) {
 +				opts->current_fixup_count++;
 +				p++;
 +			}
 +		}
 +
  		return 0;
  	}
  
 @@ -2413,21 +2411,9 @@ static int error_with_patch(struct commit *commit,
  static int error_failed_squash(struct commit *commit,
  	struct replay_opts *opts, int subject_len, const char *subject)
  {
 -	const char *amend_type = "squash";
 -
 -	if (rename(rebase_path_squash_msg(), rebase_path_message()))
 -		return error(_("could not rename '%s' to '%s'"),
 +	if (copy_file(rebase_path_message(), rebase_path_squash_msg(), 0666))
 +		return error(_("could not copy '%s' to '%s'"),
  			rebase_path_squash_msg(), rebase_path_message());
 -
 -	if (file_exists(rebase_path_fixup_msg())) {
 -		unlink(rebase_path_fixup_msg());
 -		amend_type = "fixup";
 -	}
 -	if (write_message(amend_type, strlen(amend_type),
 -		       rebase_path_amend_type(), 0))
 -		return error(_("could not write '%s'"),
 -			     rebase_path_amend_type());
 -
  	unlink(git_path_merge_msg());
  	if (copy_file(git_path_merge_msg(), rebase_path_message(), 0666))
  		return error(_("could not copy '%s' to '%s'"),
 @@ -2604,7 +2590,6 @@ static int pick_commits(struct todo_list *todo_list, struct replay_opts *opts)
  			unlink(rebase_path_author_script());
  			unlink(rebase_path_stopped_sha());
  			unlink(rebase_path_amend());
 -			unlink(rebase_path_amend_type());
  			delete_ref(NULL, "REBASE_HEAD", NULL, REF_NO_DEREF);
  		}
  		if (item->command <= TODO_SQUASH) {
 @@ -2794,9 +2779,11 @@ static int continue_single_pick(void)
  	return run_command_v_opt(argv, RUN_GIT_CMD);
  }
  
 -static int commit_staged_changes(struct replay_opts *opts)
 +static int commit_staged_changes(struct replay_opts *opts,
 +				 struct todo_list *todo_list)
  {
 -	unsigned int flags = ALLOW_EMPTY | EDIT_MSG, is_fixup = 0, is_clean;
 +	unsigned int flags = ALLOW_EMPTY | EDIT_MSG;
 +	unsigned int final_fixup = 0, is_clean;
  
  	if (has_unstaged_changes(1))
  		return error(_("cannot rebase: You have unstaged changes."));
 @@ -2819,21 +2806,69 @@ static int commit_staged_changes(struct replay_opts *opts)
  				       "working tree. Please, commit them\n"
  				       "first and then run 'git rebase "
  				       "--continue' again."));
 -		if (is_clean && !oidcmp(&head, &to_amend)) {
 -			strbuf_reset(&rev);
 +		/*
 +		 * When skipping a failed fixup/squash, we need to edit the
 +		 * commit message, the current fixup list and count, and if it
 +		 * was the last fixup/squash in the chain, we need to clean up
 +		 * the commit message and if there was a squash, let the user
 +		 * edit it.
 +		 */
 +		if (is_clean && !oidcmp(&head, &to_amend) &&
 +		    opts->current_fixup_count > 0 &&
 +		    file_exists(rebase_path_stopped_sha())) {
 +			const char *p = opts->current_fixups.buf;
 +			int len = opts->current_fixups.len;
 +
 +			opts->current_fixup_count--;
 +			if (!len)
 +				BUG("Incorrect current_fixups:\n%s", p);
 +			while (len && p[len - 1] != '\n')
 +				len--;
 +			strbuf_setlen(&opts->current_fixups, len);
 +			if (write_message(p, len, rebase_path_current_fixups(),
 +					  0) < 0)
 +				return error(_("could not write file: '%s'"),
 +					     rebase_path_current_fixups());
 +
  			/*
 -			 * Clean tree, but we may need to finalize a
 -			 * fixup/squash chain. A failed fixup/squash leaves the
 -			 * file amend-type in rebase-merge/; It is okay if that
 -			 * file is missing, in which case there is no such
 -			 * chain to finalize.
 +			 * If a fixup/squash in a fixup/squash chain failed, the
 +			 * commit message is already correct, no need to commit
 +			 * it again.
 +			 *
 +			 * Only if it is the final command in the fixup/squash
 +			 * chain, and only if the chain is longer than a single
 +			 * fixup/squash command (which was just skipped), do we
 +			 * actually need to re-commit with a cleaned up commit
 +			 * message.
  			 */
 -			read_oneliner(&rev, rebase_path_amend_type(), 0);
 -			if (!strcmp("squash", rev.buf))
 -				is_fixup = TODO_SQUASH;
 -			else if (!strcmp("fixup", rev.buf)) {
 -				is_fixup = TODO_FIXUP;
 -				flags = (flags & ~EDIT_MSG) | CLEANUP_MSG;
 +			if (opts->current_fixup_count > 0 &&
 +			    !is_fixup(peek_command(todo_list, 0))) {
 +				final_fixup = 1;
 +				/*
 +				 * If there was not a single "squash" in the
 +				 * chain, we only need to clean up the commit
 +				 * message, no need to bother the user with
 +				 * opening the commit message in the editor.
 +				 */
 +				if (!starts_with(p, "squash ") &&
 +				    !strstr(p, "\nsquash "))
 +					flags = (flags & ~EDIT_MSG) | CLEANUP_MSG;
 +			} else if (is_fixup(peek_command(todo_list, 0))) {
 +				/*
 +				 * We need to update the squash message to skip
 +				 * the latest commit message.
 +				 */
 +				struct commit *commit;
 +				const char *path = rebase_path_squash_msg();
 +
 +				if (parse_head(&commit) ||
 +				    !(p = get_commit_buffer(commit, NULL)) ||
 +				    write_message(p, strlen(p), path, 0)) {
 +					unuse_commit_buffer(commit, p);
 +					return error(_("could not write file: "
 +						       "'%s'"), path);
 +				}
 +				unuse_commit_buffer(commit, p);
  			}
  		}
  
 @@ -2841,18 +2876,32 @@ static int commit_staged_changes(struct replay_opts *opts)
  		flags |= AMEND_MSG;
  	}
  
 -	if (is_clean && !is_fixup) {
 +	if (is_clean) {
  		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 0;
 +		if (!final_fixup)
 +			return 0;
  	}
  
 -	if (run_git_commit(rebase_path_message(), opts, flags))
 +	if (run_git_commit(final_fixup ? NULL : rebase_path_message(),
 +			   opts, flags))
  		return error(_("could not commit staged changes."));
  	unlink(rebase_path_amend());
 -	unlink(rebase_path_amend_type());
 +	if (final_fixup) {
 +		unlink(rebase_path_fixup_msg());
 +		unlink(rebase_path_squash_msg());
 +	}
 +	if (opts->current_fixup_count > 0) {
 +		/*
 +		 * Whether final fixup or not, we just cleaned up the commit
 +		 * message...
 +		 */
 +		unlink(rebase_path_current_fixups());
 +		strbuf_reset(&opts->current_fixups);
 +		opts->current_fixup_count = 0;
 +	}
  	return 0;
  }
  
 @@ -2864,14 +2913,16 @@ int sequencer_continue(struct replay_opts *opts)
  	if (read_and_refresh_cache(opts))
  		return -1;
  
 +	if (read_populate_opts(opts))
 +		return -1;
  	if (is_rebase_i(opts)) {
 -		if (commit_staged_changes(opts))
 +		if ((res = read_populate_todo(&todo_list, opts)))
 +			goto release_todo_list;
 +		if (commit_staged_changes(opts, &todo_list))
  			return -1;
  	} else if (!file_exists(get_todo_path(opts)))
  		return continue_single_pick();
 -	if (read_populate_opts(opts))
 -		return -1;
 -	if ((res = read_populate_todo(&todo_list, opts)))
 +	else if ((res = read_populate_todo(&todo_list, opts)))
  		goto release_todo_list;
  
  	if (!is_rebase_i(opts)) {
 diff --git a/sequencer.h b/sequencer.h
 index e45b178dfc4..1898158c52d 100644
 --- a/sequencer.h
 +++ b/sequencer.h
 @@ -44,10 +44,14 @@ struct replay_opts {
  	char **xopts;
  	size_t xopts_nr, xopts_alloc;
  
 +	/* Used by fixup/squash */
 +	struct strbuf current_fixups;
 +	int current_fixup_count;
 +
  	/* Only used by REPLAY_NONE */
  	struct rev_info *revs;
  };
 -#define REPLAY_OPTS_INIT { -1 }
 +#define REPLAY_OPTS_INIT { .action = -1, .current_fixups = STRBUF_INIT }
  
  /* Call this to setup defaults before parsing command line options */
  void sequencer_init_config(struct replay_opts *opts);
 diff --git a/t/t3418-rebase-continue.sh b/t/t3418-rebase-continue.sh
 index 693f92409ec..03bf1b8a3b3 100755
 --- a/t/t3418-rebase-continue.sh
 +++ b/t/t3418-rebase-continue.sh
 @@ -95,19 +95,46 @@ test_expect_success '--skip after failed fixup cleans commit message' '
  	test_commit "fixup! wants-fixup" wants-fixup.t 1 wants-fixup-1 &&
  	test_commit "fixup! wants-fixup" wants-fixup.t 2 wants-fixup-2 &&
  	test_commit "fixup! wants-fixup" wants-fixup.t 3 wants-fixup-3 &&
 -	test_must_fail env FAKE_LINES="1 fixup 2 fixup 4" \
 +	test_must_fail env FAKE_LINES="1 fixup 2 squash 4" \
  		git rebase -i HEAD~4 &&
  
  	: now there is a conflict, and comments in the commit message &&
  	git show HEAD >out &&
 -	test_i18ngrep "This is a combination of" out &&
 +	grep "fixup! wants-fixup" out &&
  
  	: skip and continue &&
 -	git rebase --skip &&
 +	echo "cp \"\$1\" .git/copy.txt" | write_script copy-editor.sh &&
 +	(test_set_editor "$PWD/copy-editor.sh" && git rebase --skip) &&
 +
 +	: the user should not have had to edit the commit message &&
 +	test_path_is_missing .git/copy.txt &&
  
  	: now the comments in the commit message should have been cleaned up &&
  	git show HEAD >out &&
 -	test_i18ngrep ! "This is a combination of" out
 +	! grep "fixup! wants-fixup" out &&
 +
 +	: now, let us ensure that "squash" is handled correctly &&
 +	git reset --hard wants-fixup-3 &&
 +	test_must_fail env FAKE_LINES="1 squash 4 squash 2 squash 4" \
 +		git rebase -i HEAD~4 &&
 +
 +	: the first squash failed, but there are two more in the chain &&
 +	(test_set_editor "$PWD/copy-editor.sh" &&
 +	 test_must_fail git rebase --skip) &&
 +
 +	: not the final squash, no need to edit the commit message &&
 +	test_path_is_missing .git/copy.txt &&
 +
 +	: The first squash was skipped, therefore: &&
 +	git show HEAD >out &&
 +	test_i18ngrep "# This is a combination of 2 commits" out &&
 +
 +	(test_set_editor "$PWD/copy-editor.sh" && git rebase --skip) &&
 +	git show HEAD >out &&
 +	test_i18ngrep ! "# This is a combination" out &&
 +
 +	: Final squash failed, but there was still a squash &&
 +	test_i18ngrep "# This is a combination of 2 commits" .git/copy.txt
  '
  
  test_expect_success 'setup rerere database' '
-- 
2.17.0.windows.1.33.gfcbb1fa0445
Previous: Junio C HamanoNext: Johannes Schindelin
Message 280 of 412 in “rebase -i: offer to recreate merge commits”
  1. 0/8 rebase -i: offer to recreate merge commitsJohannes Schindelin, Jan 18, 2018
  2. 1/8 sequencer: introduce new commands to reset the revisionJohannes Schindelin, Jan 18, 2018
  3. Jacob KellerJan 18, 2018
  4. Johannes SchindelinJan 18, 2018
  5. Jacob KellerJan 18, 2018
  6. Philip OakleyJan 18, 2018
  7. Jacob KellerJan 18, 2018
  8. Johannes SchindelinJan 29, 2018
  9. Junio C HamanoJan 22, 2018
  10. Johannes SchindelinJan 29, 2018
  11. Eric SunshineJan 19, 2018
  12. Junio C HamanoJan 24, 2018
  13. Johannes SchindelinJan 29, 2018
  14. Johannes SchindelinJan 29, 2018
  15. Eric SunshineJan 30, 2018
  16. Phillip WoodJan 19, 2018
  17. Phillip WoodJan 19, 2018
  18. Jacob KellerJan 19, 2018
  19. Johannes SchindelinJan 29, 2018
  20. Johannes SchindelinJan 29, 2018
  21. Johannes SchindelinJan 29, 2018
  22. 2/8 sequencer: introduce the `merge` commandJohannes Schindelin, Jan 18, 2018
  23. Jacob KellerJan 18, 2018
  24. Johannes SchindelinJan 18, 2018
  25. Jacob KellerJan 18, 2018
  26. Eric SunshineJan 19, 2018
  27. Phillip WoodJan 19, 2018
  28. Jacob KellerJan 20, 2018
  29. Johannes SchindelinJan 29, 2018
  30. Johannes SchindelinJan 31, 2018
  31. Phillip WoodJan 31, 2018
  32. Jacob KellerFeb 1, 2018
  33. Junio C HamanoJan 22, 2018
  34. Johannes SchindelinJan 29, 2018
  35. 3/8 sequencer: fast-forward merge commits, if possibleJohannes Schindelin, Jan 18, 2018
  36. Phillip WoodJan 19, 2018
  37. Junio C HamanoJan 23, 2018
  38. Phillip WoodJan 24, 2018
  39. Junio C HamanoJan 24, 2018
  40. Johannes SchindelinJan 29, 2018
  41. Junio C HamanoJan 23, 2018
  42. Johannes SchindelinJan 29, 2018
  43. 4/8 rebase-helper --make-script: introduce a flag to recreate mergesJohannes Schindelin, Jan 18, 2018
  44. Philip OakleyJan 18, 2018
  45. Eric SunshineJan 19, 2018
  46. Junio C HamanoJan 23, 2018
  47. Johannes SchindelinJan 29, 2018
  48. Johannes SchindelinJan 29, 2018
  49. Junio C HamanoJan 23, 2018
  50. Johannes SchindelinJan 29, 2018
  51. 5/8 rebase: introduce the --recreate-merges optionJohannes Schindelin, Jan 18, 2018
  52. Eric SunshineJan 19, 2018
  53. Johannes SchindelinJan 29, 2018
  54. Junio C HamanoJan 23, 2018
  55. Johannes SchindelinFeb 10, 2018
  56. Sergey OrganovFeb 7, 2018
  57. Jacob KellerFeb 7, 2018
  58. Sergey OrganovFeb 7, 2018
  59. Johannes SixtFeb 7, 2018
  60. Johannes SchindelinFeb 7, 2018
  61. Øyvind RønningstadFeb 7, 2018
  62. Junio C HamanoFeb 7, 2018
  63. Johannes SchindelinFeb 8, 2018
  64. Sergey OrganovFeb 14, 2018
  65. Sergey OrganovFeb 9, 2018
  66. Johannes SixtFeb 9, 2018
  67. Jacob KellerFeb 11, 2018
  68. Sergey OrganovFeb 12, 2018
  69. Sergey OrganovFeb 9, 2018
  70. Johannes SchindelinFeb 10, 2018
  71. Sergey OrganovFeb 12, 2018
  72. Johannes SchindelinFeb 12, 2018
  73. Sergey OrganovFeb 13, 2018
  74. Johannes SchindelinFeb 15, 2018
  75. Sergey OrganovFeb 15, 2018
  76. Johannes SchindelinFeb 15, 2018
  77. Sergey OrganovFeb 12, 2018
  78. Johannes SchindelinFeb 12, 2018
  79. Jacob KellerFeb 13, 2018
  80. Sergey OrganovFeb 13, 2018
  81. Jacob KellerFeb 14, 2018
  82. Johannes SchindelinFeb 15, 2018
  83. Sergey OrganovFeb 15, 2018
  84. Johannes SchindelinFeb 15, 2018
  85. Sergey OrganovFeb 13, 2018
  86. Johannes SchindelinFeb 15, 2018
  87. 6/8 sequencer: handle autosquash and post-rewrite for merge commandsJohannes Schindelin, Jan 18, 2018
  88. Jacob KellerJan 18, 2018
  89. Johannes SchindelinJan 18, 2018
  90. Jacob KellerJan 18, 2018
  91. Junio C HamanoJan 23, 2018
  92. 7/8 pull: accept --rebase=recreate to recreate the branch topologyJohannes Schindelin, Jan 18, 2018
  93. 8/8 rebase -i: introduce --recreate-merges=no-rebase-cousinsJohannes Schindelin, Jan 18, 2018
  94. Philip OakleyJan 18, 2018
  95. Johannes SchindelinJan 29, 2018
  96. Eric SunshineJan 20, 2018
  97. Jacob KellerJan 18, 2018
  98. 10/8 interactive rebase feedbackStefan Beller, Jan 18, 2018
  99. 9/8 [DO NOT APPLY, but squash?] git-rebase--interactive: clarify argumentsStefan Beller, Jan 18, 2018
  100. Jacob KellerJan 18, 2018
  101. Johannes SchindelinJan 18, 2018
  102. Stefan BellerJan 18, 2018
  103. Junio C HamanoJan 19, 2018
  104. Jacob KellerJan 20, 2018
  105. Johannes SchindelinJan 29, 2018
  106. 10/8 [DO NOT APPLY, but improve?] rebase--interactive: introduce "stop" commandStefan Beller, Jan 18, 2018
  107. Jacob KellerJan 18, 2018
  108. Philip OakleyJan 18, 2018
  109. Jacob KellerJan 18, 2018
  110. Johannes SchindelinJan 18, 2018
  111. Stefan BellerJan 18, 2018
  112. Junio C HamanoJan 19, 2018
  113. Johannes SchindelinJan 29, 2018
  114. Junio C HamanoJan 23, 2018
  115. Johannes SchindelinJan 29, 2018
  116. 00/10 rebase -i: offer to recreate merge commitsJohannes Schindelin, Jan 29, 2018
  117. 01/10 git-rebase--interactive: clarify argumentsJohannes Schindelin, Jan 29, 2018
  118. 03/10 sequencer: introduce the `merge` commandJohannes Schindelin, Jan 29, 2018
  119. 02/10 sequencer: introduce new commands to reset the revisionJohannes Schindelin, Jan 29, 2018
  120. Eric SunshineJan 30, 2018
  121. Johannes SchindelinFeb 10, 2018
  122. Stefan BellerJan 30, 2018
  123. Johannes SchindelinJan 31, 2018
  124. Phillip WoodJan 31, 2018
  125. Johannes SchindelinFeb 10, 2018
  126. 04/10 sequencer: fast-forward merge commits, if possibleJohannes Schindelin, Jan 29, 2018
  127. 05/10 rebase-helper --make-script: introduce a flag to recreate mergesJohannes Schindelin, Jan 29, 2018
  128. 07/10 sequencer: make refs generated by the `label` command worktree-localJohannes Schindelin, Jan 29, 2018
  129. 06/10 rebase: introduce the --recreate-merges optionJohannes Schindelin, Jan 29, 2018
  130. 08/10 sequencer: handle autosquash and post-rewrite for merge commandsJohannes Schindelin, Jan 29, 2018
  131. 09/10 pull: accept --rebase=recreate to recreate the branch topologyJohannes Schindelin, Jan 29, 2018
  132. 10/10 rebase -i: introduce --recreate-merges=[no-]rebase-cousinsJohannes Schindelin, Jan 29, 2018
  133. Stefan BellerJan 30, 2018
  134. Johannes SchindelinJan 31, 2018
  135. Junio C HamanoJan 30, 2018
  136. Johannes SchindelinJan 31, 2018
  137. Jacob KellerFeb 1, 2018
  138. 00/12 rebase -i: offer to recreate merge commitsJohannes Schindelin, Feb 11, 2018
  139. 01/12 sequencer: avoid using errno clobbered by rollback_lock_file()Johannes Schindelin, Feb 11, 2018
  140. 02/12 sequencer: make rearrange_squash() a bit more obviousJohannes Schindelin, Feb 11, 2018
  141. 03/12 git-rebase--interactive: clarify argumentsJohannes Schindelin, Feb 11, 2018
  142. 04/12 sequencer: introduce new commands to reset the revisionJohannes Schindelin, Feb 11, 2018
  143. Eric SunshineFeb 12, 2018
  144. Johannes SchindelinFeb 12, 2018
  145. 05/12 sequencer: introduce the `merge` commandJohannes Schindelin, Feb 11, 2018
  146. Eric SunshineFeb 12, 2018
  147. Johannes SchindelinFeb 12, 2018
  148. 06/12 sequencer: fast-forward merge commits, if possibleJohannes Schindelin, Feb 11, 2018
  149. 07/12 rebase-helper --make-script: introduce a flag to recreate mergesJohannes Schindelin, Feb 11, 2018
  150. 08/12 rebase: introduce the --recreate-merges optionJohannes Schindelin, Feb 11, 2018
  151. 09/12 sequencer: make refs generated by the `label` command worktree-localJohannes Schindelin, Feb 11, 2018
  152. 10/12 sequencer: handle post-rewrite for merge commandsJohannes Schindelin, Feb 11, 2018
  153. 11/12 pull: accept --rebase=recreate to recreate the branch topologyJohannes Schindelin, Feb 11, 2018
  154. 12/12 rebase -i: introduce --recreate-merges=[no-]rebase-cousinsJohannes Schindelin, Feb 11, 2018
  155. 00/12 rebase -i: offer to recreate merge commitsJohannes Schindelin, Feb 23, 2018
  156. 01/12 sequencer: avoid using errno clobbered by rollback_lock_file()Johannes Schindelin, Feb 23, 2018
  157. 02/12 sequencer: make rearrange_squash() a bit more obviousJohannes Schindelin, Feb 23, 2018
  158. 04/12 sequencer: introduce new commands to reset the revisionJohannes Schindelin, Feb 23, 2018
  159. 03/12 git-rebase--interactive: clarify argumentsJohannes Schindelin, Feb 23, 2018
  160. 05/12 sequencer: introduce the `merge` commandJohannes Schindelin, Feb 23, 2018
  161. 06/12 sequencer: fast-forward merge commits, if possibleJohannes Schindelin, Feb 23, 2018
  162. 07/12 rebase-helper --make-script: introduce a flag to recreate mergesJohannes Schindelin, Feb 23, 2018
  163. 08/12 rebase: introduce the --recreate-merges optionJohannes Schindelin, Feb 23, 2018
  164. 09/12 sequencer: make refs generated by the `label` command worktree-localJohannes Schindelin, Feb 23, 2018
  165. 10/12 sequencer: handle post-rewrite for merge commandsJohannes Schindelin, Feb 23, 2018
  166. 11/12 pull: accept --rebase=recreate to recreate the branch topologyJohannes Schindelin, Feb 23, 2018
  167. 12/12 rebase -i: introduce --recreate-merges=[no-]rebase-cousinsJohannes Schindelin, Feb 23, 2018
  168. Jacob KellerFeb 25, 2018
  169. Johannes SchindelinFeb 26, 2018
  170. 00/12 rebase -i: offer to recreate merge commitsJohannes Schindelin, Feb 26, 2018
  171. 01/12 sequencer: avoid using errno clobbered by rollback_lock_file()Johannes Schindelin, Feb 26, 2018
  172. Martin ÅgrenFeb 27, 2018
  173. Johannes SchindelinMar 2, 2018
  174. 03/12 git-rebase--interactive: clarify argumentsJohannes Schindelin, Feb 26, 2018
  175. 04/12 sequencer: introduce new commands to reset the revisionJohannes Schindelin, Feb 26, 2018
  176. 05/12 sequencer: introduce the `merge` commandJohannes Schindelin, Feb 26, 2018
  177. 07/12 rebase-helper --make-script: introduce a flag to recreate mergesJohannes Schindelin, Feb 26, 2018
  178. 06/12 sequencer: fast-forward merge commits, if possibleJohannes Schindelin, Feb 26, 2018
  179. 08/12 rebase: introduce the --recreate-merges optionJohannes Schindelin, Feb 26, 2018
  180. 09/12 sequencer: make refs generated by the `label` command worktree-localJohannes Schindelin, Feb 26, 2018
  181. 10/12 sequencer: handle post-rewrite for merge commandsJohannes Schindelin, Feb 26, 2018
  182. 11/12 pull: accept --rebase=recreate to recreate the branch topologyJohannes Schindelin, Feb 26, 2018
  183. 12/12 rebase -i: introduce --recreate-merges=[no-]rebase-cousinsJohannes Schindelin, Feb 26, 2018
  184. 02/12 sequencer: make rearrange_squash() a bit more obviousJohannes Schindelin, Feb 26, 2018
  185. Igor DjordjevicMar 6, 2018
  186. Johannes SchindelinMar 7, 2018
  187. 00/15 rebase -i: offer to recreate commit topologyJohannes Schindelin, Apr 10, 2018
  188. 02/15 sequencer: make rearrange_squash() a bit more obviousJohannes Schindelin, Apr 10, 2018
  189. 01/15 sequencer: avoid using errno clobbered by rollback_lock_file()Johannes Schindelin, Apr 10, 2018
  190. 03/15 git-rebase--interactive: clarify argumentsJohannes Schindelin, Apr 10, 2018
  191. 04/15 sequencer: introduce new commands to reset the revisionJohannes Schindelin, Apr 10, 2018
  192. Sergey OrganovApr 11, 2018
  193. Johannes SchindelinApr 11, 2018
  194. Sergey OrganovApr 11, 2018
  195. Phillip WoodApr 13, 2018
  196. Philip OakleyApr 15, 2018
  197. Phillip WoodApr 18, 2018
  198. 05/15 sequencer: introduce the `merge` commandJohannes Schindelin, Apr 10, 2018
  199. Phillip WoodApr 13, 2018
  200. Phillip WoodApr 13, 2018
  201. Johannes SchindelinApr 14, 2018
  202. Phillip WoodApr 18, 2018
  203. Johannes SchindelinApr 19, 2018
  204. 06/15 sequencer: fast-forward `merge` commands, if possibleJohannes Schindelin, Apr 10, 2018
  205. 07/15 rebase-helper --make-script: introduce a flag to rebase mergesJohannes Schindelin, Apr 10, 2018
  206. 08/15 rebase: introduce the --rebase-merges optionJohannes Schindelin, Apr 10, 2018
  207. 09/15 rebase --rebase-merges: add test for --keep-emptyJohannes Schindelin, Apr 10, 2018
  208. 10/15 sequencer: make refs generated by the `label` command worktree-localJohannes Schindelin, Apr 10, 2018
  209. 12/15 rebase --rebase-merges: avoid "empty merges"Johannes Schindelin, Apr 10, 2018
  210. 13/15 pull: accept --rebase=merges to recreate the branch topologyJohannes Schindelin, Apr 10, 2018
  211. 14/15 rebase -i: introduce --rebase-merges=[no-]rebase-cousinsJohannes Schindelin, Apr 10, 2018
  212. Sergey OrganovApr 12, 2018
  213. 15/15 rebase -i --rebase-merges: add a section to the man pageJohannes Schindelin, Apr 10, 2018
  214. Martin ÅgrenApr 10, 2018
  215. Johannes SchindelinApr 10, 2018
  216. Phillip WoodApr 11, 2018
  217. Eric SunshineApr 11, 2018
  218. Johannes SchindelinApr 12, 2018
  219. Phillip WoodApr 13, 2018
  220. Johannes SchindelinApr 12, 2018
  221. Jacob KellerApr 12, 2018
  222. Phillip WoodApr 13, 2018
  223. Sergey OrganovApr 12, 2018
  224. 11/15 sequencer: handle post-rewrite for merge commandsJohannes Schindelin, Apr 10, 2018
  225. Sergey OrganovApr 10, 2018
  226. Johannes SchindelinApr 10, 2018
  227. Sergey OrganovApr 11, 2018
  228. Johannes SchindelinApr 11, 2018
  229. Sergey OrganovApr 11, 2018
  230. Johannes SchindelinApr 11, 2018
  231. Sergey OrganovApr 12, 2018
  232. Johannes SchindelinApr 12, 2018
  233. Jacob KellerApr 11, 2018
  234. Sergey OrganovApr 12, 2018
  235. Jacob KellerApr 12, 2018
  236. Johannes SchindelinApr 12, 2018
  237. Jacob KellerApr 12, 2018
  238. Johannes SchindelinApr 13, 2018
  239. Phillip WoodApr 13, 2018
  240. Johannes SchindelinApr 13, 2018
  241. Sergey OrganovApr 19, 2018
  242. Jacob KellerApr 19, 2018
  243. Sergey OrganovApr 19, 2018
  244. Johannes SchindelinApr 20, 2018
  245. Jacob KellerApr 20, 2018
  246. Sergey OrganovApr 18, 2018
  247. 00/17 rebase -i: offer to recreate commit topologyJohannes Schindelin, Apr 19, 2018
  248. 01/17 sequencer: avoid using errno clobbered by rollback_lock_file()Johannes Schindelin, Apr 19, 2018
  249. 02/17 sequencer: make rearrange_squash() a bit more obviousJohannes Schindelin, Apr 19, 2018
  250. 03/17 sequencer: refactor how original todo list lines are accessedJohannes Schindelin, Apr 19, 2018
  251. 04/17 sequencer: offer helpful advice when a command was rescheduledJohannes Schindelin, Apr 19, 2018
  252. 05/17 git-rebase--interactive: clarify argumentsJohannes Schindelin, Apr 19, 2018
  253. 06/17 sequencer: introduce new commands to reset the revisionJohannes Schindelin, Apr 19, 2018
  254. Phillip WoodApr 20, 2018
  255. Johannes SchindelinApr 20, 2018
  256. 07/17 # This is a combination of 2 commits. # This is the 1st commit message:Johannes Schindelin, Apr 19, 2018
  257. Eric SunshineApr 20, 2018
  258. Johannes SchindelinApr 20, 2018
  259. 0/4 rebase -i: avoid stale "# This is a combination of" in commit messagesJohannes Schindelin, Apr 20, 2018
  260. 1/4 rebase -i: demonstrate bugs with fixup!/squash! commit messagesJohannes Schindelin, Apr 20, 2018
  261. 2/4 rebase -i: Handle "combination of <n> commits" with GETTEXT_POISONJohannes Schindelin, Apr 20, 2018
  262. Stefan BellerApr 20, 2018
  263. Johannes SchindelinApr 21, 2018
  264. 3/4 sequencer: leave a tell-tale when a fixup/squash failedJohannes Schindelin, Apr 20, 2018
  265. Stefan BellerApr 20, 2018
  266. Johannes SchindelinApr 21, 2018
  267. 4/4 rebase --skip: clean up commit message after a failed fixup/squashJohannes Schindelin, Apr 20, 2018
  268. 0/4 rebase -i: avoid stale "# This is a combination of" in commit messagesJohannes Schindelin, Apr 21, 2018
  269. 1/4 rebase -i: demonstrate bugs with fixup!/squash! commit messagesJohannes Schindelin, Apr 21, 2018
  270. 2/4 rebase -i: Handle "combination of <n> commits" with GETTEXT_POISONJohannes Schindelin, Apr 21, 2018
  271. 3/4 sequencer: leave a tell-tale when a fixup/squash failedJohannes Schindelin, Apr 21, 2018
  272. 4/4 rebase --skip: clean up commit message after a failed fixup/squashJohannes Schindelin, Apr 21, 2018
  273. Stefan BellerApr 23, 2018
  274. Phillip WoodApr 23, 2018
  275. Johannes SchindelinApr 25, 2018
  276. Phillip WoodApr 25, 2018
  277. Johannes SchindelinApr 26, 2018
  278. Phillip WoodApr 26, 2018
  279. Junio C HamanoApr 24, 2018
  280. 0/4 rebase -i: avoid stale "# This is a combination of" in commit messagesJohannes Schindelin, Apr 27, 2018
  281. 1/4 rebase -i: demonstrate bugs with fixup!/squash! commit messagesJohannes Schindelin, Apr 27, 2018
  282. 3/4 sequencer: always commit without editing when asked forJohannes Schindelin, Apr 27, 2018
  283. 2/4 rebase -i: Handle "combination of <n> commits" with GETTEXT_POISONJohannes Schindelin, Apr 27, 2018
  284. 4/4 rebase --skip: clean up commit message after a failed fixup/squashJohannes Schindelin, Apr 27, 2018
  285. Stefan BellerApr 27, 2018
  286. Johannes SchindelinApr 28, 2018
  287. Phillip WoodMay 6, 2018
  288. Phillip WoodMay 9, 2018
  289. Johannes SchindelinOct 2, 2018
  290. Phillip WoodOct 8, 2018
  291. 08/17 sequencer: fast-forward `merge` commands, if possibleJohannes Schindelin, Apr 19, 2018
  292. 09/17 rebase-helper --make-script: introduce a flag to rebase mergesJohannes Schindelin, Apr 19, 2018
  293. 10/17 rebase: introduce the --rebase-merges optionJohannes Schindelin, Apr 19, 2018
  294. 11/17 rebase --rebase-merges: add test for --keep-emptyJohannes Schindelin, Apr 19, 2018
  295. 12/17 sequencer: make refs generated by the `label` command worktree-localJohannes Schindelin, Apr 19, 2018
  296. 13/17 sequencer: handle post-rewrite for merge commandsJohannes Schindelin, Apr 19, 2018
  297. 14/17 rebase --rebase-merges: avoid "empty merges"Johannes Schindelin, Apr 19, 2018
  298. 15/17 pull: accept --rebase=merges to recreate the branch topologyJohannes Schindelin, Apr 19, 2018
  299. 16/17 rebase -i: introduce --rebase-merges=[no-]rebase-cousinsJohannes Schindelin, Apr 19, 2018
  300. 17/17 rebase -i --rebase-merges: add a section to the man pageJohannes Schindelin, Apr 19, 2018
  301. 00/16 rebase -i: offer to recreate commit topology by rebasing mergesJohannes Schindelin, Apr 21, 2018
  302. 01/16 sequencer: avoid using errno clobbered by rollback_lock_file()Johannes Schindelin, Apr 21, 2018
  303. 02/16 sequencer: make rearrange_squash() a bit more obviousJohannes Schindelin, Apr 21, 2018
  304. 03/16 sequencer: refactor how original todo list lines are accessedJohannes Schindelin, Apr 21, 2018
  305. 04/16 sequencer: offer helpful advice when a command was rescheduledJohannes Schindelin, Apr 21, 2018
  306. 05/16 git-rebase--interactive: clarify argumentsJohannes Schindelin, Apr 21, 2018
  307. 06/16 sequencer: introduce the `merge` commandJohannes Schindelin, Apr 21, 2018
  308. Phillip WoodApr 21, 2018
  309. Phillip WoodApr 22, 2018
  310. Johannes SchindelinApr 23, 2018
  311. Johannes SchindelinApr 23, 2018
  312. Phillip WoodApr 23, 2018
  313. Martin ÅgrenApr 24, 2018
  314. 1/2 merge: setup `opts` later in `checkout_fast_forward()`Martin Ågren, Apr 24, 2018
  315. Jacob KellerApr 24, 2018
  316. Martin ÅgrenApr 24, 2018
  317. Johannes SchindelinApr 24, 2018
  318. 2/2 unpack_trees_options: free messages when doneMartin Ågren, Apr 24, 2018
  319. Elijah NewrenApr 24, 2018
  320. Martin ÅgrenApr 28, 2018
  321. Johannes SchindelinApr 28, 2018
  322. Elijah NewrenApr 28, 2018
  323. Elijah NewrenMay 16, 2018
  324. 0/3 unpack_trees_options: free messages when doneMartin Ågren, May 16, 2018
  325. 1/3 merge: setup `opts` later in `checkout_fast_forward()`Martin Ågren, May 16, 2018
  326. Stefan BellerMay 16, 2018
  327. Martin ÅgrenMay 16, 2018
  328. Jacob KellerMay 16, 2018
  329. Jacob KellerMay 16, 2018
  330. Junio C HamanoMay 17, 2018
  331. Jacob KellerMay 18, 2018
  332. 2/3 merge-recursive: provide pair of `unpack_trees_{start,finish}()`Martin Ågren, May 16, 2018
  333. 3/3 unpack_trees_options: free messages when doneMartin Ågren, May 16, 2018
  334. Junio C HamanoMay 17, 2018
  335. Martin ÅgrenMay 18, 2018
  336. 0/3 unpack_trees_options: free messages when doneMartin Ågren, May 18, 2018
  337. 1/3 merge: setup `opts` later in `checkout_fast_forward()`Martin Ågren, May 18, 2018
  338. 2/3 merge-recursive: provide pair of `unpack_trees_{start,finish}()`Martin Ågren, May 18, 2018
  339. 3/3 unpack_trees_options: free messages when doneMartin Ågren, May 18, 2018
  340. Jeff KingMay 18, 2018
  341. Elijah NewrenMay 18, 2018
  342. Jeff KingMay 19, 2018
  343. Martin ÅgrenMay 19, 2018
  344. 0/4 unpack_trees_options: free messages when doneMartin Ågren, May 20, 2018
  345. 1/4 merge: setup `opts` later in `checkout_fast_forward()`Martin Ågren, May 20, 2018
  346. 2/4 merge-recursive: provide pair of `unpack_trees_{start,finish}()`Martin Ågren, May 20, 2018
  347. 3/4 string-list: provide `string_list_appendf()`Martin Ågren, May 20, 2018
  348. Jacob KellerMay 20, 2018
  349. Re*: [PATCH v4 3/4] string-list: provide `string_list_appendf()`Junio C Hamano, May 21, 2018
  350. Junio C HamanoMay 21, 2018
  351. Jeff KingMay 21, 2018
  352. 0/4 unpack_trees_options: free messages when doneMartin Ågren, May 21, 2018
  353. 1/4 merge: setup `opts` later in `checkout_fast_forward()`Martin Ågren, May 21, 2018
  354. 2/4 merge-recursive: provide pair of `unpack_trees_{start,finish}()`Martin Ågren, May 21, 2018
  355. 3/4 argv-array: return the pushed string from argv_push*()Martin Ågren, May 21, 2018
  356. 4/4 unpack_trees_options: free messages when doneMartin Ågren, May 21, 2018
  357. Jeff KingMay 21, 2018
  358. Junio C HamanoMay 22, 2018
  359. Junio C HamanoMay 22, 2018
  360. Martin ÅgrenMay 22, 2018
  361. Junio C HamanoMay 23, 2018
  362. Jeff KingMay 21, 2018
  363. 4/4 unpack_trees_options: free messages when doneMartin Ågren, May 20, 2018
  364. Elijah NewrenMay 16, 2018
  365. Ben PeartMay 17, 2018
  366. Johannes SchindelinApr 24, 2018
  367. Philip OakleyApr 22, 2018
  368. Johannes SchindelinApr 23, 2018
  369. Philip OakleyApr 23, 2018
  370. Johannes SchindelinApr 24, 2018
  371. Philip OakleyApr 24, 2018
  372. Philip OakleyApr 22, 2018
  373. 07/16 sequencer: fast-forward `merge` commands, if possibleJohannes Schindelin, Apr 21, 2018
  374. 08/16 rebase-helper --make-script: introduce a flag to rebase mergesJohannes Schindelin, Apr 21, 2018
  375. Philip OakleyApr 22, 2018
  376. Johannes SchindelinApr 24, 2018
  377. 09/16 rebase: introduce the --rebase-merges optionJohannes Schindelin, Apr 21, 2018
  378. Philip OakleyApr 22, 2018
  379. Johannes SchindelinApr 24, 2018
  380. Philip OakleyApr 22, 2018
  381. Junio C HamanoApr 24, 2018
  382. Johannes SchindelinApr 24, 2018
  383. Johannes SchindelinApr 24, 2018
  384. 10/16 rebase --rebase-merges: add test for --keep-emptyJohannes Schindelin, Apr 21, 2018
  385. 11/16 sequencer: make refs generated by the `label` command worktree-localJohannes Schindelin, Apr 21, 2018
  386. 12/16 sequencer: handle post-rewrite for merge commandsJohannes Schindelin, Apr 21, 2018
  387. 13/16 rebase --rebase-merges: avoid "empty merges"Johannes Schindelin, Apr 21, 2018
  388. 14/16 pull: accept --rebase=merges to recreate the branch topologyJohannes Schindelin, Apr 21, 2018
  389. 15/16 rebase -i: introduce --rebase-merges=[no-]rebase-cousinsJohannes Schindelin, Apr 21, 2018
  390. 16/16 rebase -i --rebase-merges: add a section to the man pageJohannes Schindelin, Apr 21, 2018
  391. 00/17 rebase -i: offer to recreate commit topology by rebasing mergesJohannes Schindelin, Apr 25, 2018
  392. 01/17 sequencer: avoid using errno clobbered by rollback_lock_file()Johannes Schindelin, Apr 25, 2018
  393. 02/17 sequencer: make rearrange_squash() a bit more obviousJohannes Schindelin, Apr 25, 2018
  394. 03/17 sequencer: refactor how original todo list lines are accessedJohannes Schindelin, Apr 25, 2018
  395. 04/17 sequencer: offer helpful advice when a command was rescheduledJohannes Schindelin, Apr 25, 2018
  396. 05/17 git-rebase--interactive: clarify argumentsJohannes Schindelin, Apr 25, 2018
  397. 06/17 sequencer: introduce new commands to reset the revisionJohannes Schindelin, Apr 25, 2018
  398. 07/17 sequencer: introduce the `merge` commandJohannes Schindelin, Apr 25, 2018
  399. 08/17 sequencer: fast-forward `merge` commands, if possibleJohannes Schindelin, Apr 25, 2018
  400. 09/17 rebase-helper --make-script: introduce a flag to rebase mergesJohannes Schindelin, Apr 25, 2018
  401. 10/17 rebase: introduce the --rebase-merges optionJohannes Schindelin, Apr 25, 2018
  402. 11/17 rebase --rebase-merges: add test for --keep-emptyJohannes Schindelin, Apr 25, 2018
  403. 12/17 sequencer: make refs generated by the `label` command worktree-localJohannes Schindelin, Apr 25, 2018
  404. 13/17 sequencer: handle post-rewrite for merge commandsJohannes Schindelin, Apr 25, 2018
  405. 15/17 pull: accept --rebase=merges to recreate the branch topologyJohannes Schindelin, Apr 25, 2018
  406. 16/17 rebase -i: introduce --rebase-merges=[no-]rebase-cousinsJohannes Schindelin, Apr 25, 2018
  407. 14/17 rebase --rebase-merges: avoid "empty merges"Johannes Schindelin, Apr 25, 2018
  408. 17/17 rebase -i --rebase-merges: add a section to the man pageJohannes Schindelin, Apr 25, 2018
  409. Junio C HamanoApr 26, 2018
  410. Junio C HamanoApr 26, 2018
  411. Sergey OrganovMay 25, 2018
  412. Sergey OrganovMay 25, 2018

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.