git/list[1] front-page[2] threads[3] people[4] search[5] about
 

[PATCH 3/6] Add merge testcases for when index doesn't match HEAD

From
Elijah Newren <newren@gmail.com>
Date
Apr 10, 2016, 06:13 UTC
Message-ID
<1460268820-8308-4-git-send-email-newren@gmail.com>
In-Reply-To
<1460268820-8308-1-git-send-email-newren@gmail.com>
With one exception, we require the index to exactly match the current HEAD
commit at the time git merge is invoked.  This expectation was even
documented in git-merge.txt until commit ebef7e5 (Documentation: simplify
How Merge Works, 2010-01-23).  Most merge strategies enforced this
requirement, but it turns out not all did.  The current exceptions were
the following two:
  * ff updates
  * octopus merges

ff updates actually will error out if the staged change is to a path modified between HEAD and the commit being merged. If the path(s) that are staged are files unrelated to the changes between these two commits, though, then an ff update will just keep these staged changes around after the merge. This is the one exception we expected to the abort-merge-if- index-doesn't-match-HEAD rule.

For octopus merges, the rule should be enforced. Unfortunately, the current behavior of the code is to ignore the difference and use the staged changes in place of whatever is in HEAD as it proceeds to perform the merge. So if the staged changes can be cleanly merged with all the other heads, then the staged changes will just be incorported into the resulting commit. If the staged changes cannot be cleanly merged with all the other heads, the merge is not aborted -- merge conflicts are simply reported as if HEAD had originally contained whatever the index did.

Add testcases that check our expectations. A subsequent commit will correct the erroneous octopus merge behavior.

Signed-off-by: Elijah Newren <newren@gmail.com>
---
 t/t6044-merge-unrelated-index-changes.sh | 153 +++++++++++++++++++++++++++++++
 1 file changed, 153 insertions(+)
 create mode 100755 t/t6044-merge-unrelated-index-changes.sh
diff --git a/t/t6044-merge-unrelated-index-changes.sh b/t/t6044-merge-unrelated-index-changes.sh
new file mode 100755
index 0000000..eed5d95
--- /dev/null
+++ b/t/t6044-merge-unrelated-index-changes.sh
@@ -0,0 +1,153 @@
+#!/bin/sh
+
+test_description="merges with unrelated index changes"
+
+. ./test-lib.sh
+
+# Testcase for some simple merges
+#   A
+#   o-----o B
+#    \
+#     \---o C
+#      \
+#       \-o D
+#        \
+#         o E
+#   Commit A: some file a
+#   Commit B: adds file b, modifies end of a
+#   Commit C: adds file c
+#   Commit D: adds file d, modifies beginning of a
+#   Commit E: renames a->subdir/a, adds subdir/e
+
+test_expect_success 'setup trivial merges' '
+	seq 1 10 >a &&
+	git add a &&
+	test_tick && git commit -m A &&
+
+	git branch A &&
+	git branch B &&
+	git branch C &&
+	git branch D &&
+	git branch E &&
+
+	git checkout B &&
+	echo b >b &&
+	echo 11 >>a &&
+	git add a b &&
+	test_tick && git commit -m B &&
+
+	git checkout C &&
+	echo c >c &&
+	git add c &&
+	test_tick && git commit -m C &&
+
+	git checkout D &&
+	seq 2 10 >a &&
+	echo d >d &&
+	git add a d &&
+	test_tick && git commit -m D &&
+
+	git checkout E &&
+	mkdir subdir &&
+	git mv a subdir/a &&
+	echo e >subdir/e &&
+	git add subdir &&
+	test_tick && git commit -m E
+'
+
+test_expect_success 'ff update' '
+	git reset --hard &&
+	git checkout A^0 &&
+
+	touch random_file && git add random_file &&
+
+	git merge E^0 &&
+
+	test_must_fail git rev-parse HEAD:random_file &&
+	test "$(git diff --name-only --cached E)" = "random_file"
+'
+
+test_expect_success 'ff update, important file modified' '
+	git reset --hard &&
+	git checkout A^0 &&
+
+	mkdir subdir &&
+	touch subdir/e &&
+	git add subdir/e &&
+
+	test_must_fail git merge E^0
+'
+
+test_expect_success 'resolve, trivial' '
+	git reset --hard &&
+	git checkout B^0 &&
+
+	touch random_file && git add random_file &&
+
+	test_must_fail git merge -s resolve C^0
+'
+
+test_expect_success 'resolve, non-trivial' '
+	git reset --hard &&
+	git checkout B^0 &&
+
+	touch random_file && git add random_file &&
+
+	test_must_fail git merge -s resolve D^0
+'
+
+test_expect_success 'recursive' '
+	git reset --hard &&
+	git checkout B^0 &&
+
+	touch random_file && git add random_file &&
+
+	test_must_fail git merge -s recursive C^0
+'
+
+test_expect_failure 'octopus, unrelated file touched' '
+	git reset --hard &&
+	git checkout B^0 &&
+
+	touch random_file && git add random_file &&
+
+	test_must_fail git merge C^0 D^0
+'
+
+test_expect_failure 'octopus, related file removed' '
+	git reset --hard &&
+	git checkout B^0 &&
+
+	git rm b &&
+
+	test_must_fail git merge C^0 D^0
+'
+
+test_expect_failure 'octopus, related file modified' '
+	git reset --hard &&
+	git checkout B^0 &&
+
+	echo 12 >>a && git add a &&
+
+	test_must_fail git merge C^0 D^0
+'
+
+test_expect_success 'ours' '
+	git reset --hard &&
+	git checkout B^0 &&
+
+	touch random_file && git add random_file &&
+
+	test_must_fail git merge -s ours C^0
+'
+
+test_expect_success 'subtree' '
+	git reset --hard &&
+	git checkout B^0 &&
+
+	touch random_file && git add random_file &&
+
+	test_must_fail git merge -s subtree E^0
+'
+
+test_done
-- 
2.8.0.21.g229f62a
Previous: Junio C HamanoNext: Elijah Newren
Message 5 of 10 in “Miscellaneous merge fixes”
  1. 0/6 Miscellaneous merge fixesElijah Newren, Apr 10, 2016
  2. 1/6 Remove duplicate codeElijah Newren, Apr 10, 2016
  3. 2/6 Avoid checking working copy when creating a virtual merge baseElijah Newren, Apr 10, 2016
  4. Junio C HamanoApr 13, 2016
  5. 3/6 Add merge testcases for when index doesn't match HEADElijah Newren, Apr 10, 2016
  6. 4/6 merge-octopus: Abort if index does not match HEADElijah Newren, Apr 10, 2016
  7. 5/6 Add a testcase demonstrating a bug with trivial mergesElijah Newren, Apr 10, 2016
  8. 6/6 builtin/merge.c: Fix a bug with trivial mergesElijah Newren, Apr 10, 2016
  9. Junio C HamanoApr 13, 2016
  10. Elijah NewrenApr 15, 2016

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.