1 Star 0 Fork 0

小笼包/git

加入 Gitee
与超过 1400万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
克隆/下载
t6426-merge-skip-unneeded-updates.sh 17.88 KB
一键复制 编辑 原始数据 按行查看 历史
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779
#!/bin/sh
test_description="merge cases"
# The setup for all of them, pictorially, is:
#
# A
# o
# / \
# O o ?
# \ /
# o
# B
#
# To help make it easier to follow the flow of tests, they have been
# divided into sections and each test will start with a quick explanation
# of what commits O, A, and B contain.
#
# Notation:
# z/{b,c} means files z/b and z/c both exist
# x/d_1 means file x/d exists with content d1. (Purpose of the
# underscore notation is to differentiate different
# files that might be renamed into each other's paths.)
. ./test-lib.sh
. "$TEST_DIRECTORY"/lib-merge.sh
###########################################################################
# SECTION 1: Cases involving no renames (one side has subset of changes of
# the other side)
###########################################################################
# Testcase 1a, Changes on A, subset of changes on B
# Commit O: b_1
# Commit A: b_2
# Commit B: b_3
# Expected: b_2
test_setup_1a () {
test_create_repo 1a_$1 &&
(
cd 1a_$1 &&
test_write_lines 1 2 3 4 5 6 7 8 9 10 >b &&
git add b &&
test_tick &&
git commit -m "O" &&
git branch O &&
git branch A &&
git branch B &&
git checkout A &&
test_write_lines 1 2 3 4 5 5.5 6 7 8 9 10 10.5 >b &&
git add b &&
test_tick &&
git commit -m "A" &&
git checkout B &&
test_write_lines 1 2 3 4 5 5.5 6 7 8 9 10 >b &&
git add b &&
test_tick &&
git commit -m "B"
)
}
test_expect_success '1a-L: Modify(A)/Modify(B), change on B subset of A' '
test_setup_1a L &&
(
cd 1a_L &&
git checkout A^0 &&
test-tool chmtime --get -3600 b >old-mtime &&
GIT_MERGE_VERBOSITY=3 git merge -s recursive B^0 >out 2>err &&
test_must_be_empty err &&
# Make sure b was NOT updated
test-tool chmtime --get b >new-mtime &&
test_cmp old-mtime new-mtime &&
git ls-files -s >index_files &&
test_line_count = 1 index_files &&
git rev-parse >actual HEAD:b &&
git rev-parse >expect A:b &&
test_cmp expect actual &&
git hash-object b >actual &&
git rev-parse A:b >expect &&
test_cmp expect actual
)
'
test_expect_success '1a-R: Modify(A)/Modify(B), change on B subset of A' '
test_setup_1a R &&
(
cd 1a_R &&
git checkout B^0 &&
test-tool chmtime --get -3600 b >old-mtime &&
GIT_MERGE_VERBOSITY=3 git merge -s recursive A^0 >out 2>err &&
# Make sure b WAS updated
test-tool chmtime --get b >new-mtime &&
test $(cat old-mtime) -lt $(cat new-mtime) &&
test_must_be_empty err &&
git ls-files -s >index_files &&
test_line_count = 1 index_files &&
git rev-parse >actual HEAD:b &&
git rev-parse >expect A:b &&
test_cmp expect actual &&
git hash-object b >actual &&
git rev-parse A:b >expect &&
test_cmp expect actual
)
'
###########################################################################
# SECTION 2: Cases involving basic renames
###########################################################################
# Testcase 2a, Changes on A, rename on B
# Commit O: b_1
# Commit A: b_2
# Commit B: c_1
# Expected: c_2
test_setup_2a () {
test_create_repo 2a_$1 &&
(
cd 2a_$1 &&
test_seq 1 10 >b &&
git add b &&
test_tick &&
git commit -m "O" &&
git branch O &&
git branch A &&
git branch B &&
git checkout A &&
test_seq 1 11 >b &&
git add b &&
test_tick &&
git commit -m "A" &&
git checkout B &&
git mv b c &&
test_tick &&
git commit -m "B"
)
}
test_expect_success '2a-L: Modify/rename, merge into modify side' '
test_setup_2a L &&
(
cd 2a_L &&
git checkout A^0 &&
test_path_is_missing c &&
GIT_MERGE_VERBOSITY=3 git merge -s recursive B^0 >out 2>err &&
test_path_is_file c &&
git ls-files -s >index_files &&
test_line_count = 1 index_files &&
git rev-parse >actual HEAD:c &&
git rev-parse >expect A:b &&
test_cmp expect actual &&
git hash-object c >actual &&
git rev-parse A:b >expect &&
test_cmp expect actual &&
test_must_fail git rev-parse HEAD:b &&
test_path_is_missing b
)
'
test_expect_success '2a-R: Modify/rename, merge into rename side' '
test_setup_2a R &&
(
cd 2a_R &&
git checkout B^0 &&
test-tool chmtime --get -3600 c >old-mtime &&
GIT_MERGE_VERBOSITY=3 git merge -s recursive A^0 >out 2>err &&
# Make sure c WAS updated
test-tool chmtime --get c >new-mtime &&
test $(cat old-mtime) -lt $(cat new-mtime) &&
test_must_be_empty err &&
git ls-files -s >index_files &&
test_line_count = 1 index_files &&
git rev-parse >actual HEAD:c &&
git rev-parse >expect A:b &&
test_cmp expect actual &&
git hash-object c >actual &&
git rev-parse A:b >expect &&
test_cmp expect actual &&
test_must_fail git rev-parse HEAD:b &&
test_path_is_missing b
)
'
# Testcase 2b, Changed and renamed on A, subset of changes on B
# Commit O: b_1
# Commit A: c_2
# Commit B: b_3
# Expected: c_2
test_setup_2b () {
test_create_repo 2b_$1 &&
(
cd 2b_$1 &&
test_write_lines 1 2 3 4 5 6 7 8 9 10 >b &&
git add b &&
test_tick &&
git commit -m "O" &&
git branch O &&
git branch A &&
git branch B &&
git checkout A &&
test_write_lines 1 2 3 4 5 5.5 6 7 8 9 10 10.5 >b &&
git add b &&
git mv b c &&
test_tick &&
git commit -m "A" &&
git checkout B &&
test_write_lines 1 2 3 4 5 5.5 6 7 8 9 10 >b &&
git add b &&
test_tick &&
git commit -m "B"
)
}
test_expect_success '2b-L: Rename+Mod(A)/Mod(B), B mods subset of A' '
test_setup_2b L &&
(
cd 2b_L &&
git checkout A^0 &&
test-tool chmtime --get -3600 c >old-mtime &&
GIT_MERGE_VERBOSITY=3 git merge -s recursive B^0 >out 2>err &&
test_must_be_empty err &&
# Make sure c WAS updated
test-tool chmtime --get c >new-mtime &&
test_cmp old-mtime new-mtime &&
git ls-files -s >index_files &&
test_line_count = 1 index_files &&
git rev-parse >actual HEAD:c &&
git rev-parse >expect A:c &&
test_cmp expect actual &&
git hash-object c >actual &&
git rev-parse A:c >expect &&
test_cmp expect actual &&
test_must_fail git rev-parse HEAD:b &&
test_path_is_missing b
)
'
test_expect_success '2b-R: Rename+Mod(A)/Mod(B), B mods subset of A' '
test_setup_2b R &&
(
cd 2b_R &&
git checkout B^0 &&
test_path_is_missing c &&
GIT_MERGE_VERBOSITY=3 git merge -s recursive A^0 >out 2>err &&
# Make sure c now present (and thus was updated)
test_path_is_file c &&
test_must_be_empty err &&
git ls-files -s >index_files &&
test_line_count = 1 index_files &&
git rev-parse >actual HEAD:c &&
git rev-parse >expect A:c &&
test_cmp expect actual &&
git hash-object c >actual &&
git rev-parse A:c >expect &&
test_cmp expect actual &&
test_must_fail git rev-parse HEAD:b &&
test_path_is_missing b
)
'
# Testcase 2c, Changes on A, rename on B
# Commit O: b_1
# Commit A: b_2, c_3
# Commit B: c_1
# Expected: rename/add conflict c_2 vs c_3
#
# NOTE: Since A modified b_1->b_2, and B renamed b_1->c_1, the threeway
# merge of those files should result in c_2. We then should have a
# rename/add conflict between c_2 and c_3. However, if we note in
# merge_content() that A had the right contents (b_2 has same
# contents as c_2, just at a different name), and that A had the
# right path present (c_3 existed) and thus decides that it can
# skip the update, then we're in trouble. This test verifies we do
# not make that particular mistake.
test_setup_2c () {
test_create_repo 2c &&
(
cd 2c &&
test_seq 1 10 >b &&
git add b &&
test_tick &&
git commit -m "O" &&
git branch O &&
git branch A &&
git branch B &&
git checkout A &&
test_seq 1 11 >b &&
echo whatever >c &&
git add b c &&
test_tick &&
git commit -m "A" &&
git checkout B &&
git mv b c &&
test_tick &&
git commit -m "B"
)
}
test_expect_success '2c: Modify b & add c VS rename b->c' '
test_setup_2c &&
(
cd 2c &&
git checkout A^0 &&
test-tool chmtime --get -3600 c >old-mtime &&
GIT_MERGE_VERBOSITY=3 &&
export GIT_MERGE_VERBOSITY &&
test_must_fail git merge -s recursive B^0 >out 2>err &&
test_i18ngrep "CONFLICT (.*/add):" out &&
test_must_be_empty err &&
# Make sure c WAS updated
test-tool chmtime --get c >new-mtime &&
test $(cat old-mtime) -lt $(cat new-mtime)
# FIXME: rename/add conflicts are horribly broken right now;
# when I get back to my patch series fixing it and
# rename/rename(2to1) conflicts to bring them in line with
# how add/add conflicts behave, then checks like the below
# could be added. But that patch series is waiting until
# the rename-directory-detection series lands, which this
# is part of. And in the mean time, I do not want to further
# enforce broken behavior. So for now, the main test is the
# one above that err is an empty file.
#git ls-files -s >index_files &&
#test_line_count = 2 index_files &&
#git rev-parse >actual :2:c :3:c &&
#git rev-parse >expect A:b A:c &&
#test_cmp expect actual &&
#git cat-file -p A:b >>merged &&
#git cat-file -p A:c >>merge-me &&
#>empty &&
#test_must_fail git merge-file \
# -L "Temporary merge branch 1" \
# -L "" \
# -L "Temporary merge branch 2" \
# merged empty merge-me &&
#sed -e "s/^\([<=>]\)/\1\1\1/" merged >merged-internal &&
#git hash-object c >actual &&
#git hash-object merged-internal >expect &&
#test_cmp expect actual &&
#test_path_is_missing b
)
'
###########################################################################
# SECTION 3: Cases involving directory renames
#
# NOTE:
# Directory renames only apply when one side renames a directory, and the
# other side adds or renames a path into that directory. Applying the
# directory rename to that new path creates a new pathname that didn't
# exist on either side of history. Thus, it is impossible for the
# merge contents to already be at the right path, so all of these checks
# exist just to make sure that updates are not skipped.
###########################################################################
# Testcase 3a, Change + rename into dir foo on A, dir rename foo->bar on B
# Commit O: bq_1, foo/whatever
# Commit A: foo/{bq_2, whatever}
# Commit B: bq_1, bar/whatever
# Expected: bar/{bq_2, whatever}
test_setup_3a () {
test_create_repo 3a_$1 &&
(
cd 3a_$1 &&
mkdir foo &&
test_seq 1 10 >bq &&
test_write_lines a b c d e f g h i j k >foo/whatever &&
git add bq foo/whatever &&
test_tick &&
git commit -m "O" &&
git branch O &&
git branch A &&
git branch B &&
git checkout A &&
test_seq 1 11 >bq &&
git add bq &&
git mv bq foo/ &&
test_tick &&
git commit -m "A" &&
git checkout B &&
git mv foo/ bar/ &&
test_tick &&
git commit -m "B"
)
}
test_expect_success '3a-L: bq_1->foo/bq_2 on A, foo/->bar/ on B' '
test_setup_3a L &&
(
cd 3a_L &&
git checkout A^0 &&
test_path_is_missing bar/bq &&
GIT_MERGE_VERBOSITY=3 git -c merge.directoryRenames=true merge -s recursive B^0 >out 2>err &&
test_must_be_empty err &&
test_path_is_file bar/bq &&
git ls-files -s >index_files &&
test_line_count = 2 index_files &&
git rev-parse >actual HEAD:bar/bq HEAD:bar/whatever &&
git rev-parse >expect A:foo/bq A:foo/whatever &&
test_cmp expect actual &&
git hash-object bar/bq bar/whatever >actual &&
git rev-parse A:foo/bq A:foo/whatever >expect &&
test_cmp expect actual &&
test_must_fail git rev-parse HEAD:bq HEAD:foo/bq &&
test_path_is_missing bq &&
test_path_is_missing foo/bq &&
test_path_is_missing foo/whatever
)
'
test_expect_success '3a-R: bq_1->foo/bq_2 on A, foo/->bar/ on B' '
test_setup_3a R &&
(
cd 3a_R &&
git checkout B^0 &&
test_path_is_missing bar/bq &&
GIT_MERGE_VERBOSITY=3 git -c merge.directoryRenames=true merge -s recursive A^0 >out 2>err &&
test_must_be_empty err &&
test_path_is_file bar/bq &&
git ls-files -s >index_files &&
test_line_count = 2 index_files &&
git rev-parse >actual HEAD:bar/bq HEAD:bar/whatever &&
git rev-parse >expect A:foo/bq A:foo/whatever &&
test_cmp expect actual &&
git hash-object bar/bq bar/whatever >actual &&
git rev-parse A:foo/bq A:foo/whatever >expect &&
test_cmp expect actual &&
test_must_fail git rev-parse HEAD:bq HEAD:foo/bq &&
test_path_is_missing bq &&
test_path_is_missing foo/bq &&
test_path_is_missing foo/whatever
)
'
# Testcase 3b, rename into dir foo on A, dir rename foo->bar + change on B
# Commit O: bq_1, foo/whatever
# Commit A: foo/{bq_1, whatever}
# Commit B: bq_2, bar/whatever
# Expected: bar/{bq_2, whatever}
test_setup_3b () {
test_create_repo 3b_$1 &&
(
cd 3b_$1 &&
mkdir foo &&
test_seq 1 10 >bq &&
test_write_lines a b c d e f g h i j k >foo/whatever &&
git add bq foo/whatever &&
test_tick &&
git commit -m "O" &&
git branch O &&
git branch A &&
git branch B &&
git checkout A &&
git mv bq foo/ &&
test_tick &&
git commit -m "A" &&
git checkout B &&
test_seq 1 11 >bq &&
git add bq &&
git mv foo/ bar/ &&
test_tick &&
git commit -m "B"
)
}
test_expect_success '3b-L: bq_1->foo/bq_2 on A, foo/->bar/ on B' '
test_setup_3b L &&
(
cd 3b_L &&
git checkout A^0 &&
test_path_is_missing bar/bq &&
GIT_MERGE_VERBOSITY=3 git -c merge.directoryRenames=true merge -s recursive B^0 >out 2>err &&
test_must_be_empty err &&
test_path_is_file bar/bq &&
git ls-files -s >index_files &&
test_line_count = 2 index_files &&
git rev-parse >actual HEAD:bar/bq HEAD:bar/whatever &&
git rev-parse >expect B:bq A:foo/whatever &&
test_cmp expect actual &&
git hash-object bar/bq bar/whatever >actual &&
git rev-parse B:bq A:foo/whatever >expect &&
test_cmp expect actual &&
test_must_fail git rev-parse HEAD:bq HEAD:foo/bq &&
test_path_is_missing bq &&
test_path_is_missing foo/bq &&
test_path_is_missing foo/whatever
)
'
test_expect_success '3b-R: bq_1->foo/bq_2 on A, foo/->bar/ on B' '
test_setup_3b R &&
(
cd 3b_R &&
git checkout B^0 &&
test_path_is_missing bar/bq &&
GIT_MERGE_VERBOSITY=3 git -c merge.directoryRenames=true merge -s recursive A^0 >out 2>err &&
test_must_be_empty err &&
test_path_is_file bar/bq &&
git ls-files -s >index_files &&
test_line_count = 2 index_files &&
git rev-parse >actual HEAD:bar/bq HEAD:bar/whatever &&
git rev-parse >expect B:bq A:foo/whatever &&
test_cmp expect actual &&
git hash-object bar/bq bar/whatever >actual &&
git rev-parse B:bq A:foo/whatever >expect &&
test_cmp expect actual &&
test_must_fail git rev-parse HEAD:bq HEAD:foo/bq &&
test_path_is_missing bq &&
test_path_is_missing foo/bq &&
test_path_is_missing foo/whatever
)
'
###########################################################################
# SECTION 4: Cases involving dirty changes
###########################################################################
# Testcase 4a, Changed on A, subset of changes on B, locally modified
# Commit O: b_1
# Commit A: b_2
# Commit B: b_3
# Working copy: b_4
# Expected: b_2 for merge, b_4 in working copy
test_setup_4a () {
test_create_repo 4a &&
(
cd 4a &&
test_write_lines 1 2 3 4 5 6 7 8 9 10 >b &&
git add b &&
test_tick &&
git commit -m "O" &&
git branch O &&
git branch A &&
git branch B &&
git checkout A &&
test_write_lines 1 2 3 4 5 5.5 6 7 8 9 10 10.5 >b &&
git add b &&
test_tick &&
git commit -m "A" &&
git checkout B &&
test_write_lines 1 2 3 4 5 5.5 6 7 8 9 10 >b &&
git add b &&
test_tick &&
git commit -m "B"
)
}
# NOTE: For as long as we continue using unpack_trees() without index_only
# set to true, it will error out on a case like this claiming that the locally
# modified file would be overwritten by the merge. Getting this testcase
# correct requires doing the merge in-memory first, then realizing that no
# updates to the file are necessary, and thus that we can just leave the path
# alone.
test_expect_merge_algorithm failure success '4a: Change on A, change on B subset of A, dirty mods present' '
test_setup_4a &&
(
cd 4a &&
git checkout A^0 &&
echo "File rewritten" >b &&
test-tool chmtime --get -3600 b >old-mtime &&
GIT_MERGE_VERBOSITY=3 git merge -s recursive B^0 >out 2>err &&
test_must_be_empty err &&
# Make sure b was NOT updated
test-tool chmtime --get b >new-mtime &&
test_cmp old-mtime new-mtime &&
git ls-files -s >index_files &&
test_line_count = 1 index_files &&
git rev-parse >actual :0:b &&
git rev-parse >expect A:b &&
test_cmp expect actual &&
git hash-object b >actual &&
echo "File rewritten" | git hash-object --stdin >expect &&
test_cmp expect actual
)
'
# Testcase 4b, Changed+renamed on A, subset of changes on B, locally modified
# Commit O: b_1
# Commit A: c_2
# Commit B: b_3
# Working copy: c_4
# Expected: c_2
test_setup_4b () {
test_create_repo 4b &&
(
cd 4b &&
test_write_lines 1 2 3 4 5 6 7 8 9 10 >b &&
git add b &&
test_tick &&
git commit -m "O" &&
git branch O &&
git branch A &&
git branch B &&
git checkout A &&
test_write_lines 1 2 3 4 5 5.5 6 7 8 9 10 10.5 >b &&
git add b &&
git mv b c &&
test_tick &&
git commit -m "A" &&
git checkout B &&
test_write_lines 1 2 3 4 5 5.5 6 7 8 9 10 >b &&
git add b &&
test_tick &&
git commit -m "B"
)
}
test_expect_success '4b: Rename+Mod(A)/Mod(B), change on B subset of A, dirty mods present' '
test_setup_4b &&
(
cd 4b &&
git checkout A^0 &&
echo "File rewritten" >c &&
test-tool chmtime --get -3600 c >old-mtime &&
GIT_MERGE_VERBOSITY=3 git merge -s recursive B^0 >out 2>err &&
test_must_be_empty err &&
# Make sure c was NOT updated
test-tool chmtime --get c >new-mtime &&
test_cmp old-mtime new-mtime &&
git ls-files -s >index_files &&
test_line_count = 1 index_files &&
git rev-parse >actual :0:c &&
git rev-parse >expect A:c &&
test_cmp expect actual &&
git hash-object c >actual &&
echo "File rewritten" | git hash-object --stdin >expect &&
test_cmp expect actual &&
test_must_fail git rev-parse HEAD:b &&
test_path_is_missing b
)
'
test_done
Loading...
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
1
https://gitee.com/xiaobaola/git.git
git@gitee.com:xiaobaola/git.git
xiaobaola
git
git
main

搜索帮助