From: "Elijah Newren via GitGitGadget" <gitgitgadget@gmail.com>
To: git@vger.kernel.org
Cc: "ZheNing Hu" <adlternative@gmail.com>,
"Eric Sunshine" <sunshine@sunshineco.com>,
"Junio C Hamano" <gitster@pobox.com>,
"Elijah Newren" <newren@gmail.com>,
"Ævar Arnfjörð Bjarmason" <avarab@gmail.com>,
"Elijah Newren" <newren@gmail.com>
Subject: [PATCH v5 0/8] Fix merge restore state
Date: Sat, 23 Jul 2022 01:53:10 +0000 [thread overview]
Message-ID: <pull.1231.v5.git.1658541198.gitgitgadget@gmail.com> (raw)
In-Reply-To: <pull.1231.v4.git.1658466942.gitgitgadget@gmail.com>
This started as a simple series to fix restore_state() in builtin/merge.c,
fixing an issue reported by ZheNing Hu[3]. It now fixes several bugs and has
grown so much it's hard to call it simple. Anyway...
Changes since v4:
* Made use of the error() function in another place to simplify code
(should have caught this in v3)
* Split the fixes for 'resolve' and the trivial merge into separate
patches, and make sure one doesn't mask the other but both codepaths are
exercises in the testsuite
* better test descriptions
* use strvec to simplify some code
[1]
https://lore.kernel.org/git/CAOLTT8R7QmpvaFPTRs3xTpxr7eiuxF-ZWtvUUSC0-JOo9Y+SqA@mail.gmail.com/
Elijah Newren (8):
merge-ort-wrappers: make printed message match the one from recursive
merge-resolve: abort if index does not match HEAD
merge: abort if index does not match HEAD for trivial merges
merge: do not abort early if one strategy fails to handle the merge
merge: fix save_state() to work when there are stat-dirty files
merge: make restore_state() restore staged state too
merge: ensure we can actually restore pre-merge state
merge: do not exit restore_state() prematurely
builtin/merge.c | 57 ++++++++++++++++-----
git-merge-resolve.sh | 10 ++++
merge-ort-wrappers.c | 4 +-
t/t6402-merge-rename.sh | 2 +-
t/t6424-merge-unrelated-index-changes.sh | 65 ++++++++++++++++++++++++
t/t6439-merge-co-error-msgs.sh | 1 +
t/t7607-merge-state.sh | 32 ++++++++++++
7 files changed, 154 insertions(+), 17 deletions(-)
create mode 100755 t/t7607-merge-state.sh
base-commit: e72d93e88cb20b06e88e6e7d81bd1dc4effe453f
Published-As: https://github.com/gitgitgadget/git/releases/tag/pr-1231%2Fnewren%2Ffix-merge-restore-state-v5
Fetch-It-Via: git fetch https://github.com/gitgitgadget/git pr-1231/newren/fix-merge-restore-state-v5
Pull-Request: https://github.com/gitgitgadget/git/pull/1231
Range-diff vs v4:
1: bd36d16c8d9 = 1: bd36d16c8d9 merge-ort-wrappers: make printed message match the one from recursive
2: b79f44e54b9 ! 2: b656756fd37 merge-resolve: abort if index does not match HEAD
@@ Commit message
Signed-off-by: Elijah Newren <newren@gmail.com>
- ## builtin/merge.c ##
-@@ builtin/merge.c: int cmd_merge(int argc, const char **argv, const char *prefix)
- */
- refresh_cache(REFRESH_QUIET);
- if (allow_trivial && fast_forward != FF_ONLY) {
-+ /*
-+ * Must first ensure that index matches HEAD before
-+ * attempting a trivial merge.
-+ */
-+ struct tree *head_tree = get_commit_tree(head_commit);
-+ struct strbuf sb = STRBUF_INIT;
-+
-+ if (repo_index_has_changes(the_repository, head_tree,
-+ &sb)) {
-+ struct strbuf err = STRBUF_INIT;
-+ strbuf_addstr(&err, "error: ");
-+ strbuf_addf(&err, _("Your local changes to the following files would be overwritten by merge:\n %s"),
-+ sb.buf);
-+ strbuf_addch(&err, '\n');
-+ fputs(err.buf, stderr);
-+ strbuf_release(&err);
-+ strbuf_release(&sb);
-+ return -1;
-+ }
-+
- /* See if it is really trivial. */
- git_committer_info(IDENT_STRICT);
- printf(_("Trying really trivial in-index merge...\n"));
-
## git-merge-resolve.sh ##
@@
#
@@ t/t6424-merge-unrelated-index-changes.sh: test_expect_success 'resolve, non-triv
test_path_is_missing .git/MERGE_HEAD
'
-+test_expect_success 'resolve, trivial, related file removed' '
-+ git reset --hard &&
-+ git checkout B^0 &&
-+
-+ git rm a &&
-+ test_path_is_missing a &&
-+
-+ test_must_fail git merge -s resolve C^0 &&
-+
-+ test_path_is_missing a &&
-+ test_path_is_missing .git/MERGE_HEAD
-+'
-+
+test_expect_success 'resolve, non-trivial, related file removed' '
+ git reset --hard &&
+ git checkout B^0 &&
-: ----------- > 3: 3adfd921995 merge: abort if index does not match HEAD for trivial merges
3: 02930448ea1 ! 4: c5755271cf1 merge: do not abort early if one strategy fails to handle the merge
@@ t/t6424-merge-unrelated-index-changes.sh: test_expect_success 'subtree' '
test_path_is_missing .git/MERGE_HEAD
'
-+test_expect_success 'resolve && recursive && ort' '
++test_expect_success 'with multiple strategies, recursive or ort failure do not early abort' '
+ git reset --hard &&
+ git checkout B^0 &&
+
@@ t/t6424-merge-unrelated-index-changes.sh: test_expect_success 'subtree' '
+ git add a &&
+
+ sane_unset GIT_TEST_MERGE_ALGORITHM &&
-+ test_must_fail git merge -s resolve -s recursive -s ort C^0 >output 2>&1 &&
++ test_must_fail git merge -s recursive -s ort -s octopus C^0 >output 2>&1 &&
+
-+ grep "Trying merge strategy resolve..." output &&
+ grep "Trying merge strategy recursive..." output &&
+ grep "Trying merge strategy ort..." output &&
++ grep "Trying merge strategy octopus..." output &&
+ grep "No merge strategy handled the merge." output
+'
+
4: daf8d224160 ! 5: e7c6de9e0c1 merge: fix save_state() to work when there are stat-dirty files
@@ t/t6424-merge-unrelated-index-changes.sh: test_expect_success 'subtree' '
+ git merge -s resolve -s recursive D^0
+'
+
- test_expect_success 'resolve && recursive && ort' '
+ test_expect_success 'with multiple strategies, recursive or ort failure do not early abort' '
git reset --hard &&
git checkout B^0 &&
5: f401bd5ad0d ! 6: d39d6472455 merge: make restore_state() restore staged state too
@@ Commit message
changes. Fix this by adding the "--index" option to "git stash apply".
While at it, also squelch the stash apply output; we already report
"Rewinding the tree to pristine..." and don't need a detailed `git
- status` report afterwards.
+ status` report afterwards. Also while at it, switch to using strvec
+ so folks don't have to count the arguments to ensure we avoided an
+ off-by-one error, and so it's easier to add additional arguments to
+ the command.
Signed-off-by: Elijah Newren <newren@gmail.com>
@@ builtin/merge.c: static void reset_hard(const struct object_id *oid, int verbose
const struct object_id *stash)
{
- const char *args[] = { "stash", "apply", NULL, NULL };
-+ const char *args[] = { "stash", "apply", "--index", "--quiet",
-+ NULL, NULL };
++ struct strvec args = STRVEC_INIT;
if (is_null_oid(stash))
return;
@@ builtin/merge.c: static void reset_hard(const struct object_id *oid, int verbose
reset_hard(head, 1);
- args[2] = oid_to_hex(stash);
-+ args[4] = oid_to_hex(stash);
++ strvec_pushl(&args, "stash", "apply", "--index", "--quiet", NULL);
++ strvec_push(&args, oid_to_hex(stash));
/*
* It is OK to ignore error here, for example when there was
+ * nothing to restore.
+ */
+- run_command_v_opt(args, RUN_GIT_CMD);
++ run_command_v_opt(args.v, RUN_GIT_CMD);
++ strvec_clear(&args);
+
+ refresh_cache(REFRESH_QUIET);
+ }
## t/t6424-merge-unrelated-index-changes.sh ##
-@@ t/t6424-merge-unrelated-index-changes.sh: test_expect_success 'resolve && recursive && ort' '
+@@ t/t6424-merge-unrelated-index-changes.sh: test_expect_success 'with multiple strategies, recursive or ort failure do not e
test_seq 0 10 >a &&
git add a &&
+ git rev-parse :a >expect &&
sane_unset GIT_TEST_MERGE_ALGORITHM &&
- test_must_fail git merge -s resolve -s recursive -s ort C^0 >output 2>&1 &&
-@@ t/t6424-merge-unrelated-index-changes.sh: test_expect_success 'resolve && recursive && ort' '
- grep "Trying merge strategy resolve..." output &&
+ test_must_fail git merge -s recursive -s ort -s octopus C^0 >output 2>&1 &&
+@@ t/t6424-merge-unrelated-index-changes.sh: test_expect_success 'with multiple strategies, recursive or ort failure do not e
grep "Trying merge strategy recursive..." output &&
grep "Trying merge strategy ort..." output &&
+ grep "Trying merge strategy octopus..." output &&
- grep "No merge strategy handled the merge." output
+ grep "No merge strategy handled the merge." output &&
+
6: ad5354c219c = 7: 7f5c6884d68 merge: ensure we can actually restore pre-merge state
7: 6212d572604 ! 8: 954dec526a2 merge: do not exit restore_state() prematurely
@@ Commit message
## builtin/merge.c ##
@@ builtin/merge.c: static void restore_state(const struct object_id *head,
- const char *args[] = { "stash", "apply", "--index", "--quiet",
- NULL, NULL };
+ {
+ struct strvec args = STRVEC_INIT;
- if (is_null_oid(stash))
- return;
@@ builtin/merge.c: static void restore_state(const struct object_id *head,
+ if (is_null_oid(stash))
+ goto refresh_cache;
+
- args[4] = oid_to_hex(stash);
+ strvec_pushl(&args, "stash", "apply", "--index", "--quiet", NULL);
+ strvec_push(&args, oid_to_hex(stash));
- /*
@@ builtin/merge.c: static void restore_state(const struct object_id *head,
- */
- run_command_v_opt(args, RUN_GIT_CMD);
+ run_command_v_opt(args.v, RUN_GIT_CMD);
+ strvec_clear(&args);
- refresh_cache(REFRESH_QUIET);
+refresh_cache:
@@ t/t7607-merge-state.sh (new)
+export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+. ./test-lib.sh
+
-+test_expect_success 'set up custom strategy' '
++test_expect_success 'Ensure we restore original state if no merge strategy handles it' '
+ test_commit --no-tag "Initial" base base &&
+
+ for b in branch1 branch2 branch3
--
gitgitgadget
next prev parent reply other threads:[~2022-07-23 1:53 UTC|newest]
Thread overview: 87+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-05-19 16:26 [PATCH 0/2] Fix merge restore state Elijah Newren via GitGitGadget
2022-05-19 16:26 ` [PATCH 1/2] merge: remove unused variable Elijah Newren via GitGitGadget
2022-05-19 17:45 ` Junio C Hamano
2022-05-19 16:26 ` [PATCH 2/2] merge: make restore_state() do as its name says Elijah Newren via GitGitGadget
2022-05-19 17:44 ` Junio C Hamano
2022-05-19 18:32 ` Junio C Hamano
2022-06-12 6:58 ` [PATCH 0/2] Fix merge restore state Elijah Newren
2022-06-12 8:54 ` ZheNing Hu
2022-06-19 6:50 ` [PATCH v2 0/6] " Elijah Newren via GitGitGadget
2022-06-19 6:50 ` [PATCH v2 1/6] t6424: make sure a failed merge preserves local changes Junio C Hamano via GitGitGadget
2022-06-19 6:50 ` [PATCH v2 2/6] merge: remove unused variable Elijah Newren via GitGitGadget
2022-07-19 23:14 ` Junio C Hamano
2022-06-19 6:50 ` [PATCH v2 3/6] merge: fix save_state() to work when there are racy-dirty files Elijah Newren via GitGitGadget
2022-07-17 16:28 ` ZheNing Hu
2022-07-19 22:49 ` Junio C Hamano
2022-07-21 1:09 ` Elijah Newren
2022-07-19 22:43 ` Junio C Hamano
2022-06-19 6:50 ` [PATCH v2 4/6] merge: make restore_state() restore staged state too Elijah Newren via GitGitGadget
2022-07-17 16:37 ` ZheNing Hu
2022-07-19 23:14 ` Junio C Hamano
2022-07-19 23:28 ` Junio C Hamano
2022-07-21 1:37 ` Elijah Newren
2022-06-19 6:50 ` [PATCH v2 5/6] merge: ensure we can actually restore pre-merge state Elijah Newren via GitGitGadget
2022-07-17 16:41 ` ZheNing Hu
2022-07-19 22:57 ` Junio C Hamano
2022-07-21 2:03 ` Elijah Newren
2022-06-19 6:50 ` [PATCH v2 6/6] merge: do not exit restore_state() prematurely Elijah Newren via GitGitGadget
2022-07-17 16:44 ` ZheNing Hu
2022-07-19 23:13 ` Junio C Hamano
2022-07-20 0:09 ` Eric Sunshine
2022-07-21 2:03 ` Elijah Newren
2022-07-21 3:27 ` Elijah Newren
2022-07-21 8:16 ` [PATCH v3 0/7] Fix merge restore state Elijah Newren via GitGitGadget
2022-07-21 8:16 ` [PATCH v3 1/7] merge-ort-wrappers: make printed message match the one from recursive Elijah Newren via GitGitGadget
2022-07-21 15:47 ` Junio C Hamano
2022-07-21 19:51 ` Elijah Newren
2022-07-21 20:05 ` Junio C Hamano
2022-07-21 21:14 ` Elijah Newren
2022-07-21 8:16 ` [PATCH v3 2/7] merge-resolve: abort if index does not match HEAD Elijah Newren via GitGitGadget
2022-07-21 8:16 ` [PATCH v3 3/7] merge: do not abort early if one strategy fails to handle the merge Elijah Newren via GitGitGadget
2022-07-21 16:09 ` Junio C Hamano
2022-07-25 10:38 ` Ævar Arnfjörð Bjarmason
2022-07-26 1:31 ` Elijah Newren
2022-07-26 6:54 ` Ævar Arnfjörð Bjarmason
2022-07-21 8:16 ` [PATCH v3 4/7] merge: fix save_state() to work when there are stat-dirty files Elijah Newren via GitGitGadget
2022-07-21 8:16 ` [PATCH v3 5/7] merge: make restore_state() restore staged state too Elijah Newren via GitGitGadget
2022-07-21 16:16 ` Junio C Hamano
2022-07-21 16:24 ` Junio C Hamano
2022-07-21 19:52 ` Elijah Newren
2022-07-21 8:16 ` [PATCH v3 6/7] merge: ensure we can actually restore pre-merge state Elijah Newren via GitGitGadget
2022-07-21 16:31 ` Junio C Hamano
2023-03-02 7:17 ` Ben Humphreys
2023-03-02 15:35 ` Elijah Newren
2023-03-02 16:19 ` Junio C Hamano
2023-03-04 16:18 ` Rudy Rigot
2023-03-06 22:19 ` Ben Humphreys
2022-07-21 8:16 ` [PATCH v3 7/7] merge: do not exit restore_state() prematurely Elijah Newren via GitGitGadget
2022-07-21 16:34 ` Junio C Hamano
2022-07-22 5:15 ` [PATCH v4 0/7] Fix merge restore state Elijah Newren via GitGitGadget
2022-07-22 5:15 ` [PATCH v4 1/7] merge-ort-wrappers: make printed message match the one from recursive Elijah Newren via GitGitGadget
2022-07-22 5:15 ` [PATCH v4 2/7] merge-resolve: abort if index does not match HEAD Elijah Newren via GitGitGadget
2022-07-22 10:27 ` Ævar Arnfjörð Bjarmason
2022-07-23 0:28 ` Elijah Newren
2022-07-23 5:44 ` Ævar Arnfjörð Bjarmason
2022-07-26 1:58 ` Elijah Newren
2022-07-26 6:35 ` Ævar Arnfjörð Bjarmason
2022-07-22 5:15 ` [PATCH v4 3/7] merge: do not abort early if one strategy fails to handle the merge Elijah Newren via GitGitGadget
2022-07-22 10:47 ` Ævar Arnfjörð Bjarmason
2022-07-23 0:36 ` Elijah Newren
2022-07-22 5:15 ` [PATCH v4 4/7] merge: fix save_state() to work when there are stat-dirty files Elijah Newren via GitGitGadget
2022-07-22 5:15 ` [PATCH v4 5/7] merge: make restore_state() restore staged state too Elijah Newren via GitGitGadget
2022-07-22 10:53 ` Ævar Arnfjörð Bjarmason
2022-07-23 1:56 ` Elijah Newren
2022-07-22 5:15 ` [PATCH v4 6/7] merge: ensure we can actually restore pre-merge state Elijah Newren via GitGitGadget
2022-07-22 5:15 ` [PATCH v4 7/7] merge: do not exit restore_state() prematurely Elijah Newren via GitGitGadget
2022-07-23 1:53 ` Elijah Newren via GitGitGadget [this message]
2022-07-23 1:53 ` [PATCH v5 1/8] merge-ort-wrappers: make printed message match the one from recursive Elijah Newren via GitGitGadget
2022-07-23 1:53 ` [PATCH v5 2/8] merge-resolve: abort if index does not match HEAD Elijah Newren via GitGitGadget
2022-07-23 1:53 ` [PATCH v5 3/8] merge: abort if index does not match HEAD for trivial merges Elijah Newren via GitGitGadget
2022-07-23 1:53 ` [PATCH v5 4/8] merge: do not abort early if one strategy fails to handle the merge Elijah Newren via GitGitGadget
2022-07-23 1:53 ` [PATCH v5 5/8] merge: fix save_state() to work when there are stat-dirty files Elijah Newren via GitGitGadget
2022-07-23 1:53 ` [PATCH v5 6/8] merge: make restore_state() restore staged state too Elijah Newren via GitGitGadget
2022-07-23 1:53 ` [PATCH v5 7/8] merge: ensure we can actually restore pre-merge state Elijah Newren via GitGitGadget
2022-07-23 1:53 ` [PATCH v5 8/8] merge: do not exit restore_state() prematurely Elijah Newren via GitGitGadget
2022-07-25 19:03 ` [PATCH v5 0/8] Fix merge restore state Junio C Hamano
2022-07-26 1:59 ` Elijah Newren
2022-07-26 4:03 ` ZheNing Hu
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=pull.1231.v5.git.1658541198.gitgitgadget@gmail.com \
--to=gitgitgadget@gmail.com \
--cc=adlternative@gmail.com \
--cc=avarab@gmail.com \
--cc=git@vger.kernel.org \
--cc=gitster@pobox.com \
--cc=newren@gmail.com \
--cc=sunshine@sunshineco.com \
/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).