75388bf5b4
"git branch --recurse-submodules" does not propagate "--track=inherit"
or "--no-track" to submodules, which causes submodule branches to use
the wrong tracking mode [1]. To fix this, pass the correct options to
the "submodule--helper create-branch" child process and test for it.
While we are refactoring the same code, replace "--track" with the
synonymous, but more consistent-looking "--track=direct" option
(introduced at the same time as "--track=inherit", d3115660b4
(branch:
add flags and config to inherit tracking, 2021-12-20)).
[1] This bug is partially a timing issue: "branch --recurse-submodules"
was introduced around the same time as "--track=inherit", and even
though I rebased "branch --recurse-submodules" on top of that, I had
neglected to support the new tracking mode. Omitting "--no-track"
was just a plain old mistake, though.
Signed-off-by: Glen Choo <chooglen@google.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
329 lines
11 KiB
Bash
Executable File
329 lines
11 KiB
Bash
Executable File
#!/bin/sh
|
|
|
|
test_description='git branch submodule tests'
|
|
|
|
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
|
|
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
|
|
|
|
. ./test-lib.sh
|
|
. "$TEST_DIRECTORY"/lib-rebase.sh
|
|
|
|
pwd=$(pwd)
|
|
|
|
# Creates a clean test environment in "pwd" by copying the repo setup
|
|
# from test_dirs.
|
|
reset_test () {
|
|
rm -fr super &&
|
|
rm -fr sub-sub-upstream &&
|
|
rm -fr sub-upstream &&
|
|
cp -r test_dirs/* .
|
|
}
|
|
|
|
# Tests that the expected branch does not exist
|
|
test_no_branch () {
|
|
DIR=$1 &&
|
|
BRANCH_NAME=$2 &&
|
|
test_must_fail git -C "$DIR" rev-parse "$BRANCH_NAME" 2>err &&
|
|
grep "ambiguous argument .$BRANCH_NAME." err
|
|
}
|
|
|
|
test_expect_success 'setup superproject and submodule' '
|
|
mkdir test_dirs &&
|
|
(
|
|
cd test_dirs &&
|
|
git init super &&
|
|
test_commit -C super foo &&
|
|
git init sub-sub-upstream &&
|
|
test_commit -C sub-sub-upstream foo &&
|
|
git init sub-upstream &&
|
|
# Submodule in a submodule
|
|
git -C sub-upstream submodule add "${pwd}/test_dirs/sub-sub-upstream" sub-sub &&
|
|
git -C sub-upstream commit -m "add submodule" &&
|
|
# Regular submodule
|
|
git -C super submodule add "${pwd}/test_dirs/sub-upstream" sub &&
|
|
# Submodule in a subdirectory
|
|
git -C super submodule add "${pwd}/test_dirs/sub-sub-upstream" second/sub &&
|
|
git -C super commit -m "add submodule" &&
|
|
git -C super config submodule.propagateBranches true &&
|
|
git -C super/sub submodule update --init
|
|
) &&
|
|
reset_test
|
|
'
|
|
|
|
# Test the argument parsing
|
|
test_expect_success '--recurse-submodules should create branches' '
|
|
test_when_finished "reset_test" &&
|
|
(
|
|
cd super &&
|
|
git branch --recurse-submodules branch-a &&
|
|
git rev-parse branch-a &&
|
|
git -C sub rev-parse branch-a &&
|
|
git -C sub/sub-sub rev-parse branch-a &&
|
|
git -C second/sub rev-parse branch-a
|
|
)
|
|
'
|
|
|
|
test_expect_success '--recurse-submodules should die if submodule.propagateBranches is false' '
|
|
test_when_finished "reset_test" &&
|
|
(
|
|
cd super &&
|
|
echo "fatal: branch with --recurse-submodules can only be used if submodule.propagateBranches is enabled" >expected &&
|
|
test_must_fail git -c submodule.propagateBranches=false branch --recurse-submodules branch-a 2>actual &&
|
|
test_cmp expected actual
|
|
)
|
|
'
|
|
|
|
test_expect_success '--recurse-submodules should fail when not creating branches' '
|
|
test_when_finished "reset_test" &&
|
|
(
|
|
cd super &&
|
|
git branch --recurse-submodules branch-a &&
|
|
echo "fatal: --recurse-submodules can only be used to create branches" >expected &&
|
|
test_must_fail git branch --recurse-submodules -D branch-a 2>actual &&
|
|
test_cmp expected actual &&
|
|
# Assert that the branches were not deleted
|
|
git rev-parse branch-a &&
|
|
git -C sub rev-parse branch-a
|
|
)
|
|
'
|
|
|
|
test_expect_success 'should respect submodule.recurse when creating branches' '
|
|
test_when_finished "reset_test" &&
|
|
(
|
|
cd super &&
|
|
git -c submodule.recurse=true branch branch-a &&
|
|
git rev-parse branch-a &&
|
|
git -C sub rev-parse branch-a
|
|
)
|
|
'
|
|
|
|
test_expect_success 'should ignore submodule.recurse when not creating branches' '
|
|
test_when_finished "reset_test" &&
|
|
(
|
|
cd super &&
|
|
git branch --recurse-submodules branch-a &&
|
|
git -c submodule.recurse=true branch -D branch-a &&
|
|
test_no_branch . branch-a &&
|
|
git -C sub rev-parse branch-a
|
|
)
|
|
'
|
|
|
|
# Test branch creation behavior
|
|
test_expect_success 'should create branches based off commit id in superproject' '
|
|
test_when_finished "reset_test" &&
|
|
(
|
|
cd super &&
|
|
git branch --recurse-submodules branch-a &&
|
|
git checkout --recurse-submodules branch-a &&
|
|
git -C sub rev-parse HEAD >expected &&
|
|
# Move the tip of sub:branch-a so that it no longer matches the commit in super:branch-a
|
|
git -C sub checkout branch-a &&
|
|
test_commit -C sub bar &&
|
|
# Create a new branch-b branch with start-point=branch-a
|
|
git branch --recurse-submodules branch-b branch-a &&
|
|
git rev-parse branch-b &&
|
|
git -C sub rev-parse branch-b >actual &&
|
|
# Assert that the commit id of sub:second-branch matches super:branch-a and not sub:branch-a
|
|
test_cmp expected actual
|
|
)
|
|
'
|
|
|
|
test_expect_success 'should not create any branches if branch is not valid for all repos' '
|
|
test_when_finished "reset_test" &&
|
|
(
|
|
cd super &&
|
|
git -C sub branch branch-a &&
|
|
test_must_fail git branch --recurse-submodules branch-a 2>actual &&
|
|
test_no_branch . branch-a &&
|
|
grep "submodule .sub.: fatal: A branch named .branch-a. already exists" actual
|
|
)
|
|
'
|
|
|
|
test_expect_success 'should create branches if branch exists and --force is given' '
|
|
test_when_finished "reset_test" &&
|
|
(
|
|
cd super &&
|
|
git -C sub rev-parse HEAD >expected &&
|
|
test_commit -C sub baz &&
|
|
# branch-a in sub now points to a newer commit.
|
|
git -C sub branch branch-a HEAD &&
|
|
git -C sub rev-parse branch-a >actual-old-branch-a &&
|
|
git branch --recurse-submodules --force branch-a &&
|
|
git rev-parse branch-a &&
|
|
git -C sub rev-parse branch-a >actual-new-branch-a &&
|
|
test_cmp expected actual-new-branch-a &&
|
|
# assert that branch --force actually moved the sub
|
|
# branch
|
|
! test_cmp expected actual-old-branch-a
|
|
)
|
|
'
|
|
|
|
test_expect_success 'should create branch when submodule is not in HEAD:.gitmodules' '
|
|
test_when_finished "reset_test" &&
|
|
(
|
|
cd super &&
|
|
git branch branch-a &&
|
|
git checkout -b branch-b &&
|
|
git submodule add ../sub-upstream sub2 &&
|
|
git -C sub2 submodule update --init &&
|
|
# branch-b now has a committed submodule not in branch-a
|
|
git commit -m "add second submodule" &&
|
|
git checkout branch-a &&
|
|
git branch --recurse-submodules branch-c branch-b &&
|
|
git checkout --recurse-submodules branch-c &&
|
|
git -C sub2 rev-parse branch-c &&
|
|
git -C sub2/sub-sub rev-parse branch-c
|
|
)
|
|
'
|
|
|
|
test_expect_success 'should not create branches in inactive submodules' '
|
|
test_when_finished "reset_test" &&
|
|
test_config -C super submodule.sub.active false &&
|
|
(
|
|
cd super &&
|
|
git branch --recurse-submodules branch-a &&
|
|
git rev-parse branch-a &&
|
|
test_no_branch sub branch-a
|
|
)
|
|
'
|
|
|
|
test_expect_success 'should set up tracking of local branches with track=always' '
|
|
test_when_finished "reset_test" &&
|
|
(
|
|
cd super &&
|
|
git -c branch.autoSetupMerge=always branch --recurse-submodules branch-a main &&
|
|
git -C sub rev-parse main &&
|
|
test_cmp_config -C sub . branch.branch-a.remote &&
|
|
test_cmp_config -C sub refs/heads/main branch.branch-a.merge
|
|
)
|
|
'
|
|
|
|
test_expect_success 'should set up tracking of local branches with explicit track' '
|
|
test_when_finished "reset_test" &&
|
|
(
|
|
cd super &&
|
|
git branch --track --recurse-submodules branch-a main &&
|
|
git -C sub rev-parse main &&
|
|
test_cmp_config -C sub . branch.branch-a.remote &&
|
|
test_cmp_config -C sub refs/heads/main branch.branch-a.merge
|
|
)
|
|
'
|
|
|
|
test_expect_success 'should not set up unnecessary tracking of local branches' '
|
|
test_when_finished "reset_test" &&
|
|
(
|
|
cd super &&
|
|
git branch --recurse-submodules branch-a main &&
|
|
git -C sub rev-parse main &&
|
|
test_cmp_config -C sub "" --default "" branch.branch-a.remote &&
|
|
test_cmp_config -C sub "" --default "" branch.branch-a.merge
|
|
)
|
|
'
|
|
|
|
reset_remote_test () {
|
|
rm -fr super-clone &&
|
|
reset_test
|
|
}
|
|
|
|
test_expect_success 'setup tests with remotes' '
|
|
(
|
|
cd test_dirs &&
|
|
(
|
|
cd super &&
|
|
git branch branch-a &&
|
|
git checkout -b branch-b &&
|
|
git submodule add ../sub-upstream sub2 &&
|
|
# branch-b now has a committed submodule not in branch-a
|
|
git commit -m "add second submodule"
|
|
) &&
|
|
git clone --branch main --recurse-submodules super super-clone &&
|
|
git -C super-clone config submodule.propagateBranches true
|
|
) &&
|
|
reset_remote_test
|
|
'
|
|
|
|
test_expect_success 'should get fatal error upon branch creation when submodule is not in .git/modules' '
|
|
test_when_finished "reset_remote_test" &&
|
|
(
|
|
cd super-clone &&
|
|
# This should succeed because super-clone has sub in .git/modules
|
|
git branch --recurse-submodules branch-a origin/branch-a &&
|
|
# This should fail because super-clone does not have sub2 .git/modules
|
|
test_must_fail git branch --recurse-submodules branch-b origin/branch-b 2>actual &&
|
|
grep "fatal: submodule .sub2.: unable to find submodule" actual &&
|
|
test_no_branch . branch-b &&
|
|
test_no_branch sub branch-b &&
|
|
# User can fix themselves by initializing the submodule
|
|
git checkout origin/branch-b &&
|
|
git submodule update --init --recursive &&
|
|
git branch --recurse-submodules branch-b origin/branch-b
|
|
)
|
|
'
|
|
|
|
test_expect_success 'should set up tracking of remote-tracking branches by default' '
|
|
test_when_finished "reset_remote_test" &&
|
|
(
|
|
cd super-clone &&
|
|
git branch --recurse-submodules branch-a origin/branch-a &&
|
|
test_cmp_config origin branch.branch-a.remote &&
|
|
test_cmp_config refs/heads/branch-a branch.branch-a.merge &&
|
|
# "origin/branch-a" does not exist for "sub", but it matches the refspec
|
|
# so tracking should be set up
|
|
test_cmp_config -C sub origin branch.branch-a.remote &&
|
|
test_cmp_config -C sub refs/heads/branch-a branch.branch-a.merge &&
|
|
test_cmp_config -C sub/sub-sub origin branch.branch-a.remote &&
|
|
test_cmp_config -C sub/sub-sub refs/heads/branch-a branch.branch-a.merge
|
|
)
|
|
'
|
|
|
|
test_expect_success 'should not fail when unable to set up tracking in submodule' '
|
|
test_when_finished "reset_remote_test" &&
|
|
(
|
|
cd super-clone &&
|
|
git remote rename origin ex-origin &&
|
|
git branch --recurse-submodules branch-a ex-origin/branch-a &&
|
|
test_cmp_config ex-origin branch.branch-a.remote &&
|
|
test_cmp_config refs/heads/branch-a branch.branch-a.merge &&
|
|
test_cmp_config -C sub "" --default "" branch.branch-a.remote &&
|
|
test_cmp_config -C sub "" --default "" branch.branch-a.merge
|
|
)
|
|
'
|
|
|
|
test_expect_success '--track=inherit should set up tracking correctly' '
|
|
test_when_finished "reset_remote_test" &&
|
|
(
|
|
cd super-clone &&
|
|
git branch --recurse-submodules branch-a origin/branch-a &&
|
|
# Set this manually instead of using branch --set-upstream-to
|
|
# to circumvent the "nonexistent upstream" check.
|
|
git -C sub config branch.branch-a.remote origin &&
|
|
git -C sub config branch.branch-a.merge refs/heads/sub-branch-a &&
|
|
git -C sub/sub-sub config branch.branch-a.remote other &&
|
|
git -C sub/sub-sub config branch.branch-a.merge refs/heads/sub-sub-branch-a &&
|
|
|
|
git branch --recurse-submodules --track=inherit branch-b branch-a &&
|
|
test_cmp_config origin branch.branch-b.remote &&
|
|
test_cmp_config refs/heads/branch-a branch.branch-b.merge &&
|
|
test_cmp_config -C sub origin branch.branch-b.remote &&
|
|
test_cmp_config -C sub refs/heads/sub-branch-a branch.branch-b.merge &&
|
|
test_cmp_config -C sub/sub-sub other branch.branch-b.remote &&
|
|
test_cmp_config -C sub/sub-sub refs/heads/sub-sub-branch-a branch.branch-b.merge
|
|
)
|
|
'
|
|
|
|
test_expect_success '--no-track should not set up tracking' '
|
|
test_when_finished "reset_remote_test" &&
|
|
(
|
|
cd super-clone &&
|
|
git branch --recurse-submodules --no-track branch-a origin/branch-a &&
|
|
test_cmp_config "" --default "" branch.branch-a.remote &&
|
|
test_cmp_config "" --default "" branch.branch-a.merge &&
|
|
test_cmp_config -C sub "" --default "" branch.branch-a.remote &&
|
|
test_cmp_config -C sub "" --default "" branch.branch-a.merge &&
|
|
test_cmp_config -C sub/sub-sub "" --default "" branch.branch-a.remote &&
|
|
test_cmp_config -C sub/sub-sub "" --default "" branch.branch-a.merge
|
|
)
|
|
'
|
|
|
|
test_done
|