Merge branch 'pb/status-rebase-fixes' into jch
A few fixes around "git status" while "git rebase" is running, plus a corner case bug fix for "git rebase -r". * pb/status-rebase-fixes: wt-status: suggest 'git rebase --continue' to conclude 'merge' instruction wt-status: also abbreviate 'merge' and 'fixup -C' lines during rebase SQUASH??? - <CAPig+cS92W_gYuNsaTvQxiP3xBK7Wpg0__uVkgAU1x0OFJUZgQ@mail.gmail.com> rebase -r: do create merge commit after empty resolution
commit
ec902f4769
|
@ -4333,6 +4333,7 @@ static int do_merge(struct repository *r,
|
||||||
error(_("could not even attempt to merge '%.*s'"),
|
error(_("could not even attempt to merge '%.*s'"),
|
||||||
merge_arg_len, arg);
|
merge_arg_len, arg);
|
||||||
unlink(git_path_merge_msg(r));
|
unlink(git_path_merge_msg(r));
|
||||||
|
unlink(git_path_merge_head(r));
|
||||||
goto leave_merge;
|
goto leave_merge;
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
|
@ -5348,7 +5349,7 @@ static int commit_staged_changes(struct repository *r,
|
||||||
flags |= AMEND_MSG;
|
flags |= AMEND_MSG;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (is_clean) {
|
if (is_clean && !file_exists(git_path_merge_head(r))) {
|
||||||
if (refs_ref_exists(get_main_ref_store(r),
|
if (refs_ref_exists(get_main_ref_store(r),
|
||||||
"CHERRY_PICK_HEAD") &&
|
"CHERRY_PICK_HEAD") &&
|
||||||
refs_delete_ref(get_main_ref_store(r), "",
|
refs_delete_ref(get_main_ref_store(r), "",
|
||||||
|
|
|
@ -111,6 +111,30 @@ test_expect_success 'rebase -r passes merge strategy options correctly' '
|
||||||
git rebase --continue
|
git rebase --continue
|
||||||
'
|
'
|
||||||
|
|
||||||
|
test_expect_success '--continue creates merge commit after empty resolution' '
|
||||||
|
git reset --hard main &&
|
||||||
|
git checkout -b rebase_i_merge &&
|
||||||
|
test_commit unrelated &&
|
||||||
|
git checkout -b rebase_i_merge_side &&
|
||||||
|
test_commit side2 main.txt &&
|
||||||
|
git checkout rebase_i_merge &&
|
||||||
|
test_commit side1 main.txt &&
|
||||||
|
PICK=$(git rev-parse --short rebase_i_merge) &&
|
||||||
|
test_must_fail git merge rebase_i_merge_side &&
|
||||||
|
echo side1 >main.txt &&
|
||||||
|
git add main.txt &&
|
||||||
|
test_tick &&
|
||||||
|
git commit --no-edit &&
|
||||||
|
|
||||||
|
test_must_fail env FAKE_LINES="1 2 3 5 6 7 8 9 10 11" \
|
||||||
|
git rebase -ir main &&
|
||||||
|
echo side1 >main.txt &&
|
||||||
|
git add main.txt &&
|
||||||
|
git rebase --continue &&
|
||||||
|
git log --merges >out &&
|
||||||
|
test_grep "Merge branch .rebase_i_merge_side." out
|
||||||
|
'
|
||||||
|
|
||||||
test_expect_success '--skip after failed fixup cleans commit message' '
|
test_expect_success '--skip after failed fixup cleans commit message' '
|
||||||
test_when_finished "test_might_fail git rebase --abort" &&
|
test_when_finished "test_might_fail git rebase --abort" &&
|
||||||
git checkout -b with-conflicting-fixup &&
|
git checkout -b with-conflicting-fixup &&
|
||||||
|
|
|
@ -183,6 +183,81 @@ EOF
|
||||||
test_cmp expected actual
|
test_cmp expected actual
|
||||||
'
|
'
|
||||||
|
|
||||||
|
test_expect_success 'status during rebase -ir after conflicted merge (exec git merge)' '
|
||||||
|
git reset --hard main &&
|
||||||
|
git checkout -b rebase_i_merge &&
|
||||||
|
test_commit unrelated &&
|
||||||
|
git checkout -b rebase_i_merge_side &&
|
||||||
|
test_commit side2 main.txt &&
|
||||||
|
git checkout rebase_i_merge &&
|
||||||
|
test_commit side1 main.txt &&
|
||||||
|
PICK=$(git rev-parse --short rebase_i_merge) &&
|
||||||
|
test_must_fail git merge rebase_i_merge_side &&
|
||||||
|
echo side1 >main.txt &&
|
||||||
|
git add main.txt &&
|
||||||
|
test_tick &&
|
||||||
|
git commit --no-edit &&
|
||||||
|
MERGE=$(git rev-parse --short rebase_i_merge) &&
|
||||||
|
ONTO=$(git rev-parse --short main) &&
|
||||||
|
test_when_finished "git rebase --abort" &&
|
||||||
|
FAKE_LINES="1 2 3 5 6 7 8 9 10 exec_git_merge_refs/rewritten/rebase-i-merge-side" &&
|
||||||
|
export FAKE_LINES &&
|
||||||
|
test_must_fail git rebase -ir main &&
|
||||||
|
cat >expect <<EOF &&
|
||||||
|
interactive rebase in progress; onto $ONTO
|
||||||
|
Last commands done (8 commands done):
|
||||||
|
pick $PICK side1
|
||||||
|
exec git merge refs/rewritten/rebase-i-merge-side
|
||||||
|
(see more in file .git/rebase-merge/done)
|
||||||
|
No commands remaining.
|
||||||
|
|
||||||
|
You have unmerged paths.
|
||||||
|
(fix conflicts and run "git commit")
|
||||||
|
(use "git merge --abort" to abort the merge)
|
||||||
|
|
||||||
|
Unmerged paths:
|
||||||
|
(use "git add <file>..." to mark resolution)
|
||||||
|
both modified: main.txt
|
||||||
|
|
||||||
|
no changes added to commit (use "git add" and/or "git commit -a")
|
||||||
|
EOF
|
||||||
|
git status --untracked-files=no >actual &&
|
||||||
|
test_cmp expect actual
|
||||||
|
'
|
||||||
|
|
||||||
|
test_expect_success 'status during rebase -ir after replaying conflicted merge (merge)' '
|
||||||
|
PICK=$(git rev-parse --short :/side1) &&
|
||||||
|
UNRELATED=$(git rev-parse --short :/unrelated) &&
|
||||||
|
MERGE=$(git rev-parse --short rebase_i_merge) &&
|
||||||
|
ONTO=$(git rev-parse --short main) &&
|
||||||
|
test_when_finished "git rebase --abort" &&
|
||||||
|
FAKE_LINES="1 2 3 5 6 7 8 9 10 11 4" &&
|
||||||
|
export FAKE_LINES &&
|
||||||
|
test_must_fail git rebase -ir main &&
|
||||||
|
cat >expect <<EOF &&
|
||||||
|
interactive rebase in progress; onto $ONTO
|
||||||
|
Last commands done (8 commands done):
|
||||||
|
pick $PICK side1
|
||||||
|
merge -C $MERGE rebase-i-merge-side # Merge branch '\''rebase_i_merge_side'\'' into rebase_i_merge
|
||||||
|
(see more in file .git/rebase-merge/done)
|
||||||
|
Next command to do (1 remaining command):
|
||||||
|
pick $UNRELATED unrelated
|
||||||
|
(use "git rebase --edit-todo" to view and edit)
|
||||||
|
You are currently rebasing branch '\''rebase_i_merge'\'' on '\''$ONTO'\''.
|
||||||
|
(fix conflicts and then run "git rebase --continue")
|
||||||
|
(use "git rebase --skip" to skip this patch)
|
||||||
|
(use "git rebase --abort" to check out the original branch)
|
||||||
|
|
||||||
|
Unmerged paths:
|
||||||
|
(use "git add <file>..." to mark resolution)
|
||||||
|
both modified: main.txt
|
||||||
|
|
||||||
|
no changes added to commit (use "git add" and/or "git commit -a")
|
||||||
|
EOF
|
||||||
|
git status --untracked-files=no >actual &&
|
||||||
|
test_cmp expect actual
|
||||||
|
'
|
||||||
|
|
||||||
|
|
||||||
test_expect_success 'status when rebasing -i in edit mode' '
|
test_expect_success 'status when rebasing -i in edit mode' '
|
||||||
git reset --hard main &&
|
git reset --hard main &&
|
||||||
|
|
47
wt-status.c
47
wt-status.c
|
@ -1342,9 +1342,11 @@ static int split_commit_in_progress(struct wt_status *s)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Turn
|
* Turn
|
||||||
* "pick d6a2f0303e897ec257dd0e0a39a5ccb709bc2047 some message"
|
* "pick d6a2f0303e897ec257dd0e0a39a5ccb709bc2047 some message" and
|
||||||
|
* "merge -C d6a2f0303e897ec257dd0e0a39a5ccb709bc2047 some-branch"
|
||||||
* into
|
* into
|
||||||
* "pick d6a2f03 some message"
|
* "pick d6a2f03 some message" and
|
||||||
|
* "merge -C d6a2f03 some-branch"
|
||||||
*
|
*
|
||||||
* The function assumes that the line does not contain useless spaces
|
* The function assumes that the line does not contain useless spaces
|
||||||
* before or after the command.
|
* before or after the command.
|
||||||
|
@ -1360,20 +1362,31 @@ static void abbrev_oid_in_line(struct strbuf *line)
|
||||||
starts_with(line->buf, "l "))
|
starts_with(line->buf, "l "))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
split = strbuf_split_max(line, ' ', 3);
|
split = strbuf_split_max(line, ' ', 4);
|
||||||
if (split[0] && split[1]) {
|
if (split[0] && split[1]) {
|
||||||
struct object_id oid;
|
struct object_id oid;
|
||||||
|
struct strbuf *hash;
|
||||||
|
|
||||||
|
if ((!strcmp(split[0]->buf, "merge ") ||
|
||||||
|
!strcmp(split[0]->buf, "m " ) ||
|
||||||
|
!strcmp(split[0]->buf, "fixup ") ||
|
||||||
|
!strcmp(split[0]->buf, "f " )) &&
|
||||||
|
(!strcmp(split[1]->buf, "-C ") ||
|
||||||
|
!strcmp(split[1]->buf, "-c "))) {
|
||||||
|
hash = split[2];
|
||||||
|
} else {
|
||||||
|
hash = split[1];
|
||||||
|
}
|
||||||
/*
|
/*
|
||||||
* strbuf_split_max left a space. Trim it and re-add
|
* strbuf_split_max left a space. Trim it and re-add
|
||||||
* it after abbreviation.
|
* it after abbreviation.
|
||||||
*/
|
*/
|
||||||
strbuf_trim(split[1]);
|
strbuf_trim(hash);
|
||||||
if (!repo_get_oid(the_repository, split[1]->buf, &oid)) {
|
if (!repo_get_oid(the_repository, hash->buf, &oid)) {
|
||||||
strbuf_reset(split[1]);
|
strbuf_reset(hash);
|
||||||
strbuf_add_unique_abbrev(split[1], &oid,
|
strbuf_add_unique_abbrev(hash, &oid,
|
||||||
DEFAULT_ABBREV);
|
DEFAULT_ABBREV);
|
||||||
strbuf_addch(split[1], ' ');
|
strbuf_addch(hash, ' ');
|
||||||
strbuf_reset(line);
|
strbuf_reset(line);
|
||||||
for (i = 0; split[i]; i++)
|
for (i = 0; split[i]; i++)
|
||||||
strbuf_addbuf(line, split[i]);
|
strbuf_addbuf(line, split[i]);
|
||||||
|
@ -1731,6 +1744,7 @@ int wt_status_check_rebase(const struct worktree *wt,
|
||||||
struct wt_status_state *state)
|
struct wt_status_state *state)
|
||||||
{
|
{
|
||||||
struct stat st;
|
struct stat st;
|
||||||
|
struct string_list have_done = STRING_LIST_INIT_DUP;
|
||||||
|
|
||||||
if (!stat(worktree_git_path(the_repository, wt, "rebase-apply"), &st)) {
|
if (!stat(worktree_git_path(the_repository, wt, "rebase-apply"), &st)) {
|
||||||
if (!stat(worktree_git_path(the_repository, wt, "rebase-apply/applying"), &st)) {
|
if (!stat(worktree_git_path(the_repository, wt, "rebase-apply/applying"), &st)) {
|
||||||
|
@ -1747,8 +1761,12 @@ int wt_status_check_rebase(const struct worktree *wt,
|
||||||
state->rebase_interactive_in_progress = 1;
|
state->rebase_interactive_in_progress = 1;
|
||||||
else
|
else
|
||||||
state->rebase_in_progress = 1;
|
state->rebase_in_progress = 1;
|
||||||
|
read_rebase_todolist("rebase-merge/done", &have_done);
|
||||||
|
if (have_done.nr > 0 && starts_with(have_done.items[have_done.nr - 1].string, "merge"))
|
||||||
|
state->merge_during_rebase_in_progress = 1;
|
||||||
state->branch = get_branch(wt, "rebase-merge/head-name");
|
state->branch = get_branch(wt, "rebase-merge/head-name");
|
||||||
state->onto = get_branch(wt, "rebase-merge/onto");
|
state->onto = get_branch(wt, "rebase-merge/onto");
|
||||||
|
string_list_clear(&have_done, 0);
|
||||||
} else
|
} else
|
||||||
return 0;
|
return 0;
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -1842,10 +1860,15 @@ static void wt_longstatus_print_state(struct wt_status *s)
|
||||||
|
|
||||||
if (state->merge_in_progress) {
|
if (state->merge_in_progress) {
|
||||||
if (state->rebase_interactive_in_progress) {
|
if (state->rebase_interactive_in_progress) {
|
||||||
show_rebase_information(s, state_color);
|
if (state->merge_during_rebase_in_progress)
|
||||||
fputs("\n", s->fp);
|
show_rebase_in_progress(s, state_color);
|
||||||
}
|
else {
|
||||||
show_merge_in_progress(s, state_color);
|
show_rebase_information(s, state_color);
|
||||||
|
fputs("\n", s->fp);
|
||||||
|
show_merge_in_progress(s, state_color);
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
show_merge_in_progress(s, state_color);
|
||||||
} else if (state->am_in_progress)
|
} else if (state->am_in_progress)
|
||||||
show_am_in_progress(s, state_color);
|
show_am_in_progress(s, state_color);
|
||||||
else if (state->rebase_in_progress || state->rebase_interactive_in_progress)
|
else if (state->rebase_in_progress || state->rebase_interactive_in_progress)
|
||||||
|
|
|
@ -87,6 +87,7 @@ struct wt_status_state {
|
||||||
int am_empty_patch;
|
int am_empty_patch;
|
||||||
int rebase_in_progress;
|
int rebase_in_progress;
|
||||||
int rebase_interactive_in_progress;
|
int rebase_interactive_in_progress;
|
||||||
|
int merge_during_rebase_in_progress;
|
||||||
int cherry_pick_in_progress;
|
int cherry_pick_in_progress;
|
||||||
int bisect_in_progress;
|
int bisect_in_progress;
|
||||||
int revert_in_progress;
|
int revert_in_progress;
|
||||||
|
|
Loading…
Reference in New Issue