(CommandList
  children: [
    (Assignment
      keyword: Assign_None
      pairs: [
        (assign_pair
          lhs: (LhsName name:test_description)
          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]
        )
      ]
      spids: [4]
    )
    (C {(.)} {(./test-lib.sh)})
    (Assignment
      keyword: Assign_None
      pairs: [
        (assign_pair
          lhs: (LhsName name:D)
          op: Equal
          rhs: 
            {
              (CommandSubPart
                command_list: (CommandList children:[(C {(pwd)})])
                left_token: <Left_CommandSub '$('>
                spids: [27 29]
              )
            }
          spids: [26]
        )
      ]
      spids: [26]
    )
    (FuncDef
      name: mk_empty
      body: 
        (BraceGroup
          children: [
            (Assignment
              keyword: Assign_None
              pairs: [
                (assign_pair
                  lhs: (LhsName name:repo_name)
                  op: Equal
                  rhs: {(DQ ($ VSub_Number '$1'))}
                  spids: [40]
                )
              ]
              spids: [40]
            )
            (AndOr
              children: [
                (C {(rm)} {(-fr)} {(DQ ($ VSub_Name '$repo_name'))})
                (AndOr
                  children: [
                    (C {(mkdir)} {(DQ ($ VSub_Name '$repo_name'))})
                    (Subshell
                      child: 
                        (AndOr
                          children: [
                            (C {(cd)} {(DQ ($ VSub_Name '$repo_name'))})
                            (AndOr
                              children: [
                                (C {(git)} {(init)})
                                (AndOr
                                  children: [
                                    (C {(git)} {(config)} {(receive.denyCurrentBranch)} {(warn)})
                                    (C {(mv)} {(.git/hooks)} {(.git/hooks-disabled)})
                                  ]
                                  op_id: Op_DAmp
                                )
                              ]
                              op_id: Op_DAmp
                            )
                          ]
                          op_id: Op_DAmp
                        )
                      spids: [66 103]
                    )
                  ]
                  op_id: Op_DAmp
                )
              ]
              op_id: Op_DAmp
            )
          ]
          spids: [37]
        )
      spids: [32 36]
    )
    (FuncDef
      name: mk_test
      body: 
        (BraceGroup
          children: [
            (Assignment
              keyword: Assign_None
              pairs: [
                (assign_pair
                  lhs: (LhsName name:repo_name)
                  op: Equal
                  rhs: {(DQ ($ VSub_Number '$1'))}
                  spids: [116]
                )
              ]
              spids: [116]
            )
            (C {(shift)})
            (AndOr
              children: [
                (C {(mk_empty)} {(DQ ($ VSub_Name '$repo_name'))})
                (Subshell
                  child: 
                    (AndOr
                      children: [
                        (ForEach
                          iter_name: ref
                          iter_words: [{(DQ ($ VSub_At '$@'))}]
                          do_arg_iter: False
                          body: 
                            (DoGroup
                              children: [
                                (AndOr
                                  children: [
                                    (C {(git)} {(push)} {(DQ ($ VSub_Name '$repo_name'))} 
                                      {($ VSub_Name '$the_first_commit') (Lit_Other ':') (refs/) 
                                        ($ VSub_Name '$ref')
                                      }
                                    )
                                    (C {(exit)})
                                  ]
                                  op_id: Op_DPipe
                                )
                              ]
                              spids: [149 171]
                            )
                          spids: [143 -1]
                        )
                        (AndOr
                          children: [
                            (C {(cd)} {(DQ ($ VSub_Name '$repo_name'))})
                            (AndOr
                              children: [
                                (ForEach
                                  iter_name: ref
                                  iter_words: [{(DQ ($ VSub_At '$@'))}]
                                  do_arg_iter: False
                                  body: 
                                    (DoGroup
                                      children: [
                                        (AndOr
                                          children: [
                                            (SimpleCommand
                                              words: [{(echo)} {(DQ ($ VSub_Name '$the_first_commit'))}]
                                              redirects: [
                                                (Redir
                                                  op_id: Redir_Great
                                                  fd: -1
                                                  arg_word: {(expect)}
                                                  spids: [205]
                                                )
                                              ]
                                            )
                                            (AndOr
                                              children: [
                                                (SimpleCommand
                                                  words: [
                                                    {(git)}
                                                    {(show-ref)}
                                                    {(-s)}
                                                    {(--verify)}
                                                    {(refs/) ($ VSub_Name '$ref')}
                                                  ]
                                                  redirects: [
                                                    (Redir
                                                      op_id: Redir_Great
                                                      fd: -1
                                                      arg_word: {(actual)}
                                                      spids: [222]
                                                    )
                                                  ]
                                                )
                                                (AndOr
                                                  children: [
                                                    (C {(test_cmp)} {(expect)} {(actual)})
                                                    (C {(exit)})
                                                  ]
                                                  op_id: Op_DPipe
                                                )
                                              ]
                                              op_id: Op_DAmp
                                            )
                                          ]
                                          op_id: Op_DAmp
                                        )
                                      ]
                                      spids: [196 240]
                                    )
                                  spids: [190 -1]
                                )
                                (C {(git)} {(fsck)} {(--full)})
                              ]
                              op_id: Op_DAmp
                            )
                          ]
                          op_id: Op_DAmp
                        )
                      ]
                      op_id: Op_DAmp
                    )
                  spids: [135 252]
                )
              ]
              op_id: Op_DAmp
            )
          ]
          spids: [113]
        )
      spids: [108 112]
    )
    (FuncDef
      name: mk_test_with_hooks
      body: 
        (BraceGroup
          children: [
            (Assignment
              keyword: Assign_None
              pairs: [
                (assign_pair
                  lhs: (LhsName name:repo_name)
                  op: Equal
                  rhs: {($ VSub_Number '$1')}
                  spids: [264]
                )
              ]
              spids: [264]
            )
            (AndOr
              children: [
                (C {(mk_test)} {(DQ ($ VSub_At '$@'))})
                (Subshell
                  child: 
                    (AndOr
                      children: [
                        (C {(cd)} {(DQ ($ VSub_Name '$repo_name'))})
                        (AndOr
                          children: [
                            (C {(mkdir)} {(.git/hooks)})
                            (AndOr
                              children: [
                                (C {(cd)} {(.git/hooks)})
                                (AndOr
                                  children: [
                                    (SimpleCommand
                                      words: [{(cat)}]
                                      redirects: [
                                        (Redir
                                          op_id: Redir_Great
                                          fd: -1
                                          arg_word: {(pre-receive)}
                                          spids: [306]
                                        )
                                        (HereDoc
                                          op_id: Redir_DLessDash
                                          fd: -1
                                          body: {('#!/bin/sh\n') ('cat - >>pre-receive.actual\n')}
                                          do_expansion: False
                                          here_end: EOF
                                          was_filled: True
                                          spids: [309]
                                        )
                                      ]
                                    )
                                    (AndOr
                                      children: [
                                        (SimpleCommand
                                          words: [{(cat)}]
                                          redirects: [
                                            (Redir
                                              op_id: Redir_Great
                                              fd: -1
                                              arg_word: {(update)}
                                              spids: [320]
                                            )
                                            (HereDoc
                                              op_id: Redir_DLessDash
                                              fd: -1
                                              body: 
                                                {('#!/bin/sh\n') 
                                                  ('printf "%s %s %s\\n" "$@" >>update.actual\n')
                                                }
                                              do_expansion: False
                                              here_end: EOF
                                              was_filled: True
                                              spids: [323]
                                            )
                                          ]
                                        )
                                        (AndOr
                                          children: [
                                            (SimpleCommand
                                              words: [{(cat)}]
                                              redirects: [
                                                (Redir
                                                  op_id: Redir_Great
                                                  fd: -1
                                                  arg_word: {(post-receive)}
                                                  spids: [334]
                                                )
                                                (HereDoc
                                                  op_id: Redir_DLessDash
                                                  fd: -1
                                                  body: 
                                                    {('#!/bin/sh\n') 
                                                      ('cat - >>post-receive.actual\n')
                                                    }
                                                  do_expansion: False
                                                  here_end: EOF
                                                  was_filled: True
                                                  spids: [337]
                                                )
                                              ]
                                            )
                                            (AndOr
                                              children: [
                                                (SimpleCommand
                                                  words: [{(cat)}]
                                                  redirects: [
                                                    (Redir
                                                      op_id: Redir_Great
                                                      fd: -1
                                                      arg_word: {(post-update)}
                                                      spids: [348]
                                                    )
                                                    (HereDoc
                                                      op_id: Redir_DLessDash
                                                      fd: -1
                                                      body: 
                                                        {('#!/bin/sh\n') ('for ref in "$@"\n') 
                                                          ('do\n') ('printf "%s\\n" "$ref" >>post-update.actual\n') ('done\n')
                                                        }
                                                      do_expansion: False
                                                      here_end: EOF
                                                      was_filled: True
                                                      spids: [351]
                                                    )
                                                  ]
                                                )
                                                (C {(chmod)} {(Lit_Other '+') (x)} {(pre-receive)} 
                                                  {(update)} {(post-receive)} {(post-update)}
                                                )
                                              ]
                                              op_id: Op_DAmp
                                            )
                                          ]
                                          op_id: Op_DAmp
                                        )
                                      ]
                                      op_id: Op_DAmp
                                    )
                                  ]
                                  op_id: Op_DAmp
                                )
                              ]
                              op_id: Op_DAmp
                            )
                          ]
                          op_id: Op_DAmp
                        )
                      ]
                      op_id: Op_DAmp
                    )
                  spids: [277 374]
                )
              ]
              op_id: Op_DAmp
            )
          ]
          spids: [261]
        )
      spids: [257 260]
    )
    (FuncDef
      name: mk_child
      body: 
        (BraceGroup
          children: [
            (AndOr
              children: [
                (C {(rm)} {(-rf)} {(DQ ($ VSub_Number '$2'))})
                (C {(git)} {(clone)} {(DQ ($ VSub_Number '$1'))} {(DQ ($ VSub_Number '$2'))})
              ]
              op_id: Op_DAmp
            )
          ]
          spids: [383]
        )
      spids: [379 382]
    )
    (FuncDef
      name: check_push_result
      body: 
        (BraceGroup
          children: [
            (Assignment
              keyword: Assign_None
              pairs: [
                (assign_pair
                  lhs: (LhsName name:repo_name)
                  op: Equal
                  rhs: {(DQ ($ VSub_Number '$1'))}
                  spids: [420]
                )
              ]
              spids: [420]
            )
            (C {(shift)})
            (Subshell
              child: 
                (AndOr
                  children: [
                    (C {(cd)} {(DQ ($ VSub_Name '$repo_name'))})
                    (AndOr
                      children: [
                        (SimpleCommand
                          words: [{(echo)} {(DQ ($ VSub_Number '$1'))}]
                          redirects: [(Redir op_id:Redir_Great fd:-1 arg_word:{(expect)} spids:[448])]
                        )
                        (AndOr
                          children: [
                            (C {(shift)})
                            (AndOr
                              children: [
                                (ForEach
                                  iter_name: ref
                                  iter_words: [{(DQ ($ VSub_At '$@'))}]
                                  do_arg_iter: False
                                  body: 
                                    (DoGroup
                                      children: [
                                        (AndOr
                                          children: [
                                            (SimpleCommand
                                              words: [
                                                {(git)}
                                                {(show-ref)}
                                                {(-s)}
                                                {(--verify)}
                                                {(refs/) ($ VSub_Name '$ref')}
                                              ]
                                              redirects: [
                                                (Redir
                                                  op_id: Redir_Great
                                                  fd: -1
                                                  arg_word: {(actual)}
                                                  spids: [484]
                                                )
                                              ]
                                            )
                                            (AndOr
                                              children: [
                                                (C {(test_cmp)} {(expect)} {(actual)})
                                                (C {(exit)})
                                              ]
                                              op_id: Op_DPipe
                                            )
                                          ]
                                          op_id: Op_DAmp
                                        )
                                      ]
                                      spids: [470 502]
                                    )
                                  spids: [464 -1]
                                )
                                (C {(git)} {(fsck)} {(--full)})
                              ]
                              op_id: Op_DAmp
                            )
                          ]
                          op_id: Op_DAmp
                        )
                      ]
                      op_id: Op_DAmp
                    )
                  ]
                  op_id: Op_DAmp
                )
              spids: [430 514]
            )
          ]
          spids: [417]
        )
      spids: [412 416]
    )
    (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'>
        )
      }
    )
    (ForEach
      iter_name: configsection
      iter_words: [{(transfer)} {(receive)}]
      do_arg_iter: False
      body: 
        (DoGroup
          children: [
            (C {(test_expect_success)} 
              {(DQ ('push to update a ref hidden by ') ($ VSub_Name '$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'>
                )
              }
            )
          ]
          spids: [2028 2065]
        )
      spids: [2023 -1]
    )
    (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'>
        )
      }
    )
    (ForEach
      iter_name: configallowtipsha1inwant
      iter_words: [{(true)} {(false)}]
      do_arg_iter: False
      body: 
        (DoGroup
          children: [
            (C {(test_expect_success)} 
              {
                (DQ ('shallow fetch reachable SHA1 (but not a ref), allowtipsha1inwant=') 
                  ($ VSub_Name '$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=') 
                  ($ VSub_Name '$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'>
                )
              }
            )
          ]
          spids: [2127 2202]
        )
      spids: [2122 -1]
    )
    (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)})
  ]
)