(command.CommandList children: [ (command.ShAssignment pairs: [ (assign_pair lhs: (sh_lhs_expr.Name name:test_description) op: assign_op.Equal rhs: {(SQ <'checkout into detached HEAD state'>)} spids: [4] ) ] ) (C {<.>} {<'./test-lib.sh'>}) (command.ShFunction name: check_detached body: (BraceGroup children: [ (command.Simple words: [{<test_must_fail>} {<git>} {<symbolic-ref>} {<-q>} {<HEAD>}] redirects: [(redir op:<Id.Redir_Great '>'> loc:(redir_loc.Fd fd:1) arg:{<'/dev/null'>})] do_fork: T ) ] ) ) (command.ShFunction name: check_not_detached body: (BraceGroup children: [ (command.Simple words: [{<git>} {<symbolic-ref>} {<-q>} {<HEAD>}] redirects: [(redir op:<Id.Redir_Great '>'> loc:(redir_loc.Fd fd:1) arg:{<'/dev/null'>})] do_fork: T ) ] ) ) (command.ShAssignment pairs: [ (assign_pair lhs: (sh_lhs_expr.Name name:PREV_HEAD_DESC) op: assign_op.Equal rhs: {(SQ <'Previous HEAD position was'>)} spids: [60] ) ] ) (command.ShFunction name: check_orphan_warning body: (BraceGroup children: [ (command.AndOr ops: [Id.Op_DAmp] children: [ (C {<test_i18ngrep>} {(DQ <'you are leaving '> ($ Id.VSub_Number '$2') <' behind'>)} {(DQ ($ Id.VSub_Number '$1'))} ) (C {<test_i18ngrep>} {<Id.KW_Bang '!'>} {(DQ ($ Id.VSub_DollarName '$PREV_HEAD_DESC'))} {(DQ ($ Id.VSub_Number '$1'))} ) ] ) ] ) ) (command.ShFunction name: check_no_orphan_warning body: (BraceGroup children: [ (command.AndOr ops: [Id.Op_DAmp] children: [ (C {<test_i18ngrep>} {<Id.KW_Bang '!'>} {(DQ <'you are leaving .* commit.*behind'>)} {(DQ ($ Id.VSub_Number '$1'))} ) (C {<test_i18ngrep>} {(DQ ($ Id.VSub_DollarName '$PREV_HEAD_DESC'))} {(DQ ($ Id.VSub_Number '$1'))} ) ] ) ] ) ) (command.ShFunction name: reset body: (BraceGroup children: [ (command.AndOr ops: [Id.Op_DAmp] children: [(C {<git>} {<checkout>} {<master>}) (C {<check_not_detached>})] ) ] ) ) (C {<test_expect_success>} {(SQ <setup>)} { (SQ <'\n'> <'\ttest_commit one &&\n'> <'\ttest_commit two &&\n'> <'\ttest_commit three && git tag -d three &&\n'> <'\ttest_commit four && git tag -d four &&\n'> <'\tgit branch branch &&\n'> <'\tgit tag tag\n'> ) } ) (C {<test_expect_success>} {(SQ <'checkout branch does not detach'>)} {(SQ <'\n'> <'\treset &&\n'> <'\tgit checkout branch &&\n'> <'\tcheck_not_detached\n'>)} ) (C {<test_expect_success>} {(SQ <'checkout tag detaches'>)} {(SQ <'\n'> <'\treset &&\n'> <'\tgit checkout tag &&\n'> <'\tcheck_detached\n'>)} ) (C {<test_expect_success>} {(SQ <'checkout branch by full name detaches'>)} {(SQ <'\n'> <'\treset &&\n'> <'\tgit checkout refs/heads/branch &&\n'> <'\tcheck_detached\n'>)} ) (C {<test_expect_success>} {(SQ <'checkout non-ref detaches'>)} {(SQ <'\n'> <'\treset &&\n'> <'\tgit checkout branch^ &&\n'> <'\tcheck_detached\n'>)} ) (C {<test_expect_success>} {(SQ <'checkout ref^0 detaches'>)} {(SQ <'\n'> <'\treset &&\n'> <'\tgit checkout branch^0 &&\n'> <'\tcheck_detached\n'>)} ) (C {<test_expect_success>} {(SQ <'checkout --detach detaches'>)} {(SQ <'\n'> <'\treset &&\n'> <'\tgit checkout --detach branch &&\n'> <'\tcheck_detached\n'>)} ) (C {<test_expect_success>} {(SQ <'checkout --detach without branch name'>)} {(SQ <'\n'> <'\treset &&\n'> <'\tgit checkout --detach &&\n'> <'\tcheck_detached\n'>)} ) (C {<test_expect_success>} {(SQ <'checkout --detach errors out for non-commit'>)} { (SQ <'\n'> <'\treset &&\n'> <'\ttest_must_fail git checkout --detach one^{tree} &&\n'> <'\tcheck_not_detached\n'> ) } ) (C {<test_expect_success>} {(SQ <'checkout --detach errors out for extra argument'>)} { (SQ <'\n'> <'\treset &&\n'> <'\tgit checkout master &&\n'> <'\ttest_must_fail git checkout --detach tag one.t &&\n'> <'\tcheck_not_detached\n'> ) } ) (C {<test_expect_success>} {(SQ <'checkout --detached and -b are incompatible'>)} { (SQ <'\n'> <'\treset &&\n'> <'\ttest_must_fail git checkout --detach -b newbranch tag &&\n'> <'\tcheck_not_detached\n'> ) } ) (C {<test_expect_success>} {(SQ <'checkout --detach moves HEAD'>)} { (SQ <'\n'> <'\treset &&\n'> <'\tgit checkout one &&\n'> <'\tgit checkout --detach two &&\n'> <'\tgit diff --exit-code HEAD &&\n'> <'\tgit diff --exit-code two\n'> ) } ) (C {<test_expect_success>} {(SQ <'checkout warns on orphan commits'>)} { (SQ <'\n'> <'\treset &&\n'> <'\tgit checkout --detach two &&\n'> <'\techo content >orphan &&\n'> <'\tgit add orphan &&\n'> <'\tgit commit -a -m orphan1 &&\n'> <'\techo new content >orphan &&\n'> <'\tgit commit -a -m orphan2 &&\n'> <'\torphan2=$(git rev-parse HEAD) &&\n'> <'\tgit checkout master 2>stderr\n'> ) } ) (C {<test_expect_success>} {(SQ <'checkout warns on orphan commits: output'>)} {(SQ <'\n'> <'\tcheck_orphan_warning stderr "2 commits"\n'>)} ) (C {<test_expect_success>} {(SQ <'checkout warns orphaning 1 of 2 commits'>)} {(SQ <'\n'> <'\tgit checkout "$orphan2" &&\n'> <'\tgit checkout HEAD^ 2>stderr\n'>)} ) (C {<test_expect_success>} {(SQ <'checkout warns orphaning 1 of 2 commits: output'>)} {(SQ <'\n'> <'\tcheck_orphan_warning stderr "1 commit"\n'>)} ) (C {<test_expect_success>} {(SQ <'checkout does not warn leaving ref tip'>)} { (SQ <'\n'> <'\treset &&\n'> <'\tgit checkout --detach two &&\n'> <'\tgit checkout master 2>stderr\n'> ) } ) (C {<test_expect_success>} {(SQ <'checkout does not warn leaving ref tip'>)} {(SQ <'\n'> <'\tcheck_no_orphan_warning stderr\n'>)} ) (C {<test_expect_success>} {(SQ <'checkout does not warn leaving reachable commit'>)} { (SQ <'\n'> <'\treset &&\n'> <'\tgit checkout --detach HEAD^ &&\n'> <'\tgit checkout master 2>stderr\n'> ) } ) (C {<test_expect_success>} {(SQ <'checkout does not warn leaving reachable commit'>)} {(SQ <'\n'> <'\tcheck_no_orphan_warning stderr\n'>)} ) (command.Simple words: [{<cat>}] redirects: [ (redir op:<Id.Redir_Great '>'> loc:(redir_loc.Fd fd:1) arg:{<expect>}) (redir op: <Id.Redir_DLess '<<'> loc: (redir_loc.Fd fd:0) arg: (redir_param.HereDoc here_begin: {(SQ <EOF>)} here_end_span_id: 453 stdin_parts: [ <'Your branch is behind \'master\' by 1 commit, and can be fast-forwarded.\n'> <' (use "git pull" to update your local branch)\n'> ] ) ) ] do_fork: T ) (C {<test_expect_success>} {(SQ <'tracking count is accurate after orphan check'>)} { (SQ <'\n'> <'\treset &&\n'> <'\tgit branch child master^ &&\n'> <'\tgit config branch.child.remote . &&\n'> <'\tgit config branch.child.merge refs/heads/master &&\n'> <'\tgit checkout child^ &&\n'> <'\tgit checkout child >stdout &&\n'> <'\ttest_i18ncmp expect stdout\n'> ) } ) (C {<test_expect_success>} {(SQ <'no advice given for explicit detached head state'>)} { (SQ <'\n'> <'\t# baseline\n'> <'\ttest_config advice.detachedHead true &&\n'> <'\tgit checkout child && git checkout HEAD^0 >expect.advice 2>&1 &&\n'> <'\ttest_config advice.detachedHead false &&\n'> <'\tgit checkout child && git checkout HEAD^0 >expect.no-advice 2>&1 &&\n'> <'\ttest_unconfig advice.detachedHead &&\n'> <'\t# without configuration, the advice.* variables default to true\n'> <'\tgit checkout child && git checkout HEAD^0 >actual 2>&1 &&\n'> <'\ttest_cmp expect.advice actual &&\n'> <'\n'> <'\t# with explicit --detach\n'> <'\t# no configuration\n'> <'\ttest_unconfig advice.detachedHead &&\n'> <'\tgit checkout child && git checkout --detach HEAD^0 >actual 2>&1 &&\n'> <'\ttest_cmp expect.no-advice actual &&\n'> <'\n'> <'\t# explicitly decline advice\n'> <'\ttest_config advice.detachedHead false &&\n'> <'\tgit checkout child && git checkout --detach HEAD^0 >actual 2>&1 &&\n'> <'\ttest_cmp expect.no-advice actual\n'> ) } ) (C {<test_done>}) ] )