{"thread":{"id":"36417","subject":"[RFC] t7410: 210 tests for various 'git submodule update' scenarios","startedAt":"2014-04-16T00:54:48Z","lastAt":"2014-04-17T16:04:42Z","messageCount":5,"participants":["Johan Herland","W. Trevor King","Jens Lehmann"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"238913","messageId":"1397609688-25634-1-git-send-email-johan@herland.net","threadId":"36417","inReplyTo":null,"subject":"[RFC] t7410: 210 tests for various 'git submodule update' scenarios","fromName":"Johan Herland","fromEmail":"johan@herland.net","sentAt":"2014-04-16T00:54:48Z","receivedAt":"2014-04-16T00:54:48Z","isPatch":false,"sender":{"key":"johan@herland.net","avatar":"https://avatars.githubusercontent.com/u/547031?v=4"},"body":"This is a work-in-progress to flesh out (and promote discussion about)\nthe expected behaviors for all possible scenarios in which\n'git submodule update' might be run.\n\nMore details in the top of t/t7410-submodule-update-scenarios.sh\n\nCc: W. Trevor King <wking@tremily.us>\nCc: Jens Lehmann <Jens.Lehmann@web.de>\nCc: Heiko Voigt <hvoigt@hvoigt.net>\nCc: Junio C Hamano <gitster@pobox.com>\n\n---\n\nHi,\n\nThis started as an exercise for myself to figure out all the various\ncorner cases under which \"git submodule update\" may be run. Then, as I\nfound some cases where the current behavior was not immediately obvious\nto me, and some other cases where the current behaviour is likely buggy\nand/or Wrong(tm), I figured these tests might serve as a backdrop for a\ncloser discussion of those cases.\n\nI've attempted to include all variables/axes that combine to directly\naffect the behavior of 'submodule update'. I've excluded some variables\nwhose effect on 'submodule update' is completely orthogonal/independent\n(i.e. how 'submodule update' is affected by unstaged/uncommitted\nchanges in the submodule). That said, there might be more variables\nthat I have missed in my analysis...\n\nI've attempted to split the areas to be discussed into 3 todo items and\n7 discussion items (labeled T1 - T3. and D1 - D7, respectively), and\nI've cross-referenced them to the specific test cases that are affected\nby each todo/discussion item.\n\nI'll leave it up to Jens and Junio to determine whether this patch\nis worth applying or not. There is certainly considerable overlap\nbetween these tests and existing tests for 'submodule update'. There's\nalso plenty of room for refactoring and deduplication in this file,\nitself, although I hope the current format of the tests makes it fairly\neasy to see what is being tested, and what is the expected behavior.\n\nHave fun! :)\n\n...Johan\n\n\n t/t7410-submodule-update-scenarios.sh | 2859 +++++++++++++++++++++++++++++++++\n 1 file changed, 2859 insertions(+)\n create mode 100755 t/t7410-submodule-update-scenarios.sh\n\ndiff --git a/t/t7410-submodule-update-scenarios.sh b/t/t7410-submodule-update-scenarios.sh\nnew file mode 100755\nindex 0000000..22056cc\n--- /dev/null\n+++ b/t/t7410-submodule-update-scenarios.sh\n@@ -0,0 +1,2859 @@\n+#!/bin/sh\n+#\n+# Copyright (c) 2014 Johan Herland\n+#\n+\n+test_description='Test \"git submodule update\" in a variety of scenarios\n+\n+This test attempts to map out the various scenarios in which submodule update\n+is run, and verify their expected behaviour (according to the git submodule\n+documentation).\n+'\n+\n+. ./test-lib.sh\n+\n+# First a textual representation of the various cases we are testing:\n+#\n+# The factors/variables being explored are:\n+#  - submodule.sub.branch\n+#     1.* - unset\n+#     2.* - == foo (exists upstream)\n+#     3.* - == bar (MISSING upstream)\n+#  - submodule.sub.update\n+#     ?.1.* - none\n+#     ?.2.* - checkout\n+#     ?.3.* - merge\n+#     ?.4.* - rebase\n+#     ?.5.* - !command\n+#  - remote mode (whether or not --remote is given on command-line)\n+#     ?.?.1.* - disabled\n+#     ?.?.2.* - enabled\n+#  - current state of submodule:\n+#     ?.?.?.1 - not yet cloned\n+#     ?.?.?.2 - cloned, detached, HEAD == gitlink\n+#     ?.?.?.3 - cloned, detached, HEAD != gitlink\n+#     ?.?.?.4 - cloned, on branch foo (exists upstream), HEAD == gitlink\n+#     ?.?.?.5 - cloned, on branch foo (exists upstream), HEAD != gitlink\n+#     ?.?.?.6 - cloned, on branch bar (MISSING upstream), HEAD == gitlink\n+#     ?.?.?.7 - cloned, on branch bar (MISSING upstream), HEAD != gitlink\n+#\n+# The above variables are combined to enumerate all possible cases, from\n+# 1.1.1.1 to 3.5.2.7 (yes, that's 210 separate test cases). Each test case is\n+# named with its number followed by a short description of its expected outcome.\n+\n+# TODO ITEMS:\n+#\n+# T1: Rename \"master\" branch to \"default\" to test correct behaviour when\n+#     submodule's upstream has no master branch.\n+#     Affects: pre, 1.3.1.1, 1.3.2.1, 1.4.1.1, 1.4.2.1\n+#\n+# T2: Test with submodule.<name>.url != submodule's remote.origin.url. Does\n+#     \"submodule update --remote\" sync with submodule.<name>.url, or with the\n+#     submodule's origin? (or with the submodule's current branch's upstream)?\n+#\n+# T3: Fix uninitialized submodule state after attempting to clone from upstream\n+#     where .branch is missing.\n+#     Affects: pre, 3.2.2.1, 3.3.2.1, 3.4.2.1, 3.5.2.1\n+\n+# DISCUSSION ITEMS:\n+#\n+# D1: When submodule is already at right commit, checkout-mode currently does\n+#     nothing. Should it instead detach, even when no update is needed?\n+#     Affects: 1.2.1.4, 1.2.1.6, 2.2.1.4, 2.2.1.6, 3.2.1.4, 3.2.1.6\n+#\n+# D2: Should all/some of 1.3.*/1.4.* abort/error because we don't know what to\n+#     merge/rebase with (because .branch is unset)? Or is the current default\n+#     to origin/HEAD OK?\n+#     Affects: 1.3.*, 1.4.*\n+#\n+# D3: When submodule is already at right commit, merge/rebase-mode currently\n+#     does nothing. Should it do something else (e.g. not leave submodule\n+#     detached, or checked out on the \"wrong\" branch (i.e. != .branch))?\n+#     (This discussion point is related to D1, D5 and D6)\n+#     Affects: 1.3.1.2, 1.3.1.4, 1.3.1.6,\n+#              1.4.1.2, 1.4.1.4, 1.4.1.6,\n+#              2.3.1.2, 2.3.1.4, 2.3.1.6, 2.3.2.3, 2.3.2.5, 2.3.2.7,\n+#              2.4.1.2, 2.4.1.4, 2.4.1.6, 2.4.2.3, 2.4.2.5, 2.4.2.7,\n+#              3.3.1.2, 3.3.1.4, 3.3.1.6\n+#              3.4.1.2, 3.4.1.4, 3.4.1.6\n+#\n+# D4: When 'submodule update' performs a clone to populate a submodule, it\n+#     currently also creates a default branch (named after origin/HEAD) in\n+#     that submodule, EVEN WHEN THAT BRANCH WILL NEVER BE USED (e.g. because\n+#     we're in checkout-mode and submodule will always be detached). Is this\n+#     good, or should the clone performed by 'submodule update' skip the\n+#     automatic local branch creation?\n+#     Affects: 1.2.*.1, 1.3.*.1, 1.4.*.1, 1.5.*.1,\n+#              2.2.*.1, 2.3.*.1, 2.4.*.1, 2.5.*.1,\n+#              3.2.1.1, 3.3.1.1, 3.4.1.1, 3.5.1.1\n+#\n+# D5: When in merge/rebase-mode, and 'submodule update' actually ends up doing\n+#     a merge/rebase, that will happen on the current branch (or detached HEAD)\n+#     and NOT on the configured (or default) .branch. Is this OK? Should we\n+#     abort (or at least warn) instead? (In general, .branch seems only to\n+#     affect the submodule's HEAD when the submodule is first cloned.)\n+#     (This discussion point is related to D3 and D6)\n+#     Affects: 1.3.1.3, 1.3.1.5, 1.3.1.7, 1.3.2.>=2,\n+#              1.4.1.3, 1.4.1.5, 1.4.1.7, 1.4.2.>=2,\n+#              2.3.1.3, 2.3.1.5, 2.3.1.7, 2.3.2.2, 2.3.2.4, 2.3.2.6,\n+#              2.4.1.3, 2.4.1.5, 2.4.1.7, 2.4.2.2, 2.4.2.4, 2.4.2.6\n+#              3.3.1.3, 3.3.1.5, 3.3.1.7\n+#              3.4.1.3, 3.4.1.5, 3.4.1.7\n+#\n+# D6: The meaning of submodule.<name>.branch is initially confusing, as it does\n+#     not really concern the submodule's local branch (except as a naming hint\n+#     when the submodule is first cloned). Instead, submodule.<name>.branch is\n+#     really about which branch in the _upstream_ submodule (as defined by\n+#     submodule.<name>.url, or by the submodule's remote.origin.url?) that we\n+#     want to integrate with. This is probably the more useful setting, and it\n+#     becomes obviously correct after (re-)reading gitmodules(5) and\n+#     git-config(1). However, from just reading the \"update\" section in\n+#     git-submodule(1) (or not even that), things are not so clear-cut. Would\n+#     submodule.<name>.upstream (or .remote-branch, or similar) be a better\n+#     name for this?\n+#\n+# D7: What to do when .branch refers to a branch that is missing from upstream?\n+#     Currently, when trying to clone, the clone fails (which causes 'git\n+#     submodule update --remote' to fail), but leaves the submodule in an\n+#     uninitialized state (there is a .git, but the work tree is missing).\n+#     This is probably not the behavior we want...\n+#     Affects: pre, 3.2.2.1, 3.3.2.1, 3.4.2.1, 3.5.2.1\n+\n+# First, we need to setup the environment in which the test cases are run.\n+# This consists of an upstream super-repo containing a single submodule.\n+# The submodule commit graph looks like this:\n+#\n+#   $root_commit --->  $old_commit ---> $new_commit  <- master (HEAD) # T1\n+#                \\          ^- (superproject's gitlink points here)\n+#                 --> $foo_commit  <- foo\n+#\n+# Each test case then starts by cloning upstream_super -> super and setting up\n+# its submodule + configuration according to the current test case. It then\n+# runs \"git submodule update\" (with or without --remote) and verifies the\n+# expected results.\n+\n+test_expect_success 'preliminaries: setup upstream super and sub' '\n+\tgit init upstream_sub &&\n+\t(cd upstream_sub &&\n+\t test_commit root_commit &&\n+\t test_commit foo_commit &&\n+\t git branch foo &&\n+\t git reset --hard HEAD^ &&\n+#\t git branch -m default &&  # T1\n+\t test_commit old_commit\n+\t) &&\n+\tgit init upstream_super &&\n+\t(cd upstream_super &&\n+\t git submodule add ../upstream_sub sub &&\n+\t test_tick &&\n+\t git commit -m \"Add sub\"\n+\t) &&\n+\t(cd upstream_sub &&\n+\t test_commit new_commit\n+\t)\n+'\n+\n+# The following commit IDs are used in various test cases\n+root_commit=$(git -C upstream_sub rev-parse --verify -q root_commit)\n+foo_commit=$(git -C upstream_sub rev-parse --verify -q foo_commit)\n+old_commit=$(git -C upstream_sub rev-parse --verify -q old_commit)\n+new_commit=$(git -C upstream_sub rev-parse --verify -q new_commit)\n+\n+fail()\n+{\n+\techo \"$@\"\n+\tfalse\n+}\n+\n+# Verify that the path in $1 contains a cloned git repo\n+verify_is_cloned()\n+{\n+\ttest -e \"$1/.git\" ||\n+\t\tfail \"Failed to find cloned repo at '$1'\"\n+}\n+\n+# Verify that commit $2 in repo $1 has parents $3, $4, ... (in the given order).\n+verify_parents()\n+{\n+\trepo=$1; shift\n+\tcommit=$1; shift\n+\texpect_p=$@\n+\tactual_p=$(git --git-dir=\"$repo/.git\" log --format=%P -1 \"$commit\")\n+\ttest \"$expect_p\" = \"$actual_p\" ||\n+\t\tfail \"Expected $commit parents '$expect_p' != '$actual_p'\"\n+}\n+\n+# Verify that HEAD in repo $1 points to commit $2.\n+# If $2 is of the form 'parents.<SHA1>[.<SHA1>...]', then check that HEAD\n+# currently points to a commit whose parents are the given SHA1s (in order).\n+verify_head()\n+{\n+\thead=$(git --git-dir=\"$1/.git\" rev-parse -q HEAD)\n+\tcase \"$2\" in\n+\tparents.*)\n+\t\tparents=$(echo \"$2\" | sed -e 's/^parents\\.//' -e 's/\\./ /g')\n+\t\tverify_parents \"$1\" \"$head\" $parents ||\n+\t\t\tfail \"Failed to verify parents of HEAD in '$1'\"\n+\t\t;;\n+\t*)\n+\t\ttest \"$2\" = \"$head\" ||\n+\t\t\tfail \"Expected HEAD in '$1' to be '$2', but is '$head'\"\n+\tesac\n+}\n+\n+# Verify that the repo in $1 is currently checked out on branch $2.\n+# If $2 is \"detached\", verify that $1'a HEAD is in fact detached.\n+verify_branch()\n+{\n+\texpect=$2\n+\tif test \"$expect\" = \"detached\"\n+\tthen\n+\t\texpect=\n+\tfi\n+\tactual=$(git --git-dir=\"$1/.git\" symbolic-ref --short -q HEAD)\n+\ttest \"$expect\" = \"$actual\" ||\n+\t\tfail \"Expected branch in '$1' to be '$expect', but is '$actual'\"\n+}\n+\n+# Clone upstream_super to super, and run \"git submodule init\"\n+setup_super()\n+{\n+\trm -rf super &&\n+\tgit clone upstream_super super &&\n+\t(cd super &&\n+\t git submodule init &&\n+\t test_must_fail verify_is_cloned sub &&\n+\t test \"$(git rev-parse -q HEAD:sub)\" = \"$old_commit\"\n+\t)\n+}\n+\n+# Setup submodule.sub.branch == $1\n+# If $1 == \"unset\", ensure submodule.sub.branch is unset\n+setup_sub_branch()\n+{\n+\tif test \"$1\" = \"unset\"\n+\tthen\n+\t\tgit config --unset-all \"submodule.sub.branch\"\n+\t\ttest_must_fail git config \"submodule.sub.branch\" ||\n+\t\t\terror \"Failed to unset submodule.sub.branch\"\n+\telse\n+\t\tgit config \"submodule.sub.branch\" \"$1\"\n+\t\tactual=$(git config \"submodule.sub.branch\")\n+\t\ttest \"$actual\" = \"$1\" ||\n+\t\t\terror \"Failed to set submodule.sub.branch to '$1'\"\n+\tfi\n+}\n+\n+# Setup submodule.sub.update == $1\n+setup_sub_update()\n+{\n+\tgit config \"submodule.sub.update\" \"$1\"\n+\tactual=$(git config \"submodule.sub.update\")\n+\ttest \"$actual\" = \"$1\" ||\n+\t\terror \"Failed to set submodule.sub.update to '$1'\"\n+}\n+\n+# Setup the state of the sub submodule according to $1, which is one of:\n+#  - \"uncloned\" - sub is an empty dir.\n+#  - \"detach\" - sub is detached at the commit in $2.\n+#  - * - sub is checked out on branch named in $1, at the commit in $2.\n+setup_sub_state()\n+{\n+\tcase \"$1\" in\n+\tuncloned)\n+\t\ttest_must_fail verify_is_cloned sub ||\n+\t\t\terror \"Failed to verify uncloned sub\"\n+\t\t;;\n+\tdetach)\n+\t\tgit submodule update --checkout sub &&\n+\t\t(cd sub &&\n+\t\t git checkout \"$2\"\n+\t\t) &&\n+\t\tverify_is_cloned sub &&\n+\t\tverify_branch sub detached &&\n+\t\tverify_head sub \"$2\" ||\n+\t\t\terror \"Failed to detach sub at '$2'\"\n+\t\t;;\n+\t*)\n+\t\tgit submodule update --checkout sub &&\n+\t\t(cd sub &&\n+\t\t git checkout -b \"$1\" \"$2\"\n+\t\t) &&\n+\t\tverify_is_cloned sub &&\n+\t\tverify_branch sub \"$1\" &&\n+\t\tverify_head sub \"$2\" ||\n+\t\t\terror \"Failed to attach sub to '$1' at '$2'\"\n+\tesac\n+}\n+\n+# Verify the state of the sub submodule according to $1, which is one of:\n+#  - \"uncloned\" - sub is an empty dir.\n+#  - \"detach\" - sub is detached at the commit in $2.\n+#  - * - sub is checked out on branch named in $1, at the commit in $2.\n+# If $2 is of the form 'parents.<SHA1>[.<SHA1>...]', then check that HEAD\n+# currently points to a commit whose parents are the given SHA1s (in order).\n+verify_sub_state()\n+{\n+\tcase \"$1\" in\n+\tuncloned)\n+\t\ttest_must_fail verify_is_cloned sub ||\n+\t\t\tfail \"Failed to verify uncloned sub\"\n+\t\t;;\n+\tdetach)\n+\t\tverify_is_cloned sub &&\n+\t\tverify_branch sub detached &&\n+\t\tverify_head sub \"$2\" ||\n+\t\t\tfail \"Failed to verify detached sub at '$2'\"\n+\t\t;;\n+\t*)\n+\t\tverify_is_cloned sub &&\n+\t\tverify_branch sub \"$1\" &&\n+\t\tverify_head sub \"$2\" ||\n+\t\t\tfail \"Failed to verify attached sub at '$1' -> '$2'\"\n+\tesac\n+}\n+\n+verify_sub_patch_id()\n+{\n+\tp1=$(git --git-dir=sub/.git show $1 | git patch-id | cut -d' ' -f1)\n+\tp2=$(git --git-dir=sub/.git show $2 | git patch-id | cut -d' ' -f1)\n+\ttest \"$p1\" = \"$p2\" ||\n+\t\tfail \"'$1' and '$2' has different patch-ids ('$p1' != '$p2')\"\n+}\n+\n+# 1.1.* - .branch is unset, .update == none\n+\n+test_expect_success '1.1.1.1 - do nothing (.update == none)' '\n+\tsetup_super &&\n+\t(cd super &&\n+\t setup_sub_state uncloned &&\n+\t setup_sub_update none &&\n+\t setup_sub_branch unset &&\n+\t git submodule update &&\n+\t verify_sub_state uncloned\n+\t)\n+'\n+\n+test_expect_success '1.1.1.2 - do nothing (.update == none)' '\n+\tsetup_super &&\n+\t(cd super &&\n+\t setup_sub_state detach $old_commit &&\n+\t setup_sub_update none &&\n+\t setup_sub_branch unset &&\n+\t git submodule update &&\n+\t verify_sub_state detach $old_commit\n+\t)\n+'\n+\n+test_expect_success '1.1.1.3 - do nothing (.update == none)' '\n+\tsetup_super &&\n+\t(cd super &&\n+\t setup_sub_state detach $foo_commit &&\n+\t setup_sub_update none &&\n+\t setup_sub_branch unset &&\n+\t git submodule update &&\n+\t verify_sub_state detach $foo_commit\n+\t)\n+'\n+\n+test_expect_success '1.1.1.4 - do nothing (.update == none)' '\n+\tsetup_super &&\n+\t(cd super &&\n+\t setup_sub_state foo $old_commit &&\n+\t setup_sub_update none &&\n+\t setup_sub_branch unset &&\n+\t git submodule update &&\n+\t verify_sub_state foo $old_commit\n+\t)\n+'\n+\n+test_expect_success '1.1.1.5 - do nothing (.update == none)' '\n+\tsetup_super &&\n+\t(cd super &&\n+\t setup_sub_state foo $foo_commit &&\n+\t setup_sub_update none &&\n+\t setup_sub_branch unset &&\n+\t git submodule update &&\n+\t verify_sub_state foo $foo_commit\n+\t)\n+'\n+\n+test_expect_success '1.1.1.6 - do nothing (.update == none)' '\n+\tsetup_super &&\n+\t(cd super &&\n+\t setup_sub_state bar $old_commit &&\n+\t setup_sub_update none &&\n+\t setup_sub_branch unset &&\n+\t git submodule update &&\n+\t verify_sub_state bar $old_commit\n+\t)\n+'\n+\n+test_expect_success '1.1.1.7 - do nothing (.update == none)' '\n+\tsetup_super &&\n+\t(cd super &&\n+\t setup_sub_state bar $foo_commit &&\n+\t setup_sub_update none &&\n+\t setup_sub_branch unset &&\n+\t git submodule update &&\n+\t verify_sub_state bar $foo_commit\n+\t)\n+'\n+\n+test_expect_success '1.1.2.1 - do nothing (.update == none)' '\n+\tsetup_super &&\n+\t(cd super &&\n+\t setup_sub_state uncloned &&\n+\t setup_sub_update none &&\n+\t setup_sub_branch unset &&\n+\t git submodule update --remote &&\n+\t verify_sub_state uncloned\n+\t)\n+'\n+\n+test_expect_success '1.1.2.2 - do nothing (.update == none)' '\n+\tsetup_super &&\n+\t(cd super &&\n+\t setup_sub_state detach $old_commit &&\n+\t setup_sub_update none &&\n+\t setup_sub_branch unset &&\n+\t git submodule update --remote &&\n+\t verify_sub_state detach $old_commit\n+\t)\n+'\n+\n+test_expect_success '1.1.2.3 - do nothing (.update == none)' '\n+\tsetup_super &&\n+\t(cd super &&\n+\t setup_sub_state detach $foo_commit &&\n+\t setup_sub_update none &&\n+\t setup_sub_branch unset &&\n+\t git submodule update --remote &&\n+\t verify_sub_state detach $foo_commit\n+\t)\n+'\n+\n+test_expect_success '1.1.2.4 - do nothing (.update == none)' '\n+\tsetup_super &&\n+\t(cd super &&\n+\t setup_sub_state foo $old_commit &&\n+\t setup_sub_update none &&\n+\t setup_sub_branch unset &&\n+\t git submodule update --remote &&\n+\t verify_sub_state foo $old_commit\n+\t)\n+'\n+\n+test_expect_success '1.1.2.5 - do nothing (.update == none)' '\n+\tsetup_super &&\n+\t(cd super &&\n+\t setup_sub_state foo $foo_commit &&\n+\t setup_sub_update none &&\n+\t setup_sub_branch unset &&\n+\t git submodule update --remote &&\n+\t verify_sub_state foo $foo_commit\n+\t)\n+'\n+\n+test_expect_success '1.1.2.6 - do nothing (.update == none)' '\n+\tsetup_super &&\n+\t(cd super &&\n+\t setup_sub_state bar $old_commit &&\n+\t setup_sub_update none &&\n+\t setup_sub_branch unset &&\n+\t git submodule update --remote &&\n+\t verify_sub_state bar $old_commit\n+\t)\n+'\n+\n+test_expect_success '1.1.2.7 - do nothing (.update == none)' '\n+\tsetup_super &&\n+\t(cd super &&\n+\t setup_sub_state bar $foo_commit &&\n+\t setup_sub_update none &&\n+\t setup_sub_branch unset &&\n+\t git submodule update --remote &&\n+\t verify_sub_state bar $foo_commit\n+\t)\n+'\n+\n+# 1.2.* - .branch is unset, .update == checkout\n+\n+test_expect_success '1.2.1.1 - clone, detach @ $old_commit' '\n+\tsetup_super &&\n+\t(cd super &&\n+\t setup_sub_state uncloned &&\n+\t setup_sub_update checkout &&\n+\t setup_sub_branch unset &&\n+\t git submodule update &&\n+\t verify_sub_state detach $old_commit # D4\n+\t)\n+'\n+\n+test_expect_success '1.2.1.2 - already @ $old_commit -> keep detached' '\n+\tsetup_super &&\n+\t(cd super &&\n+\t setup_sub_state detach $old_commit &&\n+\t setup_sub_update checkout &&\n+\t setup_sub_branch unset &&\n+\t git submodule update &&\n+\t verify_sub_state detach $old_commit\n+\t)\n+'\n+\n+test_expect_success '1.2.1.3 - detach @ $old_commit' '\n+\tsetup_super &&\n+\t(cd super &&\n+\t setup_sub_state detach $foo_commit &&\n+\t setup_sub_update checkout &&\n+\t setup_sub_branch unset &&\n+\t git submodule update &&\n+\t verify_sub_state detach $old_commit\n+\t)\n+'\n+\n+test_expect_success '1.2.1.4 - already @ $old_commit -> keep attached' ' # D1\n+\tsetup_super &&\n+\t(cd super &&\n+\t setup_sub_state foo $old_commit &&\n+\t setup_sub_update checkout &&\n+\t setup_sub_branch unset &&\n+\t git submodule update &&\n+\t verify_sub_state foo $old_commit\n+\t)\n+'\n+\n+test_expect_success '1.2.1.5 - detach @ $old_commit' '\n+\tsetup_super &&\n+\t(cd super &&\n+\t setup_sub_state foo $foo_commit &&\n+\t setup_sub_update checkout &&\n+\t setup_sub_branch unset &&\n+\t git submodule update &&\n+\t verify_sub_state detach $old_commit\n+\t)\n+'\n+\n+test_expect_success '1.2.1.6 - already @ $old_commit -> keep attached' ' # D1\n+\tsetup_super &&\n+\t(cd super &&\n+\t setup_sub_state bar $old_commit &&\n+\t setup_sub_update checkout &&\n+\t setup_sub_branch unset &&\n+\t git submodule update &&\n+\t verify_sub_state bar $old_commit\n+\t)\n+'\n+\n+test_expect_success '1.2.1.7 - detach @ $old_commit' '\n+\tsetup_super &&\n+\t(cd super &&\n+\t setup_sub_state bar $foo_commit &&\n+\t setup_sub_update checkout &&\n+\t setup_sub_branch unset &&\n+\t git submodule update &&\n+\t verify_sub_state detach $old_commit\n+\t)\n+'\n+\n+test_expect_success '1.2.2.1 - clone, detach @ $new_commit' '\n+\tsetup_super &&\n+\t(cd super &&\n+\t setup_sub_state uncloned &&\n+\t setup_sub_update checkout &&\n+\t setup_sub_branch unset &&\n+\t git submodule update --remote &&\n+\t verify_sub_state detach $new_commit # D4\n+\t)\n+'\n+\n+test_expect_success '1.2.2.2 - detach @ $new_commit' '\n+\tsetup_super &&\n+\t(cd super &&\n+\t setup_sub_state detach $old_commit &&\n+\t setup_sub_update checkout &&\n+\t setup_sub_branch unset &&\n+\t git submodule update --remote &&\n+\t verify_sub_state detach $new_commit\n+\t)\n+'\n+\n+test_expect_success '1.2.2.3 - detach @ $new_commit' '\n+\tsetup_super &&\n+\t(cd super &&\n+\t setup_sub_state detach $foo_commit &&\n+\t setup_sub_update checkout &&\n+\t setup_sub_branch unset &&\n+\t git submodule update --remote &&\n+\t verify_sub_state detach $new_commit\n+\t)\n+'\n+\n+test_expect_success '1.2.2.4 - detach @ $new_commit' '\n+\tsetup_super &&\n+\t(cd super &&\n+\t setup_sub_state foo $old_commit &&\n+\t setup_sub_update checkout &&\n+\t setup_sub_branch unset &&\n+\t git submodule update --remote &&\n+\t verify_sub_state detach $new_commit\n+\t)\n+'\n+\n+test_expect_success '1.2.2.5 - detach @ $new_commit' '\n+\tsetup_super &&\n+\t(cd super &&\n+\t setup_sub_state foo $foo_commit &&\n+\t setup_sub_update checkout &&\n+\t setup_sub_branch unset &&\n+\t git submodule update --remote &&\n+\t verify_sub_state detach $new_commit\n+\t)\n+'\n+\n+test_expect_success '1.2.2.6 - detach @ $new_commit' '\n+\tsetup_super &&\n+\t(cd super &&\n+\t setup_sub_state bar $old_commit &&\n+\t setup_sub_update checkout &&\n+\t setup_sub_branch unset &&\n+\t git submodule update --remote &&\n+\t verify_sub_state detach $new_commit\n+\t)\n+'\n+\n+test_expect_success '1.2.2.7 - detach @ $new_commit' '\n+\tsetup_super &&\n+\t(cd super &&\n+\t setup_sub_state bar $foo_commit &&\n+\t setup_sub_update checkout &&\n+\t setup_sub_branch unset &&\n+\t git submodule update --remote &&\n+\t verify_sub_state detach $new_commit\n+\t)\n+'\n+\n+# 1.3.* - .branch is unset, .update == merge # D2\n+\n+test_expect_success '1.3.1.1 - clone, create branch named from origin/HEAD @ $old_commit' '\n+\tsetup_super &&\n+\t(cd super &&\n+\t setup_sub_state uncloned &&\n+\t setup_sub_update merge &&\n+\t setup_sub_branch unset &&\n+\t git submodule update &&\n+\t verify_sub_state detach $old_commit # T1, D4, FIXME: s/detach/master/?\n+\t)\n+'\n+\n+test_expect_success '1.3.1.2 - already at $old_commit, remain detached' ' # D3\n+\tsetup_super &&\n+\t(cd super &&\n+\t setup_sub_state detach $old_commit &&\n+\t setup_sub_update merge &&\n+\t setup_sub_branch unset &&\n+\t git submodule update &&\n+\t verify_sub_state detach $old_commit\n+\t)\n+'\n+\n+test_expect_success '1.3.1.3 - merge $old_commit -> $foo_commit, remain detached' ' # D5\n+\tsetup_super &&\n+\t(cd super &&\n+\t setup_sub_state detach $foo_commit &&\n+\t setup_sub_update merge &&\n+\t setup_sub_branch unset &&\n+\t git submodule update &&\n+\t verify_sub_state detach parents.$foo_commit.$old_commit\n+\t)\n+'\n+\n+test_expect_success '1.3.1.4 - already at $old_commit, remain attached to foo' ' # D3\n+\tsetup_super &&\n+\t(cd super &&\n+\t setup_sub_state foo $old_commit &&\n+\t setup_sub_update merge &&\n+\t setup_sub_branch unset &&\n+\t git submodule update &&\n+\t verify_sub_state foo $old_commit\n+\t)\n+'\n+\n+test_expect_success '1.3.1.5 - merge $old_commit -> $foo_commit, remain attached to foo' ' # D5\n+\tsetup_super &&\n+\t(cd super &&\n+\t setup_sub_state foo $foo_commit &&\n+\t setup_sub_update merge &&\n+\t setup_sub_branch unset &&\n+\t git submodule update &&\n+\t verify_sub_state foo parents.$foo_commit.$old_commit\n+\t)\n+'\n+\n+test_expect_success '1.3.1.6 - already at $old_commit, remain attached to bar' ' # D3\n+\tsetup_super &&\n+\t(cd super &&\n+\t setup_sub_state bar $old_commit &&\n+\t setup_sub_update merge &&\n+\t setup_sub_branch unset &&\n+\t git submodule update &&\n+\t verify_sub_state bar $old_commit\n+\t)\n+'\n+\n+test_expect_success '1.3.1.7 - merge $old_commit -> $foo_commit, remain attached to bar' ' # D5\n+\tsetup_super &&\n+\t(cd super &&\n+\t setup_sub_state bar $foo_commit &&\n+\t setup_sub_update merge &&\n+\t setup_sub_branch unset &&\n+\t git submodule update &&\n+\t verify_sub_state bar parents.$foo_commit.$old_commit\n+\t)\n+'\n+\n+test_expect_success '1.3.2.1 - clone, create branch from origin/HEAD @ $new_commit' '\n+\tsetup_super &&\n+\t(cd super &&\n+\t setup_sub_state uncloned &&\n+\t setup_sub_update merge &&\n+\t setup_sub_branch unset &&\n+\t git submodule update --remote &&\n+\t verify_sub_state detach $new_commit # T1, D4, FIXME: s/detach/master/?\n+\t)\n+'\n+\n+test_expect_success '1.3.2.2 - ffwd $old_commit -> $new_commit, remain detached' ' # D5\n+\tsetup_super &&\n+\t(cd super &&\n+\t setup_sub_state detach $old_commit &&\n+\t setup_sub_update merge &&\n+\t setup_sub_branch unset &&\n+\t git submodule update --remote &&\n+\t verify_sub_state detach $new_commit\n+\t)\n+'\n+\n+test_expect_success '1.3.2.3 - merge $new_commit -> $foo_commit, remain detached' ' # D5\n+\tsetup_super &&\n+\t(cd super &&\n+\t setup_sub_state detach $foo_commit &&\n+\t setup_sub_update merge &&\n+\t setup_sub_branch unset &&\n+\t git submodule update --remote &&\n+\t verify_sub_state detach parents.$foo_commit.$new_commit\n+\t)\n+'\n+\n+test_expect_success '1.3.2.4 - ffwd $old_commit -> $new_commit, remain attached to foo' ' # D5\n+\tsetup_super &&\n+\t(cd super &&\n+\t setup_sub_state foo $old_commit &&\n+\t setup_sub_update merge &&\n+\t setup_sub_branch unset &&\n+\t git submodule update --remote &&\n+\t verify_sub_state foo $new_commit\n+\t)\n+'\n+\n+test_expect_success '1.3.2.5 - merge $new_commit -> $foo_commit, remain attached to foo' ' # D5\n+\tsetup_super &&\n+\t(cd super &&\n+\t setup_sub_state foo $foo_commit &&\n+\t setup_sub_update merge &&\n+\t setup_sub_branch unset &&\n+\t git submodule update --remote &&\n+\t verify_sub_state foo parents.$foo_commit.$new_commit\n+\t)\n+'\n+\n+test_expect_success '1.3.2.6 - ffwd $old_commit -> $new_commit, remain attached to bar' ' # D5\n+\tsetup_super &&\n+\t(cd super &&\n+\t setup_sub_state bar $old_commit &&\n+\t setup_sub_update merge &&\n+\t setup_sub_branch unset &&\n+\t git submodule update --remote &&\n+\t verify_sub_state bar $new_commit\n+\t)\n+'\n+\n+test_expect_success '1.3.2.7 - merge $new_commit -> $foo_commit, remain attached to bar' ' # D5\n+\tsetup_super &&\n+\t(cd super &&\n+\t setup_sub_state bar $foo_commit &&\n+\t setup_sub_update merge &&\n+\t setup_sub_branch unset &&\n+\t git submodule update --remote &&\n+\t verify_sub_state bar parents.$foo_commit.$new_commit\n+\t)\n+'\n+\n+# 1.4.* - .branch is unset, .update == rebase # D2\n+\n+test_expect_success '1.4.1.1 - clone, create branch named from origin/HEAD @ $old_commit' '\n+\tsetup_super &&\n+\t(cd super &&\n+\t setup_sub_state uncloned &&\n+\t setup_sub_update rebase &&\n+\t setup_sub_branch unset &&\n+\t git submodule update &&\n+\t verify_sub_state detach $old_commit # T1, D4, FIXME: s/detach/master/?\n+\t)\n+'\n+\n+test_expect_success '1.4.1.2 - already at $old_commit, remain detached' ' # D3\n+\tsetup_super &&\n+\t(cd super &&\n+\t setup_sub_state detach $old_commit &&\n+\t setup_sub_update rebase &&\n+\t setup_sub_branch unset &&\n+\t git submodule update &&\n+\t verify_sub_state detach $old_commit\n+\t)\n+'\n+\n+test_expect_success '1.4.1.3 - rebase $foo_commit onto $old_commit, remain detached' ' # D5\n+\tsetup_super &&\n+\t(cd super &&\n+\t setup_sub_state detach $foo_commit &&\n+\t setup_sub_update rebase &&\n+\t setup_sub_branch unset &&\n+\t git submodule update &&\n+\t verify_sub_state detach parents.$old_commit &&\n+\t verify_sub_patch_id HEAD $foo_commit\n+\t)\n+'\n+\n+test_expect_success '1.4.1.4 - already at $old_commit, remain attached to foo' ' # D3\n+\tsetup_super &&\n+\t(cd super &&\n+\t setup_sub_state foo $old_commit &&\n+\t setup_sub_update rebase &&\n+\t setup_sub_branch unset &&\n+\t git submodule update &&\n+\t verify_sub_state foo $old_commit\n+\t)\n+'\n+\n+test_expect_success '1.4.1.5 - rebase $foo_commit onto $old_commit, remain attached to foo' ' # D5\n+\tsetup_super &&\n+\t(cd super &&\n+\t setup_sub_state foo $foo_commit &&\n+\t setup_sub_update rebase &&\n+\t setup_sub_branch unset &&\n+\t git submodule update &&\n+\t verify_sub_state foo parents.$old_commit &&\n+\t verify_sub_patch_id HEAD $foo_commit\n+\t)\n+'\n+\n+test_expect_success '1.4.1.6 - already at $old_commit, remain attached to bar' ' # D3\n+\tsetup_super &&\n+\t(cd super &&\n+\t setup_sub_state bar $old_commit &&\n+\t setup_sub_update rebase &&\n+\t setup_sub_branch unset &&\n+\t git submodule update &&\n+\t verify_sub_state bar $old_commit\n+\t)\n+'\n+\n+test_expect_success '1.4.1.7 - rebase $foo_commit onto $old_commit, remain attached to bar' ' # D5\n+\tsetup_super &&\n+\t(cd super &&\n+\t setup_sub_state bar $foo_commit &&\n+\t setup_sub_update rebase &&\n+\t setup_sub_branch unset &&\n+\t git submodule update &&\n+\t verify_sub_state bar parents.$old_commit &&\n+\t verify_sub_patch_id HEAD $foo_commit\n+\t)\n+'\n+\n+test_expect_success '1.4.2.1 - clone, create branch from origin/HEAD @ $new_commit' '\n+\tsetup_super &&\n+\t(cd super &&\n+\t setup_sub_state uncloned &&\n+\t setup_sub_update rebase &&\n+\t setup_sub_branch unset &&\n+\t git submodule update --remote &&\n+\t verify_sub_state detach $new_commit # T1, D4, FIXME: s/detach/master/?\n+\t)\n+'\n+\n+test_expect_success '1.4.2.2 - ffwd $old_commit -> $new_commit, remain detached' ' # D5\n+\tsetup_super &&\n+\t(cd super &&\n+\t setup_sub_state detach $old_commit &&\n+\t setup_sub_update rebase &&\n+\t setup_sub_branch unset &&\n+\t git submodule update --remote &&\n+\t verify_sub_state detach $new_commit\n+\t)\n+'\n+\n+test_expect_success '1.4.2.3 - rebase $foo_commit onto $new_commit, remain detached' ' # D5\n+\tsetup_super &&\n+\t(cd super &&\n+\t setup_sub_state detach $foo_commit &&\n+\t setup_sub_update rebase &&\n+\t setup_sub_branch unset &&\n+\t git submodule update --remote &&\n+\t verify_sub_state detach parents.$new_commit &&\n+\t verify_sub_patch_id HEAD $foo_commit\n+\t)\n+'\n+\n+test_expect_success '1.4.2.4 - ffwd $old_commit -> $new_commit, remain attached to foo' ' # D5\n+\tsetup_super &&\n+\t(cd super &&\n+\t setup_sub_state foo $old_commit &&\n+\t setup_sub_update rebase &&\n+\t setup_sub_branch unset &&\n+\t git submodule update --remote &&\n+\t verify_sub_state foo $new_commit\n+\t)\n+'\n+\n+test_expect_success '1.4.2.5 - rebase $foo_commit onto $new_commit, remain attached to foo' ' # D5\n+\tsetup_super &&\n+\t(cd super &&\n+\t setup_sub_state foo $foo_commit &&\n+\t setup_sub_update rebase &&\n+\t setup_sub_branch unset &&\n+\t git submodule update --remote &&\n+\t verify_sub_state foo parents.$new_commit &&\n+\t verify_sub_patch_id HEAD $foo_commit\n+\t)\n+'\n+\n+test_expect_success '1.4.2.6 - ffwd $old_commit -> $new_commit, remain attached to bar' ' # D5\n+\tsetup_super &&\n+\t(cd super &&\n+\t setup_sub_state bar $old_commit &&\n+\t setup_sub_update rebase &&\n+\t setup_sub_branch unset &&\n+\t git submodule update --remote &&\n+\t verify_sub_state bar $new_commit\n+\t)\n+'\n+\n+test_expect_success '1.4.2.7 - rebase $foo_commit onto $new_commit, remain attached to bar' ' # D5\n+\tsetup_super &&\n+\t(cd super &&\n+\t setup_sub_state bar $foo_commit &&\n+\t setup_sub_update rebase &&\n+\t setup_sub_branch unset &&\n+\t git submodule update --remote &&\n+\t verify_sub_state bar parents.$new_commit\n+\t verify_sub_patch_id HEAD $foo_commit\n+\t)\n+'\n+\n+# 1.5.* - .branch is unset, .update == !command\n+\n+test_expect_success '1.5.1.1 - clone, create branch named from origin/HEAD @ $old_commit. !command is NOT invoked' '\n+\tsetup_super &&\n+\t(cd super &&\n+\t setup_sub_state uncloned &&\n+\t setup_sub_update !false &&\n+\t setup_sub_branch unset &&\n+\t git submodule update && # should not invoke \"false\"\n+\t verify_sub_state detach $old_commit # T1, D4, FIXME: s/detach/master/?\n+\t)\n+'\n+\n+test_expect_success '1.5.1.2 - already at $old_commit, remain detached. !command is NOT invoked' '\n+\tsetup_super &&\n+\t(cd super &&\n+\t setup_sub_state detach $old_commit &&\n+\t setup_sub_update !false &&\n+\t setup_sub_branch unset &&\n+\t git submodule update && # should not invoke \"false\"\n+\t verify_sub_state detach $old_commit\n+\t)\n+'\n+\n+cat > test_command.sh <<EOF\n+#!/bin/sh\n+# Verify: detached @ $foo_commit, and asked to integrate $old_commit\n+test \"\\$(git symbolic-ref --short -q HEAD)\" = \"\" &&\n+test \"\\$(git rev-parse -q --verify HEAD)\" = \"$foo_commit\" &&\n+test \"\\$1\" = \"$old_commit\" &&\n+git checkout -b success $root_commit\n+EOF\n+chmod +x test_command.sh\n+\n+test_expect_success '1.5.1.3 - !command invoked to integrate $old_commit -> $foo_commit' '\n+\tsetup_super &&\n+\t(cd super &&\n+\t setup_sub_state detach $foo_commit &&\n+\t setup_sub_update !../../test_command.sh &&\n+\t setup_sub_branch unset &&\n+\t git submodule update &&\n+\t verify_sub_state success $root_commit # test_command.sh is happy\n+\t)\n+'\n+\n+test_expect_success '1.5.1.4 - already at $old_commit, remain attached to foo. !command is NOT invoked' '\n+\tsetup_super &&\n+\t(cd super &&\n+\t setup_sub_state foo $old_commit &&\n+\t setup_sub_update !false &&\n+\t setup_sub_branch unset &&\n+\t git submodule update &&\n+\t verify_sub_state foo $old_commit\n+\t)\n+'\n+\n+cat > test_command.sh <<EOF\n+#!/bin/sh\n+# Verify: attached to foo @ $foo_commit, and asked to integrate $old_commit\n+test \"\\$(git symbolic-ref --short -q HEAD)\" = \"foo\" &&\n+test \"\\$(git rev-parse -q --verify HEAD)\" = \"$foo_commit\" &&\n+test \"\\$1\" = \"$old_commit\" &&\n+git checkout -b success $root_commit\n+EOF\n+chmod +x test_command.sh\n+\n+test_expect_success '1.5.1.5 - !command invoked to integrate $old_commit -> foo/$foo_commit' '\n+\tsetup_super &&\n+\t(cd super &&\n+\t setup_sub_state foo $foo_commit &&\n+\t setup_sub_update !../../test_command.sh &&\n+\t setup_sub_branch unset &&\n+\t git submodule update &&\n+\t verify_sub_state success $root_commit # test_command.sh is happy\n+\t)\n+'\n+\n+test_expect_success '1.5.1.6 - already at $old_commit, remain attached to bar. !command is NOT invoked' '\n+\tsetup_super &&\n+\t(cd super &&\n+\t setup_sub_state bar $old_commit &&\n+\t setup_sub_update !false &&\n+\t setup_sub_branch unset &&\n+\t git submodule update &&\n+\t verify_sub_state bar $old_commit\n+\t)\n+'\n+\n+cat > test_command.sh <<EOF\n+#!/bin/sh\n+# Verify: attached to bar @ $foo_commit, and asked to integrate $old_commit\n+test \"\\$(git symbolic-ref --short -q HEAD)\" = \"bar\" &&\n+test \"\\$(git rev-parse -q --verify HEAD)\" = \"$foo_commit\" &&\n+test \"\\$1\" = \"$old_commit\" &&\n+git checkout -b success $root_commit\n+EOF\n+chmod +x test_command.sh\n+\n+test_expect_success '1.5.1.7 - !command invoked to integrate $old_commit -> bar/$foo_commit' '\n+\tsetup_super &&\n+\t(cd super &&\n+\t setup_sub_state bar $foo_commit &&\n+\t setup_sub_update !../../test_command.sh &&\n+\t setup_sub_branch unset &&\n+\t git submodule update &&\n+\t verify_sub_state success $root_commit # test_command.sh is happy\n+\t)\n+'\n+\n+test_expect_success '1.5.2.1 - clone, create branch from origin/HEAD @ $new_commit. !command is NOT invoked' '\n+\tsetup_super &&\n+\t(cd super &&\n+\t setup_sub_state uncloned &&\n+\t setup_sub_update !false &&\n+\t setup_sub_branch unset &&\n+\t git submodule update --remote &&\n+\t verify_sub_state detach $new_commit # T1, D4, FIXME: s/detach/master/?\n+\t)\n+'\n+\n+cat > test_command.sh <<EOF\n+#!/bin/sh\n+# Verify: detached @ $old_commit, and asked to integrate $new_commit\n+test \"\\$(git symbolic-ref --short -q HEAD)\" = \"\" &&\n+test \"\\$(git rev-parse -q --verify HEAD)\" = \"$old_commit\" &&\n+test \"\\$1\" = \"$new_commit\" &&\n+git checkout -b success $root_commit\n+EOF\n+chmod +x test_command.sh\n+\n+test_expect_success '1.5.2.2 - !command invoked to integrate $new_commit -> $old_commit' '\n+\tsetup_super &&\n+\t(cd super &&\n+\t setup_sub_state detach $old_commit &&\n+\t setup_sub_update !../../test_command.sh &&\n+\t setup_sub_branch unset &&\n+\t git submodule update --remote &&\n+\t verify_sub_state success $root_commit # test_command.sh is happy\n+\t)\n+'\n+\n+cat > test_command.sh <<EOF\n+#!/bin/sh\n+# Verify: detached @ $foo_commit, and asked to integrate $new_commit\n+test \"\\$(git symbolic-ref --short -q HEAD)\" = \"\" &&\n+test \"\\$(git rev-parse -q --verify HEAD)\" = \"$foo_commit\" &&\n+test \"\\$1\" = \"$new_commit\" &&\n+git checkout -b success $root_commit\n+EOF\n+chmod +x test_command.sh\n+\n+test_expect_success '1.5.2.3 - !command invoked to integrate $new_commit -> $foo_commit' '\n+\tsetup_super &&\n+\t(cd super &&\n+\t setup_sub_state detach $foo_commit &&\n+\t setup_sub_update !../../test_command.sh &&\n+\t setup_sub_branch unset &&\n+\t git submodule update --remote &&\n+\t verify_sub_state success $root_commit # test_command.sh is happy\n+\t)\n+'\n+\n+cat > test_command.sh <<EOF\n+#!/bin/sh\n+# Verify: attached to foo @ $old_commit, and asked to integrate $new_commit\n+test \"\\$(git symbolic-ref --short -q HEAD)\" = \"foo\" &&\n+test \"\\$(git rev-parse -q --verify HEAD)\" = \"$old_commit\" &&\n+test \"\\$1\" = \"$new_commit\" &&\n+git checkout -b success $root_commit\n+EOF\n+chmod +x test_command.sh\n+\n+test_expect_success '1.5.2.4 - !command invoked to integrate $new_commit -> foo/$old_commit' '\n+\tsetup_super &&\n+\t(cd super &&\n+\t setup_sub_state foo $old_commit &&\n+\t setup_sub_update !../../test_command.sh &&\n+\t setup_sub_branch unset &&\n+\t git submodule update --remote &&\n+\t verify_sub_state success $root_commit # test_command.sh is happy\n+\t)\n+'\n+\n+cat > test_command.sh <<EOF\n+#!/bin/sh\n+# Verify: attached to foo @ $foo_commit, and asked to integrate $new_commit\n+test \"\\$(git symbolic-ref --short -q HEAD)\" = \"foo\" &&\n+test \"\\$(git rev-parse -q --verify HEAD)\" = \"$foo_commit\" &&\n+test \"\\$1\" = \"$new_commit\" &&\n+git checkout -b success $root_commit\n+EOF\n+chmod +x test_command.sh\n+\n+test_expect_success '1.5.2.5 - !command invoked to integrate $new_commit -> foo/$foo_commit' '\n+\tsetup_super &&\n+\t(cd super &&\n+\t setup_sub_state foo $foo_commit &&\n+\t setup_sub_update !../../test_command.sh &&\n+\t setup_sub_branch unset &&\n+\t git submodule update --remote &&\n+\t verify_sub_state success $root_commit # test_command.sh is happy\n+\t)\n+'\n+\n+cat > test_command.sh <<EOF\n+#!/bin/sh\n+# Verify: attached to bar @ $old_commit, and asked to integrate $new_commit\n+test \"\\$(git symbolic-ref --short -q HEAD)\" = \"bar\" &&\n+test \"\\$(git rev-parse -q --verify HEAD)\" = \"$old_commit\" &&\n+test \"\\$1\" = \"$new_commit\" &&\n+git checkout -b success $root_commit\n+EOF\n+chmod +x test_command.sh\n+\n+test_expect_success '1.5.2.6 - !command invoked to integrate $new_commit -> bar/$old_commit' '\n+\tsetup_super &&\n+\t(cd super &&\n+\t setup_sub_state bar $old_commit &&\n+\t setup_sub_update !../../test_command.sh &&\n+\t setup_sub_branch unset &&\n+\t git submodule update --remote &&\n+\t verify_sub_state success $root_commit # test_command.sh is happy\n+\t)\n+'\n+\n+cat > test_command.sh <<EOF\n+#!/bin/sh\n+# Verify: attached to bar @ $foo_commit, and asked to integrate $new_commit\n+test \"\\$(git symbolic-ref --short -q HEAD)\" = \"bar\" &&\n+test \"\\$(git rev-parse -q --verify HEAD)\" = \"$foo_commit\" &&\n+test \"\\$1\" = \"$new_commit\" &&\n+git checkout -b success $root_commit\n+EOF\n+chmod +x test_command.sh\n+\n+test_expect_success '1.5.2.7 - !command invoked to integrate $new_commit -> bar/$foo_commit' '\n+\tsetup_super &&\n+\t(cd super &&\n+\t setup_sub_state bar $foo_commit &&\n+\t setup_sub_update !../../test_command.sh &&\n+\t setup_sub_branch unset &&\n+\t git submodule update --remote &&\n+\t verify_sub_state success $root_commit # test_command.sh is happy\n+\t)\n+'\n+\n+# 2.1.* - .branch == foo (exists upstream), .update == none\n+\n+test_expect_success '2.1.1.1 - do nothing (.update == none)' '\n+\tsetup_super &&\n+\t(cd super &&\n+\t setup_sub_state uncloned &&\n+\t setup_sub_update none &&\n+\t setup_sub_branch foo &&\n+\t git submodule update &&\n+\t verify_sub_state uncloned\n+\t)\n+'\n+\n+test_expect_success '2.1.1.2 - do nothing (.update == none)' '\n+\tsetup_super &&\n+\t(cd super &&\n+\t setup_sub_state detach $old_commit &&\n+\t setup_sub_update none &&\n+\t setup_sub_branch foo &&\n+\t git submodule update &&\n+\t verify_sub_state detach $old_commit\n+\t)\n+'\n+\n+test_expect_success '2.1.1.3 - do nothing (.update == none)' '\n+\tsetup_super &&\n+\t(cd super &&\n+\t setup_sub_state detach $foo_commit &&\n+\t setup_sub_update none &&\n+\t setup_sub_branch foo &&\n+\t git submodule update &&\n+\t verify_sub_state detach $foo_commit\n+\t)\n+'\n+\n+test_expect_success '2.1.1.4 - do nothing (.update == none)' '\n+\tsetup_super &&\n+\t(cd super &&\n+\t setup_sub_state foo $old_commit &&\n+\t setup_sub_update none &&\n+\t setup_sub_branch foo &&\n+\t git submodule update &&\n+\t verify_sub_state foo $old_commit\n+\t)\n+'\n+\n+test_expect_success '2.1.1.5 - do nothing (.update == none)' '\n+\tsetup_super &&\n+\t(cd super &&\n+\t setup_sub_state foo $foo_commit &&\n+\t setup_sub_update none &&\n+\t setup_sub_branch foo &&\n+\t git submodule update &&\n+\t verify_sub_state foo $foo_commit\n+\t)\n+'\n+\n+test_expect_success '2.1.1.6 - do nothing (.update == none)' '\n+\tsetup_super &&\n+\t(cd super &&\n+\t setup_sub_state bar $old_commit &&\n+\t setup_sub_update none &&\n+\t setup_sub_branch foo &&\n+\t git submodule update &&\n+\t verify_sub_state bar $old_commit\n+\t)\n+'\n+\n+test_expect_success '2.1.1.7 - do nothing (.update == none)' '\n+\tsetup_super &&\n+\t(cd super &&\n+\t setup_sub_state bar $foo_commit &&\n+\t setup_sub_update none &&\n+\t setup_sub_branch foo &&\n+\t git submodule update &&\n+\t verify_sub_state bar $foo_commit\n+\t)\n+'\n+\n+test_expect_success '2.1.2.1 - do nothing (.update == none)' '\n+\tsetup_super &&\n+\t(cd super &&\n+\t setup_sub_state uncloned &&\n+\t setup_sub_update none &&\n+\t setup_sub_branch foo &&\n+\t git submodule update --remote &&\n+\t verify_sub_state uncloned\n+\t)\n+'\n+\n+test_expect_success '2.1.2.2 - do nothing (.update == none)' '\n+\tsetup_super &&\n+\t(cd super &&\n+\t setup_sub_state detach $old_commit &&\n+\t setup_sub_update none &&\n+\t setup_sub_branch foo &&\n+\t git submodule update --remote &&\n+\t verify_sub_state detach $old_commit\n+\t)\n+'\n+\n+test_expect_success '2.1.2.3 - do nothing (.update == none)' '\n+\tsetup_super &&\n+\t(cd super &&\n+\t setup_sub_state detach $foo_commit &&\n+\t setup_sub_update none &&\n+\t setup_sub_branch foo &&\n+\t git submodule update --remote &&\n+\t verify_sub_state detach $foo_commit\n+\t)\n+'\n+\n+test_expect_success '2.1.2.4 - do nothing (.update == none)' '\n+\tsetup_super &&\n+\t(cd super &&\n+\t setup_sub_state foo $old_commit &&\n+\t setup_sub_update none &&\n+\t setup_sub_branch foo &&\n+\t git submodule update --remote &&\n+\t verify_sub_state foo $old_commit\n+\t)\n+'\n+\n+test_expect_success '2.1.2.5 - do nothing (.update == none)' '\n+\tsetup_super &&\n+\t(cd super &&\n+\t setup_sub_state foo $foo_commit &&\n+\t setup_sub_update none &&\n+\t setup_sub_branch foo &&\n+\t git submodule update --remote &&\n+\t verify_sub_state foo $foo_commit\n+\t)\n+'\n+\n+test_expect_success '2.1.2.6 - do nothing (.update == none)' '\n+\tsetup_super &&\n+\t(cd super &&\n+\t setup_sub_state bar $old_commit &&\n+\t setup_sub_update none &&\n+\t setup_sub_branch foo &&\n+\t git submodule update --remote &&\n+\t verify_sub_state bar $old_commit\n+\t)\n+'\n+\n+test_expect_success '2.1.2.7 - do nothing (.update == none)' '\n+\tsetup_super &&\n+\t(cd super &&\n+\t setup_sub_state bar $foo_commit &&\n+\t setup_sub_update none &&\n+\t setup_sub_branch foo &&\n+\t git submodule update --remote &&\n+\t verify_sub_state bar $foo_commit\n+\t)\n+'\n+\n+# 2.2.* - .branch == foo (exists upstream), .update == checkout\n+\n+test_expect_success '2.2.1.1 - clone, detach @ $old_commit (.branch is ignored)' '\n+\tsetup_super &&\n+\t(cd super &&\n+\t setup_sub_state uncloned &&\n+\t setup_sub_update checkout &&\n+\t setup_sub_branch foo &&\n+\t git submodule update &&\n+\t verify_sub_state detach $old_commit # D4\n+\t)\n+'\n+\n+test_expect_success '2.2.1.2 - already @ $old_commit -> keep detached' '\n+\tsetup_super &&\n+\t(cd super &&\n+\t setup_sub_state detach $old_commit &&\n+\t setup_sub_update checkout &&\n+\t setup_sub_branch foo &&\n+\t git submodule update &&\n+\t verify_sub_state detach $old_commit\n+\t)\n+'\n+\n+test_expect_success '2.2.1.3 - detach @ $old_commit' '\n+\tsetup_super &&\n+\t(cd super &&\n+\t setup_sub_state detach $foo_commit &&\n+\t setup_sub_update checkout &&\n+\t setup_sub_branch foo &&\n+\t git submodule update &&\n+\t verify_sub_state detach $old_commit\n+\t)\n+'\n+\n+test_expect_success '2.2.1.4 - already @ $old_commit -> keep attached' ' # D1\n+\tsetup_super &&\n+\t(cd super &&\n+\t setup_sub_state foo $old_commit &&\n+\t setup_sub_update checkout &&\n+\t setup_sub_branch foo &&\n+\t git submodule update &&\n+\t verify_sub_state foo $old_commit\n+\t)\n+'\n+\n+test_expect_success '2.2.1.5 - detach @ $old_commit' '\n+\tsetup_super &&\n+\t(cd super &&\n+\t setup_sub_state foo $foo_commit &&\n+\t setup_sub_update checkout &&\n+\t setup_sub_branch foo &&\n+\t git submodule update &&\n+\t verify_sub_state detach $old_commit\n+\t)\n+'\n+\n+test_expect_success '2.2.1.6 - already @ $old_commit -> keep attached' ' # D1\n+\tsetup_super &&\n+\t(cd super &&\n+\t setup_sub_state bar $old_commit &&\n+\t setup_sub_update checkout &&\n+\t setup_sub_branch foo &&\n+\t git submodule update &&\n+\t verify_sub_state bar $old_commit\n+\t)\n+'\n+\n+test_expect_success '2.2.1.7 - detach @ $old_commit' '\n+\tsetup_super &&\n+\t(cd super &&\n+\t setup_sub_state bar $foo_commit &&\n+\t setup_sub_update checkout &&\n+\t setup_sub_branch foo &&\n+\t git submodule update &&\n+\t verify_sub_state detach $old_commit\n+\t)\n+'\n+\n+test_expect_success '2.2.2.1 - clone, detach @ $foo_commit' '\n+\tsetup_super &&\n+\t(cd super &&\n+\t setup_sub_state uncloned &&\n+\t setup_sub_update checkout &&\n+\t setup_sub_branch foo &&\n+\t git submodule update --remote &&\n+\t verify_sub_state detach $foo_commit # D4\n+\t)\n+'\n+\n+test_expect_success '2.2.2.2 - detach @ $foo_commit' '\n+\tsetup_super &&\n+\t(cd super &&\n+\t setup_sub_state detach $old_commit &&\n+\t setup_sub_update checkout &&\n+\t setup_sub_branch foo &&\n+\t git submodule update --remote &&\n+\t verify_sub_state detach $foo_commit\n+\t)\n+'\n+\n+test_expect_success '2.2.2.3 - already @ $foo_commit, remain detached' '\n+\tsetup_super &&\n+\t(cd super &&\n+\t setup_sub_state detach $foo_commit &&\n+\t setup_sub_update checkout &&\n+\t setup_sub_branch foo &&\n+\t git submodule update --remote &&\n+\t verify_sub_state detach $foo_commit\n+\t)\n+'\n+\n+test_expect_success '2.2.2.4 - detach @ $foo_commit' '\n+\tsetup_super &&\n+\t(cd super &&\n+\t setup_sub_state foo $old_commit &&\n+\t setup_sub_update checkout &&\n+\t setup_sub_branch foo &&\n+\t git submodule update --remote &&\n+\t verify_sub_state detach $foo_commit\n+\t)\n+'\n+\n+test_expect_success '2.2.2.5 - already @ $foo_commit, remain attached to foo' '\n+\tsetup_super &&\n+\t(cd super &&\n+\t setup_sub_state foo $foo_commit &&\n+\t setup_sub_update checkout &&\n+\t setup_sub_branch foo &&\n+\t git submodule update --remote &&\n+\t verify_sub_state foo $foo_commit\n+\t)\n+'\n+\n+test_expect_success '2.2.2.6 - detach @ $foo_commit' '\n+\tsetup_super &&\n+\t(cd super &&\n+\t setup_sub_state bar $old_commit &&\n+\t setup_sub_update checkout &&\n+\t setup_sub_branch foo &&\n+\t git submodule update --remote &&\n+\t verify_sub_state detach $foo_commit\n+\t)\n+'\n+\n+test_expect_success '2.2.2.7 - already @ $foo_commit, remain attached to bar' '\n+\tsetup_super &&\n+\t(cd super &&\n+\t setup_sub_state bar $foo_commit &&\n+\t setup_sub_update checkout &&\n+\t setup_sub_branch foo &&\n+\t git submodule update --remote &&\n+\t verify_sub_state bar $foo_commit\n+\t)\n+'\n+\n+# 2.3.* - .branch == foo (exists upstream), .update == merge\n+\n+test_expect_success '2.3.1.1 - clone, create branch called foo @ $old_commit' '\n+\tsetup_super &&\n+\t(cd super &&\n+\t setup_sub_state uncloned &&\n+\t setup_sub_update merge &&\n+\t setup_sub_branch foo &&\n+\t git submodule update &&\n+\t verify_sub_state detach $old_commit # D4, FIXME: s/detach/foo/?\n+\t)\n+'\n+\n+test_expect_success '2.3.1.2 - already at $old_commit, remain detached' ' # D3\n+\tsetup_super &&\n+\t(cd super &&\n+\t setup_sub_state detach $old_commit &&\n+\t setup_sub_update merge &&\n+\t setup_sub_branch foo &&\n+\t git submodule update &&\n+\t verify_sub_state detach $old_commit\n+\t)\n+'\n+\n+test_expect_success '2.3.1.3 - merge $old_commit -> $foo_commit, remain detached' ' # D5\n+\tsetup_super &&\n+\t(cd super &&\n+\t setup_sub_state detach $foo_commit &&\n+\t setup_sub_update merge &&\n+\t setup_sub_branch foo &&\n+\t git submodule update &&\n+\t verify_sub_state detach parents.$foo_commit.$old_commit\n+\t)\n+'\n+\n+test_expect_success '2.3.1.4 - already at $old_commit, remain attached to foo' ' # D3\n+\tsetup_super &&\n+\t(cd super &&\n+\t setup_sub_state foo $old_commit &&\n+\t setup_sub_update merge &&\n+\t setup_sub_branch foo &&\n+\t git submodule update &&\n+\t verify_sub_state foo $old_commit\n+\t)\n+'\n+\n+test_expect_success '2.3.1.5 - merge $old_commit -> $foo_commit, remain attached to foo' ' # D5\n+\tsetup_super &&\n+\t(cd super &&\n+\t setup_sub_state foo $foo_commit &&\n+\t setup_sub_update merge &&\n+\t setup_sub_branch foo &&\n+\t git submodule update &&\n+\t verify_sub_state foo parents.$foo_commit.$old_commit\n+\t)\n+'\n+\n+test_expect_success '2.3.1.6 - already at $old_commit, remain attached to bar' ' # D3\n+\tsetup_super &&\n+\t(cd super &&\n+\t setup_sub_state bar $old_commit &&\n+\t setup_sub_update merge &&\n+\t setup_sub_branch foo &&\n+\t git submodule update &&\n+\t verify_sub_state bar $old_commit\n+\t)\n+'\n+\n+test_expect_success '2.3.1.7 - merge $old_commit -> $foo_commit, remain attached to bar' ' # D5\n+\tsetup_super &&\n+\t(cd super &&\n+\t setup_sub_state bar $foo_commit &&\n+\t setup_sub_update merge &&\n+\t setup_sub_branch foo &&\n+\t git submodule update &&\n+\t verify_sub_state bar parents.$foo_commit.$old_commit\n+\t)\n+'\n+\n+test_expect_success '2.3.2.1 - clone, create branch from origin/foo @ $foo_commit' '\n+\tsetup_super &&\n+\t(cd super &&\n+\t setup_sub_state uncloned &&\n+\t setup_sub_update merge &&\n+\t setup_sub_branch foo &&\n+\t git submodule update --remote &&\n+\t verify_sub_state detach $foo_commit # D4, FIXME: s/detach/foo/?\n+\t)\n+'\n+\n+test_expect_success '2.3.2.2 - merge $foo_commit -> $old_commit, remain detached' ' # D5\n+\tsetup_super &&\n+\t(cd super &&\n+\t setup_sub_state detach $old_commit &&\n+\t setup_sub_update merge &&\n+\t setup_sub_branch foo &&\n+\t git submodule update --remote &&\n+\t verify_sub_state detach parents.$old_commit.$foo_commit\n+\t)\n+'\n+\n+test_expect_success '2.3.2.3 - already @ $foo_commit, remain detached' ' # D3\n+\tsetup_super &&\n+\t(cd super &&\n+\t setup_sub_state detach $foo_commit &&\n+\t setup_sub_update merge &&\n+\t setup_sub_branch foo &&\n+\t git submodule update --remote &&\n+\t verify_sub_state detach $foo_commit\n+\t)\n+'\n+\n+test_expect_success '2.3.2.4 - merge $foo_commit -> $old_commit, remain attached to foo' ' # D5\n+\tsetup_super &&\n+\t(cd super &&\n+\t setup_sub_state foo $old_commit &&\n+\t setup_sub_update merge &&\n+\t setup_sub_branch foo &&\n+\t git submodule update --remote &&\n+\t verify_sub_state foo parents.$old_commit.$foo_commit\n+\t)\n+'\n+\n+test_expect_success '2.3.2.5 - already @ $foo_commit, remain attached to foo' ' # D3\n+\tsetup_super &&\n+\t(cd super &&\n+\t setup_sub_state foo $foo_commit &&\n+\t setup_sub_update merge &&\n+\t setup_sub_branch foo &&\n+\t git submodule update --remote &&\n+\t verify_sub_state foo $foo_commit\n+\t)\n+'\n+\n+test_expect_success '2.3.2.6 - merge $foo_commit -> $old_commit, remain attached to bar' ' # D5\n+\tsetup_super &&\n+\t(cd super &&\n+\t setup_sub_state bar $old_commit &&\n+\t setup_sub_update merge &&\n+\t setup_sub_branch foo &&\n+\t git submodule update --remote &&\n+\t verify_sub_state bar parents.$old_commit.$foo_commit\n+\t)\n+'\n+\n+test_expect_success '2.3.2.7 - already @ $foo_commit, remain attached to bar' ' # D3\n+\tsetup_super &&\n+\t(cd super &&\n+\t setup_sub_state bar $foo_commit &&\n+\t setup_sub_update merge &&\n+\t setup_sub_branch foo &&\n+\t git submodule update --remote &&\n+\t verify_sub_state bar $foo_commit\n+\t)\n+'\n+\n+# 2.4.* - .branch == foo (exists upstream), .update == rebase\n+\n+test_expect_success '2.4.1.1 - clone, create branch called foo @ $old_commit' '\n+\tsetup_super &&\n+\t(cd super &&\n+\t setup_sub_state uncloned &&\n+\t setup_sub_update rebase &&\n+\t setup_sub_branch foo &&\n+\t git submodule update &&\n+\t verify_sub_state detach $old_commit # D4, FIXME: s/detach/foo/?\n+\t)\n+'\n+\n+test_expect_success '2.4.1.2 - already at $old_commit, remain detached' ' # D3\n+\tsetup_super &&\n+\t(cd super &&\n+\t setup_sub_state detach $old_commit &&\n+\t setup_sub_update rebase &&\n+\t setup_sub_branch foo &&\n+\t git submodule update &&\n+\t verify_sub_state detach $old_commit\n+\t)\n+'\n+\n+test_expect_success '2.4.1.3 - rebase $foo_commit onto $old_commit, remain detached' ' # D5\n+\tsetup_super &&\n+\t(cd super &&\n+\t setup_sub_state detach $foo_commit &&\n+\t setup_sub_update rebase &&\n+\t setup_sub_branch foo &&\n+\t git submodule update &&\n+\t verify_sub_state detach parents.$old_commit &&\n+\t verify_sub_patch_id HEAD $foo_commit\n+\t)\n+'\n+\n+test_expect_success '2.4.1.4 - already at $old_commit, remain attached to foo' ' # D3\n+\tsetup_super &&\n+\t(cd super &&\n+\t setup_sub_state foo $old_commit &&\n+\t setup_sub_update rebase &&\n+\t setup_sub_branch foo &&\n+\t git submodule update &&\n+\t verify_sub_state foo $old_commit\n+\t)\n+'\n+\n+test_expect_success '2.4.1.5 - rebase $foo_commit onto $old_commit, remain attached to foo' ' # D5\n+\tsetup_super &&\n+\t(cd super &&\n+\t setup_sub_state foo $foo_commit &&\n+\t setup_sub_update rebase &&\n+\t setup_sub_branch foo &&\n+\t git submodule update &&\n+\t verify_sub_state foo parents.$old_commit &&\n+\t verify_sub_patch_id HEAD $foo_commit\n+\t)\n+'\n+\n+test_expect_success '2.4.1.6 - already at $old_commit, remain attached to bar' ' # D3\n+\tsetup_super &&\n+\t(cd super &&\n+\t setup_sub_state bar $old_commit &&\n+\t setup_sub_update rebase &&\n+\t setup_sub_branch foo &&\n+\t git submodule update &&\n+\t verify_sub_state bar $old_commit\n+\t)\n+'\n+\n+test_expect_success '2.4.1.7 - rebase $foo_commit onto $old_commit, remain attached to bar' ' # D5\n+\tsetup_super &&\n+\t(cd super &&\n+\t setup_sub_state bar $foo_commit &&\n+\t setup_sub_update rebase &&\n+\t setup_sub_branch foo &&\n+\t git submodule update &&\n+\t verify_sub_state bar parents.$old_commit &&\n+\t verify_sub_patch_id HEAD $foo_commit\n+\t)\n+'\n+\n+test_expect_success '2.4.2.1 - clone, create branch from origin/foo @ $foo_commit' '\n+\tsetup_super &&\n+\t(cd super &&\n+\t setup_sub_state uncloned &&\n+\t setup_sub_update rebase &&\n+\t setup_sub_branch foo &&\n+\t git submodule update --remote &&\n+\t verify_sub_state detach $foo_commit # D4, FIXME: s/detach/foo/?\n+\t)\n+'\n+\n+test_expect_success '2.4.2.2 - rebase $old_commit onto $foo_commit, remain detached' ' # D5\n+\tsetup_super &&\n+\t(cd super &&\n+\t setup_sub_state detach $old_commit &&\n+\t setup_sub_update rebase &&\n+\t setup_sub_branch foo &&\n+\t git submodule update --remote &&\n+\t verify_sub_state detach parents.$foo_commit &&\n+\t verify_sub_patch_id HEAD $old_commit\n+\t)\n+'\n+\n+test_expect_success '2.4.2.3 - already @ $foo_commit, remain detached' ' # D3\n+\tsetup_super &&\n+\t(cd super &&\n+\t setup_sub_state detach $foo_commit &&\n+\t setup_sub_update rebase &&\n+\t setup_sub_branch foo &&\n+\t git submodule update --remote &&\n+\t verify_sub_state detach $foo_commit\n+\t)\n+'\n+\n+test_expect_success '2.4.2.4 - rebase $old_commit onto $foo_commit, remain attached to foo' ' # D5\n+\tsetup_super &&\n+\t(cd super &&\n+\t setup_sub_state foo $old_commit &&\n+\t setup_sub_update rebase &&\n+\t setup_sub_branch foo &&\n+\t git submodule update --remote &&\n+\t verify_sub_state foo parents.$foo_commit &&\n+\t verify_sub_patch_id HEAD $old_commit\n+\t)\n+'\n+\n+test_expect_success '2.4.2.5 - already @ $foo_commit, remain attached to foo' ' # D3\n+\tsetup_super &&\n+\t(cd super &&\n+\t setup_sub_state foo $foo_commit &&\n+\t setup_sub_update rebase &&\n+\t setup_sub_branch foo &&\n+\t git submodule update --remote &&\n+\t verify_sub_state foo $foo_commit\n+\t)\n+'\n+\n+test_expect_success '2.4.2.6 - rebase $old_commit onto $foo_commit, remain attached to bar' ' # D5\n+\tsetup_super &&\n+\t(cd super &&\n+\t setup_sub_state bar $old_commit &&\n+\t setup_sub_update rebase &&\n+\t setup_sub_branch foo &&\n+\t git submodule update --remote &&\n+\t verify_sub_state bar parents.$foo_commit &&\n+\t verify_sub_patch_id HEAD $old_commit\n+\t)\n+'\n+\n+test_expect_success '2.4.2.7 - already @ $foo_commit, remain attached to bar' ' # D3\n+\tsetup_super &&\n+\t(cd super &&\n+\t setup_sub_state bar $foo_commit &&\n+\t setup_sub_update rebase &&\n+\t setup_sub_branch foo &&\n+\t git submodule update --remote &&\n+\t verify_sub_state bar $foo_commit\n+\t)\n+'\n+\n+# 2.5.* - .branch == foo (exists upstream), .update == !command\n+\n+test_expect_success '2.5.1.1 - clone, create branch called foo @ $old_commit. !command is NOT invoked' '\n+\tsetup_super &&\n+\t(cd super &&\n+\t setup_sub_state uncloned &&\n+\t setup_sub_update !false &&\n+\t setup_sub_branch foo &&\n+\t git submodule update && # should not invoke \"false\"\n+\t verify_sub_state detach $old_commit # D4, FIXME: s/detach/foo/?\n+\t)\n+'\n+\n+test_expect_success '2.5.1.2 - already at $old_commit, remain detached. !command is NOT invoked' '\n+\tsetup_super &&\n+\t(cd super &&\n+\t setup_sub_state detach $old_commit &&\n+\t setup_sub_update !false &&\n+\t setup_sub_branch foo &&\n+\t git submodule update && # should not invoke \"false\"\n+\t verify_sub_state detach $old_commit\n+\t)\n+'\n+\n+cat > test_command.sh <<EOF\n+#!/bin/sh\n+# Verify: detached @ $foo_commit, and asked to integrate $old_commit\n+test \"\\$(git symbolic-ref --short -q HEAD)\" = \"\" &&\n+test \"\\$(git rev-parse -q --verify HEAD)\" = \"$foo_commit\" &&\n+test \"\\$1\" = \"$old_commit\" &&\n+git checkout -b success $root_commit\n+EOF\n+chmod +x test_command.sh\n+\n+test_expect_success '2.5.1.3 - !command invoked to integrate $old_commit -> $foo_commit' '\n+\tsetup_super &&\n+\t(cd super &&\n+\t setup_sub_state detach $foo_commit &&\n+\t setup_sub_update !../../test_command.sh &&\n+\t setup_sub_branch foo &&\n+\t git submodule update &&\n+\t verify_sub_state success $root_commit # test_command.sh is happy\n+\t)\n+'\n+\n+test_expect_success '2.5.1.4 - already at $old_commit, remain attached to foo. !command is NOT invoked' '\n+\tsetup_super &&\n+\t(cd super &&\n+\t setup_sub_state foo $old_commit &&\n+\t setup_sub_update !false &&\n+\t setup_sub_branch foo &&\n+\t git submodule update &&\n+\t verify_sub_state foo $old_commit\n+\t)\n+'\n+\n+cat > test_command.sh <<EOF\n+#!/bin/sh\n+# Verify: attached to foo @ $foo_commit, and asked to integrate $old_commit\n+test \"\\$(git symbolic-ref --short -q HEAD)\" = \"foo\" &&\n+test \"\\$(git rev-parse -q --verify HEAD)\" = \"$foo_commit\" &&\n+test \"\\$1\" = \"$old_commit\" &&\n+git checkout -b success $root_commit\n+EOF\n+chmod +x test_command.sh\n+\n+test_expect_success '2.5.1.5 - !command invoked to integrate $old_commit -> foo/$foo_commit' '\n+\tsetup_super &&\n+\t(cd super &&\n+\t setup_sub_state foo $foo_commit &&\n+\t setup_sub_update !../../test_command.sh &&\n+\t setup_sub_branch foo &&\n+\t git submodule update &&\n+\t verify_sub_state success $root_commit # test_command.sh is happy\n+\t)\n+'\n+\n+test_expect_success '2.5.1.6 - already at $old_commit, remain attached to bar. !command is NOT invoked' '\n+\tsetup_super &&\n+\t(cd super &&\n+\t setup_sub_state bar $old_commit &&\n+\t setup_sub_update !false &&\n+\t setup_sub_branch foo &&\n+\t git submodule update &&\n+\t verify_sub_state bar $old_commit\n+\t)\n+'\n+\n+cat > test_command.sh <<EOF\n+#!/bin/sh\n+# Verify: attached to bar @ $foo_commit, and asked to integrate $old_commit\n+test \"\\$(git symbolic-ref --short -q HEAD)\" = \"bar\" &&\n+test \"\\$(git rev-parse -q --verify HEAD)\" = \"$foo_commit\" &&\n+test \"\\$1\" = \"$old_commit\" &&\n+git checkout -b success $root_commit\n+EOF\n+chmod +x test_command.sh\n+\n+test_expect_success '2.5.1.7 - !command invoked to integrate $old_commit -> bar/$foo_commit' '\n+\tsetup_super &&\n+\t(cd super &&\n+\t setup_sub_state bar $foo_commit &&\n+\t setup_sub_update !../../test_command.sh &&\n+\t setup_sub_branch foo &&\n+\t git submodule update &&\n+\t verify_sub_state success $root_commit # test_command.sh is happy\n+\t)\n+'\n+\n+test_expect_success '2.5.2.1 - clone, create branch from origin/foo @ $foo_commit. !command is NOT invoked' '\n+\tsetup_super &&\n+\t(cd super &&\n+\t setup_sub_state uncloned &&\n+\t setup_sub_update !false &&\n+\t setup_sub_branch foo &&\n+\t git submodule update --remote &&\n+\t verify_sub_state detach $foo_commit # D4, FIXME: s/detach/foo/?\n+\t)\n+'\n+\n+cat > test_command.sh <<EOF\n+#!/bin/sh\n+# Verify: detached @ $old_commit, and asked to integrate $foo_commit\n+test \"\\$(git symbolic-ref --short -q HEAD)\" = \"\" &&\n+test \"\\$(git rev-parse -q --verify HEAD)\" = \"$old_commit\" &&\n+test \"\\$1\" = \"$foo_commit\" &&\n+git checkout -b success $root_commit\n+EOF\n+chmod +x test_command.sh\n+\n+test_expect_success '2.5.2.2 - !command invoked to integrate $foo_commit -> $old_commit' '\n+\tsetup_super &&\n+\t(cd super &&\n+\t setup_sub_state detach $old_commit &&\n+\t setup_sub_update !../../test_command.sh &&\n+\t setup_sub_branch foo &&\n+\t git submodule update --remote &&\n+\t verify_sub_state success $root_commit # test_command.sh is happy\n+\t)\n+'\n+\n+test_expect_success '2.5.2.3 - already at $foo_commit, remain detached. !command is NOT invoked' '\n+\tsetup_super &&\n+\t(cd super &&\n+\t setup_sub_state detach $foo_commit &&\n+\t setup_sub_update !false &&\n+\t setup_sub_branch foo &&\n+\t git submodule update --remote &&\n+\t verify_sub_state detach $foo_commit\n+\t)\n+'\n+\n+cat > test_command.sh <<EOF\n+#!/bin/sh\n+# Verify: attached to foo @ $old_commit, and asked to integrate $foo_commit\n+test \"\\$(git symbolic-ref --short -q HEAD)\" = \"foo\" &&\n+test \"\\$(git rev-parse -q --verify HEAD)\" = \"$old_commit\" &&\n+test \"\\$1\" = \"$foo_commit\" &&\n+git checkout -b success $root_commit\n+EOF\n+chmod +x test_command.sh\n+\n+test_expect_success '2.5.2.4 - !command invoked to integrate $foo_commit -> foo/$old_commit' '\n+\tsetup_super &&\n+\t(cd super &&\n+\t setup_sub_state foo $old_commit &&\n+\t setup_sub_update !../../test_command.sh &&\n+\t setup_sub_branch foo &&\n+\t git submodule update --remote &&\n+\t verify_sub_state success $root_commit # test_command.sh is happy\n+\t)\n+'\n+\n+test_expect_success '2.5.2.5 - already at $foo_commit, remain attached to foo. !command is NOT invoked' '\n+\tsetup_super &&\n+\t(cd super &&\n+\t setup_sub_state foo $foo_commit &&\n+\t setup_sub_update !false &&\n+\t setup_sub_branch foo &&\n+\t git submodule update --remote &&\n+\t verify_sub_state foo $foo_commit\n+\t)\n+'\n+\n+cat > test_command.sh <<EOF\n+#!/bin/sh\n+# Verify: attached to bar @ $old_commit, and asked to integrate $foo_commit\n+test \"\\$(git symbolic-ref --short -q HEAD)\" = \"bar\" &&\n+test \"\\$(git rev-parse -q --verify HEAD)\" = \"$old_commit\" &&\n+test \"\\$1\" = \"$foo_commit\" &&\n+git checkout -b success $root_commit\n+EOF\n+chmod +x test_command.sh\n+\n+test_expect_success '2.5.2.6 - !command invoked to integrate $foo_commit -> bar/$old_commit' '\n+\tsetup_super &&\n+\t(cd super &&\n+\t setup_sub_state bar $old_commit &&\n+\t setup_sub_update !../../test_command.sh &&\n+\t setup_sub_branch foo &&\n+\t git submodule update --remote &&\n+\t verify_sub_state success $root_commit # test_command.sh is happy\n+\t)\n+'\n+\n+test_expect_success '2.5.2.7 - already at $foo_commit, remain attached to bar. !command is NOT invoked' '\n+\tsetup_super &&\n+\t(cd super &&\n+\t setup_sub_state bar $foo_commit &&\n+\t setup_sub_update !false &&\n+\t setup_sub_branch foo &&\n+\t git submodule update --remote &&\n+\t verify_sub_state bar $foo_commit\n+\t)\n+'\n+\n+# 3.1.* - .branch == bar (MISSING upstream), .update == none\n+\n+test_expect_success '3.1.1.1 - do nothing (.update == none)' '\n+\tsetup_super &&\n+\t(cd super &&\n+\t setup_sub_state uncloned &&\n+\t setup_sub_update none &&\n+\t setup_sub_branch bar &&\n+\t git submodule update &&\n+\t verify_sub_state uncloned\n+\t)\n+'\n+\n+test_expect_success '3.1.1.2 - do nothing (.update == none)' '\n+\tsetup_super &&\n+\t(cd super &&\n+\t setup_sub_state detach $old_commit &&\n+\t setup_sub_update none &&\n+\t setup_sub_branch bar &&\n+\t git submodule update &&\n+\t verify_sub_state detach $old_commit\n+\t)\n+'\n+\n+test_expect_success '3.1.1.3 - do nothing (.update == none)' '\n+\tsetup_super &&\n+\t(cd super &&\n+\t setup_sub_state detach $foo_commit &&\n+\t setup_sub_update none &&\n+\t setup_sub_branch bar &&\n+\t git submodule update &&\n+\t verify_sub_state detach $foo_commit\n+\t)\n+'\n+\n+test_expect_success '3.1.1.4 - do nothing (.update == none)' '\n+\tsetup_super &&\n+\t(cd super &&\n+\t setup_sub_state foo $old_commit &&\n+\t setup_sub_update none &&\n+\t setup_sub_branch bar &&\n+\t git submodule update &&\n+\t verify_sub_state foo $old_commit\n+\t)\n+'\n+\n+test_expect_success '3.1.1.5 - do nothing (.update == none)' '\n+\tsetup_super &&\n+\t(cd super &&\n+\t setup_sub_state foo $foo_commit &&\n+\t setup_sub_update none &&\n+\t setup_sub_branch bar &&\n+\t git submodule update &&\n+\t verify_sub_state foo $foo_commit\n+\t)\n+'\n+\n+test_expect_success '3.1.1.6 - do nothing (.update == none)' '\n+\tsetup_super &&\n+\t(cd super &&\n+\t setup_sub_state bar $old_commit &&\n+\t setup_sub_update none &&\n+\t setup_sub_branch bar &&\n+\t git submodule update &&\n+\t verify_sub_state bar $old_commit\n+\t)\n+'\n+\n+test_expect_success '3.1.1.7 - do nothing (.update == none)' '\n+\tsetup_super &&\n+\t(cd super &&\n+\t setup_sub_state bar $foo_commit &&\n+\t setup_sub_update none &&\n+\t setup_sub_branch bar &&\n+\t git submodule update &&\n+\t verify_sub_state bar $foo_commit\n+\t)\n+'\n+\n+test_expect_success '3.1.2.1 - do nothing (.update == none)' '\n+\tsetup_super &&\n+\t(cd super &&\n+\t setup_sub_state uncloned &&\n+\t setup_sub_update none &&\n+\t setup_sub_branch bar &&\n+\t git submodule update --remote &&\n+\t verify_sub_state uncloned\n+\t)\n+'\n+\n+test_expect_success '3.1.2.2 - do nothing (.update == none)' '\n+\tsetup_super &&\n+\t(cd super &&\n+\t setup_sub_state detach $old_commit &&\n+\t setup_sub_update none &&\n+\t setup_sub_branch bar &&\n+\t git submodule update --remote &&\n+\t verify_sub_state detach $old_commit\n+\t)\n+'\n+\n+test_expect_success '3.1.2.3 - do nothing (.update == none)' '\n+\tsetup_super &&\n+\t(cd super &&\n+\t setup_sub_state detach $foo_commit &&\n+\t setup_sub_update none &&\n+\t setup_sub_branch bar &&\n+\t git submodule update --remote &&\n+\t verify_sub_state detach $foo_commit\n+\t)\n+'\n+\n+test_expect_success '3.1.2.4 - do nothing (.update == none)' '\n+\tsetup_super &&\n+\t(cd super &&\n+\t setup_sub_state foo $old_commit &&\n+\t setup_sub_update none &&\n+\t setup_sub_branch bar &&\n+\t git submodule update --remote &&\n+\t verify_sub_state foo $old_commit\n+\t)\n+'\n+\n+test_expect_success '3.1.2.5 - do nothing (.update == none)' '\n+\tsetup_super &&\n+\t(cd super &&\n+\t setup_sub_state foo $foo_commit &&\n+\t setup_sub_update none &&\n+\t setup_sub_branch bar &&\n+\t git submodule update --remote &&\n+\t verify_sub_state foo $foo_commit\n+\t)\n+'\n+\n+test_expect_success '3.1.2.6 - do nothing (.update == none)' '\n+\tsetup_super &&\n+\t(cd super &&\n+\t setup_sub_state bar $old_commit &&\n+\t setup_sub_update none &&\n+\t setup_sub_branch bar &&\n+\t git submodule update --remote &&\n+\t verify_sub_state bar $old_commit\n+\t)\n+'\n+\n+test_expect_success '3.1.2.7 - do nothing (.update == none)' '\n+\tsetup_super &&\n+\t(cd super &&\n+\t setup_sub_state bar $foo_commit &&\n+\t setup_sub_update none &&\n+\t setup_sub_branch bar &&\n+\t git submodule update --remote &&\n+\t verify_sub_state bar $foo_commit\n+\t)\n+'\n+\n+# 3.2.* - .branch == bar (MISSING upstream), .update == checkout\n+\n+test_expect_success '3.2.1.1 - clone, detach @ $old_commit (.branch is ignored)' '\n+\tsetup_super &&\n+\t(cd super &&\n+\t setup_sub_state uncloned &&\n+\t setup_sub_update checkout &&\n+\t setup_sub_branch bar &&\n+\t git submodule update &&\n+\t verify_sub_state detach $old_commit # D4\n+\t)\n+'\n+\n+test_expect_success '3.2.1.2 - already @ $old_commit -> keep detached' '\n+\tsetup_super &&\n+\t(cd super &&\n+\t setup_sub_state detach $old_commit &&\n+\t setup_sub_update checkout &&\n+\t setup_sub_branch bar &&\n+\t git submodule update &&\n+\t verify_sub_state detach $old_commit\n+\t)\n+'\n+\n+test_expect_success '3.2.1.3 - detach @ $old_commit' '\n+\tsetup_super &&\n+\t(cd super &&\n+\t setup_sub_state detach $foo_commit &&\n+\t setup_sub_update checkout &&\n+\t setup_sub_branch bar &&\n+\t git submodule update &&\n+\t verify_sub_state detach $old_commit\n+\t)\n+'\n+\n+test_expect_success '3.2.1.4 - already @ $old_commit -> keep attached' ' # D1\n+\tsetup_super &&\n+\t(cd super &&\n+\t setup_sub_state foo $old_commit &&\n+\t setup_sub_update checkout &&\n+\t setup_sub_branch bar &&\n+\t git submodule update &&\n+\t verify_sub_state foo $old_commit\n+\t)\n+'\n+\n+test_expect_success '3.2.1.5 - detach @ $old_commit' '\n+\tsetup_super &&\n+\t(cd super &&\n+\t setup_sub_state foo $foo_commit &&\n+\t setup_sub_update checkout &&\n+\t setup_sub_branch bar &&\n+\t git submodule update &&\n+\t verify_sub_state detach $old_commit\n+\t)\n+'\n+\n+test_expect_success '3.2.1.6 - already @ $old_commit -> keep attached' ' # D1\n+\tsetup_super &&\n+\t(cd super &&\n+\t setup_sub_state bar $old_commit &&\n+\t setup_sub_update checkout &&\n+\t setup_sub_branch bar &&\n+\t git submodule update &&\n+\t verify_sub_state bar $old_commit\n+\t)\n+'\n+\n+test_expect_success '3.2.1.7 - detach @ $old_commit' '\n+\tsetup_super &&\n+\t(cd super &&\n+\t setup_sub_state bar $foo_commit &&\n+\t setup_sub_update checkout &&\n+\t setup_sub_branch bar &&\n+\t git submodule update &&\n+\t verify_sub_state detach $old_commit\n+\t)\n+'\n+\n+test_expect_failure '3.2.2.1 - fail to clone (remote branch bar missing), leave uncloned' ' # T3, D7\n+\tsetup_super &&\n+\t(cd super &&\n+\t setup_sub_state uncloned &&\n+\t setup_sub_update checkout &&\n+\t setup_sub_branch bar &&\n+\t test_must_fail git submodule update --remote &&\n+\t verify_sub_state uncloned\n+\t)\n+'\n+\n+test_expect_success '3.2.2.2 - fail (remote branch bar missing)' '\n+\tsetup_super &&\n+\t(cd super &&\n+\t setup_sub_state detach $old_commit &&\n+\t setup_sub_update checkout &&\n+\t setup_sub_branch bar &&\n+\t test_must_fail git submodule update --remote &&\n+\t verify_sub_state detach $old_commit\n+\t)\n+'\n+\n+test_expect_success '3.2.2.3 - fail (remote branch bar missing)' '\n+\tsetup_super &&\n+\t(cd super &&\n+\t setup_sub_state detach $foo_commit &&\n+\t setup_sub_update checkout &&\n+\t setup_sub_branch bar &&\n+\t test_must_fail git submodule update --remote &&\n+\t verify_sub_state detach $foo_commit\n+\t)\n+'\n+\n+test_expect_success '3.2.2.4 - fail (remote branch bar missing)' '\n+\tsetup_super &&\n+\t(cd super &&\n+\t setup_sub_state foo $old_commit &&\n+\t setup_sub_update checkout &&\n+\t setup_sub_branch bar &&\n+\t test_must_fail git submodule update --remote &&\n+\t verify_sub_state foo $old_commit\n+\t)\n+'\n+\n+test_expect_success '3.2.2.5 - fail (remote branch bar missing)' '\n+\tsetup_super &&\n+\t(cd super &&\n+\t setup_sub_state foo $foo_commit &&\n+\t setup_sub_update checkout &&\n+\t setup_sub_branch bar &&\n+\t test_must_fail git submodule update --remote &&\n+\t verify_sub_state foo $foo_commit\n+\t)\n+'\n+\n+test_expect_success '3.2.2.6 - fail (remote branch bar missing)' '\n+\tsetup_super &&\n+\t(cd super &&\n+\t setup_sub_state bar $old_commit &&\n+\t setup_sub_update checkout &&\n+\t setup_sub_branch bar &&\n+\t test_must_fail git submodule update --remote &&\n+\t verify_sub_state bar $old_commit\n+\t)\n+'\n+\n+test_expect_success '3.2.2.7 - fail (remote branch bar missing)' '\n+\tsetup_super &&\n+\t(cd super &&\n+\t setup_sub_state bar $foo_commit &&\n+\t setup_sub_update checkout &&\n+\t setup_sub_branch bar &&\n+\t test_must_fail git submodule update --remote &&\n+\t verify_sub_state bar $foo_commit\n+\t)\n+'\n+\n+# 3.3.* - .branch == bar (MISSING upstream), .update == merge\n+\n+test_expect_success '3.3.1.1 - clone, create branch called bar @ $old_commit' '\n+\tsetup_super &&\n+\t(cd super &&\n+\t setup_sub_state uncloned &&\n+\t setup_sub_update merge &&\n+\t setup_sub_branch bar &&\n+\t git submodule update &&\n+\t verify_sub_state detach $old_commit # D4, FIXME: s/detach/bar/?\n+\t)\n+'\n+\n+test_expect_success '3.3.1.2 - already at $old_commit, remain detached' ' # D3\n+\tsetup_super &&\n+\t(cd super &&\n+\t setup_sub_state detach $old_commit &&\n+\t setup_sub_update merge &&\n+\t setup_sub_branch bar &&\n+\t git submodule update &&\n+\t verify_sub_state detach $old_commit\n+\t)\n+'\n+\n+test_expect_success '3.3.1.3 - merge $old_commit -> $foo_commit, remain detached' ' # D5\n+\tsetup_super &&\n+\t(cd super &&\n+\t setup_sub_state detach $foo_commit &&\n+\t setup_sub_update merge &&\n+\t setup_sub_branch bar &&\n+\t git submodule update &&\n+\t verify_sub_state detach parents.$foo_commit.$old_commit\n+\t)\n+'\n+\n+test_expect_success '3.3.1.4 - already at $old_commit, remain attached to foo' ' # D3\n+\tsetup_super &&\n+\t(cd super &&\n+\t setup_sub_state foo $old_commit &&\n+\t setup_sub_update merge &&\n+\t setup_sub_branch bar &&\n+\t git submodule update &&\n+\t verify_sub_state foo $old_commit\n+\t)\n+'\n+\n+test_expect_success '3.3.1.5 - merge $old_commit -> $foo_commit, remain attached to foo' ' # D5\n+\tsetup_super &&\n+\t(cd super &&\n+\t setup_sub_state foo $foo_commit &&\n+\t setup_sub_update merge &&\n+\t setup_sub_branch bar &&\n+\t git submodule update &&\n+\t verify_sub_state foo parents.$foo_commit.$old_commit\n+\t)\n+'\n+\n+test_expect_success '3.3.1.6 - already at $old_commit, remain attached to bar' ' # D3\n+\tsetup_super &&\n+\t(cd super &&\n+\t setup_sub_state bar $old_commit &&\n+\t setup_sub_update merge &&\n+\t setup_sub_branch bar &&\n+\t git submodule update &&\n+\t verify_sub_state bar $old_commit\n+\t)\n+'\n+\n+test_expect_success '3.3.1.7 - merge $old_commit -> $foo_commit, remain attached to bar' ' # D5\n+\tsetup_super &&\n+\t(cd super &&\n+\t setup_sub_state bar $foo_commit &&\n+\t setup_sub_update merge &&\n+\t setup_sub_branch bar &&\n+\t git submodule update &&\n+\t verify_sub_state bar parents.$foo_commit.$old_commit\n+\t)\n+'\n+\n+test_expect_failure '3.3.2.1 - fail to clone (remote branch bar missing), leave uncloned' ' # T3, D7\n+\tsetup_super &&\n+\t(cd super &&\n+\t setup_sub_state uncloned &&\n+\t setup_sub_update merge &&\n+\t setup_sub_branch bar &&\n+\t test_must_fail git submodule update --remote &&\n+\t verify_sub_state uncloned\n+\t)\n+'\n+\n+test_expect_success '3.3.2.2 - fail (remote branch bar missing)' '\n+\tsetup_super &&\n+\t(cd super &&\n+\t setup_sub_state detach $old_commit &&\n+\t setup_sub_update merge &&\n+\t setup_sub_branch bar &&\n+\t test_must_fail git submodule update --remote &&\n+\t verify_sub_state detach $old_commit\n+\t)\n+'\n+\n+test_expect_success '3.3.2.3 - fail (remote branch bar missing)' '\n+\tsetup_super &&\n+\t(cd super &&\n+\t setup_sub_state detach $foo_commit &&\n+\t setup_sub_update merge &&\n+\t setup_sub_branch bar &&\n+\t test_must_fail git submodule update --remote &&\n+\t verify_sub_state detach $foo_commit\n+\t)\n+'\n+\n+test_expect_success '3.3.2.4 - fail (remote branch bar missing)' '\n+\tsetup_super &&\n+\t(cd super &&\n+\t setup_sub_state foo $old_commit &&\n+\t setup_sub_update merge &&\n+\t setup_sub_branch bar &&\n+\t test_must_fail git submodule update --remote &&\n+\t verify_sub_state foo $old_commit\n+\t)\n+'\n+\n+test_expect_success '3.3.2.5 - fail (remote branch bar missing)' '\n+\tsetup_super &&\n+\t(cd super &&\n+\t setup_sub_state foo $foo_commit &&\n+\t setup_sub_update merge &&\n+\t setup_sub_branch bar &&\n+\t test_must_fail git submodule update --remote &&\n+\t verify_sub_state foo $foo_commit\n+\t)\n+'\n+\n+test_expect_success '3.3.2.6 - fail (remote branch bar missing)' '\n+\tsetup_super &&\n+\t(cd super &&\n+\t setup_sub_state bar $old_commit &&\n+\t setup_sub_update merge &&\n+\t setup_sub_branch bar &&\n+\t test_must_fail git submodule update --remote &&\n+\t verify_sub_state bar $old_commit\n+\t)\n+'\n+\n+test_expect_success '3.3.2.7 - fail (remote branch bar missing)' '\n+\tsetup_super &&\n+\t(cd super &&\n+\t setup_sub_state bar $foo_commit &&\n+\t setup_sub_update merge &&\n+\t setup_sub_branch bar &&\n+\t test_must_fail git submodule update --remote &&\n+\t verify_sub_state bar $foo_commit\n+\t)\n+'\n+\n+# 3.4.* - .branch == bar (MISSING upstream), .update == rebase\n+\n+test_expect_success '3.4.1.1 - clone, create branch called bar @ $old_commit' '\n+\tsetup_super &&\n+\t(cd super &&\n+\t setup_sub_state uncloned &&\n+\t setup_sub_update rebase &&\n+\t setup_sub_branch bar &&\n+\t git submodule update &&\n+\t verify_sub_state detach $old_commit # D4, FIXME: s/detach/bar/?\n+\t)\n+'\n+\n+test_expect_success '3.4.1.2 - already at $old_commit, remain detached' ' # D3\n+\tsetup_super &&\n+\t(cd super &&\n+\t setup_sub_state detach $old_commit &&\n+\t setup_sub_update rebase &&\n+\t setup_sub_branch bar &&\n+\t git submodule update &&\n+\t verify_sub_state detach $old_commit\n+\t)\n+'\n+\n+test_expect_success '3.4.1.3 - rebase $foo_commit onto $old_commit, remain detached' ' # D5\n+\tsetup_super &&\n+\t(cd super &&\n+\t setup_sub_state detach $foo_commit &&\n+\t setup_sub_update rebase &&\n+\t setup_sub_branch bar &&\n+\t git submodule update &&\n+\t verify_sub_state detach parents.$old_commit &&\n+\t verify_sub_patch_id HEAD $foo_commit\n+\t)\n+'\n+\n+test_expect_success '3.4.1.4 - already at $old_commit, remain attached to foo' ' # D3\n+\tsetup_super &&\n+\t(cd super &&\n+\t setup_sub_state foo $old_commit &&\n+\t setup_sub_update rebase &&\n+\t setup_sub_branch bar &&\n+\t git submodule update &&\n+\t verify_sub_state foo $old_commit\n+\t)\n+'\n+\n+test_expect_success '3.4.1.5 - rebase $foo_commit onto $old_commit, remain attached to foo' ' # D5\n+\tsetup_super &&\n+\t(cd super &&\n+\t setup_sub_state foo $foo_commit &&\n+\t setup_sub_update rebase &&\n+\t setup_sub_branch bar &&\n+\t git submodule update &&\n+\t verify_sub_state foo parents.$old_commit &&\n+\t verify_sub_patch_id HEAD $foo_commit\n+\t)\n+'\n+\n+test_expect_success '3.4.1.6 - already at $old_commit, remain attached to bar' ' # D3\n+\tsetup_super &&\n+\t(cd super &&\n+\t setup_sub_state bar $old_commit &&\n+\t setup_sub_update rebase &&\n+\t setup_sub_branch bar &&\n+\t git submodule update &&\n+\t verify_sub_state bar $old_commit\n+\t)\n+'\n+\n+test_expect_success '3.4.1.7 - rebase $foo_commit onto $old_commit, remain attached to bar' ' # D5\n+\tsetup_super &&\n+\t(cd super &&\n+\t setup_sub_state bar $foo_commit &&\n+\t setup_sub_update rebase &&\n+\t setup_sub_branch bar &&\n+\t git submodule update &&\n+\t verify_sub_state bar parents.$old_commit &&\n+\t verify_sub_patch_id HEAD $foo_commit\n+\t)\n+'\n+\n+test_expect_failure '3.4.2.1 - fail to clone (remote branch bar missing), leave uncloned' ' # T3, D7\n+\tsetup_super &&\n+\t(cd super &&\n+\t setup_sub_state uncloned &&\n+\t setup_sub_update rebase &&\n+\t setup_sub_branch bar &&\n+\t test_must_fail git submodule update --remote &&\n+\t verify_sub_state uncloned\n+\t)\n+'\n+\n+test_expect_success '3.4.2.2 - fail (remote branch bar missing)' '\n+\tsetup_super &&\n+\t(cd super &&\n+\t setup_sub_state detach $old_commit &&\n+\t setup_sub_update rebase &&\n+\t setup_sub_branch bar &&\n+\t test_must_fail git submodule update --remote &&\n+\t verify_sub_state detach $old_commit\n+\t)\n+'\n+\n+test_expect_success '3.4.2.3 - fail (remote branch bar missing)' '\n+\tsetup_super &&\n+\t(cd super &&\n+\t setup_sub_state detach $foo_commit &&\n+\t setup_sub_update rebase &&\n+\t setup_sub_branch bar &&\n+\t test_must_fail git submodule update --remote &&\n+\t verify_sub_state detach $foo_commit\n+\t)\n+'\n+\n+test_expect_success '3.4.2.4 - fail (remote branch bar missing)' '\n+\tsetup_super &&\n+\t(cd super &&\n+\t setup_sub_state foo $old_commit &&\n+\t setup_sub_update rebase &&\n+\t setup_sub_branch bar &&\n+\t test_must_fail git submodule update --remote &&\n+\t verify_sub_state foo $old_commit\n+\t)\n+'\n+\n+test_expect_success '3.4.2.5 - fail (remote branch bar missing)' '\n+\tsetup_super &&\n+\t(cd super &&\n+\t setup_sub_state foo $foo_commit &&\n+\t setup_sub_update rebase &&\n+\t setup_sub_branch bar &&\n+\t test_must_fail git submodule update --remote &&\n+\t verify_sub_state foo $foo_commit\n+\t)\n+'\n+\n+test_expect_success '3.4.2.6 - fail (remote branch bar missing)' '\n+\tsetup_super &&\n+\t(cd super &&\n+\t setup_sub_state bar $old_commit &&\n+\t setup_sub_update rebase &&\n+\t setup_sub_branch bar &&\n+\t test_must_fail git submodule update --remote &&\n+\t verify_sub_state bar $old_commit\n+\t)\n+'\n+\n+test_expect_success '3.4.2.7 - fail (remote branch bar missing)' '\n+\tsetup_super &&\n+\t(cd super &&\n+\t setup_sub_state bar $foo_commit &&\n+\t setup_sub_update rebase &&\n+\t setup_sub_branch bar &&\n+\t test_must_fail git submodule update --remote &&\n+\t verify_sub_state bar $foo_commit\n+\t)\n+'\n+\n+# 3.5.* - .branch == bar (MISSING upstream), .update == !command\n+\n+test_expect_success '3.5.1.1 - clone, create branch called bat @ $old_commit. !command is NOT invoked' '\n+\tsetup_super &&\n+\t(cd super &&\n+\t setup_sub_state uncloned &&\n+\t setup_sub_update !false &&\n+\t setup_sub_branch bar &&\n+\t git submodule update && # should not invoke \"false\"\n+\t verify_sub_state detach $old_commit # D4, FIXME: s/detach/bar/?\n+\t)\n+'\n+\n+test_expect_success '3.5.1.2 - already at $old_commit, remain detached. !command is NOT invoked' '\n+\tsetup_super &&\n+\t(cd super &&\n+\t setup_sub_state detach $old_commit &&\n+\t setup_sub_update !false &&\n+\t setup_sub_branch bar &&\n+\t git submodule update && # should not invoke \"false\"\n+\t verify_sub_state detach $old_commit\n+\t)\n+'\n+\n+cat > test_command.sh <<EOF\n+#!/bin/sh\n+# Verify: detached @ $foo_commit, and asked to integrate $old_commit\n+test \"\\$(git symbolic-ref --short -q HEAD)\" = \"\" &&\n+test \"\\$(git rev-parse -q --verify HEAD)\" = \"$foo_commit\" &&\n+test \"\\$1\" = \"$old_commit\" &&\n+git checkout -b success $root_commit\n+EOF\n+chmod +x test_command.sh\n+\n+test_expect_success '3.5.1.3 - !command invoked to integrate $old_commit -> $foo_commit' '\n+\tsetup_super &&\n+\t(cd super &&\n+\t setup_sub_state detach $foo_commit &&\n+\t setup_sub_update !../../test_command.sh &&\n+\t setup_sub_branch bar &&\n+\t git submodule update &&\n+\t verify_sub_state success $root_commit # test_command.sh is happy\n+\t)\n+'\n+\n+test_expect_success '3.5.1.4 - already at $old_commit, remain attached to foo. !command is NOT invoked' '\n+\tsetup_super &&\n+\t(cd super &&\n+\t setup_sub_state foo $old_commit &&\n+\t setup_sub_update !false &&\n+\t setup_sub_branch bar &&\n+\t git submodule update &&\n+\t verify_sub_state foo $old_commit\n+\t)\n+'\n+\n+cat > test_command.sh <<EOF\n+#!/bin/sh\n+# Verify: attached to foo @ $foo_commit, and asked to integrate $old_commit\n+test \"\\$(git symbolic-ref --short -q HEAD)\" = \"foo\" &&\n+test \"\\$(git rev-parse -q --verify HEAD)\" = \"$foo_commit\" &&\n+test \"\\$1\" = \"$old_commit\" &&\n+git checkout -b success $root_commit\n+EOF\n+chmod +x test_command.sh\n+\n+test_expect_success '3.5.1.5 - !command invoked to integrate $old_commit -> foo/$foo_commit' '\n+\tsetup_super &&\n+\t(cd super &&\n+\t setup_sub_state foo $foo_commit &&\n+\t setup_sub_update !../../test_command.sh &&\n+\t setup_sub_branch bar &&\n+\t git submodule update &&\n+\t verify_sub_state success $root_commit # test_command.sh is happy\n+\t)\n+'\n+\n+test_expect_success '3.5.1.6 - already at $old_commit, remain attached to bar. !command is NOT invoked' '\n+\tsetup_super &&\n+\t(cd super &&\n+\t setup_sub_state bar $old_commit &&\n+\t setup_sub_update !false &&\n+\t setup_sub_branch bar &&\n+\t git submodule update &&\n+\t verify_sub_state bar $old_commit\n+\t)\n+'\n+\n+cat > test_command.sh <<EOF\n+#!/bin/sh\n+# Verify: attached to bar @ $foo_commit, and asked to integrate $old_commit\n+test \"\\$(git symbolic-ref --short -q HEAD)\" = \"bar\" &&\n+test \"\\$(git rev-parse -q --verify HEAD)\" = \"$foo_commit\" &&\n+test \"\\$1\" = \"$old_commit\" &&\n+git checkout -b success $root_commit\n+EOF\n+chmod +x test_command.sh\n+\n+test_expect_success '3.5.1.7 - !command invoked to integrate $old_commit -> bar/$foo_commit' '\n+\tsetup_super &&\n+\t(cd super &&\n+\t setup_sub_state bar $foo_commit &&\n+\t setup_sub_update !../../test_command.sh &&\n+\t setup_sub_branch bar &&\n+\t git submodule update &&\n+\t verify_sub_state success $root_commit # test_command.sh is happy\n+\t)\n+'\n+\n+test_expect_failure '3.5.2.1 - fail to clone (remote branch bar missing), leave uncloned' ' # T3, D7\n+\tsetup_super &&\n+\t(cd super &&\n+\t setup_sub_state uncloned &&\n+\t setup_sub_update !false &&\n+\t setup_sub_branch bar &&\n+\t test_must_fail git submodule update --remote &&\n+\t verify_sub_state uncloned\n+\t)\n+'\n+\n+test_expect_success '3.5.2.2 - fail (remote branch bar missing, !command not invoked)' '\n+\tsetup_super &&\n+\t(cd super &&\n+\t setup_sub_state detach $old_commit &&\n+\t setup_sub_update !false &&\n+\t setup_sub_branch bar &&\n+\t test_must_fail git submodule update --remote &&\n+\t verify_sub_state detach $old_commit\n+\t)\n+'\n+\n+test_expect_success '3.5.2.3 - fail (remote branch bar missing, !command not invoked)' '\n+\tsetup_super &&\n+\t(cd super &&\n+\t setup_sub_state detach $foo_commit &&\n+\t setup_sub_update !false &&\n+\t setup_sub_branch bar &&\n+\t test_must_fail git submodule update --remote &&\n+\t verify_sub_state detach $foo_commit\n+\t)\n+'\n+\n+test_expect_success '3.5.2.4 - fail (remote branch bar missing, !command not invoked)' '\n+\tsetup_super &&\n+\t(cd super &&\n+\t setup_sub_state foo $old_commit &&\n+\t setup_sub_update !false &&\n+\t setup_sub_branch bar &&\n+\t test_must_fail git submodule update --remote &&\n+\t verify_sub_state foo $old_commit\n+\t)\n+'\n+\n+test_expect_success '3.5.2.5 - fail (remote branch bar missing, !command not invoked)' '\n+\tsetup_super &&\n+\t(cd super &&\n+\t setup_sub_state foo $foo_commit &&\n+\t setup_sub_update !false &&\n+\t setup_sub_branch bar &&\n+\t test_must_fail git submodule update --remote &&\n+\t verify_sub_state foo $foo_commit\n+\t)\n+'\n+\n+test_expect_success '3.5.2.6 - fail (remote branch bar missing, !command not invoked)' '\n+\tsetup_super &&\n+\t(cd super &&\n+\t setup_sub_state bar $old_commit &&\n+\t setup_sub_update !false &&\n+\t setup_sub_branch bar &&\n+\t test_must_fail git submodule update --remote &&\n+\t verify_sub_state bar $old_commit\n+\t)\n+'\n+\n+test_expect_success '3.5.2.7 - fail (remote branch bar missing, !command not invoked)' '\n+\tsetup_super &&\n+\t(cd super &&\n+\t setup_sub_state bar $foo_commit &&\n+\t setup_sub_update !false &&\n+\t setup_sub_branch bar &&\n+\t test_must_fail git submodule update --remote &&\n+\t verify_sub_state bar $foo_commit\n+\t)\n+'\n+\n+test_done\n-- \n1.9.1.587.g6ba9303\n"},{"id":"238951","messageId":"20140416172153.GW21805@odin.tremily.us","threadId":"36417","inReplyTo":"1397609688-25634-1-git-send-email-johan@herland.net","subject":"Re: [RFC] t7410: 210 tests for various 'git submodule update' scenarios","fromName":"W. Trevor King","fromEmail":"wking@tremily.us","sentAt":"2014-04-16T17:21:53Z","receivedAt":"2014-04-16T17:21:53Z","isPatch":false,"sender":{"key":"wking@tremily.us","avatar":"https://avatars.githubusercontent.com/u/209920?v=4"},"body":"On Wed, Apr 16, 2014 at 02:54:48AM +0200, Johan Herland wrote:\n> This is a work-in-progress to flesh out (and promote discussion about)\n> the expected behaviors for all possible scenarios in which\n> 'git submodule update' might be run.\n\nThis is lovely :).\n\n> +#  - current state of submodule:\n> +#     ?.?.?.1 - not yet cloned\n> +#     ?.?.?.2 - cloned, detached, HEAD == gitlink\n> +#     ?.?.?.3 - cloned, detached, HEAD != gitlink\n> +#     ?.?.?.4 - cloned, on branch foo (exists upstream), HEAD == gitlink\n> +#     ?.?.?.5 - cloned, on branch foo (exists upstream), HEAD != gitlink\n> +#     ?.?.?.6 - cloned, on branch bar (MISSING upstream), HEAD == gitlink\n> +#     ?.?.?.7 - cloned, on branch bar (MISSING upstream), HEAD != gitlink\n\nThe remote branches should only matter for the initial clone and\n--remote updates.  Also, only the configured submodule.<name>.branch\n(your first axis) should be checked; the locally checked-out submodule\nbranch shouldn't matter.\n\n> +# T2: Test with submodule.<name>.url != submodule's remote.origin.url. Does\n> +#     \"submodule update --remote\" sync with submodule.<name>.url, or with the\n> +#     submodule's origin? (or with the submodule's current branch's upstream)?\n\nAll fetches should currently use the submodule's remote.origin.url.\nsubmodule.<name>.url is only used for the initial clone (*.*.*.1), and\nnever referenced again.  This would change using my tightly-bound\nsubmodule proposal [1], where a difference between\nsubmodule.<name>.url and the submodule's @{upstream} URL would be\ntrigger a dirty-tree condition (for folks with tight-bind syncing\nenabled) from which you couldn't update before resolving the\ndifference.\n\n> +# D1: When submodule is already at right commit, checkout-mode currently does\n> +#     nothing. Should it instead detach, even when no update is needed?\n> +#     Affects: 1.2.1.4, 1.2.1.6, 2.2.1.4, 2.2.1.6, 3.2.1.4, 3.2.1.6\n\n“Checkout updates always leave a detached HEAD” seems easier to\nexplain, so I'm leaning that way.\n\n> +# D2: Should all/some of 1.3.*/1.4.* abort/error because we don't know what to\n> +#     merge/rebase with (because .branch is unset)? Or is the current default\n> +#     to origin/HEAD OK?\n> +#     Affects: 1.3.*, 1.4.*\n\nMaybe you mean 1.3.*, 1.4.*, and 1.5.* (merge, rebase, and !command)?\nIn all of these cases, we're integrating the current HEAD with the\ngitlinked (*.*.1.*) or remote-tracking branch (*.*.2.*).  Since\nsubmodule.<name>.branch defaults to master (and may be changed to HEAD\nafter a long transition period? [2,3]), I don't think we should\nabort/error in those cases.\n\n> +# D3: When submodule is already at right commit, merge/rebase-mode currently\n> +#     does nothing. Should it do something else (e.g. not leave submodule\n> +#     detached, or checked out on the \"wrong\" branch (i.e. != .branch))?\n> +#     (This discussion point is related to D1, D5 and D6)\n\n“Non-checkout updates always leave you on a branch” seems easier to\nexplain, but I think we'd want to distinguish between the local branch\nand the remote submodule.<name>.branch [1].  Lacking that distinction,\nI'd prefer to leave the checked-out branch unchanged.\n\n> +# D4: When 'submodule update' performs a clone to populate a submodule, it\n> +#     currently also creates a default branch (named after origin/HEAD) in\n> +#     that submodule, EVEN WHEN THAT BRANCH WILL NEVER BE USED (e.g. because\n> +#     we're in checkout-mode and submodule will always be detached). Is this\n> +#     good, or should the clone performed by 'submodule update' skip the\n> +#     automatic local branch creation?\n> +#     Affects: 1.2.*.1, 1.3.*.1, 1.4.*.1, 1.5.*.1,\n> +#              2.2.*.1, 2.3.*.1, 2.4.*.1, 2.5.*.1,\n> +#              3.2.1.1, 3.3.1.1, 3.4.1.1, 3.5.1.1\n\n“Checkout updates always leave a detached HEAD” seems easier to\nexplain, so I'm leaning that way.\n\n> +# D5: When in merge/rebase-mode, and 'submodule update' actually ends up doing\n> +#     a merge/rebase, that will happen on the current branch (or detached HEAD)\n> +#     and NOT on the configured (or default) .branch. Is this OK? Should we\n> +#     abort (or at least warn) instead? (In general, .branch seems only to\n> +#     affect the submodule's HEAD when the submodule is first cloned.)\n> +#     (This discussion point is related to D3 and D6)\n> +#     Affects: 1.3.1.3, 1.3.1.5, 1.3.1.7, 1.3.2.>=2,\n> +#              1.4.1.3, 1.4.1.5, 1.4.1.7, 1.4.2.>=2,\n> +#              2.3.1.3, 2.3.1.5, 2.3.1.7, 2.3.2.2, 2.3.2.4, 2.3.2.6,\n> +#              2.4.1.3, 2.4.1.5, 2.4.1.7, 2.4.2.2, 2.4.2.4, 2.4.2.6\n> +#              3.3.1.3, 3.3.1.5, 3.3.1.7\n> +#              3.4.1.3, 3.4.1.5, 3.4.1.7\n\nWith the --remote option that added submodule.<name>.branch (which\neventually landed with v8 of that series [4]), I initially imagined it\nas the name of the local branch [5], but transitioned to imagining it\nas the name of the remote-tracking branch in v5 of that series [6].\nThere were no major logical changes between v5 and v8.  With the v8\nversion that landed in Git v1.8.2, submodule.<name>.branch was clearly\nthe name of the remote-tracking branch, and we gave no way to\nseparately configure the local branch.\n\nRecently, we decided that local branches might be important after all\n[7], which lead to the partially landed v5 of my local-branch-creation\nseries [8], now partially reverted with d851ffb (Revert \"submodule:\nexplicit local branch creation in module_clone\", 2014-04-02).  Like v4\nof that series [9], I considered the landed-and-now-reverted v5 to be\na stop-gap until we got better local-branch handling.\n\nAnyhow, that's why submodule.<name>.branch is only important when we\ninteract with the remote repository (during clones and --remote\nupdates).  We've never landed a patch that explicitly addresses what\nthe local branch should be.\n\n> +# D6: The meaning of submodule.<name>.branch is initially confusing, as it does\n> +#     not really concern the submodule's local branch (except as a naming hint\n> +#     when the submodule is first cloned). Instead, submodule.<name>.branch is\n> +#     really about which branch in the _upstream_ submodule\n\nWhich is how gitmodules(5) explains it:\n\n  submodule.<name>.branch\n    A remote branch name for tracking updates…\n\n> +#     submodule.<name>.url, or by the submodule's remote.origin.url?)\n> +#     want to integrate with.\n\nThe submodule's remote.origin.url for everything except the initial\nclone (*.*.*.1).  See my response to T2.\n\n> …                               This is probably the more useful setting, and it\n> +#     becomes obviously correct after (re-)reading gitmodules(5) and\n> +#     git-config(1). However, from just reading the \"update\" section in\n> +#     git-submodule(1) (or not even that), things are not so clear-cut. Would\n> +#     submodule.<name>.upstream (or .remote-branch, or similar) be a better\n> +#     name for this?\n\nAre the docs from 23d25e4 (submodule: explicit local branch creation\nin module_clone, 2014-01-26; now reverted with d851ffb, Revert\n\"submodule: explicit local branch creation in module_clone\",\n2014-04-02) clearer?  Maybe we can salvage some of those docs even\nthough we've reverted the actual code changes?\n\n> +# D7: What to do when .branch refers to a branch that is missing from upstream?\n> +#     Currently, when trying to clone, the clone fails (which causes 'git\n> +#     submodule update --remote' to fail), but leaves the submodule in an\n> +#     uninitialized state (there is a .git, but the work tree is missing).\n> +#     This is probably not the behavior we want...\n> +#     Affects: pre, 3.2.2.1, 3.3.2.1, 3.4.2.1, 3.5.2.1\n\nI think we should remove the submodule's .git file after the failed clone.\n\nCheers,\nTrevor\n\n[1]: http://thread.gmane.org/gmane.comp.version-control.git/240336\n[2]: http://thread.gmane.org/gmane.comp.version-control.git/245283\n[3]: http://thread.gmane.org/gmane.comp.version-control.git/245357\n[4]: http://thread.gmane.org/gmane.comp.version-control.git/211830\n[5]: http://article.gmane.org/gmane.comp.version-control.git/210730\n[6]: http://article.gmane.org/gmane.comp.version-control.git/210764\n[7]: http://thread.gmane.org/gmane.comp.version-control.git/239799\n[8]: http://thread.gmane.org/gmane.comp.version-control.git/241112\n[9]: http://article.gmane.org/gmane.comp.version-control.git/240498\n\n-- \nThis email may be signed or encrypted with GnuPG (http://www.gnupg.org).\nFor more information, see http://en.wikipedia.org/wiki/Pretty_Good_Privacy\n"},{"id":"239013","messageId":"CALKQrgfF2Kkk4itvtm_yU9qm9GrJf-DWQQG8y+CAwisOUqY=eg@mail.gmail.com","threadId":"36417","inReplyTo":"20140416172153.GW21805@odin.tremily.us","subject":"Re: [RFC] t7410: 210 tests for various 'git submodule update' scenarios","fromName":"Johan Herland","fromEmail":"johan@herland.net","sentAt":"2014-04-17T11:42:42Z","receivedAt":"2014-04-17T11:42:42Z","isPatch":false,"sender":{"key":"johan@herland.net","avatar":"https://avatars.githubusercontent.com/u/547031?v=4"},"body":"TL;DR: I believe the update-related submodule.<name>.* options\n(.branch, .update, .url, and even the --remote option) are\nslowly growing into a separate DSL for specfying how to update\nsubmodules. This adds a confusing and opaque layer in front of\nwhat is essentially git commands run by \"git submodule update\"\nwithin the submodule. Instead of adding more submodule.<name>.*\noptions to handle even more use cases, we should scale back on\nthe config options, and allow the user to specify what should\nhappen on \"git submodule update\" in the existing language of\ngit commands.\n\nOn Wed, Apr 16, 2014 at 7:21 PM, W. Trevor King <wking@tremily.us> wrote:\n> On Wed, Apr 16, 2014 at 02:54:48AM +0200, Johan Herland wrote:\n>> This is a work-in-progress to flesh out (and promote discussion about)\n>> the expected behaviors for all possible scenarios in which\n>> 'git submodule update' might be run.\n>\n> This is lovely :).\n\nThanks!\n\nHaving been active in git-submodule development a few years ago,\nI thought I had a fairly firm grasp of most details regarding\nsubmodules, but when I recently tried to explain to someone how\n\"git submodule update\" was supposed to work, I quickly found that\nI had forgotten a lot, and that git-submodule had also changed.\nAfter (albeit casually) reading the docs, I still didn't feel much\nwiser, and this humongous testcase is sort of my ultimate attempt\nto regain some understanding.\n\nSo far, my impression is that there are too many details/variables\nand too much state to be able to sanely comprehend what is the intended\nbehavior in all cases, much less document in a way that is approachable\nto regular users...\n\n>> +#  - current state of submodule:\n>> +#     ?.?.?.1 - not yet cloned\n>> +#     ?.?.?.2 - cloned, detached, HEAD == gitlink\n>> +#     ?.?.?.3 - cloned, detached, HEAD != gitlink\n>> +#     ?.?.?.4 - cloned, on branch foo (exists upstream), HEAD == gitlink\n>> +#     ?.?.?.5 - cloned, on branch foo (exists upstream), HEAD != gitlink\n>> +#     ?.?.?.6 - cloned, on branch bar (MISSING upstream), HEAD == gitlink\n>> +#     ?.?.?.7 - cloned, on branch bar (MISSING upstream), HEAD != gitlink\n>\n> The remote branches should only matter for the initial clone and\n> --remote updates.  Also, only the configured submodule.<name>.branch\n> (your first axis) should be checked; the locally checked-out submodule\n> branch shouldn't matter.\n\nYes, I realized that while working out the various cases, but it was\nnot at all obvious from the start, given that the config option is\ncalled submodule.<name>.branch and not submodule.<name>.upstream or\nsimilar (which might prevent a casual user from misinterpreting the\noption as having something to do with the current local branch in the\nsubmodule). See D6 for more discussion about the naming of .branch.\n\nIn general, I experimented with a few different ways of organizing the\naxes to get a \"flow\" of testcases that more naturally \"revealed\" the\nbehavior of \"git submodule update\", but I haven't found a good\norganization, yet. I suspect there is none...\n\n>> +# T2: Test with submodule.<name>.url != submodule's remote.origin.url. Does\n>> +#     \"submodule update --remote\" sync with submodule.<name>.url, or with the\n>> +#     submodule's origin? (or with the submodule's current branch's upstream)?\n>\n> All fetches should currently use the submodule's remote.origin.url.\n> submodule.<name>.url is only used for the initial clone (*.*.*.1), and\n> never referenced again.  This would change using my tightly-bound\n> submodule proposal [1], where a difference between\n> submodule.<name>.url and the submodule's @{upstream} URL would be\n> trigger a dirty-tree condition (for folks with tight-bind syncing\n> enabled) from which you couldn't update before resolving the\n> difference.\n\nOk. As stated above, I am worried about the amount of duplicated\nstate between the superproject's submodule config (which itself is\nsplit between .gitmodules and .git/config) and the submodule's own\nconfig. And from the above paragraph, I suspect two more dimensions\nneed to be added to the test matrix:\n\n - submodule's remote.origin.url ==/!= submodule.<name>.url\n\n - \"tightly-bound submodule\" is enabled/disabled\n\nEven if we might successfully deal with the duplicate state (and the\nexploding test matrix), it will certainly not be easy to\ndescribe/document the intended behavior in a way that's simple to\ngrasp and straightforward to use.\n\nWe should instead seek ways to minimize the duplication of state.\nIf it is indeed the case that several submodule.<name>.* values in the\nsuperproject are only consulted _once_ (when cloning the submodule),\nwe should make it obvious that they will not be used after the clone\nis done. Similarly, we should make it obvious that the update-related\noptions only apply exactly when \"git submodule update\" is run.\n\nWhat about something like this:\n\n - submodule.<name>.create: The command that will be used by\n   \"git submodule update\" to initially populate the contents of\n   the submodule. The command is run from within the submodule\n   directory, and the following environment variables are available:\n\n    - $SUPER_URL: The URL of the superproject's current upstream\n      remote.\n\n    - $SUPER_HEAD: The current value of the superproject's HEAD.\n      Typically a refname, but may be commit id (if detached).\n\n    - $GITLINK: The current value of the superproject's gitlink\n      for this submodule.\n\n   Example values for submodule.<name>.create:\n\n    - 'git clone -n $SUPER_URL/../sub.git . && git reset --hard $GITLINK'\n      This clones from a relative submodule URL (by using $SUPER_URL),\n      and then does a detached checkout of $GITLINK. This would be\n      equivalent to the current \"checkout-mode\".\n\n    - 'git clone -n git://url.to/sub.git . && git checkout dev-branch'\n      This clones from an absolute submodule URL, and then (assuming\n      \"dev-branch\" exists upstream, which triggers a checkout's DWIM\n      behavior) creates a local \"dev-branch\" with origin/dev-branch\n      as its upstream. This would be a suitable start point for\n      developing on \"dev-branch\" in the submodule.\n\n    - 'git clone -n -c branch.autosetuprebase=remote git://url.to/sub.git . \\\n       && git checkout dev-branch'\n      Same as above, but prepares for a rebase-style workflow instead.\n\n - submodule.<name>.update: The command that will be run within the\n   already-existing submodule by \"git submodule update\". The same\n   enviroment variables as above are available. Example values for\n   submodule.<name>.update:\n\n    - 'git reset --hard $GITLINK'\n      Equivalent to checkout-mode (without --remote).\n\n    - 'git fetch && git reset --hard origin/HEAD'\n      Equivalent to checkout-mode with --remote.\n\n    - 'git merge $GITLINK'\n      Equivalent to merge-mode (without --remote).\n\n    - 'git pull origin next'\n      Equivalent to merge-mode with --remote and .branch == next.\n\n    - 'git rebase $GITLINK'\n      Equivalent to rebase-mode (without --remote)\n\n    - 'git pull --rebase origin pu'\n      Equivalent to rebase-mode with --remote and .branch == pu.\n\n    - 'git pull'\n      Defer completely to the submodule's own config.\n\nPros/Cons:\n\n Pro: It is obvious to everybody exactly what will happen when\n      \"git submodule update\" is run.\n\n Pro: We no longer duplicate state with the submodule's config.\n      Instead, it is obvious when and how these options modify\n      the submodule, and whether or not they operate independently\n      of the submodule's own config.\n\n Pro: We reuse the current \"language\" (of git commands and\n      command-line options) for describing how to perform updates,\n      instead of having to invent a duplicate (but terser) language\n      in the form of submodule.<name>.* options.\n\n Pro: With just a couple of options, we can obsolete most of the\n      existing submodule.<name>.* options:\n\n       - .branch == $foo is replaced by \"git pull origin $foo\" in\n         the new .update command.\n\n       - .update == none/checkout/merge/rebase is replaced by an\n         appropriate git command in the new .update command.\n\n       - .url becomes a 'clone' argument in the .create command.\n\n       - The --remote option is replaced by updating against remote\n         .branch instead of $GITLINK\n\n Pro: Allows for ultimate flexibility in handling submodule updates\n      without increasing the pressure to keep adding\n      submodule.<name>.* options.\n\n Con: Wildly backwards-incompatible with existing submodule.* configs.\n\n Con: Probably missing proper error handling and/or other handling of\n      corner cases in the above example commands.\n\n Con: A user who has copied/modified these options into his\n      superproject's .git/config will manually have to reconcile that\n      with any future updates to .gitmodules.\n\n Con: Too much information in each config option? Maybe consider using\n      hooks instead of config options?\n\n>> +# D1: When submodule is already at right commit, checkout-mode currently does\n>> +#     nothing. Should it instead detach, even when no update is needed?\n>> +#     Affects: 1.2.1.4, 1.2.1.6, 2.2.1.4, 2.2.1.6, 3.2.1.4, 3.2.1.6\n>\n> “Checkout updates always leave a detached HEAD” seems easier to\n> explain, so I'm leaning that way.\n\nYes, although I suspect different people using different workflows will\nhave different (but valid) opinions on how this should be handled.\nWhich is why I'm approaching the conclusion outlined in the TL;DR; i.e.\nthat adding more submodule.<name>.* options (which often interacts\nwith other options in complex ways) is probably NOT the way to go.\n\nInstead, we should recognize that people may want to have their\nsubmodules updated in so many different ways, that trying to encode it\nin a collection of submodule.<name>.* options is pointless. We can then\nprovide something more flexible that reuses existing syntax, like the\n\"free-form\" options suggested above, or maybe a \"submodule-update\" hook\nthat allows even more customization.\n\nObviously, we should still have good defaults to deal with the most\ncommon cases, but the current set of options is growing too large to be\nunderstandable by most users.\n\n>> +# D2: Should all/some of 1.3.*/1.4.* abort/error because we don't know what to\n>> +#     merge/rebase with (because .branch is unset)? Or is the current default\n>> +#     to origin/HEAD OK?\n>> +#     Affects: 1.3.*, 1.4.*\n>\n> Maybe you mean 1.3.*, 1.4.*, and 1.5.* (merge, rebase, and !command)?\n> In all of these cases, we're integrating the current HEAD with the\n> gitlinked (*.*.1.*) or remote-tracking branch (*.*.2.*).  Since\n> submodule.<name>.branch defaults to master (and may be changed to HEAD\n> after a long transition period? [2,3]), I don't think we should\n> abort/error in those cases.\n\nYes, it seems we're settling on origin/HEAD as an acceptable default.\n\n>> +# D3: When submodule is already at right commit, merge/rebase-mode currently\n>> +#     does nothing. Should it do something else (e.g. not leave submodule\n>> +#     detached, or checked out on the \"wrong\" branch (i.e. != .branch))?\n>> +#     (This discussion point is related to D1, D5 and D6)\n>\n> “Non-checkout updates always leave you on a branch” seems easier to\n> explain, but I think we'd want to distinguish between the local branch\n> and the remote submodule.<name>.branch [1].  Lacking that distinction,\n> I'd prefer to leave the checked-out branch unchanged.\n\nYes, although again I feel that we are making policy decision based on\nwhat we _believe_ would be ok in our use cases. Adding a .local-branch\nconfig option to specify what happens to the local branch would maybe\nfix things for other use cases, but it would also compound the overall\ncomplexity of \"submodule update\". See above arguments for replacing\nconfig options with explicit git commands, to make \"submodule update\"\nmore transparent.\n\n>> +# D4: When 'submodule update' performs a clone to populate a submodule, it\n>> +#     currently also creates a default branch (named after origin/HEAD) in\n>> +#     that submodule, EVEN WHEN THAT BRANCH WILL NEVER BE USED (e.g. because\n>> +#     we're in checkout-mode and submodule will always be detached). Is this\n>> +#     good, or should the clone performed by 'submodule update' skip the\n>> +#     automatic local branch creation?\n>> +#     Affects: 1.2.*.1, 1.3.*.1, 1.4.*.1, 1.5.*.1,\n>> +#              2.2.*.1, 2.3.*.1, 2.4.*.1, 2.5.*.1,\n>> +#              3.2.1.1, 3.3.1.1, 3.4.1.1, 3.5.1.1\n>\n> “Checkout updates always leave a detached HEAD” seems easier to\n> explain, so I'm leaning that way.\n\nThis is not about detached HEAD. This is about the \"extra\" local branch\nautomatically created by \"git clone\". This branch is unused and\nunnecessary in checkout-mode, and only coincidentally useful in other\nmodes (when .branch == origin/HEAD).\n\nHowever, this is probably a git-clone problem, and not a git-submodule\nproblem: I am surprised that \"git clone --no-checkout\" produces the\nsame local branch (without checking it out). I would instead have\nexpected the clone to only have the refs/remote/origin/* refs (and\nHEAD pointing to an unborn branch - like \"git init\" does).\n\n>> +# D5: When in merge/rebase-mode, and 'submodule update' actually ends up doing\n>> +#     a merge/rebase, that will happen on the current branch (or detached HEAD)\n>> +#     and NOT on the configured (or default) .branch. Is this OK? Should we\n>> +#     abort (or at least warn) instead? (In general, .branch seems only to\n>> +#     affect the submodule's HEAD when the submodule is first cloned.)\n>> +#     (This discussion point is related to D3 and D6)\n>> +#     Affects: 1.3.1.3, 1.3.1.5, 1.3.1.7, 1.3.2.>=2,\n>> +#              1.4.1.3, 1.4.1.5, 1.4.1.7, 1.4.2.>=2,\n>> +#              2.3.1.3, 2.3.1.5, 2.3.1.7, 2.3.2.2, 2.3.2.4, 2.3.2.6,\n>> +#              2.4.1.3, 2.4.1.5, 2.4.1.7, 2.4.2.2, 2.4.2.4, 2.4.2.6\n>> +#              3.3.1.3, 3.3.1.5, 3.3.1.7\n>> +#              3.4.1.3, 3.4.1.5, 3.4.1.7\n>\n> With the --remote option that added submodule.<name>.branch (which\n> eventually landed with v8 of that series [4]), I initially imagined it\n> as the name of the local branch [5], but transitioned to imagining it\n> as the name of the remote-tracking branch in v5 of that series [6].\n> There were no major logical changes between v5 and v8.  With the v8\n> version that landed in Git v1.8.2, submodule.<name>.branch was clearly\n> the name of the remote-tracking branch, and we gave no way to\n> separately configure the local branch.\n\nFirst of all, shame on me for not following the discussion at the time.\nI still think that when the meaning changed from local to remote-\ntracking branch, the actual option name should have changed as well.\nDocumenting that it specifies a remote branch is good, but not as good\nas choosing a better name for it in the first place.\n\n> Recently, we decided that local branches might be important after all\n> [7], which lead to the partially landed v5 of my local-branch-creation\n> series [8], now partially reverted with d851ffb (Revert \"submodule:\n> explicit local branch creation in module_clone\", 2014-04-02).  Like v4\n> of that series [9], I considered the landed-and-now-reverted v5 to be\n> a stop-gap until we got better local-branch handling.\n>\n> Anyhow, that's why submodule.<name>.branch is only important when we\n> interact with the remote repository (during clones and --remote\n> updates).  We've never landed a patch that explicitly addresses what\n> the local branch should be.\n\nThanks for the recap. I now realize that my above arguments against\nincreased complexity in submodule.<name>.* options arrive way too\nlate, and is probably more like trolling than like constructive input.\nI am sorry for having been absent during most of this discussion.\nStill, I'm afraid that the current set of options are so complex that\nthey will only ever be fully understood by the very small set of people\ninvolved with their development.\n\n>> +# D6: The meaning of submodule.<name>.branch is initially confusing, as it does\n>> +#     not really concern the submodule's local branch (except as a naming hint\n>> +#     when the submodule is first cloned). Instead, submodule.<name>.branch is\n>> +#     really about which branch in the _upstream_ submodule\n>\n> Which is how gitmodules(5) explains it:\n>\n>   submodule.<name>.branch\n>     A remote branch name for tracking updates…\n\nGood, but I fear gitmodules(5) is too hidden for the regular user.\nIt'd be better to mention this in git-submodule(1), as I expect\ngitmodules(5) is largely read by .gitmodules _authors_, and not\nregular users. Obviously, the real fix would be a better name...\n\n>> +#     submodule.<name>.url, or by the submodule's remote.origin.url?)\n>> +#     want to integrate with.\n>\n> The submodule's remote.origin.url for everything except the initial\n> clone (*.*.*.1).  See my response to T2.\n\nAs mentioned above, submodule.<name>.url is then an unnecessary state\nduplication. We should make it more obvious that it is only ever used\non the initial clone (see my above argument for moving .url into an\nexplicit git-clone command)\n\n>> …                               This is probably the more useful setting, and it\n>> +#     becomes obviously correct after (re-)reading gitmodules(5) and\n>> +#     git-config(1). However, from just reading the \"update\" section in\n>> +#     git-submodule(1) (or not even that), things are not so clear-cut. Would\n>> +#     submodule.<name>.upstream (or .remote-branch, or similar) be a better\n>> +#     name for this?\n>\n> Are the docs from 23d25e4 (submodule: explicit local branch creation\n> in module_clone, 2014-01-26; now reverted with d851ffb, Revert\n> \"submodule: explicit local branch creation in module_clone\",\n> 2014-04-02) clearer?  Maybe we can salvage some of those docs even\n> though we've reverted the actual code changes?\n\nAs I said above, better docs is good, but no replacement for a better\nnamed option.\n\n>> +# D7: What to do when .branch refers to a branch that is missing from upstream?\n>> +#     Currently, when trying to clone, the clone fails (which causes 'git\n>> +#     submodule update --remote' to fail), but leaves the submodule in an\n>> +#     uninitialized state (there is a .git, but the work tree is missing).\n>> +#     This is probably not the behavior we want...\n>> +#     Affects: pre, 3.2.2.1, 3.3.2.1, 3.4.2.1, 3.5.2.1\n>\n> I think we should remove the submodule's .git file after the failed clone.\n\nAgreed, but does that extend to the superproject's .git/modules/<name> too?\n\n\nAgain, sorry for the length and lateness of this discussion. I still\nhope it may be of some use, though.\n\n...Johan\n\n--\nJohan Herland, <johan@herland.net>\nwww.herland.net\n"},{"id":"239016","messageId":"20140417153109.GM21805@odin.tremily.us","threadId":"36417","inReplyTo":"CALKQrgfF2Kkk4itvtm_yU9qm9GrJf-DWQQG8y+CAwisOUqY=eg@mail.gmail.com","subject":"Re: [RFC] t7410: 210 tests for various 'git submodule update' scenarios","fromName":"W. Trevor King","fromEmail":"wking@tremily.us","sentAt":"2014-04-17T15:31:09Z","receivedAt":"2014-04-17T15:31:09Z","isPatch":false,"sender":{"key":"wking@tremily.us","avatar":"https://avatars.githubusercontent.com/u/209920?v=4"},"body":"On Thu, Apr 17, 2014 at 01:42:42PM +0200, Johan Herland wrote:\n> >> +# T2: Test with submodule.<name>.url != submodule's remote.origin.url. Does\n> >> +#     \"submodule update --remote\" sync with submodule.<name>.url, or with the\n> >> +#     submodule's origin? (or with the submodule's current branch's upstream)?\n> >\n> > All fetches should currently use the submodule's remote.origin.url.\n> > submodule.<name>.url is only used for the initial clone (*.*.*.1), and\n> > never referenced again.  This would change using my tightly-bound\n> > submodule proposal [1], where a difference between\n> > submodule.<name>.url and the submodule's @{upstream} URL would be\n> > trigger a dirty-tree condition (for folks with tight-bind syncing\n> > enabled) from which you couldn't update before resolving the\n> > difference.\n> \n> Ok. As stated above, I am worried about the amount of duplicated\n> state between the superproject's submodule config (which itself is\n> split between .gitmodules and .git/config) and the submodule's own\n> config. And from the above paragraph, I suspect two more dimensions\n> need to be added to the test matrix:\n> \n>  - submodule's remote.origin.url ==/!= submodule.<name>.url\n> \n>  - \"tightly-bound submodule\" is enabled/disabled\n\nTight-binding hasn't been implemented yet, or even accumulated much\nsupport from other folks ;).  However, the idea is to unify the state\nbetween the superproject's .gitmodules and .git/config and the\nsubmodule's .git/config (or ../.git/modules/<name>/config, or\nwhatever).  Then folks with tightly-bound syncing enabled have only\none state space to maintain (and get auto-updates for each\nsuperproject checkout), and folks who opt-out of tightly-bound syncing\nare presumably embracing the complexity of our current system, with\nit's two, confusingly-aligned configuration spaces.\n\nI'm happy to force syncing (i.e. no opting-out allowed) [1], but I\nimagine there are folks who would resist ;).  Maybe a deprecation\nperiod to help ease the transition?  This is all assuming that I get\nmore folks to buy into the tight-syncing ;).\n\nThe end-goal of my tightly-bound approach is to remove 'submodule\nupdate' altogether and end up with a simpler interface [2]:\n\nOn Sat, Jan 11, 2014 at 05:08:47PM -0800, W. Trevor King wrote:\n> * git submodule [--quiet] add [-b <branch>] [-f|--force] [--name <name>]\n>                 [--reference <repository>] [--] <repository> [<path>]\n> * git submodule [--quiet] init [--] [<path>...]\n> * git submodule [--quiet] deinit [-f|--force] [--] <path>...\n> * git submodule [--quiet] foreach [--recursive] <command>\n\nAll of this 'submodule update' integration confusion would be resolved\nby the developer who updated the gitlink, and superproject checkouts\nwould just swap the local submodule branch/HEAD without having to\nworry about clobbering uncommitted state.\n\nOn Thu, Apr 17, 2014 at 01:42:42PM +0200, Johan Herland wrote:\n> We should instead seek ways to minimize the duplication of state.\n\nThe tightly-bound-submodules I'm proposing try to use the submodule's\nconfig settings (plus submodule.<name>.local-branch) as the familiar\nlanguage, while your proposal uses Git commands as the familiar\nlanguage.  I think both would work, but config settings are easier to\nparse automatically, which helps with automatically syncing between\nthe superproject and submodule configs.  Syncing, in turn, helps\nbridge the gap between the easily shared superproject/.gitmodules and\nsuperproject/.git/modules/<name>/config (enabling familiar-to-use Git\ncommands in the submodule).\n\n>  - submodule.<name>.create: …\n\nSyncing submodule state back up into this is going to be a manual\noperation.  For example, changing the submodule's remote.origin.url is\ngoing to require hand-tweaking to update this setting.\n\n>  - submodule.<name>.update: …\n>     …\n>     - 'git reset --hard $GITLINK'\n>       Equivalent to checkout-mode (without --remote).\n> \n>     - 'git fetch && git reset --hard origin/HEAD'\n>       Equivalent to checkout-mode with --remote.\n\nFolks who sometimes use --remote updates will still need non-remote\nupdates.  For example, if Alice and Bob are both developers on the\nsame superproject:\n\n  alice$ git submodule update --recursive --remote # integrate upstream changes\n  alice$ git commit -m 'Bumped submodules to upstream tips'\n  alice$ git push\n  bob$ git pull\n  bob$ git submodule update --recursive # integrate Alice's gitlink changes\n\nso it should be easy to toggle back and forth between the two\nintegration targets.  However:\n\n  git fetch && git reset --hard origin/HEAD\n\nis easy to run using 'git submodule foreach', or after changing into\nthe submodule directory, so I'm not particularly concerned here.\n\nWith tight-binding and superproject-checkout-time auto-updates, the\nabove would be:\n\n  alice$ git submodule foreach --recursive 'git pull'\n  alice$ git commit -m 'Bumped submodules to upstream tips'\n  alice$ git push\n  bob$ git pull  # update to Alice's new gitlinks happens automatically\n\nAnother problem with a single submodule.<name>.update is if I want to\npull origin/HEAD into my submodule's master branch, but origin/dev\ninto my dev and feature-x branches (table and further discussion in\n[3]).  That's not going to pack down into a single command.  In [3], I\nlay out how you could setup per-superproject-branch configs for\n.local-branch; you'd need something similar for .update.\n\n> I now realize that my above arguments against increased complexity\n> in submodule.<name>.* options arrive way too late, and is probably\n> more like trolling than like constructive input.\n\nI'm happy to have more input :).  It's hard to imagine an interface so\npolished that it can't be improved, and the current submodule\ninterface is certainly well short of that hypothetical goal ;).\n\n> >> +# D6: The meaning of submodule.<name>.branch is initially confusing, as it does\n> >> +#     not really concern the submodule's local branch (except as a naming hint\n> >> +#     when the submodule is first cloned). Instead, submodule.<name>.branch is\n> >> +#     really about which branch in the _upstream_ submodule\n> >\n> > Which is how gitmodules(5) explains it:\n> >\n> >   submodule.<name>.branch\n> >     A remote branch name for tracking updates…\n> \n> Good, but I fear gitmodules(5) is too hidden for the regular user.\n> It'd be better to mention this in git-submodule(1), as I expect\n> gitmodules(5) is largely read by .gitmodules _authors_, and not\n> regular users. Obviously, the real fix would be a better name...\n\nI'm fine with a rename to .remote-branch.  Migrating through a config\nrename should be pretty easy to do, but it's going to make future\nchanges more difficult until the migration wraps up $n releases in the\nfuture.  I'd prefer jumping straight to my tight-binding approach,\nthough; where --remote updates are replaced by the more familiar:\n\n  $ git submodule foreach [--recursive] 'git pull …'\n\n> >> +#     submodule.<name>.url, or by the submodule's remote.origin.url?)\n> >> +#     want to integrate with.\n> >\n> > The submodule's remote.origin.url for everything except the initial\n> > clone (*.*.*.1).  See my response to T2.\n> \n> As mentioned above, submodule.<name>.url is then an unnecessary state\n> duplication.\n\nIt's not unnecessary before you've cloned.  And you'll also want to\nupdate it if you change the submodule's remote.origin.url, so other\nfolks (who haven't cloned yet) aren't stranded with the old URL.\n\n> >> +# D7: What to do when .branch refers to a branch that is missing from upstream?\n> >> +#     Currently, when trying to clone, the clone fails (which causes 'git\n> >> +#     submodule update --remote' to fail), but leaves the submodule in an\n> >> +#     uninitialized state (there is a .git, but the work tree is missing).\n> >> +#     This is probably not the behavior we want...\n> >> +#     Affects: pre, 3.2.2.1, 3.3.2.1, 3.4.2.1, 3.5.2.1\n> >\n> > I think we should remove the submodule's .git file after the failed clone.\n> \n> Agreed, but does that extend to the superproject's .git/modules/<name> too?\n\nThat's what 'git clone' usually does, so yes.  Ideally we'd add a\ncheck to the initial clone that bailed out before fetching tons of\nobjects in the event that the referenced branch / commit was not\npresent on the remote.\n\nCheers,\nTrevor\n\n[1]: http://article.gmane.org/gmane.comp.version-control.git/240370\n[2]: http://article.gmane.org/gmane.comp.version-control.git/240336\n[3]: http://article.gmane.org/gmane.comp.version-control.git/240251\n\n-- \nThis email may be signed or encrypted with GnuPG (http://www.gnupg.org).\nFor more information, see http://en.wikipedia.org/wiki/Pretty_Good_Privacy\n"},{"id":"239018","messageId":"534FFB9A.3010701@web.de","threadId":"36417","inReplyTo":"1397609688-25634-1-git-send-email-johan@herland.net","subject":"Re: [RFC] t7410: 210 tests for various 'git submodule update' scenarios","fromName":"Jens Lehmann","fromEmail":"jens.lehmann@web.de","sentAt":"2014-04-17T16:04:42Z","receivedAt":"2014-04-17T16:04:42Z","isPatch":false,"sender":{"key":"jens.lehmann@web.de","avatar":"https://avatars.githubusercontent.com/u/135220?v=4"},"body":"Am 16.04.2014 02:54, schrieb Johan Herland:\n> This is a work-in-progress to flesh out (and promote discussion about)\n> the expected behaviors for all possible scenarios in which\n> 'git submodule update' might be run.\n\nThanks a lot, this is a very good idea. After fixing the hidden\nstaged ignored submodules I'm back working on a very similar topic\nI posted an RFC for some time ago. The focus there lies on how git\ncommands currently handle all possible types of submodule changes\ntogether with \"submodule update\", which shows some inconsistencies\nwe currently have:\n\n   http://article.gmane.org/gmane.comp.version-control.git/245046\n\nThis is in preparation of the recursive update series, where I\nintend to extend these tests to also cover how checkout update\nmode handles submodules.\n\nI think it makes lots of sense to nail down our current behavior\nfirst and then talk about what is inconsistent there and how we\nshould change it. Will try to read this discussion when I find\nsome time, maybe we can join our efforts to cover all combinations\nof configurations and command line options.\n\n> More details in the top of t/t7410-submodule-update-scenarios.sh\n> \n> Cc: W. Trevor King <wking@tremily.us>\n> Cc: Jens Lehmann <Jens.Lehmann@web.de>\n> Cc: Heiko Voigt <hvoigt@hvoigt.net>\n> Cc: Junio C Hamano <gitster@pobox.com>\n> \n> ---\n> \n> Hi,\n> \n> This started as an exercise for myself to figure out all the various\n> corner cases under which \"git submodule update\" may be run. Then, as I\n> found some cases where the current behavior was not immediately obvious\n> to me, and some other cases where the current behaviour is likely buggy\n> and/or Wrong(tm), I figured these tests might serve as a backdrop for a\n> closer discussion of those cases.\n> \n> I've attempted to include all variables/axes that combine to directly\n> affect the behavior of 'submodule update'. I've excluded some variables\n> whose effect on 'submodule update' is completely orthogonal/independent\n> (i.e. how 'submodule update' is affected by unstaged/uncommitted\n> changes in the submodule). That said, there might be more variables\n> that I have missed in my analysis...\n> \n> I've attempted to split the areas to be discussed into 3 todo items and\n> 7 discussion items (labeled T1 - T3. and D1 - D7, respectively), and\n> I've cross-referenced them to the specific test cases that are affected\n> by each todo/discussion item.\n> \n> I'll leave it up to Jens and Junio to determine whether this patch\n> is worth applying or not. There is certainly considerable overlap\n> between these tests and existing tests for 'submodule update'. There's\n> also plenty of room for refactoring and deduplication in this file,\n> itself, although I hope the current format of the tests makes it fairly\n> easy to see what is being tested, and what is the expected behavior.\n> \n> Have fun! :)\n> \n> ...Johan\n> \n> \n>  t/t7410-submodule-update-scenarios.sh | 2859 +++++++++++++++++++++++++++++++++\n>  1 file changed, 2859 insertions(+)\n>  create mode 100755 t/t7410-submodule-update-scenarios.sh\n> \n> diff --git a/t/t7410-submodule-update-scenarios.sh b/t/t7410-submodule-update-scenarios.sh\n> new file mode 100755\n> index 0000000..22056cc\n> --- /dev/null\n> +++ b/t/t7410-submodule-update-scenarios.sh\n> @@ -0,0 +1,2859 @@\n> +#!/bin/sh\n> +#\n> +# Copyright (c) 2014 Johan Herland\n> +#\n> +\n> +test_description='Test \"git submodule update\" in a variety of scenarios\n> +\n> +This test attempts to map out the various scenarios in which submodule update\n> +is run, and verify their expected behaviour (according to the git submodule\n> +documentation).\n> +'\n> +\n> +. ./test-lib.sh\n> +\n> +# First a textual representation of the various cases we are testing:\n> +#\n> +# The factors/variables being explored are:\n> +#  - submodule.sub.branch\n> +#     1.* - unset\n> +#     2.* - == foo (exists upstream)\n> +#     3.* - == bar (MISSING upstream)\n> +#  - submodule.sub.update\n> +#     ?.1.* - none\n> +#     ?.2.* - checkout\n> +#     ?.3.* - merge\n> +#     ?.4.* - rebase\n> +#     ?.5.* - !command\n> +#  - remote mode (whether or not --remote is given on command-line)\n> +#     ?.?.1.* - disabled\n> +#     ?.?.2.* - enabled\n> +#  - current state of submodule:\n> +#     ?.?.?.1 - not yet cloned\n> +#     ?.?.?.2 - cloned, detached, HEAD == gitlink\n> +#     ?.?.?.3 - cloned, detached, HEAD != gitlink\n> +#     ?.?.?.4 - cloned, on branch foo (exists upstream), HEAD == gitlink\n> +#     ?.?.?.5 - cloned, on branch foo (exists upstream), HEAD != gitlink\n> +#     ?.?.?.6 - cloned, on branch bar (MISSING upstream), HEAD == gitlink\n> +#     ?.?.?.7 - cloned, on branch bar (MISSING upstream), HEAD != gitlink\n> +#\n> +# The above variables are combined to enumerate all possible cases, from\n> +# 1.1.1.1 to 3.5.2.7 (yes, that's 210 separate test cases). Each test case is\n> +# named with its number followed by a short description of its expected outcome.\n> +\n> +# TODO ITEMS:\n> +#\n> +# T1: Rename \"master\" branch to \"default\" to test correct behaviour when\n> +#     submodule's upstream has no master branch.\n> +#     Affects: pre, 1.3.1.1, 1.3.2.1, 1.4.1.1, 1.4.2.1\n> +#\n> +# T2: Test with submodule.<name>.url != submodule's remote.origin.url. Does\n> +#     \"submodule update --remote\" sync with submodule.<name>.url, or with the\n> +#     submodule's origin? (or with the submodule's current branch's upstream)?\n> +#\n> +# T3: Fix uninitialized submodule state after attempting to clone from upstream\n> +#     where .branch is missing.\n> +#     Affects: pre, 3.2.2.1, 3.3.2.1, 3.4.2.1, 3.5.2.1\n> +\n> +# DISCUSSION ITEMS:\n> +#\n> +# D1: When submodule is already at right commit, checkout-mode currently does\n> +#     nothing. Should it instead detach, even when no update is needed?\n> +#     Affects: 1.2.1.4, 1.2.1.6, 2.2.1.4, 2.2.1.6, 3.2.1.4, 3.2.1.6\n> +#\n> +# D2: Should all/some of 1.3.*/1.4.* abort/error because we don't know what to\n> +#     merge/rebase with (because .branch is unset)? Or is the current default\n> +#     to origin/HEAD OK?\n> +#     Affects: 1.3.*, 1.4.*\n> +#\n> +# D3: When submodule is already at right commit, merge/rebase-mode currently\n> +#     does nothing. Should it do something else (e.g. not leave submodule\n> +#     detached, or checked out on the \"wrong\" branch (i.e. != .branch))?\n> +#     (This discussion point is related to D1, D5 and D6)\n> +#     Affects: 1.3.1.2, 1.3.1.4, 1.3.1.6,\n> +#              1.4.1.2, 1.4.1.4, 1.4.1.6,\n> +#              2.3.1.2, 2.3.1.4, 2.3.1.6, 2.3.2.3, 2.3.2.5, 2.3.2.7,\n> +#              2.4.1.2, 2.4.1.4, 2.4.1.6, 2.4.2.3, 2.4.2.5, 2.4.2.7,\n> +#              3.3.1.2, 3.3.1.4, 3.3.1.6\n> +#              3.4.1.2, 3.4.1.4, 3.4.1.6\n> +#\n> +# D4: When 'submodule update' performs a clone to populate a submodule, it\n> +#     currently also creates a default branch (named after origin/HEAD) in\n> +#     that submodule, EVEN WHEN THAT BRANCH WILL NEVER BE USED (e.g. because\n> +#     we're in checkout-mode and submodule will always be detached). Is this\n> +#     good, or should the clone performed by 'submodule update' skip the\n> +#     automatic local branch creation?\n> +#     Affects: 1.2.*.1, 1.3.*.1, 1.4.*.1, 1.5.*.1,\n> +#              2.2.*.1, 2.3.*.1, 2.4.*.1, 2.5.*.1,\n> +#              3.2.1.1, 3.3.1.1, 3.4.1.1, 3.5.1.1\n> +#\n> +# D5: When in merge/rebase-mode, and 'submodule update' actually ends up doing\n> +#     a merge/rebase, that will happen on the current branch (or detached HEAD)\n> +#     and NOT on the configured (or default) .branch. Is this OK? Should we\n> +#     abort (or at least warn) instead? (In general, .branch seems only to\n> +#     affect the submodule's HEAD when the submodule is first cloned.)\n> +#     (This discussion point is related to D3 and D6)\n> +#     Affects: 1.3.1.3, 1.3.1.5, 1.3.1.7, 1.3.2.>=2,\n> +#              1.4.1.3, 1.4.1.5, 1.4.1.7, 1.4.2.>=2,\n> +#              2.3.1.3, 2.3.1.5, 2.3.1.7, 2.3.2.2, 2.3.2.4, 2.3.2.6,\n> +#              2.4.1.3, 2.4.1.5, 2.4.1.7, 2.4.2.2, 2.4.2.4, 2.4.2.6\n> +#              3.3.1.3, 3.3.1.5, 3.3.1.7\n> +#              3.4.1.3, 3.4.1.5, 3.4.1.7\n> +#\n> +# D6: The meaning of submodule.<name>.branch is initially confusing, as it does\n> +#     not really concern the submodule's local branch (except as a naming hint\n> +#     when the submodule is first cloned). Instead, submodule.<name>.branch is\n> +#     really about which branch in the _upstream_ submodule (as defined by\n> +#     submodule.<name>.url, or by the submodule's remote.origin.url?) that we\n> +#     want to integrate with. This is probably the more useful setting, and it\n> +#     becomes obviously correct after (re-)reading gitmodules(5) and\n> +#     git-config(1). However, from just reading the \"update\" section in\n> +#     git-submodule(1) (or not even that), things are not so clear-cut. Would\n> +#     submodule.<name>.upstream (or .remote-branch, or similar) be a better\n> +#     name for this?\n> +#\n> +# D7: What to do when .branch refers to a branch that is missing from upstream?\n> +#     Currently, when trying to clone, the clone fails (which causes 'git\n> +#     submodule update --remote' to fail), but leaves the submodule in an\n> +#     uninitialized state (there is a .git, but the work tree is missing).\n> +#     This is probably not the behavior we want...\n> +#     Affects: pre, 3.2.2.1, 3.3.2.1, 3.4.2.1, 3.5.2.1\n> +\n> +# First, we need to setup the environment in which the test cases are run.\n> +# This consists of an upstream super-repo containing a single submodule.\n> +# The submodule commit graph looks like this:\n> +#\n> +#   $root_commit --->  $old_commit ---> $new_commit  <- master (HEAD) # T1\n> +#                \\          ^- (superproject's gitlink points here)\n> +#                 --> $foo_commit  <- foo\n> +#\n> +# Each test case then starts by cloning upstream_super -> super and setting up\n> +# its submodule + configuration according to the current test case. It then\n> +# runs \"git submodule update\" (with or without --remote) and verifies the\n> +# expected results.\n> +\n> +test_expect_success 'preliminaries: setup upstream super and sub' '\n> +\tgit init upstream_sub &&\n> +\t(cd upstream_sub &&\n> +\t test_commit root_commit &&\n> +\t test_commit foo_commit &&\n> +\t git branch foo &&\n> +\t git reset --hard HEAD^ &&\n> +#\t git branch -m default &&  # T1\n> +\t test_commit old_commit\n> +\t) &&\n> +\tgit init upstream_super &&\n> +\t(cd upstream_super &&\n> +\t git submodule add ../upstream_sub sub &&\n> +\t test_tick &&\n> +\t git commit -m \"Add sub\"\n> +\t) &&\n> +\t(cd upstream_sub &&\n> +\t test_commit new_commit\n> +\t)\n> +'\n> +\n> +# The following commit IDs are used in various test cases\n> +root_commit=$(git -C upstream_sub rev-parse --verify -q root_commit)\n> +foo_commit=$(git -C upstream_sub rev-parse --verify -q foo_commit)\n> +old_commit=$(git -C upstream_sub rev-parse --verify -q old_commit)\n> +new_commit=$(git -C upstream_sub rev-parse --verify -q new_commit)\n> +\n> +fail()\n> +{\n> +\techo \"$@\"\n> +\tfalse\n> +}\n> +\n> +# Verify that the path in $1 contains a cloned git repo\n> +verify_is_cloned()\n> +{\n> +\ttest -e \"$1/.git\" ||\n> +\t\tfail \"Failed to find cloned repo at '$1'\"\n> +}\n> +\n> +# Verify that commit $2 in repo $1 has parents $3, $4, ... (in the given order).\n> +verify_parents()\n> +{\n> +\trepo=$1; shift\n> +\tcommit=$1; shift\n> +\texpect_p=$@\n> +\tactual_p=$(git --git-dir=\"$repo/.git\" log --format=%P -1 \"$commit\")\n> +\ttest \"$expect_p\" = \"$actual_p\" ||\n> +\t\tfail \"Expected $commit parents '$expect_p' != '$actual_p'\"\n> +}\n> +\n> +# Verify that HEAD in repo $1 points to commit $2.\n> +# If $2 is of the form 'parents.<SHA1>[.<SHA1>...]', then check that HEAD\n> +# currently points to a commit whose parents are the given SHA1s (in order).\n> +verify_head()\n> +{\n> +\thead=$(git --git-dir=\"$1/.git\" rev-parse -q HEAD)\n> +\tcase \"$2\" in\n> +\tparents.*)\n> +\t\tparents=$(echo \"$2\" | sed -e 's/^parents\\.//' -e 's/\\./ /g')\n> +\t\tverify_parents \"$1\" \"$head\" $parents ||\n> +\t\t\tfail \"Failed to verify parents of HEAD in '$1'\"\n> +\t\t;;\n> +\t*)\n> +\t\ttest \"$2\" = \"$head\" ||\n> +\t\t\tfail \"Expected HEAD in '$1' to be '$2', but is '$head'\"\n> +\tesac\n> +}\n> +\n> +# Verify that the repo in $1 is currently checked out on branch $2.\n> +# If $2 is \"detached\", verify that $1'a HEAD is in fact detached.\n> +verify_branch()\n> +{\n> +\texpect=$2\n> +\tif test \"$expect\" = \"detached\"\n> +\tthen\n> +\t\texpect=\n> +\tfi\n> +\tactual=$(git --git-dir=\"$1/.git\" symbolic-ref --short -q HEAD)\n> +\ttest \"$expect\" = \"$actual\" ||\n> +\t\tfail \"Expected branch in '$1' to be '$expect', but is '$actual'\"\n> +}\n> +\n> +# Clone upstream_super to super, and run \"git submodule init\"\n> +setup_super()\n> +{\n> +\trm -rf super &&\n> +\tgit clone upstream_super super &&\n> +\t(cd super &&\n> +\t git submodule init &&\n> +\t test_must_fail verify_is_cloned sub &&\n> +\t test \"$(git rev-parse -q HEAD:sub)\" = \"$old_commit\"\n> +\t)\n> +}\n> +\n> +# Setup submodule.sub.branch == $1\n> +# If $1 == \"unset\", ensure submodule.sub.branch is unset\n> +setup_sub_branch()\n> +{\n> +\tif test \"$1\" = \"unset\"\n> +\tthen\n> +\t\tgit config --unset-all \"submodule.sub.branch\"\n> +\t\ttest_must_fail git config \"submodule.sub.branch\" ||\n> +\t\t\terror \"Failed to unset submodule.sub.branch\"\n> +\telse\n> +\t\tgit config \"submodule.sub.branch\" \"$1\"\n> +\t\tactual=$(git config \"submodule.sub.branch\")\n> +\t\ttest \"$actual\" = \"$1\" ||\n> +\t\t\terror \"Failed to set submodule.sub.branch to '$1'\"\n> +\tfi\n> +}\n> +\n> +# Setup submodule.sub.update == $1\n> +setup_sub_update()\n> +{\n> +\tgit config \"submodule.sub.update\" \"$1\"\n> +\tactual=$(git config \"submodule.sub.update\")\n> +\ttest \"$actual\" = \"$1\" ||\n> +\t\terror \"Failed to set submodule.sub.update to '$1'\"\n> +}\n> +\n> +# Setup the state of the sub submodule according to $1, which is one of:\n> +#  - \"uncloned\" - sub is an empty dir.\n> +#  - \"detach\" - sub is detached at the commit in $2.\n> +#  - * - sub is checked out on branch named in $1, at the commit in $2.\n> +setup_sub_state()\n> +{\n> +\tcase \"$1\" in\n> +\tuncloned)\n> +\t\ttest_must_fail verify_is_cloned sub ||\n> +\t\t\terror \"Failed to verify uncloned sub\"\n> +\t\t;;\n> +\tdetach)\n> +\t\tgit submodule update --checkout sub &&\n> +\t\t(cd sub &&\n> +\t\t git checkout \"$2\"\n> +\t\t) &&\n> +\t\tverify_is_cloned sub &&\n> +\t\tverify_branch sub detached &&\n> +\t\tverify_head sub \"$2\" ||\n> +\t\t\terror \"Failed to detach sub at '$2'\"\n> +\t\t;;\n> +\t*)\n> +\t\tgit submodule update --checkout sub &&\n> +\t\t(cd sub &&\n> +\t\t git checkout -b \"$1\" \"$2\"\n> +\t\t) &&\n> +\t\tverify_is_cloned sub &&\n> +\t\tverify_branch sub \"$1\" &&\n> +\t\tverify_head sub \"$2\" ||\n> +\t\t\terror \"Failed to attach sub to '$1' at '$2'\"\n> +\tesac\n> +}\n> +\n> +# Verify the state of the sub submodule according to $1, which is one of:\n> +#  - \"uncloned\" - sub is an empty dir.\n> +#  - \"detach\" - sub is detached at the commit in $2.\n> +#  - * - sub is checked out on branch named in $1, at the commit in $2.\n> +# If $2 is of the form 'parents.<SHA1>[.<SHA1>...]', then check that HEAD\n> +# currently points to a commit whose parents are the given SHA1s (in order).\n> +verify_sub_state()\n> +{\n> +\tcase \"$1\" in\n> +\tuncloned)\n> +\t\ttest_must_fail verify_is_cloned sub ||\n> +\t\t\tfail \"Failed to verify uncloned sub\"\n> +\t\t;;\n> +\tdetach)\n> +\t\tverify_is_cloned sub &&\n> +\t\tverify_branch sub detached &&\n> +\t\tverify_head sub \"$2\" ||\n> +\t\t\tfail \"Failed to verify detached sub at '$2'\"\n> +\t\t;;\n> +\t*)\n> +\t\tverify_is_cloned sub &&\n> +\t\tverify_branch sub \"$1\" &&\n> +\t\tverify_head sub \"$2\" ||\n> +\t\t\tfail \"Failed to verify attached sub at '$1' -> '$2'\"\n> +\tesac\n> +}\n> +\n> +verify_sub_patch_id()\n> +{\n> +\tp1=$(git --git-dir=sub/.git show $1 | git patch-id | cut -d' ' -f1)\n> +\tp2=$(git --git-dir=sub/.git show $2 | git patch-id | cut -d' ' -f1)\n> +\ttest \"$p1\" = \"$p2\" ||\n> +\t\tfail \"'$1' and '$2' has different patch-ids ('$p1' != '$p2')\"\n> +}\n> +\n> +# 1.1.* - .branch is unset, .update == none\n> +\n> +test_expect_success '1.1.1.1 - do nothing (.update == none)' '\n> +\tsetup_super &&\n> +\t(cd super &&\n> +\t setup_sub_state uncloned &&\n> +\t setup_sub_update none &&\n> +\t setup_sub_branch unset &&\n> +\t git submodule update &&\n> +\t verify_sub_state uncloned\n> +\t)\n> +'\n> +\n> +test_expect_success '1.1.1.2 - do nothing (.update == none)' '\n> +\tsetup_super &&\n> +\t(cd super &&\n> +\t setup_sub_state detach $old_commit &&\n> +\t setup_sub_update none &&\n> +\t setup_sub_branch unset &&\n> +\t git submodule update &&\n> +\t verify_sub_state detach $old_commit\n> +\t)\n> +'\n> +\n> +test_expect_success '1.1.1.3 - do nothing (.update == none)' '\n> +\tsetup_super &&\n> +\t(cd super &&\n> +\t setup_sub_state detach $foo_commit &&\n> +\t setup_sub_update none &&\n> +\t setup_sub_branch unset &&\n> +\t git submodule update &&\n> +\t verify_sub_state detach $foo_commit\n> +\t)\n> +'\n> +\n> +test_expect_success '1.1.1.4 - do nothing (.update == none)' '\n> +\tsetup_super &&\n> +\t(cd super &&\n> +\t setup_sub_state foo $old_commit &&\n> +\t setup_sub_update none &&\n> +\t setup_sub_branch unset &&\n> +\t git submodule update &&\n> +\t verify_sub_state foo $old_commit\n> +\t)\n> +'\n> +\n> +test_expect_success '1.1.1.5 - do nothing (.update == none)' '\n> +\tsetup_super &&\n> +\t(cd super &&\n> +\t setup_sub_state foo $foo_commit &&\n> +\t setup_sub_update none &&\n> +\t setup_sub_branch unset &&\n> +\t git submodule update &&\n> +\t verify_sub_state foo $foo_commit\n> +\t)\n> +'\n> +\n> +test_expect_success '1.1.1.6 - do nothing (.update == none)' '\n> +\tsetup_super &&\n> +\t(cd super &&\n> +\t setup_sub_state bar $old_commit &&\n> +\t setup_sub_update none &&\n> +\t setup_sub_branch unset &&\n> +\t git submodule update &&\n> +\t verify_sub_state bar $old_commit\n> +\t)\n> +'\n> +\n> +test_expect_success '1.1.1.7 - do nothing (.update == none)' '\n> +\tsetup_super &&\n> +\t(cd super &&\n> +\t setup_sub_state bar $foo_commit &&\n> +\t setup_sub_update none &&\n> +\t setup_sub_branch unset &&\n> +\t git submodule update &&\n> +\t verify_sub_state bar $foo_commit\n> +\t)\n> +'\n> +\n> +test_expect_success '1.1.2.1 - do nothing (.update == none)' '\n> +\tsetup_super &&\n> +\t(cd super &&\n> +\t setup_sub_state uncloned &&\n> +\t setup_sub_update none &&\n> +\t setup_sub_branch unset &&\n> +\t git submodule update --remote &&\n> +\t verify_sub_state uncloned\n> +\t)\n> +'\n> +\n> +test_expect_success '1.1.2.2 - do nothing (.update == none)' '\n> +\tsetup_super &&\n> +\t(cd super &&\n> +\t setup_sub_state detach $old_commit &&\n> +\t setup_sub_update none &&\n> +\t setup_sub_branch unset &&\n> +\t git submodule update --remote &&\n> +\t verify_sub_state detach $old_commit\n> +\t)\n> +'\n> +\n> +test_expect_success '1.1.2.3 - do nothing (.update == none)' '\n> +\tsetup_super &&\n> +\t(cd super &&\n> +\t setup_sub_state detach $foo_commit &&\n> +\t setup_sub_update none &&\n> +\t setup_sub_branch unset &&\n> +\t git submodule update --remote &&\n> +\t verify_sub_state detach $foo_commit\n> +\t)\n> +'\n> +\n> +test_expect_success '1.1.2.4 - do nothing (.update == none)' '\n> +\tsetup_super &&\n> +\t(cd super &&\n> +\t setup_sub_state foo $old_commit &&\n> +\t setup_sub_update none &&\n> +\t setup_sub_branch unset &&\n> +\t git submodule update --remote &&\n> +\t verify_sub_state foo $old_commit\n> +\t)\n> +'\n> +\n> +test_expect_success '1.1.2.5 - do nothing (.update == none)' '\n> +\tsetup_super &&\n> +\t(cd super &&\n> +\t setup_sub_state foo $foo_commit &&\n> +\t setup_sub_update none &&\n> +\t setup_sub_branch unset &&\n> +\t git submodule update --remote &&\n> +\t verify_sub_state foo $foo_commit\n> +\t)\n> +'\n> +\n> +test_expect_success '1.1.2.6 - do nothing (.update == none)' '\n> +\tsetup_super &&\n> +\t(cd super &&\n> +\t setup_sub_state bar $old_commit &&\n> +\t setup_sub_update none &&\n> +\t setup_sub_branch unset &&\n> +\t git submodule update --remote &&\n> +\t verify_sub_state bar $old_commit\n> +\t)\n> +'\n> +\n> +test_expect_success '1.1.2.7 - do nothing (.update == none)' '\n> +\tsetup_super &&\n> +\t(cd super &&\n> +\t setup_sub_state bar $foo_commit &&\n> +\t setup_sub_update none &&\n> +\t setup_sub_branch unset &&\n> +\t git submodule update --remote &&\n> +\t verify_sub_state bar $foo_commit\n> +\t)\n> +'\n> +\n> +# 1.2.* - .branch is unset, .update == checkout\n> +\n> +test_expect_success '1.2.1.1 - clone, detach @ $old_commit' '\n> +\tsetup_super &&\n> +\t(cd super &&\n> +\t setup_sub_state uncloned &&\n> +\t setup_sub_update checkout &&\n> +\t setup_sub_branch unset &&\n> +\t git submodule update &&\n> +\t verify_sub_state detach $old_commit # D4\n> +\t)\n> +'\n> +\n> +test_expect_success '1.2.1.2 - already @ $old_commit -> keep detached' '\n> +\tsetup_super &&\n> +\t(cd super &&\n> +\t setup_sub_state detach $old_commit &&\n> +\t setup_sub_update checkout &&\n> +\t setup_sub_branch unset &&\n> +\t git submodule update &&\n> +\t verify_sub_state detach $old_commit\n> +\t)\n> +'\n> +\n> +test_expect_success '1.2.1.3 - detach @ $old_commit' '\n> +\tsetup_super &&\n> +\t(cd super &&\n> +\t setup_sub_state detach $foo_commit &&\n> +\t setup_sub_update checkout &&\n> +\t setup_sub_branch unset &&\n> +\t git submodule update &&\n> +\t verify_sub_state detach $old_commit\n> +\t)\n> +'\n> +\n> +test_expect_success '1.2.1.4 - already @ $old_commit -> keep attached' ' # D1\n> +\tsetup_super &&\n> +\t(cd super &&\n> +\t setup_sub_state foo $old_commit &&\n> +\t setup_sub_update checkout &&\n> +\t setup_sub_branch unset &&\n> +\t git submodule update &&\n> +\t verify_sub_state foo $old_commit\n> +\t)\n> +'\n> +\n> +test_expect_success '1.2.1.5 - detach @ $old_commit' '\n> +\tsetup_super &&\n> +\t(cd super &&\n> +\t setup_sub_state foo $foo_commit &&\n> +\t setup_sub_update checkout &&\n> +\t setup_sub_branch unset &&\n> +\t git submodule update &&\n> +\t verify_sub_state detach $old_commit\n> +\t)\n> +'\n> +\n> +test_expect_success '1.2.1.6 - already @ $old_commit -> keep attached' ' # D1\n> +\tsetup_super &&\n> +\t(cd super &&\n> +\t setup_sub_state bar $old_commit &&\n> +\t setup_sub_update checkout &&\n> +\t setup_sub_branch unset &&\n> +\t git submodule update &&\n> +\t verify_sub_state bar $old_commit\n> +\t)\n> +'\n> +\n> +test_expect_success '1.2.1.7 - detach @ $old_commit' '\n> +\tsetup_super &&\n> +\t(cd super &&\n> +\t setup_sub_state bar $foo_commit &&\n> +\t setup_sub_update checkout &&\n> +\t setup_sub_branch unset &&\n> +\t git submodule update &&\n> +\t verify_sub_state detach $old_commit\n> +\t)\n> +'\n> +\n> +test_expect_success '1.2.2.1 - clone, detach @ $new_commit' '\n> +\tsetup_super &&\n> +\t(cd super &&\n> +\t setup_sub_state uncloned &&\n> +\t setup_sub_update checkout &&\n> +\t setup_sub_branch unset &&\n> +\t git submodule update --remote &&\n> +\t verify_sub_state detach $new_commit # D4\n> +\t)\n> +'\n> +\n> +test_expect_success '1.2.2.2 - detach @ $new_commit' '\n> +\tsetup_super &&\n> +\t(cd super &&\n> +\t setup_sub_state detach $old_commit &&\n> +\t setup_sub_update checkout &&\n> +\t setup_sub_branch unset &&\n> +\t git submodule update --remote &&\n> +\t verify_sub_state detach $new_commit\n> +\t)\n> +'\n> +\n> +test_expect_success '1.2.2.3 - detach @ $new_commit' '\n> +\tsetup_super &&\n> +\t(cd super &&\n> +\t setup_sub_state detach $foo_commit &&\n> +\t setup_sub_update checkout &&\n> +\t setup_sub_branch unset &&\n> +\t git submodule update --remote &&\n> +\t verify_sub_state detach $new_commit\n> +\t)\n> +'\n> +\n> +test_expect_success '1.2.2.4 - detach @ $new_commit' '\n> +\tsetup_super &&\n> +\t(cd super &&\n> +\t setup_sub_state foo $old_commit &&\n> +\t setup_sub_update checkout &&\n> +\t setup_sub_branch unset &&\n> +\t git submodule update --remote &&\n> +\t verify_sub_state detach $new_commit\n> +\t)\n> +'\n> +\n> +test_expect_success '1.2.2.5 - detach @ $new_commit' '\n> +\tsetup_super &&\n> +\t(cd super &&\n> +\t setup_sub_state foo $foo_commit &&\n> +\t setup_sub_update checkout &&\n> +\t setup_sub_branch unset &&\n> +\t git submodule update --remote &&\n> +\t verify_sub_state detach $new_commit\n> +\t)\n> +'\n> +\n> +test_expect_success '1.2.2.6 - detach @ $new_commit' '\n> +\tsetup_super &&\n> +\t(cd super &&\n> +\t setup_sub_state bar $old_commit &&\n> +\t setup_sub_update checkout &&\n> +\t setup_sub_branch unset &&\n> +\t git submodule update --remote &&\n> +\t verify_sub_state detach $new_commit\n> +\t)\n> +'\n> +\n> +test_expect_success '1.2.2.7 - detach @ $new_commit' '\n> +\tsetup_super &&\n> +\t(cd super &&\n> +\t setup_sub_state bar $foo_commit &&\n> +\t setup_sub_update checkout &&\n> +\t setup_sub_branch unset &&\n> +\t git submodule update --remote &&\n> +\t verify_sub_state detach $new_commit\n> +\t)\n> +'\n> +\n> +# 1.3.* - .branch is unset, .update == merge # D2\n> +\n> +test_expect_success '1.3.1.1 - clone, create branch named from origin/HEAD @ $old_commit' '\n> +\tsetup_super &&\n> +\t(cd super &&\n> +\t setup_sub_state uncloned &&\n> +\t setup_sub_update merge &&\n> +\t setup_sub_branch unset &&\n> +\t git submodule update &&\n> +\t verify_sub_state detach $old_commit # T1, D4, FIXME: s/detach/master/?\n> +\t)\n> +'\n> +\n> +test_expect_success '1.3.1.2 - already at $old_commit, remain detached' ' # D3\n> +\tsetup_super &&\n> +\t(cd super &&\n> +\t setup_sub_state detach $old_commit &&\n> +\t setup_sub_update merge &&\n> +\t setup_sub_branch unset &&\n> +\t git submodule update &&\n> +\t verify_sub_state detach $old_commit\n> +\t)\n> +'\n> +\n> +test_expect_success '1.3.1.3 - merge $old_commit -> $foo_commit, remain detached' ' # D5\n> +\tsetup_super &&\n> +\t(cd super &&\n> +\t setup_sub_state detach $foo_commit &&\n> +\t setup_sub_update merge &&\n> +\t setup_sub_branch unset &&\n> +\t git submodule update &&\n> +\t verify_sub_state detach parents.$foo_commit.$old_commit\n> +\t)\n> +'\n> +\n> +test_expect_success '1.3.1.4 - already at $old_commit, remain attached to foo' ' # D3\n> +\tsetup_super &&\n> +\t(cd super &&\n> +\t setup_sub_state foo $old_commit &&\n> +\t setup_sub_update merge &&\n> +\t setup_sub_branch unset &&\n> +\t git submodule update &&\n> +\t verify_sub_state foo $old_commit\n> +\t)\n> +'\n> +\n> +test_expect_success '1.3.1.5 - merge $old_commit -> $foo_commit, remain attached to foo' ' # D5\n> +\tsetup_super &&\n> +\t(cd super &&\n> +\t setup_sub_state foo $foo_commit &&\n> +\t setup_sub_update merge &&\n> +\t setup_sub_branch unset &&\n> +\t git submodule update &&\n> +\t verify_sub_state foo parents.$foo_commit.$old_commit\n> +\t)\n> +'\n> +\n> +test_expect_success '1.3.1.6 - already at $old_commit, remain attached to bar' ' # D3\n> +\tsetup_super &&\n> +\t(cd super &&\n> +\t setup_sub_state bar $old_commit &&\n> +\t setup_sub_update merge &&\n> +\t setup_sub_branch unset &&\n> +\t git submodule update &&\n> +\t verify_sub_state bar $old_commit\n> +\t)\n> +'\n> +\n> +test_expect_success '1.3.1.7 - merge $old_commit -> $foo_commit, remain attached to bar' ' # D5\n> +\tsetup_super &&\n> +\t(cd super &&\n> +\t setup_sub_state bar $foo_commit &&\n> +\t setup_sub_update merge &&\n> +\t setup_sub_branch unset &&\n> +\t git submodule update &&\n> +\t verify_sub_state bar parents.$foo_commit.$old_commit\n> +\t)\n> +'\n> +\n> +test_expect_success '1.3.2.1 - clone, create branch from origin/HEAD @ $new_commit' '\n> +\tsetup_super &&\n> +\t(cd super &&\n> +\t setup_sub_state uncloned &&\n> +\t setup_sub_update merge &&\n> +\t setup_sub_branch unset &&\n> +\t git submodule update --remote &&\n> +\t verify_sub_state detach $new_commit # T1, D4, FIXME: s/detach/master/?\n> +\t)\n> +'\n> +\n> +test_expect_success '1.3.2.2 - ffwd $old_commit -> $new_commit, remain detached' ' # D5\n> +\tsetup_super &&\n> +\t(cd super &&\n> +\t setup_sub_state detach $old_commit &&\n> +\t setup_sub_update merge &&\n> +\t setup_sub_branch unset &&\n> +\t git submodule update --remote &&\n> +\t verify_sub_state detach $new_commit\n> +\t)\n> +'\n> +\n> +test_expect_success '1.3.2.3 - merge $new_commit -> $foo_commit, remain detached' ' # D5\n> +\tsetup_super &&\n> +\t(cd super &&\n> +\t setup_sub_state detach $foo_commit &&\n> +\t setup_sub_update merge &&\n> +\t setup_sub_branch unset &&\n> +\t git submodule update --remote &&\n> +\t verify_sub_state detach parents.$foo_commit.$new_commit\n> +\t)\n> +'\n> +\n> +test_expect_success '1.3.2.4 - ffwd $old_commit -> $new_commit, remain attached to foo' ' # D5\n> +\tsetup_super &&\n> +\t(cd super &&\n> +\t setup_sub_state foo $old_commit &&\n> +\t setup_sub_update merge &&\n> +\t setup_sub_branch unset &&\n> +\t git submodule update --remote &&\n> +\t verify_sub_state foo $new_commit\n> +\t)\n> +'\n> +\n> +test_expect_success '1.3.2.5 - merge $new_commit -> $foo_commit, remain attached to foo' ' # D5\n> +\tsetup_super &&\n> +\t(cd super &&\n> +\t setup_sub_state foo $foo_commit &&\n> +\t setup_sub_update merge &&\n> +\t setup_sub_branch unset &&\n> +\t git submodule update --remote &&\n> +\t verify_sub_state foo parents.$foo_commit.$new_commit\n> +\t)\n> +'\n> +\n> +test_expect_success '1.3.2.6 - ffwd $old_commit -> $new_commit, remain attached to bar' ' # D5\n> +\tsetup_super &&\n> +\t(cd super &&\n> +\t setup_sub_state bar $old_commit &&\n> +\t setup_sub_update merge &&\n> +\t setup_sub_branch unset &&\n> +\t git submodule update --remote &&\n> +\t verify_sub_state bar $new_commit\n> +\t)\n> +'\n> +\n> +test_expect_success '1.3.2.7 - merge $new_commit -> $foo_commit, remain attached to bar' ' # D5\n> +\tsetup_super &&\n> +\t(cd super &&\n> +\t setup_sub_state bar $foo_commit &&\n> +\t setup_sub_update merge &&\n> +\t setup_sub_branch unset &&\n> +\t git submodule update --remote &&\n> +\t verify_sub_state bar parents.$foo_commit.$new_commit\n> +\t)\n> +'\n> +\n> +# 1.4.* - .branch is unset, .update == rebase # D2\n> +\n> +test_expect_success '1.4.1.1 - clone, create branch named from origin/HEAD @ $old_commit' '\n> +\tsetup_super &&\n> +\t(cd super &&\n> +\t setup_sub_state uncloned &&\n> +\t setup_sub_update rebase &&\n> +\t setup_sub_branch unset &&\n> +\t git submodule update &&\n> +\t verify_sub_state detach $old_commit # T1, D4, FIXME: s/detach/master/?\n> +\t)\n> +'\n> +\n> +test_expect_success '1.4.1.2 - already at $old_commit, remain detached' ' # D3\n> +\tsetup_super &&\n> +\t(cd super &&\n> +\t setup_sub_state detach $old_commit &&\n> +\t setup_sub_update rebase &&\n> +\t setup_sub_branch unset &&\n> +\t git submodule update &&\n> +\t verify_sub_state detach $old_commit\n> +\t)\n> +'\n> +\n> +test_expect_success '1.4.1.3 - rebase $foo_commit onto $old_commit, remain detached' ' # D5\n> +\tsetup_super &&\n> +\t(cd super &&\n> +\t setup_sub_state detach $foo_commit &&\n> +\t setup_sub_update rebase &&\n> +\t setup_sub_branch unset &&\n> +\t git submodule update &&\n> +\t verify_sub_state detach parents.$old_commit &&\n> +\t verify_sub_patch_id HEAD $foo_commit\n> +\t)\n> +'\n> +\n> +test_expect_success '1.4.1.4 - already at $old_commit, remain attached to foo' ' # D3\n> +\tsetup_super &&\n> +\t(cd super &&\n> +\t setup_sub_state foo $old_commit &&\n> +\t setup_sub_update rebase &&\n> +\t setup_sub_branch unset &&\n> +\t git submodule update &&\n> +\t verify_sub_state foo $old_commit\n> +\t)\n> +'\n> +\n> +test_expect_success '1.4.1.5 - rebase $foo_commit onto $old_commit, remain attached to foo' ' # D5\n> +\tsetup_super &&\n> +\t(cd super &&\n> +\t setup_sub_state foo $foo_commit &&\n> +\t setup_sub_update rebase &&\n> +\t setup_sub_branch unset &&\n> +\t git submodule update &&\n> +\t verify_sub_state foo parents.$old_commit &&\n> +\t verify_sub_patch_id HEAD $foo_commit\n> +\t)\n> +'\n> +\n> +test_expect_success '1.4.1.6 - already at $old_commit, remain attached to bar' ' # D3\n> +\tsetup_super &&\n> +\t(cd super &&\n> +\t setup_sub_state bar $old_commit &&\n> +\t setup_sub_update rebase &&\n> +\t setup_sub_branch unset &&\n> +\t git submodule update &&\n> +\t verify_sub_state bar $old_commit\n> +\t)\n> +'\n> +\n> +test_expect_success '1.4.1.7 - rebase $foo_commit onto $old_commit, remain attached to bar' ' # D5\n> +\tsetup_super &&\n> +\t(cd super &&\n> +\t setup_sub_state bar $foo_commit &&\n> +\t setup_sub_update rebase &&\n> +\t setup_sub_branch unset &&\n> +\t git submodule update &&\n> +\t verify_sub_state bar parents.$old_commit &&\n> +\t verify_sub_patch_id HEAD $foo_commit\n> +\t)\n> +'\n> +\n> +test_expect_success '1.4.2.1 - clone, create branch from origin/HEAD @ $new_commit' '\n> +\tsetup_super &&\n> +\t(cd super &&\n> +\t setup_sub_state uncloned &&\n> +\t setup_sub_update rebase &&\n> +\t setup_sub_branch unset &&\n> +\t git submodule update --remote &&\n> +\t verify_sub_state detach $new_commit # T1, D4, FIXME: s/detach/master/?\n> +\t)\n> +'\n> +\n> +test_expect_success '1.4.2.2 - ffwd $old_commit -> $new_commit, remain detached' ' # D5\n> +\tsetup_super &&\n> +\t(cd super &&\n> +\t setup_sub_state detach $old_commit &&\n> +\t setup_sub_update rebase &&\n> +\t setup_sub_branch unset &&\n> +\t git submodule update --remote &&\n> +\t verify_sub_state detach $new_commit\n> +\t)\n> +'\n> +\n> +test_expect_success '1.4.2.3 - rebase $foo_commit onto $new_commit, remain detached' ' # D5\n> +\tsetup_super &&\n> +\t(cd super &&\n> +\t setup_sub_state detach $foo_commit &&\n> +\t setup_sub_update rebase &&\n> +\t setup_sub_branch unset &&\n> +\t git submodule update --remote &&\n> +\t verify_sub_state detach parents.$new_commit &&\n> +\t verify_sub_patch_id HEAD $foo_commit\n> +\t)\n> +'\n> +\n> +test_expect_success '1.4.2.4 - ffwd $old_commit -> $new_commit, remain attached to foo' ' # D5\n> +\tsetup_super &&\n> +\t(cd super &&\n> +\t setup_sub_state foo $old_commit &&\n> +\t setup_sub_update rebase &&\n> +\t setup_sub_branch unset &&\n> +\t git submodule update --remote &&\n> +\t verify_sub_state foo $new_commit\n> +\t)\n> +'\n> +\n> +test_expect_success '1.4.2.5 - rebase $foo_commit onto $new_commit, remain attached to foo' ' # D5\n> +\tsetup_super &&\n> +\t(cd super &&\n> +\t setup_sub_state foo $foo_commit &&\n> +\t setup_sub_update rebase &&\n> +\t setup_sub_branch unset &&\n> +\t git submodule update --remote &&\n> +\t verify_sub_state foo parents.$new_commit &&\n> +\t verify_sub_patch_id HEAD $foo_commit\n> +\t)\n> +'\n> +\n> +test_expect_success '1.4.2.6 - ffwd $old_commit -> $new_commit, remain attached to bar' ' # D5\n> +\tsetup_super &&\n> +\t(cd super &&\n> +\t setup_sub_state bar $old_commit &&\n> +\t setup_sub_update rebase &&\n> +\t setup_sub_branch unset &&\n> +\t git submodule update --remote &&\n> +\t verify_sub_state bar $new_commit\n> +\t)\n> +'\n> +\n> +test_expect_success '1.4.2.7 - rebase $foo_commit onto $new_commit, remain attached to bar' ' # D5\n> +\tsetup_super &&\n> +\t(cd super &&\n> +\t setup_sub_state bar $foo_commit &&\n> +\t setup_sub_update rebase &&\n> +\t setup_sub_branch unset &&\n> +\t git submodule update --remote &&\n> +\t verify_sub_state bar parents.$new_commit\n> +\t verify_sub_patch_id HEAD $foo_commit\n> +\t)\n> +'\n> +\n> +# 1.5.* - .branch is unset, .update == !command\n> +\n> +test_expect_success '1.5.1.1 - clone, create branch named from origin/HEAD @ $old_commit. !command is NOT invoked' '\n> +\tsetup_super &&\n> +\t(cd super &&\n> +\t setup_sub_state uncloned &&\n> +\t setup_sub_update !false &&\n> +\t setup_sub_branch unset &&\n> +\t git submodule update && # should not invoke \"false\"\n> +\t verify_sub_state detach $old_commit # T1, D4, FIXME: s/detach/master/?\n> +\t)\n> +'\n> +\n> +test_expect_success '1.5.1.2 - already at $old_commit, remain detached. !command is NOT invoked' '\n> +\tsetup_super &&\n> +\t(cd super &&\n> +\t setup_sub_state detach $old_commit &&\n> +\t setup_sub_update !false &&\n> +\t setup_sub_branch unset &&\n> +\t git submodule update && # should not invoke \"false\"\n> +\t verify_sub_state detach $old_commit\n> +\t)\n> +'\n> +\n> +cat > test_command.sh <<EOF\n> +#!/bin/sh\n> +# Verify: detached @ $foo_commit, and asked to integrate $old_commit\n> +test \"\\$(git symbolic-ref --short -q HEAD)\" = \"\" &&\n> +test \"\\$(git rev-parse -q --verify HEAD)\" = \"$foo_commit\" &&\n> +test \"\\$1\" = \"$old_commit\" &&\n> +git checkout -b success $root_commit\n> +EOF\n> +chmod +x test_command.sh\n> +\n> +test_expect_success '1.5.1.3 - !command invoked to integrate $old_commit -> $foo_commit' '\n> +\tsetup_super &&\n> +\t(cd super &&\n> +\t setup_sub_state detach $foo_commit &&\n> +\t setup_sub_update !../../test_command.sh &&\n> +\t setup_sub_branch unset &&\n> +\t git submodule update &&\n> +\t verify_sub_state success $root_commit # test_command.sh is happy\n> +\t)\n> +'\n> +\n> +test_expect_success '1.5.1.4 - already at $old_commit, remain attached to foo. !command is NOT invoked' '\n> +\tsetup_super &&\n> +\t(cd super &&\n> +\t setup_sub_state foo $old_commit &&\n> +\t setup_sub_update !false &&\n> +\t setup_sub_branch unset &&\n> +\t git submodule update &&\n> +\t verify_sub_state foo $old_commit\n> +\t)\n> +'\n> +\n> +cat > test_command.sh <<EOF\n> +#!/bin/sh\n> +# Verify: attached to foo @ $foo_commit, and asked to integrate $old_commit\n> +test \"\\$(git symbolic-ref --short -q HEAD)\" = \"foo\" &&\n> +test \"\\$(git rev-parse -q --verify HEAD)\" = \"$foo_commit\" &&\n> +test \"\\$1\" = \"$old_commit\" &&\n> +git checkout -b success $root_commit\n> +EOF\n> +chmod +x test_command.sh\n> +\n> +test_expect_success '1.5.1.5 - !command invoked to integrate $old_commit -> foo/$foo_commit' '\n> +\tsetup_super &&\n> +\t(cd super &&\n> +\t setup_sub_state foo $foo_commit &&\n> +\t setup_sub_update !../../test_command.sh &&\n> +\t setup_sub_branch unset &&\n> +\t git submodule update &&\n> +\t verify_sub_state success $root_commit # test_command.sh is happy\n> +\t)\n> +'\n> +\n> +test_expect_success '1.5.1.6 - already at $old_commit, remain attached to bar. !command is NOT invoked' '\n> +\tsetup_super &&\n> +\t(cd super &&\n> +\t setup_sub_state bar $old_commit &&\n> +\t setup_sub_update !false &&\n> +\t setup_sub_branch unset &&\n> +\t git submodule update &&\n> +\t verify_sub_state bar $old_commit\n> +\t)\n> +'\n> +\n> +cat > test_command.sh <<EOF\n> +#!/bin/sh\n> +# Verify: attached to bar @ $foo_commit, and asked to integrate $old_commit\n> +test \"\\$(git symbolic-ref --short -q HEAD)\" = \"bar\" &&\n> +test \"\\$(git rev-parse -q --verify HEAD)\" = \"$foo_commit\" &&\n> +test \"\\$1\" = \"$old_commit\" &&\n> +git checkout -b success $root_commit\n> +EOF\n> +chmod +x test_command.sh\n> +\n> +test_expect_success '1.5.1.7 - !command invoked to integrate $old_commit -> bar/$foo_commit' '\n> +\tsetup_super &&\n> +\t(cd super &&\n> +\t setup_sub_state bar $foo_commit &&\n> +\t setup_sub_update !../../test_command.sh &&\n> +\t setup_sub_branch unset &&\n> +\t git submodule update &&\n> +\t verify_sub_state success $root_commit # test_command.sh is happy\n> +\t)\n> +'\n> +\n> +test_expect_success '1.5.2.1 - clone, create branch from origin/HEAD @ $new_commit. !command is NOT invoked' '\n> +\tsetup_super &&\n> +\t(cd super &&\n> +\t setup_sub_state uncloned &&\n> +\t setup_sub_update !false &&\n> +\t setup_sub_branch unset &&\n> +\t git submodule update --remote &&\n> +\t verify_sub_state detach $new_commit # T1, D4, FIXME: s/detach/master/?\n> +\t)\n> +'\n> +\n> +cat > test_command.sh <<EOF\n> +#!/bin/sh\n> +# Verify: detached @ $old_commit, and asked to integrate $new_commit\n> +test \"\\$(git symbolic-ref --short -q HEAD)\" = \"\" &&\n> +test \"\\$(git rev-parse -q --verify HEAD)\" = \"$old_commit\" &&\n> +test \"\\$1\" = \"$new_commit\" &&\n> +git checkout -b success $root_commit\n> +EOF\n> +chmod +x test_command.sh\n> +\n> +test_expect_success '1.5.2.2 - !command invoked to integrate $new_commit -> $old_commit' '\n> +\tsetup_super &&\n> +\t(cd super &&\n> +\t setup_sub_state detach $old_commit &&\n> +\t setup_sub_update !../../test_command.sh &&\n> +\t setup_sub_branch unset &&\n> +\t git submodule update --remote &&\n> +\t verify_sub_state success $root_commit # test_command.sh is happy\n> +\t)\n> +'\n> +\n> +cat > test_command.sh <<EOF\n> +#!/bin/sh\n> +# Verify: detached @ $foo_commit, and asked to integrate $new_commit\n> +test \"\\$(git symbolic-ref --short -q HEAD)\" = \"\" &&\n> +test \"\\$(git rev-parse -q --verify HEAD)\" = \"$foo_commit\" &&\n> +test \"\\$1\" = \"$new_commit\" &&\n> +git checkout -b success $root_commit\n> +EOF\n> +chmod +x test_command.sh\n> +\n> +test_expect_success '1.5.2.3 - !command invoked to integrate $new_commit -> $foo_commit' '\n> +\tsetup_super &&\n> +\t(cd super &&\n> +\t setup_sub_state detach $foo_commit &&\n> +\t setup_sub_update !../../test_command.sh &&\n> +\t setup_sub_branch unset &&\n> +\t git submodule update --remote &&\n> +\t verify_sub_state success $root_commit # test_command.sh is happy\n> +\t)\n> +'\n> +\n> +cat > test_command.sh <<EOF\n> +#!/bin/sh\n> +# Verify: attached to foo @ $old_commit, and asked to integrate $new_commit\n> +test \"\\$(git symbolic-ref --short -q HEAD)\" = \"foo\" &&\n> +test \"\\$(git rev-parse -q --verify HEAD)\" = \"$old_commit\" &&\n> +test \"\\$1\" = \"$new_commit\" &&\n> +git checkout -b success $root_commit\n> +EOF\n> +chmod +x test_command.sh\n> +\n> +test_expect_success '1.5.2.4 - !command invoked to integrate $new_commit -> foo/$old_commit' '\n> +\tsetup_super &&\n> +\t(cd super &&\n> +\t setup_sub_state foo $old_commit &&\n> +\t setup_sub_update !../../test_command.sh &&\n> +\t setup_sub_branch unset &&\n> +\t git submodule update --remote &&\n> +\t verify_sub_state success $root_commit # test_command.sh is happy\n> +\t)\n> +'\n> +\n> +cat > test_command.sh <<EOF\n> +#!/bin/sh\n> +# Verify: attached to foo @ $foo_commit, and asked to integrate $new_commit\n> +test \"\\$(git symbolic-ref --short -q HEAD)\" = \"foo\" &&\n> +test \"\\$(git rev-parse -q --verify HEAD)\" = \"$foo_commit\" &&\n> +test \"\\$1\" = \"$new_commit\" &&\n> +git checkout -b success $root_commit\n> +EOF\n> +chmod +x test_command.sh\n> +\n> +test_expect_success '1.5.2.5 - !command invoked to integrate $new_commit -> foo/$foo_commit' '\n> +\tsetup_super &&\n> +\t(cd super &&\n> +\t setup_sub_state foo $foo_commit &&\n> +\t setup_sub_update !../../test_command.sh &&\n> +\t setup_sub_branch unset &&\n> +\t git submodule update --remote &&\n> +\t verify_sub_state success $root_commit # test_command.sh is happy\n> +\t)\n> +'\n> +\n> +cat > test_command.sh <<EOF\n> +#!/bin/sh\n> +# Verify: attached to bar @ $old_commit, and asked to integrate $new_commit\n> +test \"\\$(git symbolic-ref --short -q HEAD)\" = \"bar\" &&\n> +test \"\\$(git rev-parse -q --verify HEAD)\" = \"$old_commit\" &&\n> +test \"\\$1\" = \"$new_commit\" &&\n> +git checkout -b success $root_commit\n> +EOF\n> +chmod +x test_command.sh\n> +\n> +test_expect_success '1.5.2.6 - !command invoked to integrate $new_commit -> bar/$old_commit' '\n> +\tsetup_super &&\n> +\t(cd super &&\n> +\t setup_sub_state bar $old_commit &&\n> +\t setup_sub_update !../../test_command.sh &&\n> +\t setup_sub_branch unset &&\n> +\t git submodule update --remote &&\n> +\t verify_sub_state success $root_commit # test_command.sh is happy\n> +\t)\n> +'\n> +\n> +cat > test_command.sh <<EOF\n> +#!/bin/sh\n> +# Verify: attached to bar @ $foo_commit, and asked to integrate $new_commit\n> +test \"\\$(git symbolic-ref --short -q HEAD)\" = \"bar\" &&\n> +test \"\\$(git rev-parse -q --verify HEAD)\" = \"$foo_commit\" &&\n> +test \"\\$1\" = \"$new_commit\" &&\n> +git checkout -b success $root_commit\n> +EOF\n> +chmod +x test_command.sh\n> +\n> +test_expect_success '1.5.2.7 - !command invoked to integrate $new_commit -> bar/$foo_commit' '\n> +\tsetup_super &&\n> +\t(cd super &&\n> +\t setup_sub_state bar $foo_commit &&\n> +\t setup_sub_update !../../test_command.sh &&\n> +\t setup_sub_branch unset &&\n> +\t git submodule update --remote &&\n> +\t verify_sub_state success $root_commit # test_command.sh is happy\n> +\t)\n> +'\n> +\n> +# 2.1.* - .branch == foo (exists upstream), .update == none\n> +\n> +test_expect_success '2.1.1.1 - do nothing (.update == none)' '\n> +\tsetup_super &&\n> +\t(cd super &&\n> +\t setup_sub_state uncloned &&\n> +\t setup_sub_update none &&\n> +\t setup_sub_branch foo &&\n> +\t git submodule update &&\n> +\t verify_sub_state uncloned\n> +\t)\n> +'\n> +\n> +test_expect_success '2.1.1.2 - do nothing (.update == none)' '\n> +\tsetup_super &&\n> +\t(cd super &&\n> +\t setup_sub_state detach $old_commit &&\n> +\t setup_sub_update none &&\n> +\t setup_sub_branch foo &&\n> +\t git submodule update &&\n> +\t verify_sub_state detach $old_commit\n> +\t)\n> +'\n> +\n> +test_expect_success '2.1.1.3 - do nothing (.update == none)' '\n> +\tsetup_super &&\n> +\t(cd super &&\n> +\t setup_sub_state detach $foo_commit &&\n> +\t setup_sub_update none &&\n> +\t setup_sub_branch foo &&\n> +\t git submodule update &&\n> +\t verify_sub_state detach $foo_commit\n> +\t)\n> +'\n> +\n> +test_expect_success '2.1.1.4 - do nothing (.update == none)' '\n> +\tsetup_super &&\n> +\t(cd super &&\n> +\t setup_sub_state foo $old_commit &&\n> +\t setup_sub_update none &&\n> +\t setup_sub_branch foo &&\n> +\t git submodule update &&\n> +\t verify_sub_state foo $old_commit\n> +\t)\n> +'\n> +\n> +test_expect_success '2.1.1.5 - do nothing (.update == none)' '\n> +\tsetup_super &&\n> +\t(cd super &&\n> +\t setup_sub_state foo $foo_commit &&\n> +\t setup_sub_update none &&\n> +\t setup_sub_branch foo &&\n> +\t git submodule update &&\n> +\t verify_sub_state foo $foo_commit\n> +\t)\n> +'\n> +\n> +test_expect_success '2.1.1.6 - do nothing (.update == none)' '\n> +\tsetup_super &&\n> +\t(cd super &&\n> +\t setup_sub_state bar $old_commit &&\n> +\t setup_sub_update none &&\n> +\t setup_sub_branch foo &&\n> +\t git submodule update &&\n> +\t verify_sub_state bar $old_commit\n> +\t)\n> +'\n> +\n> +test_expect_success '2.1.1.7 - do nothing (.update == none)' '\n> +\tsetup_super &&\n> +\t(cd super &&\n> +\t setup_sub_state bar $foo_commit &&\n> +\t setup_sub_update none &&\n> +\t setup_sub_branch foo &&\n> +\t git submodule update &&\n> +\t verify_sub_state bar $foo_commit\n> +\t)\n> +'\n> +\n> +test_expect_success '2.1.2.1 - do nothing (.update == none)' '\n> +\tsetup_super &&\n> +\t(cd super &&\n> +\t setup_sub_state uncloned &&\n> +\t setup_sub_update none &&\n> +\t setup_sub_branch foo &&\n> +\t git submodule update --remote &&\n> +\t verify_sub_state uncloned\n> +\t)\n> +'\n> +\n> +test_expect_success '2.1.2.2 - do nothing (.update == none)' '\n> +\tsetup_super &&\n> +\t(cd super &&\n> +\t setup_sub_state detach $old_commit &&\n> +\t setup_sub_update none &&\n> +\t setup_sub_branch foo &&\n> +\t git submodule update --remote &&\n> +\t verify_sub_state detach $old_commit\n> +\t)\n> +'\n> +\n> +test_expect_success '2.1.2.3 - do nothing (.update == none)' '\n> +\tsetup_super &&\n> +\t(cd super &&\n> +\t setup_sub_state detach $foo_commit &&\n> +\t setup_sub_update none &&\n> +\t setup_sub_branch foo &&\n> +\t git submodule update --remote &&\n> +\t verify_sub_state detach $foo_commit\n> +\t)\n> +'\n> +\n> +test_expect_success '2.1.2.4 - do nothing (.update == none)' '\n> +\tsetup_super &&\n> +\t(cd super &&\n> +\t setup_sub_state foo $old_commit &&\n> +\t setup_sub_update none &&\n> +\t setup_sub_branch foo &&\n> +\t git submodule update --remote &&\n> +\t verify_sub_state foo $old_commit\n> +\t)\n> +'\n> +\n> +test_expect_success '2.1.2.5 - do nothing (.update == none)' '\n> +\tsetup_super &&\n> +\t(cd super &&\n> +\t setup_sub_state foo $foo_commit &&\n> +\t setup_sub_update none &&\n> +\t setup_sub_branch foo &&\n> +\t git submodule update --remote &&\n> +\t verify_sub_state foo $foo_commit\n> +\t)\n> +'\n> +\n> +test_expect_success '2.1.2.6 - do nothing (.update == none)' '\n> +\tsetup_super &&\n> +\t(cd super &&\n> +\t setup_sub_state bar $old_commit &&\n> +\t setup_sub_update none &&\n> +\t setup_sub_branch foo &&\n> +\t git submodule update --remote &&\n> +\t verify_sub_state bar $old_commit\n> +\t)\n> +'\n> +\n> +test_expect_success '2.1.2.7 - do nothing (.update == none)' '\n> +\tsetup_super &&\n> +\t(cd super &&\n> +\t setup_sub_state bar $foo_commit &&\n> +\t setup_sub_update none &&\n> +\t setup_sub_branch foo &&\n> +\t git submodule update --remote &&\n> +\t verify_sub_state bar $foo_commit\n> +\t)\n> +'\n> +\n> +# 2.2.* - .branch == foo (exists upstream), .update == checkout\n> +\n> +test_expect_success '2.2.1.1 - clone, detach @ $old_commit (.branch is ignored)' '\n> +\tsetup_super &&\n> +\t(cd super &&\n> +\t setup_sub_state uncloned &&\n> +\t setup_sub_update checkout &&\n> +\t setup_sub_branch foo &&\n> +\t git submodule update &&\n> +\t verify_sub_state detach $old_commit # D4\n> +\t)\n> +'\n> +\n> +test_expect_success '2.2.1.2 - already @ $old_commit -> keep detached' '\n> +\tsetup_super &&\n> +\t(cd super &&\n> +\t setup_sub_state detach $old_commit &&\n> +\t setup_sub_update checkout &&\n> +\t setup_sub_branch foo &&\n> +\t git submodule update &&\n> +\t verify_sub_state detach $old_commit\n> +\t)\n> +'\n> +\n> +test_expect_success '2.2.1.3 - detach @ $old_commit' '\n> +\tsetup_super &&\n> +\t(cd super &&\n> +\t setup_sub_state detach $foo_commit &&\n> +\t setup_sub_update checkout &&\n> +\t setup_sub_branch foo &&\n> +\t git submodule update &&\n> +\t verify_sub_state detach $old_commit\n> +\t)\n> +'\n> +\n> +test_expect_success '2.2.1.4 - already @ $old_commit -> keep attached' ' # D1\n> +\tsetup_super &&\n> +\t(cd super &&\n> +\t setup_sub_state foo $old_commit &&\n> +\t setup_sub_update checkout &&\n> +\t setup_sub_branch foo &&\n> +\t git submodule update &&\n> +\t verify_sub_state foo $old_commit\n> +\t)\n> +'\n> +\n> +test_expect_success '2.2.1.5 - detach @ $old_commit' '\n> +\tsetup_super &&\n> +\t(cd super &&\n> +\t setup_sub_state foo $foo_commit &&\n> +\t setup_sub_update checkout &&\n> +\t setup_sub_branch foo &&\n> +\t git submodule update &&\n> +\t verify_sub_state detach $old_commit\n> +\t)\n> +'\n> +\n> +test_expect_success '2.2.1.6 - already @ $old_commit -> keep attached' ' # D1\n> +\tsetup_super &&\n> +\t(cd super &&\n> +\t setup_sub_state bar $old_commit &&\n> +\t setup_sub_update checkout &&\n> +\t setup_sub_branch foo &&\n> +\t git submodule update &&\n> +\t verify_sub_state bar $old_commit\n> +\t)\n> +'\n> +\n> +test_expect_success '2.2.1.7 - detach @ $old_commit' '\n> +\tsetup_super &&\n> +\t(cd super &&\n> +\t setup_sub_state bar $foo_commit &&\n> +\t setup_sub_update checkout &&\n> +\t setup_sub_branch foo &&\n> +\t git submodule update &&\n> +\t verify_sub_state detach $old_commit\n> +\t)\n> +'\n> +\n> +test_expect_success '2.2.2.1 - clone, detach @ $foo_commit' '\n> +\tsetup_super &&\n> +\t(cd super &&\n> +\t setup_sub_state uncloned &&\n> +\t setup_sub_update checkout &&\n> +\t setup_sub_branch foo &&\n> +\t git submodule update --remote &&\n> +\t verify_sub_state detach $foo_commit # D4\n> +\t)\n> +'\n> +\n> +test_expect_success '2.2.2.2 - detach @ $foo_commit' '\n> +\tsetup_super &&\n> +\t(cd super &&\n> +\t setup_sub_state detach $old_commit &&\n> +\t setup_sub_update checkout &&\n> +\t setup_sub_branch foo &&\n> +\t git submodule update --remote &&\n> +\t verify_sub_state detach $foo_commit\n> +\t)\n> +'\n> +\n> +test_expect_success '2.2.2.3 - already @ $foo_commit, remain detached' '\n> +\tsetup_super &&\n> +\t(cd super &&\n> +\t setup_sub_state detach $foo_commit &&\n> +\t setup_sub_update checkout &&\n> +\t setup_sub_branch foo &&\n> +\t git submodule update --remote &&\n> +\t verify_sub_state detach $foo_commit\n> +\t)\n> +'\n> +\n> +test_expect_success '2.2.2.4 - detach @ $foo_commit' '\n> +\tsetup_super &&\n> +\t(cd super &&\n> +\t setup_sub_state foo $old_commit &&\n> +\t setup_sub_update checkout &&\n> +\t setup_sub_branch foo &&\n> +\t git submodule update --remote &&\n> +\t verify_sub_state detach $foo_commit\n> +\t)\n> +'\n> +\n> +test_expect_success '2.2.2.5 - already @ $foo_commit, remain attached to foo' '\n> +\tsetup_super &&\n> +\t(cd super &&\n> +\t setup_sub_state foo $foo_commit &&\n> +\t setup_sub_update checkout &&\n> +\t setup_sub_branch foo &&\n> +\t git submodule update --remote &&\n> +\t verify_sub_state foo $foo_commit\n> +\t)\n> +'\n> +\n> +test_expect_success '2.2.2.6 - detach @ $foo_commit' '\n> +\tsetup_super &&\n> +\t(cd super &&\n> +\t setup_sub_state bar $old_commit &&\n> +\t setup_sub_update checkout &&\n> +\t setup_sub_branch foo &&\n> +\t git submodule update --remote &&\n> +\t verify_sub_state detach $foo_commit\n> +\t)\n> +'\n> +\n> +test_expect_success '2.2.2.7 - already @ $foo_commit, remain attached to bar' '\n> +\tsetup_super &&\n> +\t(cd super &&\n> +\t setup_sub_state bar $foo_commit &&\n> +\t setup_sub_update checkout &&\n> +\t setup_sub_branch foo &&\n> +\t git submodule update --remote &&\n> +\t verify_sub_state bar $foo_commit\n> +\t)\n> +'\n> +\n> +# 2.3.* - .branch == foo (exists upstream), .update == merge\n> +\n> +test_expect_success '2.3.1.1 - clone, create branch called foo @ $old_commit' '\n> +\tsetup_super &&\n> +\t(cd super &&\n> +\t setup_sub_state uncloned &&\n> +\t setup_sub_update merge &&\n> +\t setup_sub_branch foo &&\n> +\t git submodule update &&\n> +\t verify_sub_state detach $old_commit # D4, FIXME: s/detach/foo/?\n> +\t)\n> +'\n> +\n> +test_expect_success '2.3.1.2 - already at $old_commit, remain detached' ' # D3\n> +\tsetup_super &&\n> +\t(cd super &&\n> +\t setup_sub_state detach $old_commit &&\n> +\t setup_sub_update merge &&\n> +\t setup_sub_branch foo &&\n> +\t git submodule update &&\n> +\t verify_sub_state detach $old_commit\n> +\t)\n> +'\n> +\n> +test_expect_success '2.3.1.3 - merge $old_commit -> $foo_commit, remain detached' ' # D5\n> +\tsetup_super &&\n> +\t(cd super &&\n> +\t setup_sub_state detach $foo_commit &&\n> +\t setup_sub_update merge &&\n> +\t setup_sub_branch foo &&\n> +\t git submodule update &&\n> +\t verify_sub_state detach parents.$foo_commit.$old_commit\n> +\t)\n> +'\n> +\n> +test_expect_success '2.3.1.4 - already at $old_commit, remain attached to foo' ' # D3\n> +\tsetup_super &&\n> +\t(cd super &&\n> +\t setup_sub_state foo $old_commit &&\n> +\t setup_sub_update merge &&\n> +\t setup_sub_branch foo &&\n> +\t git submodule update &&\n> +\t verify_sub_state foo $old_commit\n> +\t)\n> +'\n> +\n> +test_expect_success '2.3.1.5 - merge $old_commit -> $foo_commit, remain attached to foo' ' # D5\n> +\tsetup_super &&\n> +\t(cd super &&\n> +\t setup_sub_state foo $foo_commit &&\n> +\t setup_sub_update merge &&\n> +\t setup_sub_branch foo &&\n> +\t git submodule update &&\n> +\t verify_sub_state foo parents.$foo_commit.$old_commit\n> +\t)\n> +'\n> +\n> +test_expect_success '2.3.1.6 - already at $old_commit, remain attached to bar' ' # D3\n> +\tsetup_super &&\n> +\t(cd super &&\n> +\t setup_sub_state bar $old_commit &&\n> +\t setup_sub_update merge &&\n> +\t setup_sub_branch foo &&\n> +\t git submodule update &&\n> +\t verify_sub_state bar $old_commit\n> +\t)\n> +'\n> +\n> +test_expect_success '2.3.1.7 - merge $old_commit -> $foo_commit, remain attached to bar' ' # D5\n> +\tsetup_super &&\n> +\t(cd super &&\n> +\t setup_sub_state bar $foo_commit &&\n> +\t setup_sub_update merge &&\n> +\t setup_sub_branch foo &&\n> +\t git submodule update &&\n> +\t verify_sub_state bar parents.$foo_commit.$old_commit\n> +\t)\n> +'\n> +\n> +test_expect_success '2.3.2.1 - clone, create branch from origin/foo @ $foo_commit' '\n> +\tsetup_super &&\n> +\t(cd super &&\n> +\t setup_sub_state uncloned &&\n> +\t setup_sub_update merge &&\n> +\t setup_sub_branch foo &&\n> +\t git submodule update --remote &&\n> +\t verify_sub_state detach $foo_commit # D4, FIXME: s/detach/foo/?\n> +\t)\n> +'\n> +\n> +test_expect_success '2.3.2.2 - merge $foo_commit -> $old_commit, remain detached' ' # D5\n> +\tsetup_super &&\n> +\t(cd super &&\n> +\t setup_sub_state detach $old_commit &&\n> +\t setup_sub_update merge &&\n> +\t setup_sub_branch foo &&\n> +\t git submodule update --remote &&\n> +\t verify_sub_state detach parents.$old_commit.$foo_commit\n> +\t)\n> +'\n> +\n> +test_expect_success '2.3.2.3 - already @ $foo_commit, remain detached' ' # D3\n> +\tsetup_super &&\n> +\t(cd super &&\n> +\t setup_sub_state detach $foo_commit &&\n> +\t setup_sub_update merge &&\n> +\t setup_sub_branch foo &&\n> +\t git submodule update --remote &&\n> +\t verify_sub_state detach $foo_commit\n> +\t)\n> +'\n> +\n> +test_expect_success '2.3.2.4 - merge $foo_commit -> $old_commit, remain attached to foo' ' # D5\n> +\tsetup_super &&\n> +\t(cd super &&\n> +\t setup_sub_state foo $old_commit &&\n> +\t setup_sub_update merge &&\n> +\t setup_sub_branch foo &&\n> +\t git submodule update --remote &&\n> +\t verify_sub_state foo parents.$old_commit.$foo_commit\n> +\t)\n> +'\n> +\n> +test_expect_success '2.3.2.5 - already @ $foo_commit, remain attached to foo' ' # D3\n> +\tsetup_super &&\n> +\t(cd super &&\n> +\t setup_sub_state foo $foo_commit &&\n> +\t setup_sub_update merge &&\n> +\t setup_sub_branch foo &&\n> +\t git submodule update --remote &&\n> +\t verify_sub_state foo $foo_commit\n> +\t)\n> +'\n> +\n> +test_expect_success '2.3.2.6 - merge $foo_commit -> $old_commit, remain attached to bar' ' # D5\n> +\tsetup_super &&\n> +\t(cd super &&\n> +\t setup_sub_state bar $old_commit &&\n> +\t setup_sub_update merge &&\n> +\t setup_sub_branch foo &&\n> +\t git submodule update --remote &&\n> +\t verify_sub_state bar parents.$old_commit.$foo_commit\n> +\t)\n> +'\n> +\n> +test_expect_success '2.3.2.7 - already @ $foo_commit, remain attached to bar' ' # D3\n> +\tsetup_super &&\n> +\t(cd super &&\n> +\t setup_sub_state bar $foo_commit &&\n> +\t setup_sub_update merge &&\n> +\t setup_sub_branch foo &&\n> +\t git submodule update --remote &&\n> +\t verify_sub_state bar $foo_commit\n> +\t)\n> +'\n> +\n> +# 2.4.* - .branch == foo (exists upstream), .update == rebase\n> +\n> +test_expect_success '2.4.1.1 - clone, create branch called foo @ $old_commit' '\n> +\tsetup_super &&\n> +\t(cd super &&\n> +\t setup_sub_state uncloned &&\n> +\t setup_sub_update rebase &&\n> +\t setup_sub_branch foo &&\n> +\t git submodule update &&\n> +\t verify_sub_state detach $old_commit # D4, FIXME: s/detach/foo/?\n> +\t)\n> +'\n> +\n> +test_expect_success '2.4.1.2 - already at $old_commit, remain detached' ' # D3\n> +\tsetup_super &&\n> +\t(cd super &&\n> +\t setup_sub_state detach $old_commit &&\n> +\t setup_sub_update rebase &&\n> +\t setup_sub_branch foo &&\n> +\t git submodule update &&\n> +\t verify_sub_state detach $old_commit\n> +\t)\n> +'\n> +\n> +test_expect_success '2.4.1.3 - rebase $foo_commit onto $old_commit, remain detached' ' # D5\n> +\tsetup_super &&\n> +\t(cd super &&\n> +\t setup_sub_state detach $foo_commit &&\n> +\t setup_sub_update rebase &&\n> +\t setup_sub_branch foo &&\n> +\t git submodule update &&\n> +\t verify_sub_state detach parents.$old_commit &&\n> +\t verify_sub_patch_id HEAD $foo_commit\n> +\t)\n> +'\n> +\n> +test_expect_success '2.4.1.4 - already at $old_commit, remain attached to foo' ' # D3\n> +\tsetup_super &&\n> +\t(cd super &&\n> +\t setup_sub_state foo $old_commit &&\n> +\t setup_sub_update rebase &&\n> +\t setup_sub_branch foo &&\n> +\t git submodule update &&\n> +\t verify_sub_state foo $old_commit\n> +\t)\n> +'\n> +\n> +test_expect_success '2.4.1.5 - rebase $foo_commit onto $old_commit, remain attached to foo' ' # D5\n> +\tsetup_super &&\n> +\t(cd super &&\n> +\t setup_sub_state foo $foo_commit &&\n> +\t setup_sub_update rebase &&\n> +\t setup_sub_branch foo &&\n> +\t git submodule update &&\n> +\t verify_sub_state foo parents.$old_commit &&\n> +\t verify_sub_patch_id HEAD $foo_commit\n> +\t)\n> +'\n> +\n> +test_expect_success '2.4.1.6 - already at $old_commit, remain attached to bar' ' # D3\n> +\tsetup_super &&\n> +\t(cd super &&\n> +\t setup_sub_state bar $old_commit &&\n> +\t setup_sub_update rebase &&\n> +\t setup_sub_branch foo &&\n> +\t git submodule update &&\n> +\t verify_sub_state bar $old_commit\n> +\t)\n> +'\n> +\n> +test_expect_success '2.4.1.7 - rebase $foo_commit onto $old_commit, remain attached to bar' ' # D5\n> +\tsetup_super &&\n> +\t(cd super &&\n> +\t setup_sub_state bar $foo_commit &&\n> +\t setup_sub_update rebase &&\n> +\t setup_sub_branch foo &&\n> +\t git submodule update &&\n> +\t verify_sub_state bar parents.$old_commit &&\n> +\t verify_sub_patch_id HEAD $foo_commit\n> +\t)\n> +'\n> +\n> +test_expect_success '2.4.2.1 - clone, create branch from origin/foo @ $foo_commit' '\n> +\tsetup_super &&\n> +\t(cd super &&\n> +\t setup_sub_state uncloned &&\n> +\t setup_sub_update rebase &&\n> +\t setup_sub_branch foo &&\n> +\t git submodule update --remote &&\n> +\t verify_sub_state detach $foo_commit # D4, FIXME: s/detach/foo/?\n> +\t)\n> +'\n> +\n> +test_expect_success '2.4.2.2 - rebase $old_commit onto $foo_commit, remain detached' ' # D5\n> +\tsetup_super &&\n> +\t(cd super &&\n> +\t setup_sub_state detach $old_commit &&\n> +\t setup_sub_update rebase &&\n> +\t setup_sub_branch foo &&\n> +\t git submodule update --remote &&\n> +\t verify_sub_state detach parents.$foo_commit &&\n> +\t verify_sub_patch_id HEAD $old_commit\n> +\t)\n> +'\n> +\n> +test_expect_success '2.4.2.3 - already @ $foo_commit, remain detached' ' # D3\n> +\tsetup_super &&\n> +\t(cd super &&\n> +\t setup_sub_state detach $foo_commit &&\n> +\t setup_sub_update rebase &&\n> +\t setup_sub_branch foo &&\n> +\t git submodule update --remote &&\n> +\t verify_sub_state detach $foo_commit\n> +\t)\n> +'\n> +\n> +test_expect_success '2.4.2.4 - rebase $old_commit onto $foo_commit, remain attached to foo' ' # D5\n> +\tsetup_super &&\n> +\t(cd super &&\n> +\t setup_sub_state foo $old_commit &&\n> +\t setup_sub_update rebase &&\n> +\t setup_sub_branch foo &&\n> +\t git submodule update --remote &&\n> +\t verify_sub_state foo parents.$foo_commit &&\n> +\t verify_sub_patch_id HEAD $old_commit\n> +\t)\n> +'\n> +\n> +test_expect_success '2.4.2.5 - already @ $foo_commit, remain attached to foo' ' # D3\n> +\tsetup_super &&\n> +\t(cd super &&\n> +\t setup_sub_state foo $foo_commit &&\n> +\t setup_sub_update rebase &&\n> +\t setup_sub_branch foo &&\n> +\t git submodule update --remote &&\n> +\t verify_sub_state foo $foo_commit\n> +\t)\n> +'\n> +\n> +test_expect_success '2.4.2.6 - rebase $old_commit onto $foo_commit, remain attached to bar' ' # D5\n> +\tsetup_super &&\n> +\t(cd super &&\n> +\t setup_sub_state bar $old_commit &&\n> +\t setup_sub_update rebase &&\n> +\t setup_sub_branch foo &&\n> +\t git submodule update --remote &&\n> +\t verify_sub_state bar parents.$foo_commit &&\n> +\t verify_sub_patch_id HEAD $old_commit\n> +\t)\n> +'\n> +\n> +test_expect_success '2.4.2.7 - already @ $foo_commit, remain attached to bar' ' # D3\n> +\tsetup_super &&\n> +\t(cd super &&\n> +\t setup_sub_state bar $foo_commit &&\n> +\t setup_sub_update rebase &&\n> +\t setup_sub_branch foo &&\n> +\t git submodule update --remote &&\n> +\t verify_sub_state bar $foo_commit\n> +\t)\n> +'\n> +\n> +# 2.5.* - .branch == foo (exists upstream), .update == !command\n> +\n> +test_expect_success '2.5.1.1 - clone, create branch called foo @ $old_commit. !command is NOT invoked' '\n> +\tsetup_super &&\n> +\t(cd super &&\n> +\t setup_sub_state uncloned &&\n> +\t setup_sub_update !false &&\n> +\t setup_sub_branch foo &&\n> +\t git submodule update && # should not invoke \"false\"\n> +\t verify_sub_state detach $old_commit # D4, FIXME: s/detach/foo/?\n> +\t)\n> +'\n> +\n> +test_expect_success '2.5.1.2 - already at $old_commit, remain detached. !command is NOT invoked' '\n> +\tsetup_super &&\n> +\t(cd super &&\n> +\t setup_sub_state detach $old_commit &&\n> +\t setup_sub_update !false &&\n> +\t setup_sub_branch foo &&\n> +\t git submodule update && # should not invoke \"false\"\n> +\t verify_sub_state detach $old_commit\n> +\t)\n> +'\n> +\n> +cat > test_command.sh <<EOF\n> +#!/bin/sh\n> +# Verify: detached @ $foo_commit, and asked to integrate $old_commit\n> +test \"\\$(git symbolic-ref --short -q HEAD)\" = \"\" &&\n> +test \"\\$(git rev-parse -q --verify HEAD)\" = \"$foo_commit\" &&\n> +test \"\\$1\" = \"$old_commit\" &&\n> +git checkout -b success $root_commit\n> +EOF\n> +chmod +x test_command.sh\n> +\n> +test_expect_success '2.5.1.3 - !command invoked to integrate $old_commit -> $foo_commit' '\n> +\tsetup_super &&\n> +\t(cd super &&\n> +\t setup_sub_state detach $foo_commit &&\n> +\t setup_sub_update !../../test_command.sh &&\n> +\t setup_sub_branch foo &&\n> +\t git submodule update &&\n> +\t verify_sub_state success $root_commit # test_command.sh is happy\n> +\t)\n> +'\n> +\n> +test_expect_success '2.5.1.4 - already at $old_commit, remain attached to foo. !command is NOT invoked' '\n> +\tsetup_super &&\n> +\t(cd super &&\n> +\t setup_sub_state foo $old_commit &&\n> +\t setup_sub_update !false &&\n> +\t setup_sub_branch foo &&\n> +\t git submodule update &&\n> +\t verify_sub_state foo $old_commit\n> +\t)\n> +'\n> +\n> +cat > test_command.sh <<EOF\n> +#!/bin/sh\n> +# Verify: attached to foo @ $foo_commit, and asked to integrate $old_commit\n> +test \"\\$(git symbolic-ref --short -q HEAD)\" = \"foo\" &&\n> +test \"\\$(git rev-parse -q --verify HEAD)\" = \"$foo_commit\" &&\n> +test \"\\$1\" = \"$old_commit\" &&\n> +git checkout -b success $root_commit\n> +EOF\n> +chmod +x test_command.sh\n> +\n> +test_expect_success '2.5.1.5 - !command invoked to integrate $old_commit -> foo/$foo_commit' '\n> +\tsetup_super &&\n> +\t(cd super &&\n> +\t setup_sub_state foo $foo_commit &&\n> +\t setup_sub_update !../../test_command.sh &&\n> +\t setup_sub_branch foo &&\n> +\t git submodule update &&\n> +\t verify_sub_state success $root_commit # test_command.sh is happy\n> +\t)\n> +'\n> +\n> +test_expect_success '2.5.1.6 - already at $old_commit, remain attached to bar. !command is NOT invoked' '\n> +\tsetup_super &&\n> +\t(cd super &&\n> +\t setup_sub_state bar $old_commit &&\n> +\t setup_sub_update !false &&\n> +\t setup_sub_branch foo &&\n> +\t git submodule update &&\n> +\t verify_sub_state bar $old_commit\n> +\t)\n> +'\n> +\n> +cat > test_command.sh <<EOF\n> +#!/bin/sh\n> +# Verify: attached to bar @ $foo_commit, and asked to integrate $old_commit\n> +test \"\\$(git symbolic-ref --short -q HEAD)\" = \"bar\" &&\n> +test \"\\$(git rev-parse -q --verify HEAD)\" = \"$foo_commit\" &&\n> +test \"\\$1\" = \"$old_commit\" &&\n> +git checkout -b success $root_commit\n> +EOF\n> +chmod +x test_command.sh\n> +\n> +test_expect_success '2.5.1.7 - !command invoked to integrate $old_commit -> bar/$foo_commit' '\n> +\tsetup_super &&\n> +\t(cd super &&\n> +\t setup_sub_state bar $foo_commit &&\n> +\t setup_sub_update !../../test_command.sh &&\n> +\t setup_sub_branch foo &&\n> +\t git submodule update &&\n> +\t verify_sub_state success $root_commit # test_command.sh is happy\n> +\t)\n> +'\n> +\n> +test_expect_success '2.5.2.1 - clone, create branch from origin/foo @ $foo_commit. !command is NOT invoked' '\n> +\tsetup_super &&\n> +\t(cd super &&\n> +\t setup_sub_state uncloned &&\n> +\t setup_sub_update !false &&\n> +\t setup_sub_branch foo &&\n> +\t git submodule update --remote &&\n> +\t verify_sub_state detach $foo_commit # D4, FIXME: s/detach/foo/?\n> +\t)\n> +'\n> +\n> +cat > test_command.sh <<EOF\n> +#!/bin/sh\n> +# Verify: detached @ $old_commit, and asked to integrate $foo_commit\n> +test \"\\$(git symbolic-ref --short -q HEAD)\" = \"\" &&\n> +test \"\\$(git rev-parse -q --verify HEAD)\" = \"$old_commit\" &&\n> +test \"\\$1\" = \"$foo_commit\" &&\n> +git checkout -b success $root_commit\n> +EOF\n> +chmod +x test_command.sh\n> +\n> +test_expect_success '2.5.2.2 - !command invoked to integrate $foo_commit -> $old_commit' '\n> +\tsetup_super &&\n> +\t(cd super &&\n> +\t setup_sub_state detach $old_commit &&\n> +\t setup_sub_update !../../test_command.sh &&\n> +\t setup_sub_branch foo &&\n> +\t git submodule update --remote &&\n> +\t verify_sub_state success $root_commit # test_command.sh is happy\n> +\t)\n> +'\n> +\n> +test_expect_success '2.5.2.3 - already at $foo_commit, remain detached. !command is NOT invoked' '\n> +\tsetup_super &&\n> +\t(cd super &&\n> +\t setup_sub_state detach $foo_commit &&\n> +\t setup_sub_update !false &&\n> +\t setup_sub_branch foo &&\n> +\t git submodule update --remote &&\n> +\t verify_sub_state detach $foo_commit\n> +\t)\n> +'\n> +\n> +cat > test_command.sh <<EOF\n> +#!/bin/sh\n> +# Verify: attached to foo @ $old_commit, and asked to integrate $foo_commit\n> +test \"\\$(git symbolic-ref --short -q HEAD)\" = \"foo\" &&\n> +test \"\\$(git rev-parse -q --verify HEAD)\" = \"$old_commit\" &&\n> +test \"\\$1\" = \"$foo_commit\" &&\n> +git checkout -b success $root_commit\n> +EOF\n> +chmod +x test_command.sh\n> +\n> +test_expect_success '2.5.2.4 - !command invoked to integrate $foo_commit -> foo/$old_commit' '\n> +\tsetup_super &&\n> +\t(cd super &&\n> +\t setup_sub_state foo $old_commit &&\n> +\t setup_sub_update !../../test_command.sh &&\n> +\t setup_sub_branch foo &&\n> +\t git submodule update --remote &&\n> +\t verify_sub_state success $root_commit # test_command.sh is happy\n> +\t)\n> +'\n> +\n> +test_expect_success '2.5.2.5 - already at $foo_commit, remain attached to foo. !command is NOT invoked' '\n> +\tsetup_super &&\n> +\t(cd super &&\n> +\t setup_sub_state foo $foo_commit &&\n> +\t setup_sub_update !false &&\n> +\t setup_sub_branch foo &&\n> +\t git submodule update --remote &&\n> +\t verify_sub_state foo $foo_commit\n> +\t)\n> +'\n> +\n> +cat > test_command.sh <<EOF\n> +#!/bin/sh\n> +# Verify: attached to bar @ $old_commit, and asked to integrate $foo_commit\n> +test \"\\$(git symbolic-ref --short -q HEAD)\" = \"bar\" &&\n> +test \"\\$(git rev-parse -q --verify HEAD)\" = \"$old_commit\" &&\n> +test \"\\$1\" = \"$foo_commit\" &&\n> +git checkout -b success $root_commit\n> +EOF\n> +chmod +x test_command.sh\n> +\n> +test_expect_success '2.5.2.6 - !command invoked to integrate $foo_commit -> bar/$old_commit' '\n> +\tsetup_super &&\n> +\t(cd super &&\n> +\t setup_sub_state bar $old_commit &&\n> +\t setup_sub_update !../../test_command.sh &&\n> +\t setup_sub_branch foo &&\n> +\t git submodule update --remote &&\n> +\t verify_sub_state success $root_commit # test_command.sh is happy\n> +\t)\n> +'\n> +\n> +test_expect_success '2.5.2.7 - already at $foo_commit, remain attached to bar. !command is NOT invoked' '\n> +\tsetup_super &&\n> +\t(cd super &&\n> +\t setup_sub_state bar $foo_commit &&\n> +\t setup_sub_update !false &&\n> +\t setup_sub_branch foo &&\n> +\t git submodule update --remote &&\n> +\t verify_sub_state bar $foo_commit\n> +\t)\n> +'\n> +\n> +# 3.1.* - .branch == bar (MISSING upstream), .update == none\n> +\n> +test_expect_success '3.1.1.1 - do nothing (.update == none)' '\n> +\tsetup_super &&\n> +\t(cd super &&\n> +\t setup_sub_state uncloned &&\n> +\t setup_sub_update none &&\n> +\t setup_sub_branch bar &&\n> +\t git submodule update &&\n> +\t verify_sub_state uncloned\n> +\t)\n> +'\n> +\n> +test_expect_success '3.1.1.2 - do nothing (.update == none)' '\n> +\tsetup_super &&\n> +\t(cd super &&\n> +\t setup_sub_state detach $old_commit &&\n> +\t setup_sub_update none &&\n> +\t setup_sub_branch bar &&\n> +\t git submodule update &&\n> +\t verify_sub_state detach $old_commit\n> +\t)\n> +'\n> +\n> +test_expect_success '3.1.1.3 - do nothing (.update == none)' '\n> +\tsetup_super &&\n> +\t(cd super &&\n> +\t setup_sub_state detach $foo_commit &&\n> +\t setup_sub_update none &&\n> +\t setup_sub_branch bar &&\n> +\t git submodule update &&\n> +\t verify_sub_state detach $foo_commit\n> +\t)\n> +'\n> +\n> +test_expect_success '3.1.1.4 - do nothing (.update == none)' '\n> +\tsetup_super &&\n> +\t(cd super &&\n> +\t setup_sub_state foo $old_commit &&\n> +\t setup_sub_update none &&\n> +\t setup_sub_branch bar &&\n> +\t git submodule update &&\n> +\t verify_sub_state foo $old_commit\n> +\t)\n> +'\n> +\n> +test_expect_success '3.1.1.5 - do nothing (.update == none)' '\n> +\tsetup_super &&\n> +\t(cd super &&\n> +\t setup_sub_state foo $foo_commit &&\n> +\t setup_sub_update none &&\n> +\t setup_sub_branch bar &&\n> +\t git submodule update &&\n> +\t verify_sub_state foo $foo_commit\n> +\t)\n> +'\n> +\n> +test_expect_success '3.1.1.6 - do nothing (.update == none)' '\n> +\tsetup_super &&\n> +\t(cd super &&\n> +\t setup_sub_state bar $old_commit &&\n> +\t setup_sub_update none &&\n> +\t setup_sub_branch bar &&\n> +\t git submodule update &&\n> +\t verify_sub_state bar $old_commit\n> +\t)\n> +'\n> +\n> +test_expect_success '3.1.1.7 - do nothing (.update == none)' '\n> +\tsetup_super &&\n> +\t(cd super &&\n> +\t setup_sub_state bar $foo_commit &&\n> +\t setup_sub_update none &&\n> +\t setup_sub_branch bar &&\n> +\t git submodule update &&\n> +\t verify_sub_state bar $foo_commit\n> +\t)\n> +'\n> +\n> +test_expect_success '3.1.2.1 - do nothing (.update == none)' '\n> +\tsetup_super &&\n> +\t(cd super &&\n> +\t setup_sub_state uncloned &&\n> +\t setup_sub_update none &&\n> +\t setup_sub_branch bar &&\n> +\t git submodule update --remote &&\n> +\t verify_sub_state uncloned\n> +\t)\n> +'\n> +\n> +test_expect_success '3.1.2.2 - do nothing (.update == none)' '\n> +\tsetup_super &&\n> +\t(cd super &&\n> +\t setup_sub_state detach $old_commit &&\n> +\t setup_sub_update none &&\n> +\t setup_sub_branch bar &&\n> +\t git submodule update --remote &&\n> +\t verify_sub_state detach $old_commit\n> +\t)\n> +'\n> +\n> +test_expect_success '3.1.2.3 - do nothing (.update == none)' '\n> +\tsetup_super &&\n> +\t(cd super &&\n> +\t setup_sub_state detach $foo_commit &&\n> +\t setup_sub_update none &&\n> +\t setup_sub_branch bar &&\n> +\t git submodule update --remote &&\n> +\t verify_sub_state detach $foo_commit\n> +\t)\n> +'\n> +\n> +test_expect_success '3.1.2.4 - do nothing (.update == none)' '\n> +\tsetup_super &&\n> +\t(cd super &&\n> +\t setup_sub_state foo $old_commit &&\n> +\t setup_sub_update none &&\n> +\t setup_sub_branch bar &&\n> +\t git submodule update --remote &&\n> +\t verify_sub_state foo $old_commit\n> +\t)\n> +'\n> +\n> +test_expect_success '3.1.2.5 - do nothing (.update == none)' '\n> +\tsetup_super &&\n> +\t(cd super &&\n> +\t setup_sub_state foo $foo_commit &&\n> +\t setup_sub_update none &&\n> +\t setup_sub_branch bar &&\n> +\t git submodule update --remote &&\n> +\t verify_sub_state foo $foo_commit\n> +\t)\n> +'\n> +\n> +test_expect_success '3.1.2.6 - do nothing (.update == none)' '\n> +\tsetup_super &&\n> +\t(cd super &&\n> +\t setup_sub_state bar $old_commit &&\n> +\t setup_sub_update none &&\n> +\t setup_sub_branch bar &&\n> +\t git submodule update --remote &&\n> +\t verify_sub_state bar $old_commit\n> +\t)\n> +'\n> +\n> +test_expect_success '3.1.2.7 - do nothing (.update == none)' '\n> +\tsetup_super &&\n> +\t(cd super &&\n> +\t setup_sub_state bar $foo_commit &&\n> +\t setup_sub_update none &&\n> +\t setup_sub_branch bar &&\n> +\t git submodule update --remote &&\n> +\t verify_sub_state bar $foo_commit\n> +\t)\n> +'\n> +\n> +# 3.2.* - .branch == bar (MISSING upstream), .update == checkout\n> +\n> +test_expect_success '3.2.1.1 - clone, detach @ $old_commit (.branch is ignored)' '\n> +\tsetup_super &&\n> +\t(cd super &&\n> +\t setup_sub_state uncloned &&\n> +\t setup_sub_update checkout &&\n> +\t setup_sub_branch bar &&\n> +\t git submodule update &&\n> +\t verify_sub_state detach $old_commit # D4\n> +\t)\n> +'\n> +\n> +test_expect_success '3.2.1.2 - already @ $old_commit -> keep detached' '\n> +\tsetup_super &&\n> +\t(cd super &&\n> +\t setup_sub_state detach $old_commit &&\n> +\t setup_sub_update checkout &&\n> +\t setup_sub_branch bar &&\n> +\t git submodule update &&\n> +\t verify_sub_state detach $old_commit\n> +\t)\n> +'\n> +\n> +test_expect_success '3.2.1.3 - detach @ $old_commit' '\n> +\tsetup_super &&\n> +\t(cd super &&\n> +\t setup_sub_state detach $foo_commit &&\n> +\t setup_sub_update checkout &&\n> +\t setup_sub_branch bar &&\n> +\t git submodule update &&\n> +\t verify_sub_state detach $old_commit\n> +\t)\n> +'\n> +\n> +test_expect_success '3.2.1.4 - already @ $old_commit -> keep attached' ' # D1\n> +\tsetup_super &&\n> +\t(cd super &&\n> +\t setup_sub_state foo $old_commit &&\n> +\t setup_sub_update checkout &&\n> +\t setup_sub_branch bar &&\n> +\t git submodule update &&\n> +\t verify_sub_state foo $old_commit\n> +\t)\n> +'\n> +\n> +test_expect_success '3.2.1.5 - detach @ $old_commit' '\n> +\tsetup_super &&\n> +\t(cd super &&\n> +\t setup_sub_state foo $foo_commit &&\n> +\t setup_sub_update checkout &&\n> +\t setup_sub_branch bar &&\n> +\t git submodule update &&\n> +\t verify_sub_state detach $old_commit\n> +\t)\n> +'\n> +\n> +test_expect_success '3.2.1.6 - already @ $old_commit -> keep attached' ' # D1\n> +\tsetup_super &&\n> +\t(cd super &&\n> +\t setup_sub_state bar $old_commit &&\n> +\t setup_sub_update checkout &&\n> +\t setup_sub_branch bar &&\n> +\t git submodule update &&\n> +\t verify_sub_state bar $old_commit\n> +\t)\n> +'\n> +\n> +test_expect_success '3.2.1.7 - detach @ $old_commit' '\n> +\tsetup_super &&\n> +\t(cd super &&\n> +\t setup_sub_state bar $foo_commit &&\n> +\t setup_sub_update checkout &&\n> +\t setup_sub_branch bar &&\n> +\t git submodule update &&\n> +\t verify_sub_state detach $old_commit\n> +\t)\n> +'\n> +\n> +test_expect_failure '3.2.2.1 - fail to clone (remote branch bar missing), leave uncloned' ' # T3, D7\n> +\tsetup_super &&\n> +\t(cd super &&\n> +\t setup_sub_state uncloned &&\n> +\t setup_sub_update checkout &&\n> +\t setup_sub_branch bar &&\n> +\t test_must_fail git submodule update --remote &&\n> +\t verify_sub_state uncloned\n> +\t)\n> +'\n> +\n> +test_expect_success '3.2.2.2 - fail (remote branch bar missing)' '\n> +\tsetup_super &&\n> +\t(cd super &&\n> +\t setup_sub_state detach $old_commit &&\n> +\t setup_sub_update checkout &&\n> +\t setup_sub_branch bar &&\n> +\t test_must_fail git submodule update --remote &&\n> +\t verify_sub_state detach $old_commit\n> +\t)\n> +'\n> +\n> +test_expect_success '3.2.2.3 - fail (remote branch bar missing)' '\n> +\tsetup_super &&\n> +\t(cd super &&\n> +\t setup_sub_state detach $foo_commit &&\n> +\t setup_sub_update checkout &&\n> +\t setup_sub_branch bar &&\n> +\t test_must_fail git submodule update --remote &&\n> +\t verify_sub_state detach $foo_commit\n> +\t)\n> +'\n> +\n> +test_expect_success '3.2.2.4 - fail (remote branch bar missing)' '\n> +\tsetup_super &&\n> +\t(cd super &&\n> +\t setup_sub_state foo $old_commit &&\n> +\t setup_sub_update checkout &&\n> +\t setup_sub_branch bar &&\n> +\t test_must_fail git submodule update --remote &&\n> +\t verify_sub_state foo $old_commit\n> +\t)\n> +'\n> +\n> +test_expect_success '3.2.2.5 - fail (remote branch bar missing)' '\n> +\tsetup_super &&\n> +\t(cd super &&\n> +\t setup_sub_state foo $foo_commit &&\n> +\t setup_sub_update checkout &&\n> +\t setup_sub_branch bar &&\n> +\t test_must_fail git submodule update --remote &&\n> +\t verify_sub_state foo $foo_commit\n> +\t)\n> +'\n> +\n> +test_expect_success '3.2.2.6 - fail (remote branch bar missing)' '\n> +\tsetup_super &&\n> +\t(cd super &&\n> +\t setup_sub_state bar $old_commit &&\n> +\t setup_sub_update checkout &&\n> +\t setup_sub_branch bar &&\n> +\t test_must_fail git submodule update --remote &&\n> +\t verify_sub_state bar $old_commit\n> +\t)\n> +'\n> +\n> +test_expect_success '3.2.2.7 - fail (remote branch bar missing)' '\n> +\tsetup_super &&\n> +\t(cd super &&\n> +\t setup_sub_state bar $foo_commit &&\n> +\t setup_sub_update checkout &&\n> +\t setup_sub_branch bar &&\n> +\t test_must_fail git submodule update --remote &&\n> +\t verify_sub_state bar $foo_commit\n> +\t)\n> +'\n> +\n> +# 3.3.* - .branch == bar (MISSING upstream), .update == merge\n> +\n> +test_expect_success '3.3.1.1 - clone, create branch called bar @ $old_commit' '\n> +\tsetup_super &&\n> +\t(cd super &&\n> +\t setup_sub_state uncloned &&\n> +\t setup_sub_update merge &&\n> +\t setup_sub_branch bar &&\n> +\t git submodule update &&\n> +\t verify_sub_state detach $old_commit # D4, FIXME: s/detach/bar/?\n> +\t)\n> +'\n> +\n> +test_expect_success '3.3.1.2 - already at $old_commit, remain detached' ' # D3\n> +\tsetup_super &&\n> +\t(cd super &&\n> +\t setup_sub_state detach $old_commit &&\n> +\t setup_sub_update merge &&\n> +\t setup_sub_branch bar &&\n> +\t git submodule update &&\n> +\t verify_sub_state detach $old_commit\n> +\t)\n> +'\n> +\n> +test_expect_success '3.3.1.3 - merge $old_commit -> $foo_commit, remain detached' ' # D5\n> +\tsetup_super &&\n> +\t(cd super &&\n> +\t setup_sub_state detach $foo_commit &&\n> +\t setup_sub_update merge &&\n> +\t setup_sub_branch bar &&\n> +\t git submodule update &&\n> +\t verify_sub_state detach parents.$foo_commit.$old_commit\n> +\t)\n> +'\n> +\n> +test_expect_success '3.3.1.4 - already at $old_commit, remain attached to foo' ' # D3\n> +\tsetup_super &&\n> +\t(cd super &&\n> +\t setup_sub_state foo $old_commit &&\n> +\t setup_sub_update merge &&\n> +\t setup_sub_branch bar &&\n> +\t git submodule update &&\n> +\t verify_sub_state foo $old_commit\n> +\t)\n> +'\n> +\n> +test_expect_success '3.3.1.5 - merge $old_commit -> $foo_commit, remain attached to foo' ' # D5\n> +\tsetup_super &&\n> +\t(cd super &&\n> +\t setup_sub_state foo $foo_commit &&\n> +\t setup_sub_update merge &&\n> +\t setup_sub_branch bar &&\n> +\t git submodule update &&\n> +\t verify_sub_state foo parents.$foo_commit.$old_commit\n> +\t)\n> +'\n> +\n> +test_expect_success '3.3.1.6 - already at $old_commit, remain attached to bar' ' # D3\n> +\tsetup_super &&\n> +\t(cd super &&\n> +\t setup_sub_state bar $old_commit &&\n> +\t setup_sub_update merge &&\n> +\t setup_sub_branch bar &&\n> +\t git submodule update &&\n> +\t verify_sub_state bar $old_commit\n> +\t)\n> +'\n> +\n> +test_expect_success '3.3.1.7 - merge $old_commit -> $foo_commit, remain attached to bar' ' # D5\n> +\tsetup_super &&\n> +\t(cd super &&\n> +\t setup_sub_state bar $foo_commit &&\n> +\t setup_sub_update merge &&\n> +\t setup_sub_branch bar &&\n> +\t git submodule update &&\n> +\t verify_sub_state bar parents.$foo_commit.$old_commit\n> +\t)\n> +'\n> +\n> +test_expect_failure '3.3.2.1 - fail to clone (remote branch bar missing), leave uncloned' ' # T3, D7\n> +\tsetup_super &&\n> +\t(cd super &&\n> +\t setup_sub_state uncloned &&\n> +\t setup_sub_update merge &&\n> +\t setup_sub_branch bar &&\n> +\t test_must_fail git submodule update --remote &&\n> +\t verify_sub_state uncloned\n> +\t)\n> +'\n> +\n> +test_expect_success '3.3.2.2 - fail (remote branch bar missing)' '\n> +\tsetup_super &&\n> +\t(cd super &&\n> +\t setup_sub_state detach $old_commit &&\n> +\t setup_sub_update merge &&\n> +\t setup_sub_branch bar &&\n> +\t test_must_fail git submodule update --remote &&\n> +\t verify_sub_state detach $old_commit\n> +\t)\n> +'\n> +\n> +test_expect_success '3.3.2.3 - fail (remote branch bar missing)' '\n> +\tsetup_super &&\n> +\t(cd super &&\n> +\t setup_sub_state detach $foo_commit &&\n> +\t setup_sub_update merge &&\n> +\t setup_sub_branch bar &&\n> +\t test_must_fail git submodule update --remote &&\n> +\t verify_sub_state detach $foo_commit\n> +\t)\n> +'\n> +\n> +test_expect_success '3.3.2.4 - fail (remote branch bar missing)' '\n> +\tsetup_super &&\n> +\t(cd super &&\n> +\t setup_sub_state foo $old_commit &&\n> +\t setup_sub_update merge &&\n> +\t setup_sub_branch bar &&\n> +\t test_must_fail git submodule update --remote &&\n> +\t verify_sub_state foo $old_commit\n> +\t)\n> +'\n> +\n> +test_expect_success '3.3.2.5 - fail (remote branch bar missing)' '\n> +\tsetup_super &&\n> +\t(cd super &&\n> +\t setup_sub_state foo $foo_commit &&\n> +\t setup_sub_update merge &&\n> +\t setup_sub_branch bar &&\n> +\t test_must_fail git submodule update --remote &&\n> +\t verify_sub_state foo $foo_commit\n> +\t)\n> +'\n> +\n> +test_expect_success '3.3.2.6 - fail (remote branch bar missing)' '\n> +\tsetup_super &&\n> +\t(cd super &&\n> +\t setup_sub_state bar $old_commit &&\n> +\t setup_sub_update merge &&\n> +\t setup_sub_branch bar &&\n> +\t test_must_fail git submodule update --remote &&\n> +\t verify_sub_state bar $old_commit\n> +\t)\n> +'\n> +\n> +test_expect_success '3.3.2.7 - fail (remote branch bar missing)' '\n> +\tsetup_super &&\n> +\t(cd super &&\n> +\t setup_sub_state bar $foo_commit &&\n> +\t setup_sub_update merge &&\n> +\t setup_sub_branch bar &&\n> +\t test_must_fail git submodule update --remote &&\n> +\t verify_sub_state bar $foo_commit\n> +\t)\n> +'\n> +\n> +# 3.4.* - .branch == bar (MISSING upstream), .update == rebase\n> +\n> +test_expect_success '3.4.1.1 - clone, create branch called bar @ $old_commit' '\n> +\tsetup_super &&\n> +\t(cd super &&\n> +\t setup_sub_state uncloned &&\n> +\t setup_sub_update rebase &&\n> +\t setup_sub_branch bar &&\n> +\t git submodule update &&\n> +\t verify_sub_state detach $old_commit # D4, FIXME: s/detach/bar/?\n> +\t)\n> +'\n> +\n> +test_expect_success '3.4.1.2 - already at $old_commit, remain detached' ' # D3\n> +\tsetup_super &&\n> +\t(cd super &&\n> +\t setup_sub_state detach $old_commit &&\n> +\t setup_sub_update rebase &&\n> +\t setup_sub_branch bar &&\n> +\t git submodule update &&\n> +\t verify_sub_state detach $old_commit\n> +\t)\n> +'\n> +\n> +test_expect_success '3.4.1.3 - rebase $foo_commit onto $old_commit, remain detached' ' # D5\n> +\tsetup_super &&\n> +\t(cd super &&\n> +\t setup_sub_state detach $foo_commit &&\n> +\t setup_sub_update rebase &&\n> +\t setup_sub_branch bar &&\n> +\t git submodule update &&\n> +\t verify_sub_state detach parents.$old_commit &&\n> +\t verify_sub_patch_id HEAD $foo_commit\n> +\t)\n> +'\n> +\n> +test_expect_success '3.4.1.4 - already at $old_commit, remain attached to foo' ' # D3\n> +\tsetup_super &&\n> +\t(cd super &&\n> +\t setup_sub_state foo $old_commit &&\n> +\t setup_sub_update rebase &&\n> +\t setup_sub_branch bar &&\n> +\t git submodule update &&\n> +\t verify_sub_state foo $old_commit\n> +\t)\n> +'\n> +\n> +test_expect_success '3.4.1.5 - rebase $foo_commit onto $old_commit, remain attached to foo' ' # D5\n> +\tsetup_super &&\n> +\t(cd super &&\n> +\t setup_sub_state foo $foo_commit &&\n> +\t setup_sub_update rebase &&\n> +\t setup_sub_branch bar &&\n> +\t git submodule update &&\n> +\t verify_sub_state foo parents.$old_commit &&\n> +\t verify_sub_patch_id HEAD $foo_commit\n> +\t)\n> +'\n> +\n> +test_expect_success '3.4.1.6 - already at $old_commit, remain attached to bar' ' # D3\n> +\tsetup_super &&\n> +\t(cd super &&\n> +\t setup_sub_state bar $old_commit &&\n> +\t setup_sub_update rebase &&\n> +\t setup_sub_branch bar &&\n> +\t git submodule update &&\n> +\t verify_sub_state bar $old_commit\n> +\t)\n> +'\n> +\n> +test_expect_success '3.4.1.7 - rebase $foo_commit onto $old_commit, remain attached to bar' ' # D5\n> +\tsetup_super &&\n> +\t(cd super &&\n> +\t setup_sub_state bar $foo_commit &&\n> +\t setup_sub_update rebase &&\n> +\t setup_sub_branch bar &&\n> +\t git submodule update &&\n> +\t verify_sub_state bar parents.$old_commit &&\n> +\t verify_sub_patch_id HEAD $foo_commit\n> +\t)\n> +'\n> +\n> +test_expect_failure '3.4.2.1 - fail to clone (remote branch bar missing), leave uncloned' ' # T3, D7\n> +\tsetup_super &&\n> +\t(cd super &&\n> +\t setup_sub_state uncloned &&\n> +\t setup_sub_update rebase &&\n> +\t setup_sub_branch bar &&\n> +\t test_must_fail git submodule update --remote &&\n> +\t verify_sub_state uncloned\n> +\t)\n> +'\n> +\n> +test_expect_success '3.4.2.2 - fail (remote branch bar missing)' '\n> +\tsetup_super &&\n> +\t(cd super &&\n> +\t setup_sub_state detach $old_commit &&\n> +\t setup_sub_update rebase &&\n> +\t setup_sub_branch bar &&\n> +\t test_must_fail git submodule update --remote &&\n> +\t verify_sub_state detach $old_commit\n> +\t)\n> +'\n> +\n> +test_expect_success '3.4.2.3 - fail (remote branch bar missing)' '\n> +\tsetup_super &&\n> +\t(cd super &&\n> +\t setup_sub_state detach $foo_commit &&\n> +\t setup_sub_update rebase &&\n> +\t setup_sub_branch bar &&\n> +\t test_must_fail git submodule update --remote &&\n> +\t verify_sub_state detach $foo_commit\n> +\t)\n> +'\n> +\n> +test_expect_success '3.4.2.4 - fail (remote branch bar missing)' '\n> +\tsetup_super &&\n> +\t(cd super &&\n> +\t setup_sub_state foo $old_commit &&\n> +\t setup_sub_update rebase &&\n> +\t setup_sub_branch bar &&\n> +\t test_must_fail git submodule update --remote &&\n> +\t verify_sub_state foo $old_commit\n> +\t)\n> +'\n> +\n> +test_expect_success '3.4.2.5 - fail (remote branch bar missing)' '\n> +\tsetup_super &&\n> +\t(cd super &&\n> +\t setup_sub_state foo $foo_commit &&\n> +\t setup_sub_update rebase &&\n> +\t setup_sub_branch bar &&\n> +\t test_must_fail git submodule update --remote &&\n> +\t verify_sub_state foo $foo_commit\n> +\t)\n> +'\n> +\n> +test_expect_success '3.4.2.6 - fail (remote branch bar missing)' '\n> +\tsetup_super &&\n> +\t(cd super &&\n> +\t setup_sub_state bar $old_commit &&\n> +\t setup_sub_update rebase &&\n> +\t setup_sub_branch bar &&\n> +\t test_must_fail git submodule update --remote &&\n> +\t verify_sub_state bar $old_commit\n> +\t)\n> +'\n> +\n> +test_expect_success '3.4.2.7 - fail (remote branch bar missing)' '\n> +\tsetup_super &&\n> +\t(cd super &&\n> +\t setup_sub_state bar $foo_commit &&\n> +\t setup_sub_update rebase &&\n> +\t setup_sub_branch bar &&\n> +\t test_must_fail git submodule update --remote &&\n> +\t verify_sub_state bar $foo_commit\n> +\t)\n> +'\n> +\n> +# 3.5.* - .branch == bar (MISSING upstream), .update == !command\n> +\n> +test_expect_success '3.5.1.1 - clone, create branch called bat @ $old_commit. !command is NOT invoked' '\n> +\tsetup_super &&\n> +\t(cd super &&\n> +\t setup_sub_state uncloned &&\n> +\t setup_sub_update !false &&\n> +\t setup_sub_branch bar &&\n> +\t git submodule update && # should not invoke \"false\"\n> +\t verify_sub_state detach $old_commit # D4, FIXME: s/detach/bar/?\n> +\t)\n> +'\n> +\n> +test_expect_success '3.5.1.2 - already at $old_commit, remain detached. !command is NOT invoked' '\n> +\tsetup_super &&\n> +\t(cd super &&\n> +\t setup_sub_state detach $old_commit &&\n> +\t setup_sub_update !false &&\n> +\t setup_sub_branch bar &&\n> +\t git submodule update && # should not invoke \"false\"\n> +\t verify_sub_state detach $old_commit\n> +\t)\n> +'\n> +\n> +cat > test_command.sh <<EOF\n> +#!/bin/sh\n> +# Verify: detached @ $foo_commit, and asked to integrate $old_commit\n> +test \"\\$(git symbolic-ref --short -q HEAD)\" = \"\" &&\n> +test \"\\$(git rev-parse -q --verify HEAD)\" = \"$foo_commit\" &&\n> +test \"\\$1\" = \"$old_commit\" &&\n> +git checkout -b success $root_commit\n> +EOF\n> +chmod +x test_command.sh\n> +\n> +test_expect_success '3.5.1.3 - !command invoked to integrate $old_commit -> $foo_commit' '\n> +\tsetup_super &&\n> +\t(cd super &&\n> +\t setup_sub_state detach $foo_commit &&\n> +\t setup_sub_update !../../test_command.sh &&\n> +\t setup_sub_branch bar &&\n> +\t git submodule update &&\n> +\t verify_sub_state success $root_commit # test_command.sh is happy\n> +\t)\n> +'\n> +\n> +test_expect_success '3.5.1.4 - already at $old_commit, remain attached to foo. !command is NOT invoked' '\n> +\tsetup_super &&\n> +\t(cd super &&\n> +\t setup_sub_state foo $old_commit &&\n> +\t setup_sub_update !false &&\n> +\t setup_sub_branch bar &&\n> +\t git submodule update &&\n> +\t verify_sub_state foo $old_commit\n> +\t)\n> +'\n> +\n> +cat > test_command.sh <<EOF\n> +#!/bin/sh\n> +# Verify: attached to foo @ $foo_commit, and asked to integrate $old_commit\n> +test \"\\$(git symbolic-ref --short -q HEAD)\" = \"foo\" &&\n> +test \"\\$(git rev-parse -q --verify HEAD)\" = \"$foo_commit\" &&\n> +test \"\\$1\" = \"$old_commit\" &&\n> +git checkout -b success $root_commit\n> +EOF\n> +chmod +x test_command.sh\n> +\n> +test_expect_success '3.5.1.5 - !command invoked to integrate $old_commit -> foo/$foo_commit' '\n> +\tsetup_super &&\n> +\t(cd super &&\n> +\t setup_sub_state foo $foo_commit &&\n> +\t setup_sub_update !../../test_command.sh &&\n> +\t setup_sub_branch bar &&\n> +\t git submodule update &&\n> +\t verify_sub_state success $root_commit # test_command.sh is happy\n> +\t)\n> +'\n> +\n> +test_expect_success '3.5.1.6 - already at $old_commit, remain attached to bar. !command is NOT invoked' '\n> +\tsetup_super &&\n> +\t(cd super &&\n> +\t setup_sub_state bar $old_commit &&\n> +\t setup_sub_update !false &&\n> +\t setup_sub_branch bar &&\n> +\t git submodule update &&\n> +\t verify_sub_state bar $old_commit\n> +\t)\n> +'\n> +\n> +cat > test_command.sh <<EOF\n> +#!/bin/sh\n> +# Verify: attached to bar @ $foo_commit, and asked to integrate $old_commit\n> +test \"\\$(git symbolic-ref --short -q HEAD)\" = \"bar\" &&\n> +test \"\\$(git rev-parse -q --verify HEAD)\" = \"$foo_commit\" &&\n> +test \"\\$1\" = \"$old_commit\" &&\n> +git checkout -b success $root_commit\n> +EOF\n> +chmod +x test_command.sh\n> +\n> +test_expect_success '3.5.1.7 - !command invoked to integrate $old_commit -> bar/$foo_commit' '\n> +\tsetup_super &&\n> +\t(cd super &&\n> +\t setup_sub_state bar $foo_commit &&\n> +\t setup_sub_update !../../test_command.sh &&\n> +\t setup_sub_branch bar &&\n> +\t git submodule update &&\n> +\t verify_sub_state success $root_commit # test_command.sh is happy\n> +\t)\n> +'\n> +\n> +test_expect_failure '3.5.2.1 - fail to clone (remote branch bar missing), leave uncloned' ' # T3, D7\n> +\tsetup_super &&\n> +\t(cd super &&\n> +\t setup_sub_state uncloned &&\n> +\t setup_sub_update !false &&\n> +\t setup_sub_branch bar &&\n> +\t test_must_fail git submodule update --remote &&\n> +\t verify_sub_state uncloned\n> +\t)\n> +'\n> +\n> +test_expect_success '3.5.2.2 - fail (remote branch bar missing, !command not invoked)' '\n> +\tsetup_super &&\n> +\t(cd super &&\n> +\t setup_sub_state detach $old_commit &&\n> +\t setup_sub_update !false &&\n> +\t setup_sub_branch bar &&\n> +\t test_must_fail git submodule update --remote &&\n> +\t verify_sub_state detach $old_commit\n> +\t)\n> +'\n> +\n> +test_expect_success '3.5.2.3 - fail (remote branch bar missing, !command not invoked)' '\n> +\tsetup_super &&\n> +\t(cd super &&\n> +\t setup_sub_state detach $foo_commit &&\n> +\t setup_sub_update !false &&\n> +\t setup_sub_branch bar &&\n> +\t test_must_fail git submodule update --remote &&\n> +\t verify_sub_state detach $foo_commit\n> +\t)\n> +'\n> +\n> +test_expect_success '3.5.2.4 - fail (remote branch bar missing, !command not invoked)' '\n> +\tsetup_super &&\n> +\t(cd super &&\n> +\t setup_sub_state foo $old_commit &&\n> +\t setup_sub_update !false &&\n> +\t setup_sub_branch bar &&\n> +\t test_must_fail git submodule update --remote &&\n> +\t verify_sub_state foo $old_commit\n> +\t)\n> +'\n> +\n> +test_expect_success '3.5.2.5 - fail (remote branch bar missing, !command not invoked)' '\n> +\tsetup_super &&\n> +\t(cd super &&\n> +\t setup_sub_state foo $foo_commit &&\n> +\t setup_sub_update !false &&\n> +\t setup_sub_branch bar &&\n> +\t test_must_fail git submodule update --remote &&\n> +\t verify_sub_state foo $foo_commit\n> +\t)\n> +'\n> +\n> +test_expect_success '3.5.2.6 - fail (remote branch bar missing, !command not invoked)' '\n> +\tsetup_super &&\n> +\t(cd super &&\n> +\t setup_sub_state bar $old_commit &&\n> +\t setup_sub_update !false &&\n> +\t setup_sub_branch bar &&\n> +\t test_must_fail git submodule update --remote &&\n> +\t verify_sub_state bar $old_commit\n> +\t)\n> +'\n> +\n> +test_expect_success '3.5.2.7 - fail (remote branch bar missing, !command not invoked)' '\n> +\tsetup_super &&\n> +\t(cd super &&\n> +\t setup_sub_state bar $foo_commit &&\n> +\t setup_sub_update !false &&\n> +\t setup_sub_branch bar &&\n> +\t test_must_fail git submodule update --remote &&\n> +\t verify_sub_state bar $foo_commit\n> +\t)\n> +'\n> +\n> +test_done\n> \n"}]}