rebase -i: remove patch file after conflict resolution

When a rebase stops for the user to resolve conflicts it writes a patch
for the conflicting commit to .git/rebase-merge/patch. This file has
been written since the introduction of "git-rebase-interactive.sh" in
1b1dce4bae (Teach rebase an interactive mode, 2007-06-25). I assume the
idea was to enable the user inspect the conflicting commit in the same
way as they could for the patch based rebase. This file should be
deleted when the rebase continues as if the rebase stops for a failed
"exec" command or a "break" command it is confusing to the user if there
is a stale patch lying around from an unrelated command. As the path is
now used in two different places rebase_path_patch() is added and used
to obtain the path for the patch.

To construct the path write_patch() previously used get_dir() which
returns different paths depending on whether we're rebasing or
cherry-picking/reverting. As this function is only called when
rebasing it is safe to use a hard coded string for the directory
instead. An assertion is added to make sure we don't starting calling
this function when cherry-picking in the future.

Signed-off-by: Phillip Wood <phillip.wood@dunelm.org.uk>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
Phillip Wood 2023-09-06 15:22:46 +00:00 коммит произвёл Junio C Hamano
Родитель 36ac861a30
Коммит 206a78d710
2 изменённых файлов: 30 добавлений и 4 удалений

Просмотреть файл

@ -132,6 +132,11 @@ static GIT_PATH_FUNC(rebase_path_amend, "rebase-merge/amend")
* the commit object name of the corresponding patch.
*/
static GIT_PATH_FUNC(rebase_path_stopped_sha, "rebase-merge/stopped-sha")
/*
* When we stop for the user to resolve conflicts this file contains
* the patch of the commit that is being picked.
*/
static GIT_PATH_FUNC(rebase_path_patch, "rebase-merge/patch")
/*
* For the post-rewrite hook, we make a list of rewritten commits and
* their new sha1s. The rewritten-pending list keeps the sha1s of
@ -3485,12 +3490,14 @@ static int make_patch(struct repository *r,
char hex[GIT_MAX_HEXSZ + 1];
int res = 0;
if (!is_rebase_i(opts))
BUG("make_patch should only be called when rebasing");
oid_to_hex_r(hex, &commit->object.oid);
if (write_message(hex, strlen(hex), rebase_path_stopped_sha(), 1) < 0)
return -1;
res |= write_rebase_head(&commit->object.oid);
strbuf_addf(&buf, "%s/patch", get_dir(opts));
memset(&log_tree_opt, 0, sizeof(log_tree_opt));
repo_init_revisions(r, &log_tree_opt, NULL);
log_tree_opt.abbrev = 0;
@ -3498,15 +3505,15 @@ static int make_patch(struct repository *r,
log_tree_opt.diffopt.output_format = DIFF_FORMAT_PATCH;
log_tree_opt.disable_stdin = 1;
log_tree_opt.no_commit_id = 1;
log_tree_opt.diffopt.file = fopen(buf.buf, "w");
log_tree_opt.diffopt.file = fopen(rebase_path_patch(), "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'"),
rebase_path_patch());
else {
res |= log_tree_commit(&log_tree_opt, commit);
fclose(log_tree_opt.diffopt.file);
}
strbuf_reset(&buf);
strbuf_addf(&buf, "%s/message", get_dir(opts));
if (!file_exists(buf.buf)) {
@ -4642,6 +4649,7 @@ static int pick_commits(struct repository *r,
unlink(rebase_path_message());
unlink(rebase_path_stopped_sha());
unlink(rebase_path_amend());
unlink(rebase_path_patch());
while (todo_list->current < todo_list->nr) {
struct todo_item *item = todo_list->items + todo_list->current;

Просмотреть файл

@ -244,6 +244,24 @@ test_expect_success 'the todo command "break" works' '
test_path_is_file execed
'
test_expect_success 'patch file is removed before break command' '
test_when_finished "git rebase --abort" &&
cat >todo <<-\EOF &&
pick commit-new-file-F2-on-topic-branch
break
EOF
(
set_replace_editor todo &&
test_must_fail git rebase -i --onto commit-new-file-F2 HEAD
) &&
test_path_is_file .git/rebase-merge/patch &&
echo 22>F2 &&
git add F2 &&
git rebase --continue &&
test_path_is_missing .git/rebase-merge/patch
'
test_expect_success '--reschedule-failed-exec' '
test_when_finished "git rebase --abort" &&
test_must_fail git rebase -x false --reschedule-failed-exec HEAD^ &&