Skip to content

Commit bc9238b

Browse files
phillipwoodgitster
authored andcommitted
rebase -i: fix SIGSEGV when 'merge <branch>' fails
If a merge command in the todo list specifies just a branch to merge with no -C/-c argument then item->commit is NULL. This means that if there are merge conflicts error_with_patch() is passed a NULL commit which causes a segmentation fault when make_patch() tries to look it up. This commit implements a minimal fix which fixes the crash and allows the user to successfully commit a conflict resolution with 'git rebase --continue'. It does not write .git/rebase-merge/patch, .git/rebase-merge/stopped-sha or update REBASE_HEAD. To sensibly get the hashes of the merge parents would require refactoring do_merge() to extract the code that parses the merge parents into a separate function which error_with_patch() could then use to write the parents into the stopped-sha file. To create meaningful output make_patch() and 'git rebase --show-current-patch' would also need to be modified to diff the merge parent and merge base in this case. Signed-off-by: Phillip Wood <[email protected]> Acked-by: Johannes Schindelin <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent d54e189 commit bc9238b

File tree

2 files changed

+33
-6
lines changed

2 files changed

+33
-6
lines changed

sequencer.c

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2590,8 +2590,12 @@ static int error_with_patch(struct commit *commit,
25902590
const char *subject, int subject_len,
25912591
struct replay_opts *opts, int exit_code, int to_amend)
25922592
{
2593-
if (make_patch(commit, opts))
2594-
return -1;
2593+
if (commit) {
2594+
if (make_patch(commit, opts))
2595+
return -1;
2596+
} else if (copy_file(rebase_path_message(), git_path_merge_msg(), 0666))
2597+
return error(_("unable to copy '%s' to '%s'"),
2598+
git_path_merge_msg(), rebase_path_message());
25952599

25962600
if (to_amend) {
25972601
if (intend_to_amend())
@@ -2604,9 +2608,19 @@ static int error_with_patch(struct commit *commit,
26042608
"Once you are satisfied with your changes, run\n"
26052609
"\n"
26062610
" git rebase --continue\n", gpg_sign_opt_quoted(opts));
2607-
} else if (exit_code)
2608-
fprintf(stderr, "Could not apply %s... %.*s\n",
2609-
short_commit_name(commit), subject_len, subject);
2611+
} else if (exit_code) {
2612+
if (commit)
2613+
fprintf(stderr, "Could not apply %s... %.*s\n",
2614+
short_commit_name(commit),
2615+
subject_len, subject);
2616+
else
2617+
/*
2618+
* We don't have the hash of the parent so
2619+
* just print the line from the todo file.
2620+
*/
2621+
fprintf(stderr, "Could not merge %.*s\n",
2622+
subject_len, subject);
2623+
}
26102624

26112625
return exit_code;
26122626
}

t/t3430-rebase-merges.sh

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,7 @@ test_expect_success '`reset` refuses to overwrite untracked files' '
129129
git rebase --abort
130130
'
131131

132-
test_expect_success 'failed `merge` writes patch (may be rescheduled, too)' '
132+
test_expect_success 'failed `merge -C` writes patch (may be rescheduled, too)' '
133133
test_when_finished "test_might_fail git rebase --abort" &&
134134
git checkout -b conflicting-merge A &&
135135
@@ -151,6 +151,19 @@ test_expect_success 'failed `merge` writes patch (may be rescheduled, too)' '
151151
test_path_is_file .git/rebase-merge/patch
152152
'
153153

154+
SQ="'"
155+
test_expect_success 'failed `merge <branch>` does not crash' '
156+
test_when_finished "test_might_fail git rebase --abort" &&
157+
git checkout conflicting-G &&
158+
159+
echo "merge G" >script-from-scratch &&
160+
test_config sequence.editor \""$PWD"/replace-editor.sh\" &&
161+
test_tick &&
162+
test_must_fail git rebase -ir HEAD &&
163+
! grep "^merge G$" .git/rebase-merge/git-rebase-todo &&
164+
grep "^Merge branch ${SQ}G${SQ}$" .git/rebase-merge/message
165+
'
166+
154167
test_expect_success 'with a branch tip that was cherry-picked already' '
155168
git checkout -b already-upstream master &&
156169
base="$(git rev-parse --verify HEAD)" &&

0 commit comments

Comments
 (0)