git.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: "Philippe Blain via GitGitGadget" <gitgitgadget@gmail.com>
To: git@vger.kernel.org
Cc: Phillip Wood <phillip.wood@dunelm.org.uk>,
	Johannes Schindelin <Johannes.Schindelin@gmx.de>,
	Philippe Blain <levraiphilippeblain@gmail.com>,
	Philippe Blain <levraiphilippeblain@gmail.com>
Subject: [PATCH 3/3] wt-status: suggest 'git rebase --continue' to conclude 'merge' instruction
Date: Fri, 28 Mar 2025 17:03:21 +0000	[thread overview]
Message-ID: <db01acdd062a17b1cca62428eba8c3ed62ca7c6a.1743181401.git.gitgitgadget@gmail.com> (raw)
In-Reply-To: <pull.1897.git.1743181401.gitgitgadget@gmail.com>

From: Philippe Blain <levraiphilippeblain@gmail.com>

Since 982288e9bd (status: rebase and merge can be in progress at the
same time, 2018-11-12), when a merge is in progress as part of a 'git
rebase -r' operation, 'wt_longstatus_print_state' shows information
about the in-progress rebase (via show_rebase_information), and then
calls 'show_merge_in_progress' to help the user conclude the merge. This
function suggests using 'git commit' to do so, but this throws away the
authorship information from the original merge, which is not ideal.
Using 'git rebase --continue' instead preserves the authorship
information, since we enter 'sequencer.c:run_git_commit' which calls
read_env_script to read the author-script file.

Note however that this only works when a merge was scheduled using a
'merge' instruction in the rebase todo list. Indeed, when using 'exec
git merge', the state files necessary for 'git rebase --continue' are
not present, and one must use 'git commit' (or 'git merge --continue')
in that case.

Be more helpful to the user by suggesting either 'git rebase
--continue', when the merge was scheduled using a 'merge' instruction,
and 'git commit' otherwise. As such, add a
'merge_during_rebase_in_progress' field to 'struct wt_status_state', and
detect this situation in wt_status_check_rebase by looking at the last
command done. Adjust wt_longstatus_print_state to check this field and
suggest 'git rebase --continue' if a merge came from a 'merge'
instruction, by calling show_rebase_in_progress directly.

Add two tests for the new behaviour, using 'merge' and 'exec git merge'
instructions.

Signed-off-by: Philippe Blain <levraiphilippeblain@gmail.com>
---
 t/t7512-status-help.sh | 75 ++++++++++++++++++++++++++++++++++++++++++
 wt-status.c            | 18 +++++++---
 wt-status.h            |  1 +
 3 files changed, 90 insertions(+), 4 deletions(-)

diff --git a/t/t7512-status-help.sh b/t/t7512-status-help.sh
index 802f8f704c6..b37e99625b4 100755
--- a/t/t7512-status-help.sh
+++ b/t/t7512-status-help.sh
@@ -183,6 +183,81 @@ EOF
 	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' '
 	git reset --hard main &&
diff --git a/wt-status.c b/wt-status.c
index d11d9f9f142..f15495039e3 100644
--- a/wt-status.c
+++ b/wt-status.c
@@ -1744,6 +1744,7 @@ int wt_status_check_rebase(const struct worktree *wt,
 			   struct wt_status_state *state)
 {
 	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/applying"), &st)) {
@@ -1760,8 +1761,12 @@ int wt_status_check_rebase(const struct worktree *wt,
 			state->rebase_interactive_in_progress = 1;
 		else
 			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->onto = get_branch(wt, "rebase-merge/onto");
+		string_list_clear(&have_done, 0);
 	} else
 		return 0;
 	return 1;
@@ -1855,10 +1860,15 @@ static void wt_longstatus_print_state(struct wt_status *s)
 
 	if (state->merge_in_progress) {
 		if (state->rebase_interactive_in_progress) {
-			show_rebase_information(s, state_color);
-			fputs("\n", s->fp);
-		}
-		show_merge_in_progress(s, state_color);
+			if (state->merge_during_rebase_in_progress)
+				show_rebase_in_progress(s, state_color);
+			else {
+				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)
 		show_am_in_progress(s, state_color);
 	else if (state->rebase_in_progress || state->rebase_interactive_in_progress)
diff --git a/wt-status.h b/wt-status.h
index 4e377ce62b8..84bedfcd48f 100644
--- a/wt-status.h
+++ b/wt-status.h
@@ -87,6 +87,7 @@ struct wt_status_state {
 	int am_empty_patch;
 	int rebase_in_progress;
 	int rebase_interactive_in_progress;
+	int merge_during_rebase_in_progress;
 	int cherry_pick_in_progress;
 	int bisect_in_progress;
 	int revert_in_progress;
-- 
gitgitgadget

  parent reply	other threads:[~2025-03-28 17:03 UTC|newest]

Thread overview: 17+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-03-28 17:03 [PATCH 0/3] rebase -r: a bugfix and two status-related improvements Philippe Blain via GitGitGadget
2025-03-28 17:03 ` [PATCH 1/3] rebase -r: do create merge commit after empty resolution Philippe Blain via GitGitGadget
2025-03-28 17:14   ` Eric Sunshine
2025-03-28 17:23     ` Eric Sunshine
2025-04-01 16:17       ` Johannes Schindelin
2025-03-31 15:37   ` Phillip Wood
2025-03-28 17:03 ` [PATCH 2/3] wt-status: also abbreviate 'merge' and 'fixup -C' lines during rebase Philippe Blain via GitGitGadget
2025-03-31 15:37   ` Phillip Wood
2025-03-28 17:03 ` Philippe Blain via GitGitGadget [this message]
2025-03-31 15:38   ` [PATCH 3/3] wt-status: suggest 'git rebase --continue' to conclude 'merge' instruction Phillip Wood
2025-04-01 16:22   ` Johannes Schindelin
2025-04-02 13:09     ` phillip.wood123
2025-04-03 12:17       ` Johannes Schindelin
2025-04-03 15:08         ` phillip.wood123
2025-04-04 11:41           ` Johannes Schindelin
2025-04-04 14:13             ` Phillip Wood
2025-03-31 15:38 ` [PATCH 0/3] rebase -r: a bugfix and two status-related improvements Phillip Wood

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=db01acdd062a17b1cca62428eba8c3ed62ca7c6a.1743181401.git.gitgitgadget@gmail.com \
    --to=gitgitgadget@gmail.com \
    --cc=Johannes.Schindelin@gmx.de \
    --cc=git@vger.kernel.org \
    --cc=levraiphilippeblain@gmail.com \
    --cc=phillip.wood@dunelm.org.uk \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).