2008-02-23 22:08:25 +03:00
|
|
|
#!/bin/sh
|
|
|
|
|
|
|
|
test_description='subtree merge strategy'
|
|
|
|
|
|
|
|
. ./test-lib.sh
|
|
|
|
|
|
|
|
test_expect_success setup '
|
|
|
|
|
2010-10-31 04:46:54 +03:00
|
|
|
s="1 2 3 4 5 6 7 8" &&
|
2008-02-23 22:08:25 +03:00
|
|
|
for i in $s; do echo $i; done >hello &&
|
|
|
|
git add hello &&
|
|
|
|
git commit -m initial &&
|
|
|
|
git checkout -b side &&
|
|
|
|
echo >>hello world &&
|
|
|
|
git add hello &&
|
|
|
|
git commit -m second &&
|
|
|
|
git checkout master &&
|
|
|
|
for i in mundo $s; do echo $i; done >hello &&
|
|
|
|
git add hello &&
|
|
|
|
git commit -m master
|
|
|
|
|
|
|
|
'
|
|
|
|
|
|
|
|
test_expect_success 'subtree available and works like recursive' '
|
|
|
|
|
|
|
|
git merge -s subtree side &&
|
|
|
|
for i in mundo $s world; do echo $i; done >expect &&
|
2008-03-13 00:36:36 +03:00
|
|
|
test_cmp expect hello
|
2008-02-23 22:08:25 +03:00
|
|
|
|
|
|
|
'
|
|
|
|
|
score_trees(): fix iteration over trees with missing entries
In score_trees(), we walk over two sorted trees to find
which entries are missing or have different content between
the two. So if we have two trees with these entries:
one two
--- ---
a a
b c
c d
we'd expect the loop to:
- compare "a" to "a"
- compare "b" to "c"; because these are sorted lists, we
know that the second tree does not have "b"
- compare "c" to "c"
- compare "d" to end-of-list; we know that the first tree
does not have "d"
And prior to d8febde370 (match-trees: simplify score_trees()
using tree_entry(), 2013-03-24) that worked. But after that
commit, we mistakenly increment the tree pointers for every
loop iteration, even when we've processed the entry for only
one side. As a result, we end up doing this:
- compare "a" to "a"
- compare "b" to "c"; we know that we do not have "b", but
we still increment both tree pointers; at this point
we're out of sync and all further comparisons are wrong
- compare "c" to "d" and mistakenly claim that the second
tree does not have "c"
- exit the loop, mistakenly not realizing that the first
tree does not have "d"
So contrary to the claim in d8febde370, we really do need to
manually use update_tree_entry(), because advancing the tree
pointer depends on the entry comparison.
That means we must stop using tree_entry() to access each
entry, since it auto-advances the pointer. Instead:
- we'll use tree_desc.size directly to know if there's
anything left to look at (which is what tree_entry() was
doing under the hood)
- rather than do an extra struct assignment to "e1" and
"e2", we can just access the "entry" field of tree_desc
directly
That makes us a little more intimate with the tree_desc
code, but that's not uncommon for its callers.
The included test shows off the bug by adding a new entry
"bar.t", which sorts early in the tree and de-syncs the
comparison for "foo.t", which comes after.
Reported-by: George Shammas <georgyo@gmail.com>
Helped-by: René Scharfe <l.s.r@web.de>
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2018-08-02 21:58:21 +03:00
|
|
|
test_expect_success 'setup branch sub' '
|
|
|
|
git checkout --orphan sub &&
|
|
|
|
git rm -rf . &&
|
|
|
|
test_commit foo
|
|
|
|
'
|
|
|
|
|
2020-10-08 13:13:47 +03:00
|
|
|
test_expect_success 'setup topic branch' '
|
|
|
|
git checkout -b topic master &&
|
score_trees(): fix iteration over trees with missing entries
In score_trees(), we walk over two sorted trees to find
which entries are missing or have different content between
the two. So if we have two trees with these entries:
one two
--- ---
a a
b c
c d
we'd expect the loop to:
- compare "a" to "a"
- compare "b" to "c"; because these are sorted lists, we
know that the second tree does not have "b"
- compare "c" to "c"
- compare "d" to end-of-list; we know that the first tree
does not have "d"
And prior to d8febde370 (match-trees: simplify score_trees()
using tree_entry(), 2013-03-24) that worked. But after that
commit, we mistakenly increment the tree pointers for every
loop iteration, even when we've processed the entry for only
one side. As a result, we end up doing this:
- compare "a" to "a"
- compare "b" to "c"; we know that we do not have "b", but
we still increment both tree pointers; at this point
we're out of sync and all further comparisons are wrong
- compare "c" to "d" and mistakenly claim that the second
tree does not have "c"
- exit the loop, mistakenly not realizing that the first
tree does not have "d"
So contrary to the claim in d8febde370, we really do need to
manually use update_tree_entry(), because advancing the tree
pointer depends on the entry comparison.
That means we must stop using tree_entry() to access each
entry, since it auto-advances the pointer. Instead:
- we'll use tree_desc.size directly to know if there's
anything left to look at (which is what tree_entry() was
doing under the hood)
- rather than do an extra struct assignment to "e1" and
"e2", we can just access the "entry" field of tree_desc
directly
That makes us a little more intimate with the tree_desc
code, but that's not uncommon for its callers.
The included test shows off the bug by adding a new entry
"bar.t", which sorts early in the tree and de-syncs the
comparison for "foo.t", which comes after.
Reported-by: George Shammas <georgyo@gmail.com>
Helped-by: René Scharfe <l.s.r@web.de>
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2018-08-02 21:58:21 +03:00
|
|
|
git merge -s ours --no-commit --allow-unrelated-histories sub &&
|
|
|
|
git read-tree --prefix=dir/ -u sub &&
|
2020-10-08 13:13:47 +03:00
|
|
|
git commit -m "initial merge of sub into topic" &&
|
score_trees(): fix iteration over trees with missing entries
In score_trees(), we walk over two sorted trees to find
which entries are missing or have different content between
the two. So if we have two trees with these entries:
one two
--- ---
a a
b c
c d
we'd expect the loop to:
- compare "a" to "a"
- compare "b" to "c"; because these are sorted lists, we
know that the second tree does not have "b"
- compare "c" to "c"
- compare "d" to end-of-list; we know that the first tree
does not have "d"
And prior to d8febde370 (match-trees: simplify score_trees()
using tree_entry(), 2013-03-24) that worked. But after that
commit, we mistakenly increment the tree pointers for every
loop iteration, even when we've processed the entry for only
one side. As a result, we end up doing this:
- compare "a" to "a"
- compare "b" to "c"; we know that we do not have "b", but
we still increment both tree pointers; at this point
we're out of sync and all further comparisons are wrong
- compare "c" to "d" and mistakenly claim that the second
tree does not have "c"
- exit the loop, mistakenly not realizing that the first
tree does not have "d"
So contrary to the claim in d8febde370, we really do need to
manually use update_tree_entry(), because advancing the tree
pointer depends on the entry comparison.
That means we must stop using tree_entry() to access each
entry, since it auto-advances the pointer. Instead:
- we'll use tree_desc.size directly to know if there's
anything left to look at (which is what tree_entry() was
doing under the hood)
- rather than do an extra struct assignment to "e1" and
"e2", we can just access the "entry" field of tree_desc
directly
That makes us a little more intimate with the tree_desc
code, but that's not uncommon for its callers.
The included test shows off the bug by adding a new entry
"bar.t", which sorts early in the tree and de-syncs the
comparison for "foo.t", which comes after.
Reported-by: George Shammas <georgyo@gmail.com>
Helped-by: René Scharfe <l.s.r@web.de>
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2018-08-02 21:58:21 +03:00
|
|
|
test_path_is_file dir/foo.t &&
|
|
|
|
test_path_is_file hello
|
|
|
|
'
|
|
|
|
|
|
|
|
test_expect_success 'update branch sub' '
|
|
|
|
git checkout sub &&
|
|
|
|
test_commit bar
|
|
|
|
'
|
|
|
|
|
2020-10-08 13:13:47 +03:00
|
|
|
test_expect_success 'update topic branch' '
|
|
|
|
git checkout topic &&
|
|
|
|
git merge -s subtree sub -m "second merge of sub into topic" &&
|
score_trees(): fix iteration over trees with missing entries
In score_trees(), we walk over two sorted trees to find
which entries are missing or have different content between
the two. So if we have two trees with these entries:
one two
--- ---
a a
b c
c d
we'd expect the loop to:
- compare "a" to "a"
- compare "b" to "c"; because these are sorted lists, we
know that the second tree does not have "b"
- compare "c" to "c"
- compare "d" to end-of-list; we know that the first tree
does not have "d"
And prior to d8febde370 (match-trees: simplify score_trees()
using tree_entry(), 2013-03-24) that worked. But after that
commit, we mistakenly increment the tree pointers for every
loop iteration, even when we've processed the entry for only
one side. As a result, we end up doing this:
- compare "a" to "a"
- compare "b" to "c"; we know that we do not have "b", but
we still increment both tree pointers; at this point
we're out of sync and all further comparisons are wrong
- compare "c" to "d" and mistakenly claim that the second
tree does not have "c"
- exit the loop, mistakenly not realizing that the first
tree does not have "d"
So contrary to the claim in d8febde370, we really do need to
manually use update_tree_entry(), because advancing the tree
pointer depends on the entry comparison.
That means we must stop using tree_entry() to access each
entry, since it auto-advances the pointer. Instead:
- we'll use tree_desc.size directly to know if there's
anything left to look at (which is what tree_entry() was
doing under the hood)
- rather than do an extra struct assignment to "e1" and
"e2", we can just access the "entry" field of tree_desc
directly
That makes us a little more intimate with the tree_desc
code, but that's not uncommon for its callers.
The included test shows off the bug by adding a new entry
"bar.t", which sorts early in the tree and de-syncs the
comparison for "foo.t", which comes after.
Reported-by: George Shammas <georgyo@gmail.com>
Helped-by: René Scharfe <l.s.r@web.de>
Signed-off-by: Jeff King <peff@peff.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2018-08-02 21:58:21 +03:00
|
|
|
test_path_is_file dir/bar.t &&
|
|
|
|
test_path_is_file dir/foo.t &&
|
|
|
|
test_path_is_file hello
|
|
|
|
'
|
|
|
|
|
2008-02-28 15:36:54 +03:00
|
|
|
test_expect_success 'setup' '
|
|
|
|
mkdir git-gui &&
|
|
|
|
cd git-gui &&
|
|
|
|
git init &&
|
|
|
|
echo git-gui > git-gui.sh &&
|
|
|
|
o1=$(git hash-object git-gui.sh) &&
|
|
|
|
git add git-gui.sh &&
|
|
|
|
git commit -m "initial git-gui" &&
|
|
|
|
cd .. &&
|
|
|
|
mkdir git &&
|
|
|
|
cd git &&
|
|
|
|
git init &&
|
|
|
|
echo git >git.c &&
|
|
|
|
o2=$(git hash-object git.c) &&
|
|
|
|
git add git.c &&
|
|
|
|
git commit -m "initial git"
|
|
|
|
'
|
|
|
|
|
|
|
|
test_expect_success 'initial merge' '
|
|
|
|
git remote add -f gui ../git-gui &&
|
merge: refuse to create too cool a merge by default
While it makes sense to allow merging unrelated histories of two
projects that started independently into one, in the way "gitk" was
merged to "git" itself aka "the coolest merge ever", such a merge is
still an unusual event. Worse, if somebody creates an independent
history by starting from a tarball of an established project and
sends a pull request to the original project, "git merge" however
happily creates such a merge without any sign of something unusual
is happening.
Teach "git merge" to refuse to create such a merge by default,
unless the user passes a new "--allow-unrelated-histories" option to
tell it that the user is aware that two unrelated projects are
merged.
Because such a "two project merge" is a rare event, a configuration
option to always allow such a merge is not added.
We could add the same option to "git pull" and have it passed
through to underlying "git merge". I do not have a fundamental
opposition against such a feature, but this commit does not do so
and instead leaves it as low-hanging fruit for others, because such
a "two project merge" would be done after fetching the other project
into some location in the working tree of an existing project and
making sure how well they fit together, it is sufficient to allow a
local merge without such an option pass-through from "git pull" to
"git merge". Many tests that are updated by this patch does the
pass-through manually by turning:
git pull something
into its equivalent:
git fetch something &&
git merge --allow-unrelated-histories FETCH_HEAD
If somebody is inclined to add such an option, updated tests in this
change need to be adjusted back to:
git pull --allow-unrelated-histories something
Signed-off-by: Junio C Hamano <gitster@pobox.com>
2016-03-18 23:21:09 +03:00
|
|
|
git merge -s ours --no-commit --allow-unrelated-histories gui/master &&
|
2008-02-28 15:36:54 +03:00
|
|
|
git read-tree --prefix=git-gui/ -u gui/master &&
|
|
|
|
git commit -m "Merge git-gui as our subdirectory" &&
|
2009-11-26 05:23:59 +03:00
|
|
|
git checkout -b work &&
|
2008-02-28 15:36:54 +03:00
|
|
|
git ls-files -s >actual &&
|
|
|
|
(
|
2018-07-02 03:24:02 +03:00
|
|
|
echo "100644 $o1 0 git-gui/git-gui.sh" &&
|
2008-02-28 15:36:54 +03:00
|
|
|
echo "100644 $o2 0 git.c"
|
|
|
|
) >expected &&
|
2008-05-24 09:28:56 +04:00
|
|
|
test_cmp expected actual
|
2008-02-28 15:36:54 +03:00
|
|
|
'
|
|
|
|
|
|
|
|
test_expect_success 'merge update' '
|
|
|
|
cd ../git-gui &&
|
|
|
|
echo git-gui2 > git-gui.sh &&
|
|
|
|
o3=$(git hash-object git-gui.sh) &&
|
|
|
|
git add git-gui.sh &&
|
2020-09-27 00:04:21 +03:00
|
|
|
git checkout -b topic_2 &&
|
2008-02-28 15:36:54 +03:00
|
|
|
git commit -m "update git-gui" &&
|
|
|
|
cd ../git &&
|
2020-09-27 00:04:21 +03:00
|
|
|
git pull -s subtree gui topic_2 &&
|
2008-02-28 15:36:54 +03:00
|
|
|
git ls-files -s >actual &&
|
|
|
|
(
|
2018-07-02 03:24:02 +03:00
|
|
|
echo "100644 $o3 0 git-gui/git-gui.sh" &&
|
2008-02-28 15:36:54 +03:00
|
|
|
echo "100644 $o2 0 git.c"
|
|
|
|
) >expected &&
|
2008-05-24 09:28:56 +04:00
|
|
|
test_cmp expected actual
|
2008-02-28 15:36:54 +03:00
|
|
|
'
|
|
|
|
|
2009-11-26 05:23:59 +03:00
|
|
|
test_expect_success 'initial ambiguous subtree' '
|
|
|
|
cd ../git &&
|
|
|
|
git reset --hard master &&
|
2020-09-27 00:04:21 +03:00
|
|
|
git checkout -b topic_2 &&
|
2009-11-26 05:23:59 +03:00
|
|
|
git merge -s ours --no-commit gui/master &&
|
|
|
|
git read-tree --prefix=git-gui2/ -u gui/master &&
|
|
|
|
git commit -m "Merge git-gui2 as our subdirectory" &&
|
|
|
|
git checkout -b work2 &&
|
|
|
|
git ls-files -s >actual &&
|
|
|
|
(
|
2018-07-02 03:24:02 +03:00
|
|
|
echo "100644 $o1 0 git-gui/git-gui.sh" &&
|
|
|
|
echo "100644 $o1 0 git-gui2/git-gui.sh" &&
|
2009-11-26 05:23:59 +03:00
|
|
|
echo "100644 $o2 0 git.c"
|
|
|
|
) >expected &&
|
|
|
|
test_cmp expected actual
|
|
|
|
'
|
|
|
|
|
|
|
|
test_expect_success 'merge using explicit' '
|
|
|
|
cd ../git &&
|
2020-09-27 00:04:21 +03:00
|
|
|
git reset --hard topic_2 &&
|
|
|
|
git pull -Xsubtree=git-gui gui topic_2 &&
|
2009-11-26 05:23:59 +03:00
|
|
|
git ls-files -s >actual &&
|
|
|
|
(
|
2018-07-02 03:24:02 +03:00
|
|
|
echo "100644 $o3 0 git-gui/git-gui.sh" &&
|
|
|
|
echo "100644 $o1 0 git-gui2/git-gui.sh" &&
|
2009-11-26 05:23:59 +03:00
|
|
|
echo "100644 $o2 0 git.c"
|
|
|
|
) >expected &&
|
|
|
|
test_cmp expected actual
|
|
|
|
'
|
|
|
|
|
|
|
|
test_expect_success 'merge2 using explicit' '
|
|
|
|
cd ../git &&
|
2020-09-27 00:04:21 +03:00
|
|
|
git reset --hard topic_2 &&
|
|
|
|
git pull -Xsubtree=git-gui2 gui topic_2 &&
|
2009-11-26 05:23:59 +03:00
|
|
|
git ls-files -s >actual &&
|
|
|
|
(
|
2018-07-02 03:24:02 +03:00
|
|
|
echo "100644 $o1 0 git-gui/git-gui.sh" &&
|
|
|
|
echo "100644 $o3 0 git-gui2/git-gui.sh" &&
|
2009-11-26 05:23:59 +03:00
|
|
|
echo "100644 $o2 0 git.c"
|
|
|
|
) >expected &&
|
|
|
|
test_cmp expected actual
|
|
|
|
'
|
|
|
|
|
2008-02-23 22:08:25 +03:00
|
|
|
test_done
|