(command.CommandList
  children: [
    (command.ShAssignment
      pairs: [
        (assign_pair
          lhs: (sh_lhs_expr.Name name:test_description)
          op: assign_op.Equal
          rhs: 
            {
              (SQ <'Basic fetch/push functionality.\n'> <'\n'> 
                <'This test checks the following functionality:\n'> <'\n'> <'* command-line syntax\n'> <'* refspecs\n'> <'* fast-forward detection, and overriding it\n'> 
                <'* configuration\n'> <'* hooks\n'> <'* --porcelain output format\n'> <'* hiderefs\n'> <'* reflogs\n'>
              )
            }
          spids: [4]
        )
      ]
    )
    (C {<.>} {<'./test-lib.sh'>})
    (command.ShAssignment
      pairs: [
        (assign_pair
          lhs: (sh_lhs_expr.Name name:D)
          op: assign_op.Equal
          rhs: {(command_sub left_token:<Id.Left_DollarParen '$('> child:(C {<pwd>}))}
          spids: [26]
        )
      ]
    )
    (command.ShFunction
      name: mk_empty
      body: 
        (BraceGroup
          children: [
            (command.ShAssignment
              pairs: [
                (assign_pair
                  lhs: (sh_lhs_expr.Name name:repo_name)
                  op: assign_op.Equal
                  rhs: {(DQ ($ Id.VSub_Number '$1'))}
                  spids: [40]
                )
              ]
            )
            (command.AndOr
              ops: [Id.Op_DAmp Id.Op_DAmp]
              children: [
                (C {<rm>} {<-fr>} {(DQ ($ Id.VSub_DollarName '$repo_name'))})
                (C {<mkdir>} {(DQ ($ Id.VSub_DollarName '$repo_name'))})
                (command.Subshell
                  child: 
                    (command.AndOr
                      ops: [Id.Op_DAmp Id.Op_DAmp Id.Op_DAmp]
                      children: [
                        (C {<cd>} {(DQ ($ Id.VSub_DollarName '$repo_name'))})
                        (C {<git>} {<init>})
                        (C {<git>} {<config>} {<receive.denyCurrentBranch>} {<warn>})
                        (C {<mv>} {<'.git/hooks'>} {<'.git/hooks-disabled'>})
                      ]
                    )
                )
              ]
            )
          ]
        )
    )
    (command.ShFunction
      name: mk_test
      body: 
        (BraceGroup
          children: [
            (command.ShAssignment
              pairs: [
                (assign_pair
                  lhs: (sh_lhs_expr.Name name:repo_name)
                  op: assign_op.Equal
                  rhs: {(DQ ($ Id.VSub_Number '$1'))}
                  spids: [116]
                )
              ]
            )
            (C {<shift>})
            (command.AndOr
              ops: [Id.Op_DAmp]
              children: [
                (C {<mk_empty>} {(DQ ($ Id.VSub_DollarName '$repo_name'))})
                (command.Subshell
                  child: 
                    (command.AndOr
                      ops: [Id.Op_DAmp Id.Op_DAmp Id.Op_DAmp]
                      children: [
                        (command.ForEach
                          iter_names: [ref]
                          iterable: (for_iter.Words words:[{(DQ ($ Id.VSub_At '$@'))}])
                          body: 
                            (command.DoGroup
                              children: [
                                (command.AndOr
                                  ops: [Id.Op_DPipe]
                                  children: [
                                    (C {<git>} {<push>} {(DQ ($ Id.VSub_DollarName '$repo_name'))} 
                                      {($ Id.VSub_DollarName '$the_first_commit') <Id.Lit_Colon ':'> 
                                        <'refs/'> ($ Id.VSub_DollarName '$ref')
                                      }
                                    )
                                    (command.ControlFlow
                                      token: <Id.ControlFlow_Exit exit>
                                    )
                                  ]
                                )
                              ]
                            )
                        )
                        (C {<cd>} {(DQ ($ Id.VSub_DollarName '$repo_name'))})
                        (command.ForEach
                          iter_names: [ref]
                          iterable: (for_iter.Words words:[{(DQ ($ Id.VSub_At '$@'))}])
                          body: 
                            (command.DoGroup
                              children: [
                                (command.AndOr
                                  ops: [Id.Op_DAmp Id.Op_DAmp Id.Op_DPipe]
                                  children: [
                                    (command.Simple
                                      words: [{<echo>} {(DQ ($ Id.VSub_DollarName '$the_first_commit'))}]
                                      redirects: [
                                        (redir
                                          op: <Id.Redir_Great '>'>
                                          loc: (redir_loc.Fd fd:1)
                                          arg: {<expect>}
                                        )
                                      ]
                                      do_fork: T
                                    )
                                    (command.Simple
                                      words: [
                                        {<git>}
                                        {<show-ref>}
                                        {<-s>}
                                        {<--verify>}
                                        {<'refs/'> ($ Id.VSub_DollarName '$ref')}
                                      ]
                                      redirects: [
                                        (redir
                                          op: <Id.Redir_Great '>'>
                                          loc: (redir_loc.Fd fd:1)
                                          arg: {<actual>}
                                        )
                                      ]
                                      do_fork: T
                                    )
                                    (C {<test_cmp>} {<expect>} {<actual>})
                                    (command.ControlFlow
                                      token: <Id.ControlFlow_Exit exit>
                                    )
                                  ]
                                )
                              ]
                            )
                        )
                        (C {<git>} {<fsck>} {<--full>})
                      ]
                    )
                )
              ]
            )
          ]
        )
    )
    (command.ShFunction
      name: mk_test_with_hooks
      body: 
        (BraceGroup
          children: [
            (command.ShAssignment
              pairs: [
                (assign_pair
                  lhs: (sh_lhs_expr.Name name:repo_name)
                  op: assign_op.Equal
                  rhs: {($ Id.VSub_Number '$1')}
                  spids: [264]
                )
              ]
            )
            (command.AndOr
              ops: [Id.Op_DAmp]
              children: [
                (C {<mk_test>} {(DQ ($ Id.VSub_At '$@'))})
                (command.Subshell
                  child: 
                    (command.AndOr
                      ops: [Id.Op_DAmp Id.Op_DAmp Id.Op_DAmp Id.Op_DAmp Id.Op_DAmp Id.Op_DAmp Id.Op_DAmp]
                      children: [
                        (C {<cd>} {(DQ ($ Id.VSub_DollarName '$repo_name'))})
                        (C {<mkdir>} {<'.git/hooks'>})
                        (C {<cd>} {<'.git/hooks'>})
                        (command.Simple
                          words: [{<cat>}]
                          redirects: [
                            (redir
                              op: <Id.Redir_Great '>'>
                              loc: (redir_loc.Fd fd:1)
                              arg: {<pre-receive>}
                            )
                            (redir
                              op: <Id.Redir_DLessDash '<<-'>
                              loc: (redir_loc.Fd fd:0)
                              arg: 
                                (redir_param.HereDoc
                                  here_begin: {(SQ <EOF>)}
                                  here_end_span_id: 318
                                  stdin_parts: [<'#!/bin/sh\n'> <'cat - >>pre-receive.actual\n'>]
                                )
                            )
                          ]
                          do_fork: T
                        )
                        (command.Simple
                          words: [{<cat>}]
                          redirects: [
                            (redir
                              op: <Id.Redir_Great '>'>
                              loc: (redir_loc.Fd fd:1)
                              arg: {<update>}
                            )
                            (redir
                              op: <Id.Redir_DLessDash '<<-'>
                              loc: (redir_loc.Fd fd:0)
                              arg: 
                                (redir_param.HereDoc
                                  here_begin: {(SQ <EOF>)}
                                  here_end_span_id: 335
                                  stdin_parts: [
                                    <'#!/bin/sh\n'>
                                    <'printf "%s %s %s\\n" "$@" >>update.actual\n'>
                                  ]
                                )
                            )
                          ]
                          do_fork: T
                        )
                        (command.Simple
                          words: [{<cat>}]
                          redirects: [
                            (redir
                              op: <Id.Redir_Great '>'>
                              loc: (redir_loc.Fd fd:1)
                              arg: {<post-receive>}
                            )
                            (redir
                              op: <Id.Redir_DLessDash '<<-'>
                              loc: (redir_loc.Fd fd:0)
                              arg: 
                                (redir_param.HereDoc
                                  here_begin: {(SQ <EOF>)}
                                  here_end_span_id: 352
                                  stdin_parts: [<'#!/bin/sh\n'> <'cat - >>post-receive.actual\n'>]
                                )
                            )
                          ]
                          do_fork: T
                        )
                        (command.Simple
                          words: [{<cat>}]
                          redirects: [
                            (redir
                              op: <Id.Redir_Great '>'>
                              loc: (redir_loc.Fd fd:1)
                              arg: {<post-update>}
                            )
                            (redir
                              op: <Id.Redir_DLessDash '<<-'>
                              loc: (redir_loc.Fd fd:0)
                              arg: 
                                (redir_param.HereDoc
                                  here_begin: {(SQ <EOF>)}
                                  here_end_span_id: 372
                                  stdin_parts: [
                                    <'#!/bin/sh\n'>
                                    <'for ref in "$@"\n'>
                                    <'do\n'>
                                    <'printf "%s\\n" "$ref" >>post-update.actual\n'>
                                    <'done\n'>
                                  ]
                                )
                            )
                          ]
                          do_fork: T
                        )
                        (C {<chmod>} {<Id.Lit_Other '+'> <x>} {<pre-receive>} {<update>} {<post-receive>} 
                          {<post-update>}
                        )
                      ]
                    )
                )
              ]
            )
          ]
        )
    )
    (command.ShFunction
      name: mk_child
      body: 
        (BraceGroup
          children: [
            (command.AndOr
              ops: [Id.Op_DAmp]
              children: [
                (C {<rm>} {<-rf>} {(DQ ($ Id.VSub_Number '$2'))})
                (C {<git>} {<clone>} {(DQ ($ Id.VSub_Number '$1'))} {(DQ ($ Id.VSub_Number '$2'))})
              ]
            )
          ]
        )
    )
    (command.ShFunction
      name: check_push_result
      body: 
        (BraceGroup
          children: [
            (command.ShAssignment
              pairs: [
                (assign_pair
                  lhs: (sh_lhs_expr.Name name:repo_name)
                  op: assign_op.Equal
                  rhs: {(DQ ($ Id.VSub_Number '$1'))}
                  spids: [435]
                )
              ]
            )
            (C {<shift>})
            (command.Subshell
              child: 
                (command.AndOr
                  ops: [Id.Op_DAmp Id.Op_DAmp Id.Op_DAmp Id.Op_DAmp]
                  children: [
                    (C {<cd>} {(DQ ($ Id.VSub_DollarName '$repo_name'))})
                    (command.Simple
                      words: [{<echo>} {(DQ ($ Id.VSub_Number '$1'))}]
                      redirects: [
                        (redir
                          op: <Id.Redir_Great '>'>
                          loc: (redir_loc.Fd fd:1)
                          arg: {<expect>}
                        )
                      ]
                      do_fork: T
                    )
                    (C {<shift>})
                    (command.ForEach
                      iter_names: [ref]
                      iterable: (for_iter.Words words:[{(DQ ($ Id.VSub_At '$@'))}])
                      body: 
                        (command.DoGroup
                          children: [
                            (command.AndOr
                              ops: [Id.Op_DAmp Id.Op_DPipe]
                              children: [
                                (command.Simple
                                  words: [
                                    {<git>}
                                    {<show-ref>}
                                    {<-s>}
                                    {<--verify>}
                                    {<'refs/'> ($ Id.VSub_DollarName '$ref')}
                                  ]
                                  redirects: [
                                    (redir
                                      op: <Id.Redir_Great '>'>
                                      loc: (redir_loc.Fd fd:1)
                                      arg: {<actual>}
                                    )
                                  ]
                                  do_fork: T
                                )
                                (C {<test_cmp>} {<expect>} {<actual>})
                                (command.ControlFlow
                                  token: <Id.ControlFlow_Exit exit>
                                )
                              ]
                            )
                          ]
                        )
                    )
                    (C {<git>} {<fsck>} {<--full>})
                  ]
                )
            )
          ]
        )
    )
    (C {<test_expect_success>} {<setup>} 
      {
        (SQ <'\n'> <'\n'> <'\t>path1 &&\n'> <'\tgit add path1 &&\n'> <'\ttest_tick &&\n'> 
          <'\tgit commit -a -m repo &&\n'> <'\tthe_first_commit=$(git show-ref -s --verify refs/heads/master) &&\n'> <'\n'> <'\t>path2 &&\n'> 
          <'\tgit add path2 &&\n'> <'\ttest_tick &&\n'> <'\tgit commit -a -m second &&\n'> 
          <'\tthe_commit=$(git show-ref -s --verify refs/heads/master)\n'> <'\n'>
        )
      }
    )
    (C {<test_expect_success>} {(SQ <'fetch without wildcard'>)} 
      {
        (SQ <'\n'> <'\tmk_empty testrepo &&\n'> <'\t(\n'> <'\t\tcd testrepo &&\n'> 
          <'\t\tgit fetch .. refs/heads/master:refs/remotes/origin/master &&\n'> <'\n'> <'\t\techo "$the_commit commit\trefs/remotes/origin/master" >expect &&\n'> 
          <'\t\tgit for-each-ref refs/remotes/origin >actual &&\n'> <'\t\ttest_cmp expect actual\n'> <'\t)\n'>
        )
      }
    )
    (C {<test_expect_success>} {(SQ <'fetch with wildcard'>)} 
      {
        (SQ <'\n'> <'\tmk_empty testrepo &&\n'> <'\t(\n'> <'\t\tcd testrepo &&\n'> 
          <'\t\tgit config remote.up.url .. &&\n'> <'\t\tgit config remote.up.fetch "refs/heads/*:refs/remotes/origin/*" &&\n'> <'\t\tgit fetch up &&\n'> 
          <'\n'> <'\t\techo "$the_commit commit\trefs/remotes/origin/master" >expect &&\n'> 
          <'\t\tgit for-each-ref refs/remotes/origin >actual &&\n'> <'\t\ttest_cmp expect actual\n'> <'\t)\n'>
        )
      }
    )
    (C {<test_expect_success>} {(SQ <'fetch with insteadOf'>)} 
      {
        (SQ <'\n'> <'\tmk_empty testrepo &&\n'> <'\t(\n'> <'\t\tTRASH=$(pwd)/ &&\n'> 
          <'\t\tcd testrepo &&\n'> <'\t\tgit config "url.$TRASH.insteadOf" trash/ &&\n'> <'\t\tgit config remote.up.url trash/. &&\n'> 
          <'\t\tgit config remote.up.fetch "refs/heads/*:refs/remotes/origin/*" &&\n'> <'\t\tgit fetch up &&\n'> <'\n'> 
          <'\t\techo "$the_commit commit\trefs/remotes/origin/master" >expect &&\n'> <'\t\tgit for-each-ref refs/remotes/origin >actual &&\n'> <'\t\ttest_cmp expect actual\n'> <'\t)\n'>
        )
      }
    )
    (C {<test_expect_success>} {(SQ <'fetch with pushInsteadOf (should not rewrite)'>)} 
      {
        (SQ <'\n'> <'\tmk_empty testrepo &&\n'> <'\t(\n'> <'\t\tTRASH=$(pwd)/ &&\n'> 
          <'\t\tcd testrepo &&\n'> <'\t\tgit config "url.trash/.pushInsteadOf" "$TRASH" &&\n'> 
          <'\t\tgit config remote.up.url "$TRASH." &&\n'> <'\t\tgit config remote.up.fetch "refs/heads/*:refs/remotes/origin/*" &&\n'> <'\t\tgit fetch up &&\n'> 
          <'\n'> <'\t\techo "$the_commit commit\trefs/remotes/origin/master" >expect &&\n'> 
          <'\t\tgit for-each-ref refs/remotes/origin >actual &&\n'> <'\t\ttest_cmp expect actual\n'> <'\t)\n'>
        )
      }
    )
    (C {<test_expect_success>} {(SQ <'push without wildcard'>)} 
      {
        (SQ <'\n'> <'\tmk_empty testrepo &&\n'> <'\n'> 
          <'\tgit push testrepo refs/heads/master:refs/remotes/origin/master &&\n'> <'\t(\n'> <'\t\tcd testrepo &&\n'> 
          <'\t\techo "$the_commit commit\trefs/remotes/origin/master" >expect &&\n'> <'\t\tgit for-each-ref refs/remotes/origin >actual &&\n'> <'\t\ttest_cmp expect actual\n'> <'\t)\n'>
        )
      }
    )
    (C {<test_expect_success>} {(SQ <'push with wildcard'>)} 
      {
        (SQ <'\n'> <'\tmk_empty testrepo &&\n'> <'\n'> 
          <'\tgit push testrepo "refs/heads/*:refs/remotes/origin/*" &&\n'> <'\t(\n'> <'\t\tcd testrepo &&\n'> 
          <'\t\techo "$the_commit commit\trefs/remotes/origin/master" >expect &&\n'> <'\t\tgit for-each-ref refs/remotes/origin >actual &&\n'> <'\t\ttest_cmp expect actual\n'> <'\t)\n'>
        )
      }
    )
    (C {<test_expect_success>} {(SQ <'push with insteadOf'>)} 
      {
        (SQ <'\n'> <'\tmk_empty testrepo &&\n'> <'\tTRASH="$(pwd)/" &&\n'> 
          <'\ttest_config "url.$TRASH.insteadOf" trash/ &&\n'> <'\tgit push trash/testrepo refs/heads/master:refs/remotes/origin/master &&\n'> <'\t(\n'> 
          <'\t\tcd testrepo &&\n'> <'\t\techo "$the_commit commit\trefs/remotes/origin/master" >expect &&\n'> 
          <'\t\tgit for-each-ref refs/remotes/origin >actual &&\n'> <'\t\ttest_cmp expect actual\n'> <'\t)\n'>
        )
      }
    )
    (C {<test_expect_success>} {(SQ <'push with pushInsteadOf'>)} 
      {
        (SQ <'\n'> <'\tmk_empty testrepo &&\n'> <'\tTRASH="$(pwd)/" &&\n'> 
          <'\ttest_config "url.$TRASH.pushInsteadOf" trash/ &&\n'> <'\tgit push trash/testrepo refs/heads/master:refs/remotes/origin/master &&\n'> <'\t(\n'> 
          <'\t\tcd testrepo &&\n'> <'\t\techo "$the_commit commit\trefs/remotes/origin/master" >expect &&\n'> 
          <'\t\tgit for-each-ref refs/remotes/origin >actual &&\n'> <'\t\ttest_cmp expect actual\n'> <'\t)\n'>
        )
      }
    )
    (C {<test_expect_success>} 
      {(SQ <'push with pushInsteadOf and explicit pushurl (pushInsteadOf should not rewrite)'>)} 
      {
        (SQ <'\n'> <'\tmk_empty testrepo &&\n'> 
          <'\ttest_config "url.trash2/.pushInsteadOf" testrepo/ &&\n'> <'\ttest_config "url.trash3/.pushInsteadOf" trash/wrong &&\n'> 
          <'\ttest_config remote.r.url trash/wrong &&\n'> <'\ttest_config remote.r.pushurl "testrepo/" &&\n'> 
          <'\tgit push r refs/heads/master:refs/remotes/origin/master &&\n'> <'\t(\n'> <'\t\tcd testrepo &&\n'> 
          <'\t\techo "$the_commit commit\trefs/remotes/origin/master" >expect &&\n'> <'\t\tgit for-each-ref refs/remotes/origin >actual &&\n'> <'\t\ttest_cmp expect actual\n'> <'\t)\n'>
        )
      }
    )
    (C {<test_expect_success>} {(SQ <'push with matching heads'>)} 
      {
        (SQ <'\n'> <'\n'> <'\tmk_test testrepo heads/master &&\n'> <'\tgit push testrepo : &&\n'> 
          <'\tcheck_push_result testrepo $the_commit heads/master\n'> <'\n'>
        )
      }
    )
    (C {<test_expect_success>} {(SQ <'push with matching heads on the command line'>)} 
      {
        (SQ <'\n'> <'\n'> <'\tmk_test testrepo heads/master &&\n'> <'\tgit push testrepo : &&\n'> 
          <'\tcheck_push_result testrepo $the_commit heads/master\n'> <'\n'>
        )
      }
    )
    (C {<test_expect_success>} {(SQ <'failed (non-fast-forward) push with matching heads'>)} 
      {
        (SQ <'\n'> <'\n'> <'\tmk_test testrepo heads/master &&\n'> <'\tgit push testrepo : &&\n'> 
          <'\tgit commit --amend -massaged &&\n'> <'\ttest_must_fail git push testrepo &&\n'> 
          <'\tcheck_push_result testrepo $the_commit heads/master &&\n'> <'\tgit reset --hard $the_commit\n'> <'\n'>
        )
      }
    )
    (C {<test_expect_success>} {(SQ <'push --force with matching heads'>)} 
      {
        (SQ <'\n'> <'\n'> <'\tmk_test testrepo heads/master &&\n'> <'\tgit push testrepo : &&\n'> 
          <'\tgit commit --amend -massaged &&\n'> <'\tgit push --force testrepo : &&\n'> 
          <'\t! check_push_result testrepo $the_commit heads/master &&\n'> <'\tgit reset --hard $the_commit\n'> <'\n'>
        )
      }
    )
    (C {<test_expect_success>} {(SQ <'push with matching heads and forced update'>)} 
      {
        (SQ <'\n'> <'\n'> <'\tmk_test testrepo heads/master &&\n'> <'\tgit push testrepo : &&\n'> 
          <'\tgit commit --amend -massaged &&\n'> <'\tgit push testrepo +: &&\n'> <'\t! check_push_result testrepo $the_commit heads/master &&\n'> 
          <'\tgit reset --hard $the_commit\n'> <'\n'>
        )
      }
    )
    (C {<test_expect_success>} {(SQ <'push with no ambiguity (1)'>)} 
      {
        (SQ <'\n'> <'\n'> <'\tmk_test testrepo heads/master &&\n'> 
          <'\tgit push testrepo master:master &&\n'> <'\tcheck_push_result testrepo $the_commit heads/master\n'> <'\n'>
        )
      }
    )
    (C {<test_expect_success>} {(SQ <'push with no ambiguity (2)'>)} 
      {
        (SQ <'\n'> <'\n'> <'\tmk_test testrepo remotes/origin/master &&\n'> 
          <'\tgit push testrepo master:origin/master &&\n'> <'\tcheck_push_result testrepo $the_commit remotes/origin/master\n'> <'\n'>
        )
      }
    )
    (C {<test_expect_success>} {(SQ <'push with colon-less refspec, no ambiguity'>)} 
      {
        (SQ <'\n'> <'\n'> <'\tmk_test testrepo heads/master heads/t/master &&\n'> 
          <'\tgit branch -f t/master master &&\n'> <'\tgit push testrepo master &&\n'> <'\tcheck_push_result testrepo $the_commit heads/master &&\n'> 
          <'\tcheck_push_result testrepo $the_first_commit heads/t/master\n'> <'\n'>
        )
      }
    )
    (C {<test_expect_success>} {(SQ <'push with weak ambiguity (1)'>)} 
      {
        (SQ <'\n'> <'\n'> <'\tmk_test testrepo heads/master remotes/origin/master &&\n'> 
          <'\tgit push testrepo master:master &&\n'> <'\tcheck_push_result testrepo $the_commit heads/master &&\n'> 
          <'\tcheck_push_result testrepo $the_first_commit remotes/origin/master\n'> <'\n'>
        )
      }
    )
    (C {<test_expect_success>} {(SQ <'push with weak ambiguity (2)'>)} 
      {
        (SQ <'\n'> <'\n'> 
          <'\tmk_test testrepo heads/master remotes/origin/master remotes/another/master &&\n'> <'\tgit push testrepo master:master &&\n'> 
          <'\tcheck_push_result testrepo $the_commit heads/master &&\n'> <'\tcheck_push_result testrepo $the_first_commit remotes/origin/master remotes/another/master\n'> 
          <'\n'>
        )
      }
    )
    (C {<test_expect_success>} {(SQ <'push with ambiguity'>)} 
      {
        (SQ <'\n'> <'\n'> <'\tmk_test testrepo heads/frotz tags/frotz &&\n'> 
          <'\ttest_must_fail git push testrepo master:frotz &&\n'> <'\tcheck_push_result testrepo $the_first_commit heads/frotz tags/frotz\n'> <'\n'>
        )
      }
    )
    (C {<test_expect_success>} {(SQ <'push with colon-less refspec (1)'>)} 
      {
        (SQ <'\n'> <'\n'> <'\tmk_test testrepo heads/frotz tags/frotz &&\n'> 
          <'\tgit branch -f frotz master &&\n'> <'\tgit push testrepo frotz &&\n'> <'\tcheck_push_result testrepo $the_commit heads/frotz &&\n'> 
          <'\tcheck_push_result testrepo $the_first_commit tags/frotz\n'> <'\n'>
        )
      }
    )
    (C {<test_expect_success>} {(SQ <'push with colon-less refspec (2)'>)} 
      {
        (SQ <'\n'> <'\n'> <'\tmk_test testrepo heads/frotz tags/frotz &&\n'> 
          <'\tif git show-ref --verify -q refs/heads/frotz\n'> <'\tthen\n'> <'\t\tgit branch -D frotz\n'> <'\tfi &&\n'> <'\tgit tag -f frotz &&\n'> 
          <'\tgit push -f testrepo frotz &&\n'> <'\tcheck_push_result testrepo $the_commit tags/frotz &&\n'> 
          <'\tcheck_push_result testrepo $the_first_commit heads/frotz\n'> <'\n'>
        )
      }
    )
    (C {<test_expect_success>} {(SQ <'push with colon-less refspec (3)'>)} 
      {
        (SQ <'\n'> <'\n'> <'\tmk_test testrepo &&\n'> 
          <'\tif git show-ref --verify -q refs/tags/frotz\n'> <'\tthen\n'> <'\t\tgit tag -d frotz\n'> <'\tfi &&\n'> <'\tgit branch -f frotz master &&\n'> 
          <'\tgit push testrepo frotz &&\n'> <'\tcheck_push_result testrepo $the_commit heads/frotz &&\n'> 
          <'\ttest 1 = $( cd testrepo && git show-ref | wc -l )\n'>
        )
      }
    )
    (C {<test_expect_success>} {(SQ <'push with colon-less refspec (4)'>)} 
      {
        (SQ <'\n'> <'\n'> <'\tmk_test testrepo &&\n'> 
          <'\tif git show-ref --verify -q refs/heads/frotz\n'> <'\tthen\n'> <'\t\tgit branch -D frotz\n'> <'\tfi &&\n'> <'\tgit tag -f frotz &&\n'> 
          <'\tgit push testrepo frotz &&\n'> <'\tcheck_push_result testrepo $the_commit tags/frotz &&\n'> 
          <'\ttest 1 = $( cd testrepo && git show-ref | wc -l )\n'> <'\n'>
        )
      }
    )
    (C {<test_expect_success>} {(SQ <'push head with non-existent, incomplete dest'>)} 
      {
        (SQ <'\n'> <'\n'> <'\tmk_test testrepo &&\n'> <'\tgit push testrepo master:branch &&\n'> 
          <'\tcheck_push_result testrepo $the_commit heads/branch\n'> <'\n'>
        )
      }
    )
    (C {<test_expect_success>} {(SQ <'push tag with non-existent, incomplete dest'>)} 
      {
        (SQ <'\n'> <'\n'> <'\tmk_test testrepo &&\n'> <'\tgit tag -f v1.0 &&\n'> 
          <'\tgit push testrepo v1.0:tag &&\n'> <'\tcheck_push_result testrepo $the_commit tags/tag\n'> <'\n'>
        )
      }
    )
    (C {<test_expect_success>} {(SQ <'push sha1 with non-existent, incomplete dest'>)} 
      {
        (SQ <'\n'> <'\n'> <'\tmk_test testrepo &&\n'> 
          <'\ttest_must_fail git push testrepo $(git rev-parse master):foo\n'> <'\n'>
        )
      }
    )
    (C {<test_expect_success>} {(SQ <'push ref expression with non-existent, incomplete dest'>)} 
      {
        (SQ <'\n'> <'\n'> <'\tmk_test testrepo &&\n'> 
          <'\ttest_must_fail git push testrepo master^:branch\n'> <'\n'>
        )
      }
    )
    (C {<test_expect_success>} {(SQ <'push with HEAD'>)} 
      {
        (SQ <'\n'> <'\n'> <'\tmk_test testrepo heads/master &&\n'> <'\tgit checkout master &&\n'> 
          <'\tgit push testrepo HEAD &&\n'> <'\tcheck_push_result testrepo $the_commit heads/master\n'> <'\n'>
        )
      }
    )
    (C {<test_expect_success>} {(SQ <'push with HEAD nonexisting at remote'>)} 
      {
        (SQ <'\n'> <'\n'> <'\tmk_test testrepo heads/master &&\n'> 
          <'\tgit checkout -b local master &&\n'> <'\tgit push testrepo HEAD &&\n'> <'\tcheck_push_result testrepo $the_commit heads/local\n'>
        )
      }
    )
    (C {<test_expect_success>} {(SQ <'push with +HEAD'>)} 
      {
        (SQ <'\n'> <'\n'> <'\tmk_test testrepo heads/master &&\n'> <'\tgit checkout master &&\n'> 
          <'\tgit branch -D local &&\n'> <'\tgit checkout -b local &&\n'> <'\tgit push testrepo master local &&\n'> 
          <'\tcheck_push_result testrepo $the_commit heads/master &&\n'> <'\tcheck_push_result testrepo $the_commit heads/local &&\n'> <'\n'> 
          <'\t# Without force rewinding should fail\n'> <'\tgit reset --hard HEAD^ &&\n'> <'\ttest_must_fail git push testrepo HEAD &&\n'> 
          <'\tcheck_push_result testrepo $the_commit heads/local &&\n'> <'\n'> <'\t# With force rewinding should succeed\n'> <'\tgit push testrepo +HEAD &&\n'> 
          <'\tcheck_push_result testrepo $the_first_commit heads/local\n'> <'\n'>
        )
      }
    )
    (C {<test_expect_success>} {(SQ <'push HEAD with non-existent, incomplete dest'>)} 
      {
        (SQ <'\n'> <'\n'> <'\tmk_test testrepo &&\n'> <'\tgit checkout master &&\n'> 
          <'\tgit push testrepo HEAD:branch &&\n'> <'\tcheck_push_result testrepo $the_commit heads/branch\n'> <'\n'>
        )
      }
    )
    (C {<test_expect_success>} {(SQ <'push with config remote.*.push = HEAD'>)} 
      {
        (SQ <'\n'> <'\n'> <'\tmk_test testrepo heads/local &&\n'> <'\tgit checkout master &&\n'> 
          <'\tgit branch -f local $the_commit &&\n'> <'\t(\n'> <'\t\tcd testrepo &&\n'> <'\t\tgit checkout local &&\n'> 
          <'\t\tgit reset --hard $the_first_commit\n'> <'\t) &&\n'> <'\ttest_config remote.there.url testrepo &&\n'> 
          <'\ttest_config remote.there.push HEAD &&\n'> <'\ttest_config branch.master.remote there &&\n'> <'\tgit push &&\n'> 
          <'\tcheck_push_result testrepo $the_commit heads/master &&\n'> <'\tcheck_push_result testrepo $the_first_commit heads/local\n'>
        )
      }
    )
    (C {<test_expect_success>} {(SQ <'push with remote.pushdefault'>)} 
      {
        (SQ <'\n'> <'\tmk_test up_repo heads/master &&\n'> <'\tmk_test down_repo heads/master &&\n'> 
          <'\ttest_config remote.up.url up_repo &&\n'> <'\ttest_config remote.down.url down_repo &&\n'> <'\ttest_config branch.master.remote up &&\n'> 
          <'\ttest_config remote.pushdefault down &&\n'> <'\ttest_config push.default matching &&\n'> <'\tgit push &&\n'> 
          <'\tcheck_push_result up_repo $the_first_commit heads/master &&\n'> <'\tcheck_push_result down_repo $the_commit heads/master\n'>
        )
      }
    )
    (C {<test_expect_success>} {(SQ <'push with config remote.*.pushurl'>)} 
      {
        (SQ <'\n'> <'\n'> <'\tmk_test testrepo heads/master &&\n'> <'\tgit checkout master &&\n'> 
          <'\ttest_config remote.there.url test2repo &&\n'> <'\ttest_config remote.there.pushurl testrepo &&\n'> <'\tgit push there : &&\n'> 
          <'\tcheck_push_result testrepo $the_commit heads/master\n'>
        )
      }
    )
    (C {<test_expect_success>} {(SQ <'push with config branch.*.pushremote'>)} 
      {
        (SQ <'\n'> <'\tmk_test up_repo heads/master &&\n'> <'\tmk_test side_repo heads/master &&\n'> 
          <'\tmk_test down_repo heads/master &&\n'> <'\ttest_config remote.up.url up_repo &&\n'> <'\ttest_config remote.pushdefault side_repo &&\n'> 
          <'\ttest_config remote.down.url down_repo &&\n'> <'\ttest_config branch.master.remote up &&\n'> <'\ttest_config branch.master.pushremote down &&\n'> 
          <'\ttest_config push.default matching &&\n'> <'\tgit push &&\n'> <'\tcheck_push_result up_repo $the_first_commit heads/master &&\n'> 
          <'\tcheck_push_result side_repo $the_first_commit heads/master &&\n'> <'\tcheck_push_result down_repo $the_commit heads/master\n'>
        )
      }
    )
    (C {<test_expect_success>} {(SQ <'branch.*.pushremote config order is irrelevant'>)} 
      {
        (SQ <'\n'> <'\tmk_test one_repo heads/master &&\n'> <'\tmk_test two_repo heads/master &&\n'> 
          <'\ttest_config remote.one.url one_repo &&\n'> <'\ttest_config remote.two.url two_repo &&\n'> 
          <'\ttest_config branch.master.pushremote two_repo &&\n'> <'\ttest_config remote.pushdefault one_repo &&\n'> <'\ttest_config push.default matching &&\n'> 
          <'\tgit push &&\n'> <'\tcheck_push_result one_repo $the_first_commit heads/master &&\n'> 
          <'\tcheck_push_result two_repo $the_commit heads/master\n'>
        )
      }
    )
    (C {<test_expect_success>} {(SQ <'push with dry-run'>)} 
      {
        (SQ <'\n'> <'\n'> <'\tmk_test testrepo heads/master &&\n'> <'\t(\n'> <'\t\tcd testrepo &&\n'> 
          <'\t\told_commit=$(git show-ref -s --verify refs/heads/master)\n'> <'\t) &&\n'> <'\tgit push --dry-run testrepo : &&\n'> 
          <'\tcheck_push_result testrepo $old_commit heads/master\n'>
        )
      }
    )
    (C {<test_expect_success>} {(SQ <'push updates local refs'>)} 
      {
        (SQ <'\n'> <'\n'> <'\tmk_test testrepo heads/master &&\n'> <'\tmk_child testrepo child &&\n'> 
          <'\t(\n'> <'\t\tcd child &&\n'> <'\t\tgit pull .. master &&\n'> <'\t\tgit push &&\n'> 
          <'\t\ttest $(git rev-parse master) = \\\n'> <'\t\t\t$(git rev-parse remotes/origin/master)\n'> <'\t)\n'> <'\n'>
        )
      }
    )
    (C {<test_expect_success>} {(SQ <'push updates up-to-date local refs'>)} 
      {
        (SQ <'\n'> <'\n'> <'\tmk_test testrepo heads/master &&\n'> <'\tmk_child testrepo child1 &&\n'> 
          <'\tmk_child testrepo child2 &&\n'> <'\t(cd child1 && git pull .. master && git push) &&\n'> <'\t(\n'> <'\t\tcd child2 &&\n'> 
          <'\t\tgit pull ../child1 master &&\n'> <'\t\tgit push &&\n'> <'\t\ttest $(git rev-parse master) = \\\n'> 
          <'\t\t\t$(git rev-parse remotes/origin/master)\n'> <'\t)\n'> <'\n'>
        )
      }
    )
    (C {<test_expect_success>} {(SQ <'push preserves up-to-date packed refs'>)} 
      {
        (SQ <'\n'> <'\n'> <'\tmk_test testrepo heads/master &&\n'> <'\tmk_child testrepo child &&\n'> 
          <'\t(\n'> <'\t\tcd child &&\n'> <'\t\tgit push &&\n'> <'\t\t! test -f .git/refs/remotes/origin/master\n'> 
          <'\t)\n'> <'\n'>
        )
      }
    )
    (C {<test_expect_success>} {(SQ <'push does not update local refs on failure'>)} 
      {
        (SQ <'\n'> <'\n'> <'\tmk_test testrepo heads/master &&\n'> <'\tmk_child testrepo child &&\n'> 
          <'\tmkdir testrepo/.git/hooks &&\n'> <'\techo "#!/no/frobnication/today" >testrepo/.git/hooks/pre-receive &&\n'> 
          <'\tchmod +x testrepo/.git/hooks/pre-receive &&\n'> <'\t(\n'> <'\t\tcd child &&\n'> <'\t\tgit pull .. master\n'> <'\t\ttest_must_fail git push &&\n'> 
          <'\t\ttest $(git rev-parse master) != \\\n'> <'\t\t\t$(git rev-parse remotes/origin/master)\n'> <'\t)\n'> <'\n'>
        )
      }
    )
    (C {<test_expect_success>} {(SQ <'allow deleting an invalid remote ref'>)} 
      {
        (SQ <'\n'> <'\n'> <'\tmk_test testrepo heads/master &&\n'> 
          <'\trm -f testrepo/.git/objects/??/* &&\n'> <'\tgit push testrepo :refs/heads/master &&\n'> 
          <'\t(cd testrepo && test_must_fail git rev-parse --verify refs/heads/master)\n'> <'\n'>
        )
      }
    )
    (C {<test_expect_success>} {(SQ <'pushing valid refs triggers post-receive and post-update hooks'>)} 
      {
        (SQ <'\n'> <'\tmk_test_with_hooks testrepo heads/master heads/next &&\n'> 
          <'\torgmaster=$(cd testrepo && git show-ref -s --verify refs/heads/master) &&\n'> <'\tnewmaster=$(git show-ref -s --verify refs/heads/master) &&\n'> 
          <'\torgnext=$(cd testrepo && git show-ref -s --verify refs/heads/next) &&\n'> <'\tnewnext=$_z40 &&\n'> 
          <'\tgit push testrepo refs/heads/master:refs/heads/master :refs/heads/next &&\n'> <'\t(\n'> <'\t\tcd testrepo/.git &&\n'> <'\t\tcat >pre-receive.expect <<-EOF &&\n'> 
          <'\t\t$orgmaster $newmaster refs/heads/master\n'> <'\t\t$orgnext $newnext refs/heads/next\n'> <'\t\tEOF\n'> <'\n'> <'\t\tcat >update.expect <<-EOF &&\n'> 
          <'\t\trefs/heads/master $orgmaster $newmaster\n'> <'\t\trefs/heads/next $orgnext $newnext\n'> <'\t\tEOF\n'> <'\n'> 
          <'\t\tcat >post-receive.expect <<-EOF &&\n'> <'\t\t$orgmaster $newmaster refs/heads/master\n'> <'\t\t$orgnext $newnext refs/heads/next\n'> 
          <'\t\tEOF\n'> <'\n'> <'\t\tcat >post-update.expect <<-EOF &&\n'> <'\t\trefs/heads/master\n'> <'\t\trefs/heads/next\n'> 
          <'\t\tEOF\n'> <'\n'> <'\t\ttest_cmp pre-receive.expect pre-receive.actual &&\n'> 
          <'\t\ttest_cmp update.expect update.actual &&\n'> <'\t\ttest_cmp post-receive.expect post-receive.actual &&\n'> 
          <'\t\ttest_cmp post-update.expect post-update.actual\n'> <'\t)\n'>
        )
      }
    )
    (C {<test_expect_success>} {(SQ <'deleting dangling ref triggers hooks with correct args'>)} 
      {
        (SQ <'\n'> <'\tmk_test_with_hooks testrepo heads/master &&\n'> 
          <'\trm -f testrepo/.git/objects/??/* &&\n'> <'\tgit push testrepo :refs/heads/master &&\n'> <'\t(\n'> <'\t\tcd testrepo/.git &&\n'> 
          <'\t\tcat >pre-receive.expect <<-EOF &&\n'> <'\t\t$_z40 $_z40 refs/heads/master\n'> <'\t\tEOF\n'> <'\n'> <'\t\tcat >update.expect <<-EOF &&\n'> 
          <'\t\trefs/heads/master $_z40 $_z40\n'> <'\t\tEOF\n'> <'\n'> <'\t\tcat >post-receive.expect <<-EOF &&\n'> 
          <'\t\t$_z40 $_z40 refs/heads/master\n'> <'\t\tEOF\n'> <'\n'> <'\t\tcat >post-update.expect <<-EOF &&\n'> <'\t\trefs/heads/master\n'> 
          <'\t\tEOF\n'> <'\n'> <'\t\ttest_cmp pre-receive.expect pre-receive.actual &&\n'> 
          <'\t\ttest_cmp update.expect update.actual &&\n'> <'\t\ttest_cmp post-receive.expect post-receive.actual &&\n'> 
          <'\t\ttest_cmp post-update.expect post-update.actual\n'> <'\t)\n'>
        )
      }
    )
    (C {<test_expect_success>} 
      {(SQ <'deletion of a non-existent ref is not fed to post-receive and post-update hooks'>)} 
      {
        (SQ <'\n'> <'\tmk_test_with_hooks testrepo heads/master &&\n'> 
          <'\torgmaster=$(cd testrepo && git show-ref -s --verify refs/heads/master) &&\n'> <'\tnewmaster=$(git show-ref -s --verify refs/heads/master) &&\n'> 
          <'\tgit push testrepo master :refs/heads/nonexistent &&\n'> <'\t(\n'> <'\t\tcd testrepo/.git &&\n'> <'\t\tcat >pre-receive.expect <<-EOF &&\n'> 
          <'\t\t$orgmaster $newmaster refs/heads/master\n'> <'\t\t$_z40 $_z40 refs/heads/nonexistent\n'> <'\t\tEOF\n'> <'\n'> <'\t\tcat >update.expect <<-EOF &&\n'> 
          <'\t\trefs/heads/master $orgmaster $newmaster\n'> <'\t\trefs/heads/nonexistent $_z40 $_z40\n'> <'\t\tEOF\n'> <'\n'> 
          <'\t\tcat >post-receive.expect <<-EOF &&\n'> <'\t\t$orgmaster $newmaster refs/heads/master\n'> <'\t\tEOF\n'> <'\n'> 
          <'\t\tcat >post-update.expect <<-EOF &&\n'> <'\t\trefs/heads/master\n'> <'\t\tEOF\n'> <'\n'> 
          <'\t\ttest_cmp pre-receive.expect pre-receive.actual &&\n'> <'\t\ttest_cmp update.expect update.actual &&\n'> 
          <'\t\ttest_cmp post-receive.expect post-receive.actual &&\n'> <'\t\ttest_cmp post-update.expect post-update.actual\n'> <'\t)\n'>
        )
      }
    )
    (C {<test_expect_success>} 
      {(SQ <'deletion of a non-existent ref alone does trigger post-receive and post-update hooks'>)} 
      {
        (SQ <'\n'> <'\tmk_test_with_hooks testrepo heads/master &&\n'> 
          <'\tgit push testrepo :refs/heads/nonexistent &&\n'> <'\t(\n'> <'\t\tcd testrepo/.git &&\n'> <'\t\tcat >pre-receive.expect <<-EOF &&\n'> 
          <'\t\t$_z40 $_z40 refs/heads/nonexistent\n'> <'\t\tEOF\n'> <'\n'> <'\t\tcat >update.expect <<-EOF &&\n'> <'\t\trefs/heads/nonexistent $_z40 $_z40\n'> 
          <'\t\tEOF\n'> <'\n'> <'\t\ttest_cmp pre-receive.expect pre-receive.actual &&\n'> 
          <'\t\ttest_cmp update.expect update.actual &&\n'> <'\t\ttest_path_is_missing post-receive.actual &&\n'> 
          <'\t\ttest_path_is_missing post-update.actual\n'> <'\t)\n'>
        )
      }
    )
    (C {<test_expect_success>} 
      {(SQ <'mixed ref updates, deletes, invalid deletes trigger hooks with correct input'>)} 
      {
        (SQ <'\n'> <'\tmk_test_with_hooks testrepo heads/master heads/next heads/pu &&\n'> 
          <'\torgmaster=$(cd testrepo && git show-ref -s --verify refs/heads/master) &&\n'> <'\tnewmaster=$(git show-ref -s --verify refs/heads/master) &&\n'> 
          <'\torgnext=$(cd testrepo && git show-ref -s --verify refs/heads/next) &&\n'> <'\tnewnext=$_z40 &&\n'> <'\torgpu=$(cd testrepo && git show-ref -s --verify refs/heads/pu) &&\n'> 
          <'\tnewpu=$(git show-ref -s --verify refs/heads/master) &&\n'> <'\tgit push testrepo refs/heads/master:refs/heads/master \\\n'> 
          <'\t    refs/heads/master:refs/heads/pu :refs/heads/next \\\n'> <'\t    :refs/heads/nonexistent &&\n'> <'\t(\n'> <'\t\tcd testrepo/.git &&\n'> 
          <'\t\tcat >pre-receive.expect <<-EOF &&\n'> <'\t\t$orgmaster $newmaster refs/heads/master\n'> <'\t\t$orgnext $newnext refs/heads/next\n'> 
          <'\t\t$orgpu $newpu refs/heads/pu\n'> <'\t\t$_z40 $_z40 refs/heads/nonexistent\n'> <'\t\tEOF\n'> <'\n'> <'\t\tcat >update.expect <<-EOF &&\n'> 
          <'\t\trefs/heads/master $orgmaster $newmaster\n'> <'\t\trefs/heads/next $orgnext $newnext\n'> <'\t\trefs/heads/pu $orgpu $newpu\n'> 
          <'\t\trefs/heads/nonexistent $_z40 $_z40\n'> <'\t\tEOF\n'> <'\n'> <'\t\tcat >post-receive.expect <<-EOF &&\n'> 
          <'\t\t$orgmaster $newmaster refs/heads/master\n'> <'\t\t$orgnext $newnext refs/heads/next\n'> <'\t\t$orgpu $newpu refs/heads/pu\n'> <'\t\tEOF\n'> <'\n'> 
          <'\t\tcat >post-update.expect <<-EOF &&\n'> <'\t\trefs/heads/master\n'> <'\t\trefs/heads/next\n'> <'\t\trefs/heads/pu\n'> <'\t\tEOF\n'> <'\n'> 
          <'\t\ttest_cmp pre-receive.expect pre-receive.actual &&\n'> <'\t\ttest_cmp update.expect update.actual &&\n'> 
          <'\t\ttest_cmp post-receive.expect post-receive.actual &&\n'> <'\t\ttest_cmp post-update.expect post-update.actual\n'> <'\t)\n'>
        )
      }
    )
    (C {<test_expect_success>} {(SQ <'allow deleting a ref using --delete'>)} 
      {
        (SQ <'\n'> <'\tmk_test testrepo heads/master &&\n'> 
          <'\t(cd testrepo && git config receive.denyDeleteCurrent warn) &&\n'> <'\tgit push testrepo --delete master &&\n'> 
          <'\t(cd testrepo && test_must_fail git rev-parse --verify refs/heads/master)\n'>
        )
      }
    )
    (C {<test_expect_success>} {(SQ <'allow deleting a tag using --delete'>)} 
      {
        (SQ <'\n'> <'\tmk_test testrepo heads/master &&\n'> 
          <'\tgit tag -a -m dummy_message deltag heads/master &&\n'> <'\tgit push testrepo --tags &&\n'> 
          <'\t(cd testrepo && git rev-parse --verify -q refs/tags/deltag) &&\n'> <'\tgit push testrepo --delete tag deltag &&\n'> 
          <'\t(cd testrepo && test_must_fail git rev-parse --verify refs/tags/deltag)\n'>
        )
      }
    )
    (C {<test_expect_success>} {(SQ <'push --delete without args aborts'>)} 
      {
        (SQ <'\n'> <'\tmk_test testrepo heads/master &&\n'> 
          <'\ttest_must_fail git push testrepo --delete\n'>
        )
      }
    )
    (C {<test_expect_success>} {(SQ <'push --delete refuses src:dest refspecs'>)} 
      {
        (SQ <'\n'> <'\tmk_test testrepo heads/master &&\n'> 
          <'\ttest_must_fail git push testrepo --delete master:foo\n'>
        )
      }
    )
    (C {<test_expect_success>} {(SQ <'warn on push to HEAD of non-bare repository'>)} 
      {
        (SQ <'\n'> <'\tmk_test testrepo heads/master &&\n'> <'\t(\n'> <'\t\tcd testrepo &&\n'> 
          <'\t\tgit checkout master &&\n'> <'\t\tgit config receive.denyCurrentBranch warn\n'> <'\t) &&\n'> 
          <'\tgit push testrepo master 2>stderr &&\n'> <'\tgrep "warning: updating the current branch" stderr\n'>
        )
      }
    )
    (C {<test_expect_success>} {(SQ <'deny push to HEAD of non-bare repository'>)} 
      {
        (SQ <'\n'> <'\tmk_test testrepo heads/master &&\n'> <'\t(\n'> <'\t\tcd testrepo &&\n'> 
          <'\t\tgit checkout master &&\n'> <'\t\tgit config receive.denyCurrentBranch true\n'> <'\t) &&\n'> 
          <'\ttest_must_fail git push testrepo master\n'>
        )
      }
    )
    (C {<test_expect_success>} {(SQ <'allow push to HEAD of bare repository (bare)'>)} 
      {
        (SQ <'\n'> <'\tmk_test testrepo heads/master &&\n'> <'\t(\n'> <'\t\tcd testrepo &&\n'> 
          <'\t\tgit checkout master &&\n'> <'\t\tgit config receive.denyCurrentBranch true &&\n'> <'\t\tgit config core.bare true\n'> <'\t) &&\n'> 
          <'\tgit push testrepo master 2>stderr &&\n'> <'\t! grep "warning: updating the current branch" stderr\n'>
        )
      }
    )
    (C {<test_expect_success>} {(SQ <'allow push to HEAD of non-bare repository (config)'>)} 
      {
        (SQ <'\n'> <'\tmk_test testrepo heads/master &&\n'> <'\t(\n'> <'\t\tcd testrepo &&\n'> 
          <'\t\tgit checkout master &&\n'> <'\t\tgit config receive.denyCurrentBranch false\n'> <'\t) &&\n'> 
          <'\tgit push testrepo master 2>stderr &&\n'> <'\t! grep "warning: updating the current branch" stderr\n'>
        )
      }
    )
    (C {<test_expect_success>} {(SQ <'fetch with branches'>)} 
      {
        (SQ <'\n'> <'\tmk_empty testrepo &&\n'> <'\tgit branch second $the_first_commit &&\n'> 
          <'\tgit checkout second &&\n'> <'\techo ".." > testrepo/.git/branches/branch1 &&\n'> <'\t(\n'> <'\t\tcd testrepo &&\n'> 
          <'\t\tgit fetch branch1 &&\n'> <'\t\techo "$the_commit commit\trefs/heads/branch1" >expect &&\n'> 
          <'\t\tgit for-each-ref refs/heads >actual &&\n'> <'\t\ttest_cmp expect actual\n'> <'\t) &&\n'> <'\tgit checkout master\n'>
        )
      }
    )
    (C {<test_expect_success>} {(SQ <'fetch with branches containing #'>)} 
      {
        (SQ <'\n'> <'\tmk_empty testrepo &&\n'> 
          <'\techo "..#second" > testrepo/.git/branches/branch2 &&\n'> <'\t(\n'> <'\t\tcd testrepo &&\n'> <'\t\tgit fetch branch2 &&\n'> 
          <'\t\techo "$the_first_commit commit\trefs/heads/branch2" >expect &&\n'> <'\t\tgit for-each-ref refs/heads >actual &&\n'> <'\t\ttest_cmp expect actual\n'> <'\t) &&\n'> 
          <'\tgit checkout master\n'>
        )
      }
    )
    (C {<test_expect_success>} {(SQ <'push with branches'>)} 
      {
        (SQ <'\n'> <'\tmk_empty testrepo &&\n'> <'\tgit checkout second &&\n'> 
          <'\techo "testrepo" > .git/branches/branch1 &&\n'> <'\tgit push branch1 &&\n'> <'\t(\n'> <'\t\tcd testrepo &&\n'> 
          <'\t\techo "$the_first_commit commit\trefs/heads/master" >expect &&\n'> <'\t\tgit for-each-ref refs/heads >actual &&\n'> <'\t\ttest_cmp expect actual\n'> <'\t)\n'>
        )
      }
    )
    (C {<test_expect_success>} {(SQ <'push with branches containing #'>)} 
      {
        (SQ <'\n'> <'\tmk_empty testrepo &&\n'> 
          <'\techo "testrepo#branch3" > .git/branches/branch2 &&\n'> <'\tgit push branch2 &&\n'> <'\t(\n'> <'\t\tcd testrepo &&\n'> 
          <'\t\techo "$the_first_commit commit\trefs/heads/branch3" >expect &&\n'> <'\t\tgit for-each-ref refs/heads >actual &&\n'> <'\t\ttest_cmp expect actual\n'> <'\t) &&\n'> 
          <'\tgit checkout master\n'>
        )
      }
    )
    (C {<test_expect_success>} {(SQ <'push into aliased refs (consistent)'>)} 
      {
        (SQ <'\n'> <'\tmk_test testrepo heads/master &&\n'> <'\tmk_child testrepo child1 &&\n'> 
          <'\tmk_child testrepo child2 &&\n'> <'\t(\n'> <'\t\tcd child1 &&\n'> <'\t\tgit branch foo &&\n'> 
          <'\t\tgit symbolic-ref refs/heads/bar refs/heads/foo\n'> <'\t\tgit config receive.denyCurrentBranch false\n'> <'\t) &&\n'> <'\t(\n'> <'\t\tcd child2 &&\n'> 
          <'\t\t>path2 &&\n'> <'\t\tgit add path2 &&\n'> <'\t\ttest_tick &&\n'> <'\t\tgit commit -a -m child2 &&\n'> 
          <'\t\tgit branch foo &&\n'> <'\t\tgit branch bar &&\n'> <'\t\tgit push ../child1 foo bar\n'> <'\t)\n'>
        )
      }
    )
    (C {<test_expect_success>} {(SQ <'push into aliased refs (inconsistent)'>)} 
      {
        (SQ <'\n'> <'\tmk_test testrepo heads/master &&\n'> <'\tmk_child testrepo child1 &&\n'> 
          <'\tmk_child testrepo child2 &&\n'> <'\t(\n'> <'\t\tcd child1 &&\n'> <'\t\tgit branch foo &&\n'> 
          <'\t\tgit symbolic-ref refs/heads/bar refs/heads/foo\n'> <'\t\tgit config receive.denyCurrentBranch false\n'> <'\t) &&\n'> <'\t(\n'> <'\t\tcd child2 &&\n'> 
          <'\t\t>path2 &&\n'> <'\t\tgit add path2 &&\n'> <'\t\ttest_tick &&\n'> <'\t\tgit commit -a -m child2 &&\n'> 
          <'\t\tgit branch foo &&\n'> <'\t\t>path3 &&\n'> <'\t\tgit add path3 &&\n'> <'\t\ttest_tick &&\n'> 
          <'\t\tgit commit -a -m child2 &&\n'> <'\t\tgit branch bar &&\n'> <'\t\ttest_must_fail git push ../child1 foo bar 2>stderr &&\n'> 
          <'\t\tgrep "refusing inconsistent update" stderr\n'> <'\t)\n'>
        )
      }
    )
    (C {<test_expect_success>} {(SQ <'push requires --force to update lightweight tag'>)} 
      {
        (SQ <'\n'> <'\tmk_test testrepo heads/master &&\n'> <'\tmk_child testrepo child1 &&\n'> 
          <'\tmk_child testrepo child2 &&\n'> <'\t(\n'> <'\t\tcd child1 &&\n'> <'\t\tgit tag Tag &&\n'> <'\t\tgit push ../child2 Tag &&\n'> 
          <'\t\tgit push ../child2 Tag &&\n'> <'\t\t>file1 &&\n'> <'\t\tgit add file1 &&\n'> <'\t\tgit commit -m "file1" &&\n'> 
          <'\t\tgit tag -f Tag &&\n'> <'\t\ttest_must_fail git push ../child2 Tag &&\n'> <'\t\tgit push --force ../child2 Tag &&\n'> 
          <'\t\tgit tag -f Tag &&\n'> <'\t\ttest_must_fail git push ../child2 Tag HEAD~ &&\n'> <'\t\tgit push --force ../child2 Tag\n'> 
          <'\t)\n'>
        )
      }
    )
    (C {<test_expect_success>} {(SQ <'push --porcelain'>)} 
      {
        (SQ <'\n'> <'\tmk_empty testrepo &&\n'> <'\techo >.git/foo  "To testrepo" &&\n'> 
          <
'\techo >>.git/foo "*\trefs/heads/master:refs/remotes/origin/master\t[new branch]"  &&\n'
          > <'\techo >>.git/foo "Done" &&\n'> 
          <
'\tgit push >.git/bar --porcelain  testrepo refs/heads/master:refs/remotes/origin/master &&\n'
          > <'\t(\n'> <'\t\tcd testrepo &&\n'> 
          <'\t\techo "$the_commit commit\trefs/remotes/origin/master" >expect &&\n'> <'\t\tgit for-each-ref refs/remotes/origin >actual &&\n'> <'\t\ttest_cmp expect actual\n'> <'\t) &&\n'> 
          <'\ttest_cmp .git/foo .git/bar\n'>
        )
      }
    )
    (C {<test_expect_success>} {(SQ <'push --porcelain bad url'>)} 
      {
        (SQ <'\n'> <'\tmk_empty testrepo &&\n'> 
          <
'\ttest_must_fail git push >.git/bar --porcelain asdfasdfasd refs/heads/master:refs/remotes/origin/master &&\n'
          > <'\ttest_must_fail grep -q Done .git/bar\n'>
        )
      }
    )
    (C {<test_expect_success>} {(SQ <'push --porcelain rejected'>)} 
      {
        (SQ <'\n'> <'\tmk_empty testrepo &&\n'> 
          <'\tgit push testrepo refs/heads/master:refs/remotes/origin/master &&\n'> <'\t(cd testrepo &&\n'> <'\t\tgit reset --hard origin/master^\n'> 
          <'\t\tgit config receive.denyCurrentBranch true) &&\n'> <'\n'> <'\techo >.git/foo  "To testrepo"  &&\n'> 
          <
'\techo >>.git/foo "!\trefs/heads/master:refs/heads/master\t[remote rejected] (branch is currently checked out)" &&\n'
          > <'\n'> 
          <
'\ttest_must_fail git push >.git/bar --porcelain  testrepo refs/heads/master:refs/heads/master &&\n'
          > <'\ttest_cmp .git/foo .git/bar\n'>
        )
      }
    )
    (C {<test_expect_success>} {(SQ <'push --porcelain --dry-run rejected'>)} 
      {
        (SQ <'\n'> <'\tmk_empty testrepo &&\n'> 
          <'\tgit push testrepo refs/heads/master:refs/remotes/origin/master &&\n'> <'\t(cd testrepo &&\n'> <'\t\tgit reset --hard origin/master\n'> 
          <'\t\tgit config receive.denyCurrentBranch true) &&\n'> <'\n'> <'\techo >.git/foo  "To testrepo"  &&\n'> 
          <
'\techo >>.git/foo "!\trefs/heads/master^:refs/heads/master\t[rejected] (non-fast-forward)" &&\n'
          > <'\techo >>.git/foo "Done" &&\n'> <'\n'> 
          <
'\ttest_must_fail git push >.git/bar --porcelain  --dry-run testrepo refs/heads/master^:refs/heads/master &&\n'
          > <'\ttest_cmp .git/foo .git/bar\n'>
        )
      }
    )
    (C {<test_expect_success>} {(SQ <'push --prune'>)} 
      {
        (SQ <'\n'> <'\tmk_test testrepo heads/master heads/second heads/foo heads/bar &&\n'> 
          <'\tgit push --prune testrepo : &&\n'> <'\tcheck_push_result testrepo $the_commit heads/master &&\n'> 
          <'\tcheck_push_result testrepo $the_first_commit heads/second &&\n'> <'\t! check_push_result testrepo $the_first_commit heads/foo heads/bar\n'>
        )
      }
    )
    (C {<test_expect_success>} {(SQ <'push --prune refspec'>)} 
      {
        (SQ <'\n'> <'\tmk_test testrepo tmp/master tmp/second tmp/foo tmp/bar &&\n'> 
          <'\tgit push --prune testrepo "refs/heads/*:refs/tmp/*" &&\n'> <'\tcheck_push_result testrepo $the_commit tmp/master &&\n'> 
          <'\tcheck_push_result testrepo $the_first_commit tmp/second &&\n'> <'\t! check_push_result testrepo $the_first_commit tmp/foo tmp/bar\n'>
        )
      }
    )
    (command.ForEach
      iter_names: [configsection]
      iterable: (for_iter.Words words:[{<transfer>} {<receive>}])
      body: 
        (command.DoGroup
          children: [
            (C {<test_expect_success>} 
              {
                (DQ <'push to update a ref hidden by '> ($ Id.VSub_DollarName '$configsection') 
                  <.hiderefs>
                )
              } 
              {
                (SQ <'\n'> 
                  <'\t\tmk_test testrepo heads/master hidden/one hidden/two hidden/three &&\n'> <'\t\t(\n'> <'\t\t\tcd testrepo &&\n'> <'\t\t\tgit config $configsection.hiderefs refs/hidden\n'> 
                  <'\t\t) &&\n'> <'\n'> <'\t\t# push to unhidden ref succeeds normally\n'> 
                  <'\t\tgit push testrepo master:refs/heads/master &&\n'> <'\t\tcheck_push_result testrepo $the_commit heads/master &&\n'> <'\n'> 
                  <'\t\t# push to update a hidden ref should fail\n'> <'\t\ttest_must_fail git push testrepo master:refs/hidden/one &&\n'> 
                  <'\t\tcheck_push_result testrepo $the_first_commit hidden/one &&\n'> <'\n'> <'\t\t# push to delete a hidden ref should fail\n'> 
                  <'\t\ttest_must_fail git push testrepo :refs/hidden/two &&\n'> <'\t\tcheck_push_result testrepo $the_first_commit hidden/two &&\n'> <'\n'> 
                  <'\t\t# idempotent push to update a hidden ref should fail\n'> <'\t\ttest_must_fail git push testrepo $the_first_commit:refs/hidden/three &&\n'> 
                  <'\t\tcheck_push_result testrepo $the_first_commit hidden/three\n'> <'\t'>
                )
              }
            )
          ]
        )
    )
    (C {<test_expect_success>} {(SQ <'fetch exact SHA1'>)} 
      {
        (SQ <'\n'> <'\tmk_test testrepo heads/master hidden/one &&\n'> 
          <'\tgit push testrepo master:refs/hidden/one &&\n'> <'\t(\n'> <'\t\tcd testrepo &&\n'> <'\t\tgit config transfer.hiderefs refs/hidden\n'> <'\t) &&\n'> 
          <'\tcheck_push_result testrepo $the_commit hidden/one &&\n'> <'\n'> <'\tmk_child testrepo child &&\n'> <'\t(\n'> <'\t\tcd child &&\n'> <'\n'> 
          <'\t\t# make sure $the_commit does not exist here\n'> <'\t\tgit repack -a -d &&\n'> <'\t\tgit prune &&\n'> 
          <'\t\ttest_must_fail git cat-file -t $the_commit &&\n'> <'\n'> <'\t\t# fetching the hidden object should fail by default\n'> 
          <'\t\ttest_must_fail git fetch -v ../testrepo $the_commit:refs/heads/copy &&\n'> <'\t\ttest_must_fail git rev-parse --verify refs/heads/copy &&\n'> <'\n'> 
          <'\t\t# the server side can allow it to succeed\n'> <'\t\t(\n'> <'\t\t\tcd ../testrepo &&\n'> <'\t\t\tgit config uploadpack.allowtipsha1inwant true\n'> 
          <'\t\t) &&\n'> <'\n'> <'\t\tgit fetch -v ../testrepo $the_commit:refs/heads/copy master:refs/heads/extra &&\n'> 
          <'\t\tcat >expect <<-EOF &&\n'> <'\t\t$the_commit\n'> <'\t\t$the_first_commit\n'> <'\t\tEOF\n'> <'\t\t{\n'> 
          <'\t\t\tgit rev-parse --verify refs/heads/copy &&\n'> <'\t\t\tgit rev-parse --verify refs/heads/extra\n'> <'\t\t} >actual &&\n'> 
          <'\t\ttest_cmp expect actual\n'> <'\t)\n'>
        )
      }
    )
    (command.ForEach
      iter_names: [configallowtipsha1inwant]
      iterable: (for_iter.Words words:[{<true>} {<false>}])
      body: 
        (command.DoGroup
          children: [
            (C {<test_expect_success>} 
              {
                (DQ <'shallow fetch reachable SHA1 (but not a ref), allowtipsha1inwant='> 
                  ($ Id.VSub_DollarName '$configallowtipsha1inwant')
                )
              } 
              {
                (SQ <'\n'> <'\t\tmk_empty testrepo &&\n'> <'\t\t(\n'> <'\t\t\tcd testrepo &&\n'> 
                  <'\t\t\tgit config uploadpack.allowtipsha1inwant $configallowtipsha1inwant &&\n'> <'\t\t\tgit commit --allow-empty -m foo &&\n'> <'\t\t\tgit commit --allow-empty -m bar\n'> 
                  <'\t\t) &&\n'> <'\t\tSHA1=$(git --git-dir=testrepo/.git rev-parse HEAD^) &&\n'> <'\t\tmk_empty shallow &&\n'> 
                  <'\t\t(\n'> <'\t\t\tcd shallow &&\n'> <'\t\t\ttest_must_fail git fetch --depth=1 ../testrepo/.git $SHA1 &&\n'> 
                  <
'\t\t\tgit --git-dir=../testrepo/.git config uploadpack.allowreachablesha1inwant true &&\n'
                  > <'\t\t\tgit fetch --depth=1 ../testrepo/.git $SHA1 &&\n'> <'\t\t\tgit cat-file commit $SHA1\n'> 
                  <'\t\t)\n'> <'\t'>
                )
              }
            )
            (C {<test_expect_success>} 
              {
                (DQ <'deny fetch unreachable SHA1, allowtipsha1inwant='> 
                  ($ Id.VSub_DollarName '$configallowtipsha1inwant')
                )
              } 
              {
                (SQ <'\n'> <'\t\tmk_empty testrepo &&\n'> <'\t\t(\n'> <'\t\t\tcd testrepo &&\n'> 
                  <'\t\t\tgit config uploadpack.allowtipsha1inwant $configallowtipsha1inwant &&\n'> <'\t\t\tgit commit --allow-empty -m foo &&\n'> <'\t\t\tgit commit --allow-empty -m bar &&\n'> 
                  <'\t\t\tgit commit --allow-empty -m xyz\n'> <'\t\t) &&\n'> <'\t\tSHA1_1=$(git --git-dir=testrepo/.git rev-parse HEAD^^) &&\n'> 
                  <'\t\tSHA1_2=$(git --git-dir=testrepo/.git rev-parse HEAD^) &&\n'> <'\t\tSHA1_3=$(git --git-dir=testrepo/.git rev-parse HEAD) &&\n'> <'\t\t(\n'> 
                  <'\t\t\tcd testrepo &&\n'> <'\t\t\tgit reset --hard $SHA1_2 &&\n'> <'\t\t\tgit cat-file commit $SHA1_1 &&\n'> 
                  <'\t\t\tgit cat-file commit $SHA1_3\n'> <'\t\t) &&\n'> <'\t\tmk_empty shallow &&\n'> <'\t\t(\n'> <'\t\t\tcd shallow &&\n'> 
                  <'\t\t\ttest_must_fail ok=sigpipe git fetch ../testrepo/.git $SHA1_3 &&\n'> <'\t\t\ttest_must_fail ok=sigpipe git fetch ../testrepo/.git $SHA1_1 &&\n'> 
                  <
'\t\t\tgit --git-dir=../testrepo/.git config uploadpack.allowreachablesha1inwant true &&\n'
                  > <'\t\t\tgit fetch ../testrepo/.git $SHA1_1 &&\n'> <'\t\t\tgit cat-file commit $SHA1_1 &&\n'> 
                  <'\t\t\ttest_must_fail git cat-file commit $SHA1_2 &&\n'> <'\t\t\tgit fetch ../testrepo/.git $SHA1_2 &&\n'> <'\t\t\tgit cat-file commit $SHA1_2 &&\n'> 
                  <'\t\t\ttest_must_fail ok=sigpipe git fetch ../testrepo/.git $SHA1_3\n'> <'\t\t)\n'> <'\t'>
                )
              }
            )
          ]
        )
    )
    (C {<test_expect_success>} {(SQ <'fetch follows tags by default'>)} 
      {
        (SQ <'\n'> <'\tmk_test testrepo heads/master &&\n'> <'\trm -fr src dst &&\n'> 
          <'\tgit init src &&\n'> <'\t(\n'> <'\t\tcd src &&\n'> <'\t\tgit pull ../testrepo master &&\n'> 
          <'\t\tgit tag -m "annotated" tag &&\n'> <'\t\tgit for-each-ref >tmp1 &&\n'> <'\t\t(\n'> <'\t\t\tcat tmp1\n'> 
          <'\t\t\tsed -n "s|refs/heads/master$|refs/remotes/origin/master|p" tmp1\n'> <'\t\t) |\n'> <'\t\tsort -k 3 >../expect\n'> <'\t) &&\n'> <'\tgit init dst &&\n'> <'\t(\n'> 
          <'\t\tcd dst &&\n'> <'\t\tgit remote add origin ../src &&\n'> <'\t\tgit config branch.master.remote origin &&\n'> 
          <'\t\tgit config branch.master.merge refs/heads/master &&\n'> <'\t\tgit pull &&\n'> <'\t\tgit for-each-ref >../actual\n'> <'\t) &&\n'> <'\ttest_cmp expect actual\n'>
        )
      }
    )
    (C {<test_expect_success>} {(SQ <'pushing a specific ref applies remote.$name.push as refmap'>)} 
      {
        (SQ <'\n'> <'\tmk_test testrepo heads/master &&\n'> <'\trm -fr src dst &&\n'> 
          <'\tgit init src &&\n'> <'\tgit init --bare dst &&\n'> <'\t(\n'> <'\t\tcd src &&\n'> <'\t\tgit pull ../testrepo master &&\n'> 
          <'\t\tgit branch next &&\n'> <'\t\tgit config remote.dst.url ../dst &&\n'> 
          <'\t\tgit config remote.dst.push "+refs/heads/*:refs/remotes/src/*" &&\n'> <'\t\tgit push dst master &&\n'> <'\t\tgit show-ref refs/heads/master |\n'> 
          <'\t\tsed -e "s|refs/heads/|refs/remotes/src/|" >../dst/expect\n'> <'\t) &&\n'> <'\t(\n'> <'\t\tcd dst &&\n'> <'\t\ttest_must_fail git show-ref refs/heads/next &&\n'> 
          <'\t\ttest_must_fail git show-ref refs/heads/master &&\n'> <'\t\tgit show-ref refs/remotes/src/master >actual\n'> <'\t) &&\n'> 
          <'\ttest_cmp dst/expect dst/actual\n'>
        )
      }
    )
    (C {<test_expect_success>} {(SQ <'with no remote.$name.push, it is not used as refmap'>)} 
      {
        (SQ <'\n'> <'\tmk_test testrepo heads/master &&\n'> <'\trm -fr src dst &&\n'> 
          <'\tgit init src &&\n'> <'\tgit init --bare dst &&\n'> <'\t(\n'> <'\t\tcd src &&\n'> <'\t\tgit pull ../testrepo master &&\n'> 
          <'\t\tgit branch next &&\n'> <'\t\tgit config remote.dst.url ../dst &&\n'> <'\t\tgit config push.default matching &&\n'> 
          <'\t\tgit push dst master &&\n'> <'\t\tgit show-ref refs/heads/master >../dst/expect\n'> <'\t) &&\n'> <'\t(\n'> <'\t\tcd dst &&\n'> 
          <'\t\ttest_must_fail git show-ref refs/heads/next &&\n'> <'\t\tgit show-ref refs/heads/master >actual\n'> <'\t) &&\n'> <'\ttest_cmp dst/expect dst/actual\n'>
        )
      }
    )
    (C {<test_expect_success>} {(SQ <'with no remote.$name.push, upstream mapping is used'>)} 
      {
        (SQ <'\n'> <'\tmk_test testrepo heads/master &&\n'> <'\trm -fr src dst &&\n'> 
          <'\tgit init src &&\n'> <'\tgit init --bare dst &&\n'> <'\t(\n'> <'\t\tcd src &&\n'> <'\t\tgit pull ../testrepo master &&\n'> 
          <'\t\tgit branch next &&\n'> <'\t\tgit config remote.dst.url ../dst &&\n'> 
          <'\t\tgit config remote.dst.fetch "+refs/heads/*:refs/remotes/dst/*" &&\n'> <'\t\tgit config push.default upstream &&\n'> <'\n'> 
          <'\t\tgit config branch.master.merge refs/heads/trunk &&\n'> <'\t\tgit config branch.master.remote dst &&\n'> <'\n'> <'\t\tgit push dst master &&\n'> 
          <'\t\tgit show-ref refs/heads/master |\n'> <'\t\tsed -e "s|refs/heads/master|refs/heads/trunk|" >../dst/expect\n'> <'\t) &&\n'> <'\t(\n'> 
          <'\t\tcd dst &&\n'> <'\t\ttest_must_fail git show-ref refs/heads/master &&\n'> 
          <'\t\ttest_must_fail git show-ref refs/heads/next &&\n'> <'\t\tgit show-ref refs/heads/trunk >actual\n'> <'\t) &&\n'> <'\ttest_cmp dst/expect dst/actual\n'>
        )
      }
    )
    (C {<test_expect_success>} {(SQ <'push does not follow tags by default'>)} 
      {
        (SQ <'\n'> <'\tmk_test testrepo heads/master &&\n'> <'\trm -fr src dst &&\n'> 
          <'\tgit init src &&\n'> <'\tgit init --bare dst &&\n'> <'\t(\n'> <'\t\tcd src &&\n'> <'\t\tgit pull ../testrepo master &&\n'> 
          <'\t\tgit tag -m "annotated" tag &&\n'> <'\t\tgit checkout -b another &&\n'> <'\t\tgit commit --allow-empty -m "future commit" &&\n'> 
          <'\t\tgit tag -m "future" future &&\n'> <'\t\tgit checkout master &&\n'> <'\t\tgit for-each-ref refs/heads/master >../expect &&\n'> 
          <'\t\tgit push ../dst master\n'> <'\t) &&\n'> <'\t(\n'> <'\t\tcd dst &&\n'> <'\t\tgit for-each-ref >../actual\n'> <'\t) &&\n'> 
          <'\ttest_cmp expect actual\n'>
        )
      }
    )
    (C {<test_expect_success>} {(SQ <'push --follow-tag only pushes relevant tags'>)} 
      {
        (SQ <'\n'> <'\tmk_test testrepo heads/master &&\n'> <'\trm -fr src dst &&\n'> 
          <'\tgit init src &&\n'> <'\tgit init --bare dst &&\n'> <'\t(\n'> <'\t\tcd src &&\n'> <'\t\tgit pull ../testrepo master &&\n'> 
          <'\t\tgit tag -m "annotated" tag &&\n'> <'\t\tgit checkout -b another &&\n'> <'\t\tgit commit --allow-empty -m "future commit" &&\n'> 
          <'\t\tgit tag -m "future" future &&\n'> <'\t\tgit checkout master &&\n'> <'\t\tgit for-each-ref refs/heads/master refs/tags/tag >../expect\n'> 
          <'\t\tgit push --follow-tag ../dst master\n'> <'\t) &&\n'> <'\t(\n'> <'\t\tcd dst &&\n'> <'\t\tgit for-each-ref >../actual\n'> <'\t) &&\n'> 
          <'\ttest_cmp expect actual\n'>
        )
      }
    )
    (C {<test_expect_success>} {(SQ <'push --no-thin must produce non-thin pack'>)} 
      {
        (SQ <'\n'> <'\tcat >>path1 <<\\EOF &&\n'> 
          <'keep base version of path1 big enough, compared to the new changes\n'> <'later, in order to pass size heuristics in\n'> <'builtin/pack-objects.c:try_delta()\n'> <'EOF\n'> 
          <'\tgit commit -am initial &&\n'> <'\tgit init no-thin &&\n'> <'\tgit --git-dir=no-thin/.git config receive.unpacklimit 0 &&\n'> 
          <'\tgit push no-thin/.git refs/heads/master:refs/heads/foo &&\n'> <'\techo modified >> path1 &&\n'> <'\tgit commit -am modified &&\n'> <'\tgit repack -adf &&\n'> 
          <'\trcvpck="git receive-pack --reject-thin-pack-for-testing" &&\n'> <'\tgit push --no-thin --receive-pack="$rcvpck" no-thin/.git refs/heads/master:refs/heads/foo\n'>
        )
      }
    )
    (C {<test_expect_success>} {(SQ <'pushing a tag pushes the tagged object'>)} 
      {
        (SQ <'\n'> <'\trm -rf dst.git &&\n'> 
          <'\tblob=$(echo unreferenced | git hash-object -w --stdin) &&\n'> <'\tgit tag -m foo tag-of-blob $blob &&\n'> <'\tgit init --bare dst.git &&\n'> 
          <'\tgit push dst.git tag-of-blob &&\n'> <'\t# the receiving index-pack should have noticed\n'> <'\t# any problems, but we double check\n'> 
          <'\techo unreferenced >expect &&\n'> <'\tgit --git-dir=dst.git cat-file blob tag-of-blob >actual &&\n'> <'\ttest_cmp expect actual\n'>
        )
      }
    )
    (C {<test_expect_success>} {(SQ <'push into bare respects core.logallrefupdates'>)} 
      {
        (SQ <'\n'> <'\trm -rf dst.git &&\n'> <'\tgit init --bare dst.git &&\n'> 
          <'\tgit -C dst.git config core.logallrefupdates true &&\n'> <'\n'> <'\t# double push to test both with and without\n'> <'\t# the actual pack transfer\n'> 
          <'\tgit push dst.git master:one &&\n'> <'\techo "one@{0} push" >expect &&\n'> <'\tgit -C dst.git log -g --format="%gd %gs" one >actual &&\n'> 
          <'\ttest_cmp expect actual &&\n'> <'\n'> <'\tgit push dst.git master:two &&\n'> <'\techo "two@{0} push" >expect &&\n'> 
          <'\tgit -C dst.git log -g --format="%gd %gs" two >actual &&\n'> <'\ttest_cmp expect actual\n'>
        )
      }
    )
    (C {<test_expect_success>} {(SQ <'fetch into bare respects core.logallrefupdates'>)} 
      {
        (SQ <'\n'> <'\trm -rf dst.git &&\n'> <'\tgit init --bare dst.git &&\n'> <'\t(\n'> 
          <'\t\tcd dst.git &&\n'> <'\t\tgit config core.logallrefupdates true &&\n'> <'\n'> 
          <'\t\t# as above, we double-fetch to test both\n'> <'\t\t# with and without pack transfer\n'> <'\t\tgit fetch .. master:one &&\n'> 
          <'\t\techo "one@{0} fetch .. master:one: storing head" >expect &&\n'> <'\t\tgit log -g --format="%gd %gs" one >actual &&\n'> <'\t\ttest_cmp expect actual &&\n'> <'\n'> 
          <'\t\tgit fetch .. master:two &&\n'> <'\t\techo "two@{0} fetch .. master:two: storing head" >expect &&\n'> 
          <'\t\tgit log -g --format="%gd %gs" two >actual &&\n'> <'\t\ttest_cmp expect actual\n'> <'\t)\n'>
        )
      }
    )
    (C {<test_expect_success>} {(SQ <'receive.denyCurrentBranch = updateInstead'>)} 
      {
        (SQ <'\n'> <'\tgit push testrepo master &&\n'> <'\t(\n'> <'\t\tcd testrepo &&\n'> 
          <'\t\tgit reset --hard &&\n'> <'\t\tgit config receive.denyCurrentBranch updateInstead\n'> <'\t) &&\n'> 
          <'\ttest_commit third path2 &&\n'> <'\n'> <'\t# Try pushing into a repository with pristine working tree\n'> 
          <'\tgit push testrepo master &&\n'> <'\t(\n'> <'\t\tcd testrepo &&\n'> <'\t\tgit update-index -q --refresh &&\n'> 
          <'\t\tgit diff-files --quiet -- &&\n'> <'\t\tgit diff-index --quiet --cached HEAD -- &&\n'> <'\t\ttest third = "$(cat path2)" &&\n'> 
          <'\t\ttest $(git -C .. rev-parse HEAD) = $(git rev-parse HEAD)\n'> <'\t) &&\n'> <'\n'> <'\t# Try pushing into a repository with working tree needing a refresh\n'> 
          <'\t(\n'> <'\t\tcd testrepo &&\n'> <'\t\tgit reset --hard HEAD^ &&\n'> 
          <'\t\ttest $(git -C .. rev-parse HEAD^) = $(git rev-parse HEAD) &&\n'> <'\t\ttest-chmtime +100 path1\n'> <'\t) &&\n'> <'\tgit push testrepo master &&\n'> <'\t(\n'> 
          <'\t\tcd testrepo &&\n'> <'\t\tgit update-index -q --refresh &&\n'> <'\t\tgit diff-files --quiet -- &&\n'> 
          <'\t\tgit diff-index --quiet --cached HEAD -- &&\n'> <'\t\ttest_cmp ../path1 path1 &&\n'> <'\t\ttest third = "$(cat path2)" &&\n'> 
          <'\t\ttest $(git -C .. rev-parse HEAD) = $(git rev-parse HEAD)\n'> <'\t) &&\n'> <'\n'> <'\t# Update what is to be pushed\n'> <'\ttest_commit fourth path2 &&\n'> <'\n'> 
          <'\t# Try pushing into a repository with a dirty working tree\n'> <'\t# (1) the working tree updated\n'> <'\t(\n'> <'\t\tcd testrepo &&\n'> <'\t\techo changed >path1\n'> 
          <'\t) &&\n'> <'\ttest_must_fail git push testrepo master &&\n'> <'\t(\n'> <'\t\tcd testrepo &&\n'> 
          <'\t\ttest $(git -C .. rev-parse HEAD^) = $(git rev-parse HEAD) &&\n'> <'\t\tgit diff --quiet --cached &&\n'> <'\t\ttest changed = "$(cat path1)"\n'> <'\t) &&\n'> <'\n'> 
          <'\t# (2) the index updated\n'> <'\t(\n'> <'\t\tcd testrepo &&\n'> <'\t\techo changed >path1 &&\n'> <'\t\tgit add path1\n'> <'\t) &&\n'> 
          <'\ttest_must_fail git push testrepo master &&\n'> <'\t(\n'> <'\t\tcd testrepo &&\n'> 
          <'\t\ttest $(git -C .. rev-parse HEAD^) = $(git rev-parse HEAD) &&\n'> <'\t\tgit diff --quiet &&\n'> <'\t\ttest changed = "$(cat path1)"\n'> <'\t) &&\n'> <'\n'> 
          <'\t# Introduce a new file in the update\n'> <'\ttest_commit fifth path3 &&\n'> <'\n'> 
          <'\t# (3) the working tree has an untracked file that would interfere\n'> <'\t(\n'> <'\t\tcd testrepo &&\n'> <'\t\tgit reset --hard &&\n'> <'\t\techo changed >path3\n'> 
          <'\t) &&\n'> <'\ttest_must_fail git push testrepo master &&\n'> <'\t(\n'> <'\t\tcd testrepo &&\n'> 
          <'\t\ttest $(git -C .. rev-parse HEAD^^) = $(git rev-parse HEAD) &&\n'> <'\t\tgit diff --quiet &&\n'> <'\t\tgit diff --quiet --cached &&\n'> 
          <'\t\ttest changed = "$(cat path3)"\n'> <'\t) &&\n'> <'\n'> <'\t# (4) the target changes to what gets pushed but it still is a change\n'> 
          <'\t(\n'> <'\t\tcd testrepo &&\n'> <'\t\tgit reset --hard &&\n'> <'\t\techo fifth >path3 &&\n'> 
          <'\t\tgit add path3\n'> <'\t) &&\n'> <'\ttest_must_fail git push testrepo master &&\n'> <'\t(\n'> <'\t\tcd testrepo &&\n'> 
          <'\t\ttest $(git -C .. rev-parse HEAD^^) = $(git rev-parse HEAD) &&\n'> <'\t\tgit diff --quiet &&\n'> <'\t\ttest fifth = "$(cat path3)"\n'> <'\t) &&\n'> <'\n'> 
          <'\t# (5) push into void\n'> <'\trm -fr void &&\n'> <'\tgit init void &&\n'> <'\t(\n'> <'\t\tcd void &&\n'> 
          <'\t\tgit config receive.denyCurrentBranch updateInstead\n'> <'\t) &&\n'> <'\tgit push void master &&\n'> <'\t(\n'> <'\t\tcd void &&\n'> 
          <'\t\ttest $(git -C .. rev-parse master) = $(git rev-parse HEAD) &&\n'> <'\t\tgit diff --quiet &&\n'> <'\t\tgit diff --cached --quiet\n'> <'\t)\n'>
        )
      }
    )
    (C {<test_expect_success>} {(SQ <'updateInstead with push-to-checkout hook'>)} 
      {
        (SQ <'\n'> <'\trm -fr testrepo &&\n'> <'\tgit init testrepo &&\n'> <'\t(\n'> 
          <'\t\tcd testrepo &&\n'> <'\t\tgit pull .. master &&\n'> <'\t\tgit reset --hard HEAD^^ &&\n'> <'\t\tgit tag initial &&\n'> 
          <'\t\tgit config receive.denyCurrentBranch updateInstead &&\n'> <'\t\twrite_script .git/hooks/push-to-checkout <<-\\EOF\n'> 
          <'\t\techo >&2 updating from $(git rev-parse HEAD)\n'> <'\t\techo >&2 updating to "$1"\n'> <'\n'> <'\t\tgit update-index -q --refresh &&\n'> 
          <'\t\tgit read-tree -u -m HEAD "$1" || {\n'> <'\t\t\tstatus=$?\n'> <'\t\t\techo >&2 read-tree failed\n'> <'\t\t\texit $status\n'> <'\t\t}\n'> 
          <'\t\tEOF\n'> <'\t) &&\n'> <'\n'> <'\t# Try pushing into a pristine\n'> <'\tgit push testrepo master &&\n'> <'\t(\n'> 
          <'\t\tcd testrepo &&\n'> <'\t\tgit diff --quiet &&\n'> <'\t\tgit diff HEAD --quiet &&\n'> 
          <'\t\ttest $(git -C .. rev-parse HEAD) = $(git rev-parse HEAD)\n'> <'\t) &&\n'> <'\n'> <'\t# Try pushing into a repository with conflicting change\n'> <'\t(\n'> 
          <'\t\tcd testrepo &&\n'> <'\t\tgit reset --hard initial &&\n'> <'\t\techo conflicting >path2\n'> <'\t) &&\n'> 
          <'\ttest_must_fail git push testrepo master &&\n'> <'\t(\n'> <'\t\tcd testrepo &&\n'> <'\t\ttest $(git rev-parse initial) = $(git rev-parse HEAD) &&\n'> 
          <'\t\ttest conflicting = "$(cat path2)" &&\n'> <'\t\tgit diff-index --quiet --cached HEAD\n'> <'\t) &&\n'> <'\n'> 
          <'\t# Try pushing into a repository with unrelated change\n'> <'\t(\n'> <'\t\tcd testrepo &&\n'> <'\t\tgit reset --hard initial &&\n'> 
          <'\t\techo unrelated >path1 &&\n'> <'\t\techo irrelevant >path5 &&\n'> <'\t\tgit add path5\n'> <'\t) &&\n'> 
          <'\tgit push testrepo master &&\n'> <'\t(\n'> <'\t\tcd testrepo &&\n'> <'\t\ttest "$(cat path1)" = unrelated &&\n'> 
          <'\t\ttest "$(cat path5)" = irrelevant &&\n'> <'\t\ttest "$(git diff --name-only --cached HEAD)" = path5 &&\n'> 
          <'\t\ttest $(git -C .. rev-parse HEAD) = $(git rev-parse HEAD)\n'> <'\t) &&\n'> <'\n'> <'\t# push into void\n'> <'\trm -fr void &&\n'> <'\tgit init void &&\n'> <'\t(\n'> 
          <'\t\tcd void &&\n'> <'\t\tgit config receive.denyCurrentBranch updateInstead &&\n'> 
          <'\t\twrite_script .git/hooks/push-to-checkout <<-\\EOF\n'> <'\t\tif git rev-parse --quiet --verify HEAD\n'> <'\t\tthen\n'> <'\t\t\thas_head=yes\n'> 
          <'\t\t\techo >&2 updating from $(git rev-parse HEAD)\n'> <'\t\telse\n'> <'\t\t\thas_head=no\n'> <'\t\t\techo >&2 pushing into void\n'> <'\t\tfi\n'> 
          <'\t\techo >&2 updating to "$1"\n'> <'\n'> <'\t\tgit update-index -q --refresh &&\n'> <'\t\tcase "$has_head" in\n'> <'\t\tyes)\n'> 
          <'\t\t\tgit read-tree -u -m HEAD "$1" ;;\n'> <'\t\tno)\n'> <'\t\t\tgit read-tree -u -m "$1" ;;\n'> <'\t\tesac || {\n'> <'\t\t\tstatus=$?\n'> 
          <'\t\t\techo >&2 read-tree failed\n'> <'\t\t\texit $status\n'> <'\t\t}\n'> <'\t\tEOF\n'> <'\t) &&\n'> <'\n'> <'\tgit push void master &&\n'> 
          <'\t(\n'> <'\t\tcd void &&\n'> <'\t\tgit diff --quiet &&\n'> <'\t\tgit diff --cached --quiet &&\n'> 
          <'\t\ttest $(git -C .. rev-parse HEAD) = $(git rev-parse HEAD)\n'> <'\t)\n'>
        )
      }
    )
    (C {<test_done>})
  ]
)