Merge branch 'jk/stop-pack-objects-when-fetch-is-killed'

"git fetch" that is killed may leave a pack-objects process behind,
still computing to find a good compression, wasting cycles.  This
has been corrected.

* jk/stop-pack-objects-when-fetch-is-killed:
  upload-pack: kill pack-objects helper on signal or exit
diff --git a/.github/workflows/check-whitespace.yml b/.github/workflows/check-whitespace.yml
new file mode 100644
index 0000000..f148305
--- /dev/null
+++ b/.github/workflows/check-whitespace.yml
@@ -0,0 +1,71 @@
+name: check-whitespace
+
+# Get the repo with the commits(+1) in the series.
+# Process `git log --check` output to extract just the check errors.
+# Add a comment to the pull request with the check errors.
+
+on:
+  pull_request:
+    types: [opened, synchronize]
+
+jobs:
+  check-whitespace:
+    runs-on: ubuntu-latest
+    steps:
+    - name: Set commit count
+      shell: bash
+      run: echo "COMMIT_DEPTH=$((1+$COMMITS))" >>$GITHUB_ENV
+      env:
+        COMMITS: ${{ github.event.pull_request.commits }}
+
+    - uses: actions/checkout@v2
+      with:
+        fetch-depth: ${{ env.COMMIT_DEPTH }}
+
+    - name: git log --check
+      id: check_out
+      run: |
+        log=
+        commit=
+        while read dash etc
+        do
+          case "${dash}" in
+          "---")
+            commit="${etc}"
+            ;;
+          "")
+            ;;
+          *)
+            if test -n "${commit}"
+            then
+              log="${log}\n${commit}"
+              echo ""
+              echo "--- ${commit}"
+            fi
+            commit=
+            log="${log}\n${dash} ${etc}"
+            echo "${dash} ${etc}"
+            ;;
+          esac
+        done <<< $(git log --check --pretty=format:"---% h% s" -${{github.event.pull_request.commits}})
+
+        if test -n "${log}"
+        then
+          echo "::set-output name=checkout::"${log}""
+          exit 2
+        fi
+
+    - name: Add Check Output as Comment
+      uses: actions/github-script@v3
+      id: add-comment
+      env:
+        log: ${{ steps.check_out.outputs.checkout }}
+      with:
+        script: |
+            await github.issues.createComment({
+              issue_number: context.issue.number,
+              owner: context.repo.owner,
+              repo: context.repo.repo,
+              body: `Whitespace errors found in workflow ${{ github.workflow }}:\n\n\`\`\`\n${process.env.log.replace(/\\n/g, "\n")}\n\`\`\``
+            })
+      if: ${{ failure() }}
diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml
index a940997..6c3453a 100644
--- a/.github/workflows/main.yml
+++ b/.github/workflows/main.yml
@@ -41,35 +41,39 @@
         with:
           github-token: ${{secrets.GITHUB_TOKEN}}
           script: |
-            // Figure out workflow ID, commit and tree
-            const { data: run } = await github.actions.getWorkflowRun({
-              owner: context.repo.owner,
-              repo: context.repo.repo,
-              run_id: context.runId,
-            });
-            const workflow_id = run.workflow_id;
-            const head_sha = run.head_sha;
-            const tree_id = run.head_commit.tree_id;
+            try {
+              // Figure out workflow ID, commit and tree
+              const { data: run } = await github.actions.getWorkflowRun({
+                owner: context.repo.owner,
+                repo: context.repo.repo,
+                run_id: context.runId,
+              });
+              const workflow_id = run.workflow_id;
+              const head_sha = run.head_sha;
+              const tree_id = run.head_commit.tree_id;
 
-            // See whether there is a successful run for that commit or tree
-            const { data: runs } = await github.actions.listWorkflowRuns({
-              owner: context.repo.owner,
-              repo: context.repo.repo,
-              per_page: 500,
-              status: 'success',
-              workflow_id,
-            });
-            for (const run of runs.workflow_runs) {
-              if (head_sha === run.head_sha) {
-                core.warning(`Successful run for the commit ${head_sha}: ${run.html_url}`);
-                core.setOutput('enabled', ' but skip');
-                break;
+              // See whether there is a successful run for that commit or tree
+              const { data: runs } = await github.actions.listWorkflowRuns({
+                owner: context.repo.owner,
+                repo: context.repo.repo,
+                per_page: 500,
+                status: 'success',
+                workflow_id,
+              });
+              for (const run of runs.workflow_runs) {
+                if (head_sha === run.head_sha) {
+                  core.warning(`Successful run for the commit ${head_sha}: ${run.html_url}`);
+                  core.setOutput('enabled', ' but skip');
+                  break;
+                }
+                if (run.head_commit && tree_id === run.head_commit.tree_id) {
+                  core.warning(`Successful run for the tree ${tree_id}: ${run.html_url}`);
+                  core.setOutput('enabled', ' but skip');
+                  break;
+                }
               }
-              if (tree_id === run.head_commit.tree_id) {
-                core.warning(`Successful run for the tree ${tree_id}: ${run.html_url}`);
-                core.setOutput('enabled', ' but skip');
-                break;
-              }
+            } catch (e) {
+              core.warning(e);
             }
 
   windows-build:
diff --git a/.gitignore b/.gitignore
index 6232d33..f22b7a4 100644
--- a/.gitignore
+++ b/.gitignore
@@ -67,6 +67,7 @@
 /git-filter-branch
 /git-fmt-merge-msg
 /git-for-each-ref
+/git-for-each-repo
 /git-format-patch
 /git-fsck
 /git-fsck-objects
@@ -114,7 +115,6 @@
 /git-pack-redundant
 /git-pack-objects
 /git-pack-refs
-/git-parse-remote
 /git-patch-id
 /git-prune
 /git-prune-packed
diff --git a/Documentation/MyFirstContribution.txt b/Documentation/MyFirstContribution.txt
index 4f85a08..7c9a037 100644
--- a/Documentation/MyFirstContribution.txt
+++ b/Documentation/MyFirstContribution.txt
@@ -249,7 +249,7 @@
 the body of your commit message, which should provide the bulk of the context.
 Remember to be explicit and provide the "Why" of your change, especially if it
 couldn't easily be understood from your diff. When editing your commit message,
-don't remove the Signed-off-by line which was added by `-s` above.
+don't remove the `Signed-off-by` trailer which was added by `-s` above.
 
 ----
 psuh: add a built-in by popular demand
@@ -507,6 +507,9 @@
 easier for your user, who can skip to the section they know contains the
 information they need.
 
+NOTE: Before trying to build the docs, make sure you have the package `asciidoc`
+installed.
+
 Now that you've written your manpage, you'll need to build it explicitly. We
 convert your AsciiDoc to troff which is man-readable like so:
 
@@ -522,8 +525,6 @@
 $ man Documentation/git-psuh.1
 ----
 
-NOTE: You may need to install the package `asciidoc` to get this to work.
-
 While this isn't as satisfying as running through `git help`, you can at least
 check that your help page looks right.
 
@@ -1142,11 +1143,25 @@
 comments. Woohoo! Now you can get back to work.
 
 It's good manners to reply to each comment, notifying the reviewer that you have
-made the change requested, feel the original is better, or that the comment
+made the change suggested, feel the original is better, or that the comment
 inspired you to do something a new way which is superior to both the original
 and the suggested change. This way reviewers don't need to inspect your v2 to
 figure out whether you implemented their comment or not.
 
+Reviewers may ask you about what you wrote in the patchset, either in
+the proposed commit log message or in the changes themselves.  You
+should answer these questions in your response messages, but often the
+reason why reviewers asked these questions to understand what you meant
+to write is because your patchset needed clarification to be understood.
+
+Do not be satisfied by just answering their questions in your response
+and hear them say that they now understand what you wanted to say.
+Update your patches to clarify the points reviewers had trouble with,
+and prepare your v2; the words you used to explain your v1 to answer
+reviewers' questions may be useful thing to use.  Your goal is to make
+your v2 clear enough so that it becomes unnecessary for you to give the
+same explanation to the next person who reads it.
+
 If you are going to push back on a comment, be polite and explain why you feel
 your original is better; be prepared that the reviewer may still disagree with
 you, and the rest of the community may weigh in on one side or the other. As
diff --git a/Documentation/RelNotes/2.30.0.txt b/Documentation/RelNotes/2.30.0.txt
new file mode 100644
index 0000000..c089275
--- /dev/null
+++ b/Documentation/RelNotes/2.30.0.txt
@@ -0,0 +1,309 @@
+Git 2.30 Release Notes
+======================
+
+Updates since v2.29
+-------------------
+
+UI, Workflows & Features
+
+ * Userdiff for PHP update.
+
+ * Userdiff for Rust update.
+
+ * Userdiff for CSS update.
+
+ * The command line completion script (in contrib/) learned that "git
+   stash show" takes the options "git diff" takes.
+
+ * "git worktree list" now shows if each worktree is locked.  This
+   possibly may open us to show other kinds of states in the future.
+
+ * "git maintenance", an extended big brother of "git gc", continues
+   to evolve.
+
+ * "git push --force-with-lease[=<ref>]" can easily be misused to lose
+   commits unless the user takes good care of their own "git fetch".
+   A new option "--force-if-includes" attempts to ensure that what is
+   being force-pushed was created after examining the commit at the
+   tip of the remote ref that is about to be force-replaced.
+
+ * "git clone" learned clone.defaultremotename configuration variable
+   to customize what nickname to use to call the remote the repository
+   was cloned from.
+
+ * "git checkout" learned to use checkout.guess configuration variable
+   and enable/disable its "--[no-]guess" option accordingly.
+
+ * "git resurrect" script (in contrib/) learned that the object names
+   may be longer than 40-hex depending on the hash function in use.
+
+ * "git diff A...B" learned "git diff --merge-base A B", which is a
+   longer short-hand to say the same thing.
+
+ * A sample 'push-to-checkout' hook, that performs the same as
+   what the built-in default action does, has been added.
+
+ * "git diff" family of commands learned the "-I<regex>" option to
+   ignore hunks whose changed lines all match the given pattern.
+
+ * The userdiff pattern learned to identify the function definition in
+   POSIX shells and bash.
+
+ * "git checkout-index" did not consistently signal an error with its
+   exit status, but now it does.
+
+ * A commit and tag object may have CR at the end of each and
+   every line (you can create such an object with hash-object or
+   using --cleanup=verbatim to decline the default clean-up
+   action), but it would make it impossible to have a blank line
+   to separate the title from the body of the message.  We are now
+   more lenient and accept a line with lone CR on it as a blank line,
+   too.
+
+ * Exit codes from "git remote add" etc. were not usable by scripted
+   callers, but now they are.
+
+ * "git archive" now allows compression level higher than "-9"
+   when generating tar.gz output.
+
+ * Zsh autocompletion (in contrib/) update.
+
+ * The maximum length of output filenames "git format-patch" creates
+   has become configurable (used to be capped at 64).
+
+ * "git rev-parse" learned the "--end-of-options" to help scripts to
+   safely take a parameter that is supposed to be a revision, e.g.
+   "git rev-parse --verify -q --end-of-options $rev".
+
+ * The command line completion script (in contrib/) learned to expand
+   commands that are alias of alias.
+
+
+Performance, Internal Implementation, Development Support etc.
+
+ * Use "git archive" more to produce the release tarball.
+
+ * GitHub Actions automated test improvement to skip tests on a tree
+   identical to what has already been tested.
+
+ * Test-coverage for running commit-graph task "git maintenance" has
+   been extended.
+
+ * Our test scripts can be told to run only individual pieces while
+   skipping others with the "--run=..." option; they were taught to
+   take a substring of test title, in addition to numbers, to name the
+   test pieces to run.
+
+ * Adjust tests so that they won't scream when the default initial
+   branch name is changed to 'main'.
+
+ * Rewriting "git bisect" in C continues.
+
+ * More preliminary tests have been added to document desired outcome
+   of various "directory rename" situations.
+
+ * Micro clean-up of a couple of test scripts.
+
+ * "git diff" and other commands that share the same machinery to
+   compare with working tree files have been taught to take advantage
+   of the fsmonitor data when available.
+
+ * The code to detect premature EOF in the sideband demultiplexer has
+   been cleaned up.
+
+ * Test scripts are being prepared to transition of the default branch
+   name to 'main'.
+
+ * "git fetch --depth=<n>" over the stateless RPC / smart HTTP
+   transport handled EOF from the client poorly at the server end.
+
+ * A specialization of hashmap that uses a string as key has been
+   introduced.  Hopefully it will see wider use over time.
+
+ * "git bisect start/next" in a large span of history spends a lot of
+   time trying to come up with exactly the half-way point; this can be
+   optimized by stopping when we see a commit that is close enough to
+   the half-way point.
+
+ * A lazily defined test prerequisite can now be defined in terms of
+   another lazily defined test prerequisite.
+
+ * Expectation for the original contributor after responding to a
+   review comment to use the explanation in a patch update has been
+   described.
+
+ * Multiple "credential-store" backends can race to lock the same
+   file, causing everybody else but one to fail---reattempt locking
+   with some timeout to reduce the rate of the failure.
+
+
+Fixes since v2.29
+-----------------
+
+ * In 2.29, "--committer-date-is-author-date" option of "rebase" and
+   "am" subcommands lost the e-mail address by mistake, which has been
+   corrected.
+   (merge 5f35edd9d7 jk/committer-date-is-author-date-fix later to maint).
+
+ * "git checkout -p A...B [-- <path>]" did not work, even though the
+   same command without "-p" correctly used the merge-base between
+   commits A and B.
+   (merge 35166b1fb5 dl/checkout-p-merge-base later to maint).
+
+ * The side-band status report can be sent at the same time as the
+   primary payload multiplexed, but the demultiplexer on the receiving
+   end incorrectly split a single status report into two, which has
+   been corrected.
+   (merge 712b0377db js/avoid-split-sideband-message later to maint).
+
+ * "git fast-import" wasted a lot of memory when many marks were in use.
+   (merge 3f018ec716 jk/fast-import-marks-alloc-fix later to maint).
+
+ * A test helper "test_cmp A B" was taught to diagnose missing files A
+   or B as a bug in test, but some tests legitimately wanted to notice
+   a failure to even create file B as an error, in addition to leaving
+   the expected result in it, and were misdiagnosed as a bug.  This
+   has been corrected.
+   (merge 262d5ad5a5 es/test-cmp-typocatcher later to maint).
+
+ * When "git commit-graph" detects the same commit recorded more than
+   once while it is merging the layers, it used to die.  The code now
+   ignores all but one of them and continues.
+   (merge 85102ac71b ds/commit-graph-merging-fix later to maint).
+
+ * The meaning of a Signed-off-by trailer can vary from project to
+   project; this and also what it means to this project has been
+   clarified in the documentation.
+   (merge 3abd4a67d9 bk/sob-dco later to maint).
+
+ * "git credential' didn't honor the core.askPass configuration
+   variable (among other things), which has been corrected.
+   (merge 567ad2c0f9 tk/credential-config later to maint).
+
+ * Dev support to catch a tentative definition of a variable in our C
+   code as an error.
+   (merge 5539183622 jk/no-common later to maint).
+
+ * "git rebase --rebase-merges" did not correctly pass --gpg-sign
+   command line option to underlying "git merge" when replaying a merge
+   using non-default merge strategy or when replaying an octopus merge
+   (because replaying a two-head merge with the default strategy was
+   done in a separate codepath, the problem did not trigger for most
+   users), which has been corrected.
+   (merge 43ad4f2eca sc/sequencer-gpg-octopus later to maint).
+
+ * "git apply -R" did not handle patches that touch the same path
+   twice correctly, which has been corrected.  This is most relevant
+   in a patch that changes a path from a regular file to a symbolic
+   link (and vice versa).
+   (merge b0f266de11 jt/apply-reverse-twice later to maint).
+
+ * A recent oid->hash conversion missed one spot, breaking "git svn".
+   (merge 03bb366de4 bc/svn-hash-oid-fix later to maint).
+
+ * The documentation on the "--abbrev=<n>" option did not say the
+   output may be longer than "<n>" hexdigits, which has been
+   clarified.
+   (merge cda34e0d0c jc/abbrev-doc later to maint).
+
+ * "git p4" now honors init.defaultBranch configuration.
+   (merge 1b09d1917f js/p4-default-branch later to maint).
+
+ * Recently the format of an internal state file "rebase -i" uses has
+   been tightened up for consistency, which would hurt those who start
+   "rebase -i" with old git and then continue with new git.  Loosen
+   the reader side a bit (which we may want to tighten again in a year
+   or so).
+   (merge c779386182 jc/sequencer-stopped-sha-simplify later to maint).
+
+ * The code to see if "git stash drop" can safely remove refs/stash
+   has been made more carerful.
+   (merge 4f44c5659b rs/empty-reflog-check-fix later to maint).
+
+ * "git log -L<range>:<path>" is documented to take no pathspec, but
+   this was not enforced by the command line option parser, which has
+   been corrected.
+   (merge 39664cb0ac jc/line-log-takes-no-pathspec later to maint).
+
+ * "git format-patch --output=there" did not work as expected and
+   instead crashed.  The option is now supported.
+   (merge dc1672dd10 jk/format-patch-output later to maint).
+
+ * Define ARM64 compiled with MSVC to be little-endian.
+   (merge 0c038fc65a dg/bswap-msvc later to maint).
+
+ * "git rebase -i" did not store ORIG_HEAD correctly.
+   (merge 8843302307 pw/rebase-i-orig-head later to maint).
+
+ * "git blame -L :funcname -- path" did not work well for a path for
+   which a userdiff driver is defined.
+
+ * "make DEVELOPER=1 sparse" used to run sparse and let it emit
+   warnings; now such warnings will cause an error.
+   (merge 521dc56270 jc/sparse-error-for-developer-build later to maint).
+
+ * "git blame --ignore-revs-file=<file>" learned to ignore a
+   non-existent object name in the input, instead of complaining.
+   (merge c714d05875 jc/blame-ignore-fix later to maint).
+
+ * Running "git diff" while allowing external diff in a state with
+   unmerged paths used to segfault, which has been corrected.
+   (merge d66851806f jk/diff-release-filespec-fix later to maint).
+
+ * Build configuration cleanup.
+   (merge b990f02fd8 ab/config-mak-uname-simplify later to maint).
+
+ * Fix regression introduced when nvimdiff support in mergetool was added.
+   (merge 12026f46e7 pd/mergetool-nvimdiff later to maint).
+
+ * The exchange between receive-pack and proc-receive hook did not
+   carefully check for errors.
+
+ * The code was not prepared to deal with pack .idx file that is
+   larger than 4GB.
+   (merge 81c4c5cf2e jk/4gb-idx later to maint).
+
+ * "git fetch" did not work correctly with nested submodules where the
+   innermost submodule that is not of interest got updated in the
+   upstream, which has been corrected.
+   (merge 1b7ac4e6d4 pk/subsub-fetch-fix later to maint).
+
+ * Since jgit does not yet work with SHA-256 repositories, mark the
+   tests that uses it not to run unless we are testing with ShA-1
+   repositories.
+   (merge ea699b4adc sg/t5310-jgit-wants-sha1 later to maint).
+
+ * Config parser fix for "git notes".
+   (merge 45fef1599a na/notes-displayref-is-not-boolean later to maint).
+
+ * Move a definition of compatibility wrapper from cache.h to
+   git-compat-util.h
+   (merge a76b138daa hn/sleep-millisec-decl later to maint).
+
+ * Error message fix.
+   (merge eaf5341538 km/stash-error-message-fix later to maint).
+
+ * Other code cleanup, docfix, build fix, etc.
+   (merge 3e0a5dc9af cc/doc-filter-branch-typofix later to maint).
+   (merge 32c83afc2c cw/ci-ghwf-check-ws-errors later to maint).
+   (merge 5eb2ed691b rs/tighten-callers-of-deref-tag later to maint).
+   (merge 6db29ab213 jk/fast-import-marks-cleanup later to maint).
+   (merge e5cf6d3df4 nk/dir-c-comment-update later to maint).
+   (merge 5710dcce74 jk/report-fn-typedef later to maint).
+   (merge 9a82db1056 en/sequencer-rollback-lock-cleanup later to maint).
+   (merge 4e1bee9a99 js/t7006-cleanup later to maint).
+   (merge f5bcde6c58 es/tutorial-mention-asciidoc-early later to maint).
+   (merge 714d491af0 so/format-patch-doc-on-default-diff-format later to maint).
+   (merge 0795df4b9b rs/clear-commit-marks-in-repo later to maint).
+   (merge 9542d56379 sd/prompt-local-variable later to maint).
+   (merge 06d43fad18 rs/pack-write-hashwrite-simplify later to maint).
+   (merge b7e20b4373 mc/typofix later to maint).
+   (merge f6bcd9a8a4 js/test-whitespace-fixes later to maint).
+   (merge 53b67a801b js/test-file-size later to maint).
+   (merge 970909c2a7 rs/hashwrite-be64 later to maint).
+   (merge 5a923bb1f0 ma/list-object-filter-opt-msgfix later to maint).
+   (merge 1c3e412916 rs/archive-plug-leak-refname later to maint).
+   (merge d44e5267ea rs/plug-diff-cache-leak later to maint).
+   (merge 793c1464d3 ab/gc-keep-base-option later to maint).
+   (merge b86339b12b mt/worktree-error-message-fix later to maint).
+   (merge e01ae2a4a7 js/pull-rebase-use-advise later to maint).
diff --git a/Documentation/SubmittingPatches b/Documentation/SubmittingPatches
index 291b61e..d12094b 100644
--- a/Documentation/SubmittingPatches
+++ b/Documentation/SubmittingPatches
@@ -209,7 +209,7 @@
 (see below), the first patch, or the respective preceding patch.
 
 If your log message (including your name on the
-Signed-off-by line) is not writable in ASCII, make sure that
+`Signed-off-by` trailer) is not writable in ASCII, make sure that
 you send off a message in the correct encoding.
 
 WARNING: Be wary of your MUAs word-wrap
@@ -229,7 +229,7 @@
 The `git format-patch` command follows the best current practice to
 format the body of an e-mail message.  At the beginning of the
 patch should come your commit message, ending with the
-Signed-off-by: lines, and a line that consists of three dashes,
+`Signed-off-by` trailers, and a line that consists of three dashes,
 followed by the diffstat information and the patch itself.  If
 you are forwarding a patch from somebody else, optionally, at
 the beginning of the e-mail message just before the commit
@@ -290,25 +290,24 @@
 :git-ml: footnote:[The mailing list: git@vger.kernel.org]
 
 After the list reached a consensus that it is a good idea to apply the
-patch, re-send it with "To:" set to the maintainer{current-maintainer} and "cc:" the
-list{git-ml} for inclusion.
+patch, re-send it with "To:" set to the maintainer{current-maintainer}
+and "cc:" the list{git-ml} for inclusion.  This is especially relevant
+when the maintainer did not heavily participate in the discussion and
+instead left the review to trusted others.
 
 Do not forget to add trailers such as `Acked-by:`, `Reviewed-by:` and
 `Tested-by:` lines as necessary to credit people who helped your
-patch.
+patch, and "cc:" them when sending such a final version for inclusion.
 
 [[sign-off]]
-=== Certify your work by adding your "Signed-off-by: " line
+=== Certify your work by adding your `Signed-off-by` trailer
 
-To improve tracking of who did what, we've borrowed the
-"sign-off" procedure from the Linux kernel project on patches
-that are being emailed around.  Although core Git is a lot
-smaller project it is a good discipline to follow it.
+To improve tracking of who did what, we ask you to certify that you
+wrote the patch or have the right to pass it on under the same license
+as ours, by "signing off" your patch.  Without sign-off, we cannot
+accept your patches.
 
-The sign-off is a simple line at the end of the explanation for
-the patch, which certifies that you wrote it or otherwise have
-the right to pass it on as an open-source patch.  The rules are
-pretty simple: if you can certify the below D-C-O:
+If you can certify the below D-C-O:
 
 [[dco]]
 .Developer's Certificate of Origin 1.1
@@ -338,23 +337,29 @@
    this project or the open source license(s) involved.
 ____
 
-then you just add a line saying
+you add a "Signed-off-by" trailer to your commit, that looks like
+this:
 
 ....
 	Signed-off-by: Random J Developer <random@developer.example.org>
 ....
 
-This line can be automatically added by Git if you run the git-commit
-command with the -s option.
+This line can be added by Git if you run the git-commit command with
+the -s option.
 
-Notice that you can place your own Signed-off-by: line when
+Notice that you can place your own `Signed-off-by` trailer when
 forwarding somebody else's patch with the above rules for
 D-C-O.  Indeed you are encouraged to do so.  Do not forget to
 place an in-body "From: " line at the beginning to properly attribute
 the change to its true author (see (2) above).
 
+This procedure originally came from the Linux kernel project, so our
+rule is quite similar to theirs, but what exactly it means to sign-off
+your patch differs from project to project, so it may be different
+from that of the project you are accustomed to.
+
 [[real-name]]
-Also notice that a real name is used in the Signed-off-by: line. Please
+Also notice that a real name is used in the `Signed-off-by` trailer. Please
 don't hide your real name.
 
 [[commit-trailers]]
diff --git a/Documentation/blame-options.txt b/Documentation/blame-options.txt
index 88750af..dc3bceb 100644
--- a/Documentation/blame-options.txt
+++ b/Documentation/blame-options.txt
@@ -11,11 +11,12 @@
 
 -L <start>,<end>::
 -L :<funcname>::
-	Annotate only the given line range. May be specified multiple times.
-	Overlapping ranges are allowed.
+	Annotate only the line range given by '<start>,<end>',
+	or by the function name regex '<funcname>'.
+	May be specified multiple times. Overlapping ranges are allowed.
 +
-<start> and <end> are optional. ``-L <start>'' or ``-L <start>,'' spans from
-<start> to end of file. ``-L ,<end>'' spans from start of file to <end>.
+'<start>' and '<end>' are optional. `-L <start>` or `-L <start>,` spans from
+'<start>' to end of file. `-L ,<end>` spans from start of file to '<end>'.
 +
 include::line-range-format.txt[]
 
diff --git a/Documentation/config.txt b/Documentation/config.txt
index bf706b9..f292c26 100644
--- a/Documentation/config.txt
+++ b/Documentation/config.txt
@@ -265,7 +265,7 @@
 The basic colors accepted are `normal`, `black`, `red`, `green`, `yellow`,
 `blue`, `magenta`, `cyan` and `white`.  The first color given is the
 foreground; the second is the background.  All the basic colors except
-`normal` have a bright variant that can be speficied by prefixing the
+`normal` have a bright variant that can be specified by prefixing the
 color with `bright`, like `brightred`.
 +
 Colors may also be given as numbers between 0 and 255; these use ANSI
@@ -334,6 +334,8 @@
 
 include::config/clean.txt[]
 
+include::config/clone.txt[]
+
 include::config/color.txt[]
 
 include::config/column.txt[]
diff --git a/Documentation/config/advice.txt b/Documentation/config/advice.txt
index bdd37c3..acbd0c0 100644
--- a/Documentation/config/advice.txt
+++ b/Documentation/config/advice.txt
@@ -10,9 +10,8 @@
 		that the check is disabled.
 	pushUpdateRejected::
 		Set this variable to 'false' if you want to disable
-		'pushNonFFCurrent',
-		'pushNonFFMatching', 'pushAlreadyExists',
-		'pushFetchFirst', and 'pushNeedsForce'
+		'pushNonFFCurrent', 'pushNonFFMatching', 'pushAlreadyExists',
+		'pushFetchFirst', 'pushNeedsForce', and 'pushRefNeedsUpdate'
 		simultaneously.
 	pushNonFFCurrent::
 		Advice shown when linkgit:git-push[1] fails due to a
@@ -41,6 +40,10 @@
 		we can still suggest that the user push to either
 		refs/heads/* or refs/tags/* based on the type of the
 		source object.
+	pushRefNeedsUpdate::
+		Shown when linkgit:git-push[1] rejects a forced update of
+		a branch when its remote-tracking ref has updates that we
+		do not have locally.
 	statusAheadBehind::
 		Shown when linkgit:git-status[1] computes the ahead/behind
 		counts for a local ref compared to its remote tracking ref,
diff --git a/Documentation/config/checkout.txt b/Documentation/config/checkout.txt
index 6b64681..2cddf7b 100644
--- a/Documentation/config/checkout.txt
+++ b/Documentation/config/checkout.txt
@@ -1,18 +1,23 @@
 checkout.defaultRemote::
-	When you run 'git checkout <something>'
-	or 'git switch <something>' and only have one
+	When you run `git checkout <something>`
+	or `git switch <something>` and only have one
 	remote, it may implicitly fall back on checking out and
-	tracking e.g. 'origin/<something>'. This stops working as soon
-	as you have more than one remote with a '<something>'
+	tracking e.g. `origin/<something>`. This stops working as soon
+	as you have more than one remote with a `<something>`
 	reference. This setting allows for setting the name of a
 	preferred remote that should always win when it comes to
 	disambiguation. The typical use-case is to set this to
 	`origin`.
 +
 Currently this is used by linkgit:git-switch[1] and
-linkgit:git-checkout[1] when 'git checkout <something>'
-or 'git switch <something>'
-will checkout the '<something>' branch on another remote,
-and by linkgit:git-worktree[1] when 'git worktree add' refers to a
+linkgit:git-checkout[1] when `git checkout <something>`
+or `git switch <something>`
+will checkout the `<something>` branch on another remote,
+and by linkgit:git-worktree[1] when `git worktree add` refers to a
 remote branch. This setting might be used for other checkout-like
 commands or functionality in the future.
+
+checkout.guess::
+	Provides the default value for the `--guess` or `--no-guess`
+	option in `git checkout` and `git switch`. See
+	linkgit:git-switch[1] and linkgit:git-checkout[1].
diff --git a/Documentation/config/clone.txt b/Documentation/config/clone.txt
new file mode 100644
index 0000000..47de36a
--- /dev/null
+++ b/Documentation/config/clone.txt
@@ -0,0 +1,4 @@
+clone.defaultRemoteName::
+	The name of the remote to create when cloning a repository.  Defaults to
+	`origin`, and can be overridden by passing the `--origin` command-line
+	option to linkgit:git-clone[1].
diff --git a/Documentation/config/core.txt b/Documentation/config/core.txt
index 02002cf..160aaca 100644
--- a/Documentation/config/core.txt
+++ b/Documentation/config/core.txt
@@ -606,8 +606,8 @@
 
 core.multiPackIndex::
 	Use the multi-pack-index file to track multiple packfiles using a
-	single index. See link:technical/multi-pack-index.html[the
-	multi-pack-index design document].
+	single index. See linkgit:git-multi-pack-index[1] for more
+	information. Defaults to true.
 
 core.sparseCheckout::
 	Enable "sparse checkout" feature. See linkgit:git-sparse-checkout[1]
diff --git a/Documentation/config/credential.txt b/Documentation/config/credential.txt
index 9d01641..512f318 100644
--- a/Documentation/config/credential.txt
+++ b/Documentation/config/credential.txt
@@ -28,3 +28,9 @@
 
 credentialCache.ignoreSIGHUP::
 	Tell git-credential-cache--daemon to ignore SIGHUP, instead of quitting.
+
+credentialStore.lockTimeoutMS::
+	The length of time, in milliseconds, for git-credential-store to retry
+	when trying to lock the credentials file. Value 0 means not to retry at
+	all; -1 means to try indefinitely. Default is 1000 (i.e., retry for
+	1s).
diff --git a/Documentation/config/format.txt b/Documentation/config/format.txt
index c2efd87..fdbc06a 100644
--- a/Documentation/config/format.txt
+++ b/Documentation/config/format.txt
@@ -79,7 +79,7 @@
 
 format.signOff::
 	A boolean value which lets you enable the `-s/--signoff` option of
-	format-patch by default. *Note:* Adding the Signed-off-by: line to a
+	format-patch by default. *Note:* Adding the `Signed-off-by` trailer to a
 	patch should be a conscious act and means that you certify you have
 	the rights to submit this work under the same open source license.
 	Please see the 'SubmittingPatches' document for further discussion.
@@ -94,6 +94,11 @@
 	Set a custom directory to store the resulting files instead of the
 	current working directory. All directory components will be created.
 
+format.filenameMaxLength::
+	The maximum length of the output filenames generated by the
+	`format-patch` command; defaults to 64.  Can be overridden
+	by the `--filename-max-length=<n>` command line option.
+
 format.useAutoBase::
 	A boolean value which lets you enable the `--base=auto` option of
 	format-patch by default. Can also be set to "whenAble" to allow
diff --git a/Documentation/config/gc.txt b/Documentation/config/gc.txt
index 00ea0a6..c834e07 100644
--- a/Documentation/config/gc.txt
+++ b/Documentation/config/gc.txt
@@ -44,9 +44,9 @@
 
 gc.bigPackThreshold::
 	If non-zero, all packs larger than this limit are kept when
-	`git gc` is run. This is very similar to `--keep-base-pack`
+	`git gc` is run. This is very similar to `--keep-largest-pack`
 	except that all packs that meet the threshold are kept, not
-	just the base pack. Defaults to zero. Common unit suffixes of
+	just the largest pack. Defaults to zero. Common unit suffixes of
 	'k', 'm', or 'g' are supported.
 +
 Note that if the number of kept packs is more than gc.autoPackLimit,
@@ -57,7 +57,7 @@
 If the amount of memory estimated for `git repack` to run smoothly is
 not available and `gc.bigPackThreshold` is not set, the largest pack
 will also be excluded (this is the equivalent of running `git gc` with
-`--keep-base-pack`).
+`--keep-largest-pack`).
 
 gc.writeCommitGraph::
 	If true, then gc will rewrite the commit-graph file when
diff --git a/Documentation/config/maintenance.txt b/Documentation/config/maintenance.txt
index 7cc6700..a5ead09 100644
--- a/Documentation/config/maintenance.txt
+++ b/Documentation/config/maintenance.txt
@@ -1,3 +1,23 @@
+maintenance.auto::
+	This boolean config option controls whether some commands run
+	`git maintenance run --auto` after doing their normal work. Defaults
+	to true.
+
+maintenance.strategy::
+	This string config option provides a way to specify one of a few
+	recommended schedules for background maintenance. This only affects
+	which tasks are run during `git maintenance run --schedule=X`
+	commands, provided no `--task=<task>` arguments are provided.
+	Further, if a `maintenance.<task>.schedule` config value is set,
+	then that value is used instead of the one provided by
+	`maintenance.strategy`. The possible strategy strings are:
++
+* `none`: This default setting implies no task are run at any schedule.
+* `incremental`: This setting optimizes for performing small maintenance
+  activities that do not delete any data. This does not schedule the `gc`
+  task, but runs the `prefetch` and `commit-graph` tasks hourly and the
+  `loose-objects` and `incremental-repack` tasks daily.
+
 maintenance.<task>.enabled::
 	This boolean config option controls whether the maintenance task
 	with name `<task>` is run when no `--task` option is specified to
@@ -5,6 +25,11 @@
 	`--task` option exists. By default, only `maintenance.gc.enabled`
 	is true.
 
+maintenance.<task>.schedule::
+	This config option controls whether or not the given `<task>` runs
+	during a `git maintenance run --schedule=<frequency>` command. The
+	value must be one of "hourly", "daily", or "weekly".
+
 maintenance.commit-graph.auto::
 	This integer config option controls how often the `commit-graph` task
 	should be run as part of `git maintenance run --auto`. If zero, then
@@ -14,3 +39,21 @@
 	reachable commits that are not in the commit-graph file is at least
 	the value of `maintenance.commit-graph.auto`. The default value is
 	100.
+
+maintenance.loose-objects.auto::
+	This integer config option controls how often the `loose-objects` task
+	should be run as part of `git maintenance run --auto`. If zero, then
+	the `loose-objects` task will not run with the `--auto` option. A
+	negative value will force the task to run every time. Otherwise, a
+	positive value implies the command should run when the number of
+	loose objects is at least the value of `maintenance.loose-objects.auto`.
+	The default value is 100.
+
+maintenance.incremental-repack.auto::
+	This integer config option controls how often the `incremental-repack`
+	task should be run as part of `git maintenance run --auto`. If zero,
+	then the `incremental-repack` task will not run with the `--auto`
+	option. A negative value will force the task to run every time.
+	Otherwise, a positive value implies the command should run when the
+	number of pack-files not in the multi-pack-index is at least the value
+	of `maintenance.incremental-repack.auto`. The default value is 10.
diff --git a/Documentation/config/push.txt b/Documentation/config/push.txt
index f5e5b38..21b256e 100644
--- a/Documentation/config/push.txt
+++ b/Documentation/config/push.txt
@@ -114,3 +114,9 @@
 	specifying '--recurse-submodules=check|on-demand|no'.
 	If not set, 'no' is used by default, unless 'submodule.recurse' is
 	set (in which case a 'true' value means 'on-demand').
+
+push.useForceIfIncludes::
+	If set to "true", it is equivalent to specifying
+	`--force-if-includes` as an option to linkgit:git-push[1]
+	in the command line. Adding `--no-force-if-includes` at the
+	time of push overrides this configuration setting.
diff --git a/Documentation/diff-options.txt b/Documentation/diff-options.txt
index 573fb9b..746b144 100644
--- a/Documentation/diff-options.txt
+++ b/Documentation/diff-options.txt
@@ -36,9 +36,9 @@
 -U<n>::
 --unified=<n>::
 	Generate diffs with <n> lines of context instead of
-	the usual three. Implies `--patch`.
+	the usual three.
 ifndef::git-format-patch[]
-	Implies `-p`.
+	Implies `--patch`.
 endif::git-format-patch[]
 
 --output=<file>::
@@ -441,12 +441,16 @@
 
 --binary::
 	In addition to `--full-index`, output a binary diff that
-	can be applied with `git-apply`. Implies `--patch`.
+	can be applied with `git-apply`.
+ifndef::git-format-patch[]
+	Implies `--patch`.
+endif::git-format-patch[]
 
 --abbrev[=<n>]::
 	Instead of showing the full 40-byte hexadecimal object
 	name in diff-raw format output and diff-tree header
-	lines, show only a partial prefix.
+	lines, show the shortest prefix that is at least '<n>'
+	hexdigits long that uniquely refers the object.
 	In diff-patch output format, `--full-index` takes higher
 	precedence, i.e. if `--full-index` is specified, full blob
 	names will be shown regardless of `--abbrev`.
@@ -687,6 +691,11 @@
 --ignore-blank-lines::
 	Ignore changes whose lines are all blank.
 
+-I<regex>::
+--ignore-matching-lines=<regex>::
+	Ignore changes whose all lines match <regex>.  This option may
+	be specified more than once.
+
 --inter-hunk-context=<lines>::
 	Show the context between diff hunks, up to the specified number
 	of lines, thereby fusing hunks that are close to each other.
@@ -695,7 +704,10 @@
 
 -W::
 --function-context::
-	Show whole surrounding functions of changes.
+	Show whole function as context lines for each change.
+	The function names are determined in the same way as
+	`git diff` works out patch hunk headers (see 'Defining a
+	custom hunk-header' in linkgit:gitattributes[5]).
 
 ifndef::git-format-patch[]
 ifndef::git-log[]
diff --git a/Documentation/git-am.txt b/Documentation/git-am.txt
index 38c0852..06bc063 100644
--- a/Documentation/git-am.txt
+++ b/Documentation/git-am.txt
@@ -33,7 +33,7 @@
 
 -s::
 --signoff::
-	Add a `Signed-off-by:` line to the commit message, using
+	Add a `Signed-off-by` trailer to the commit message, using
 	the committer identity of yourself.
 	See the signoff option in linkgit:git-commit[1] for more information.
 
diff --git a/Documentation/git-blame.txt b/Documentation/git-blame.txt
index 7e81541..34b496d 100644
--- a/Documentation/git-blame.txt
+++ b/Documentation/git-blame.txt
@@ -87,7 +87,9 @@
 
 --abbrev=<n>::
 	Instead of using the default 7+1 hexadecimal digits as the
-	abbreviated object name, use <n>+1 digits. Note that 1 column
+	abbreviated object name, use <m>+1 digits, where <m> is at
+	least <n> but ensures the commit object names are unique.
+	Note that 1 column
 	is used for a caret to mark the boundary commit.
 
 
diff --git a/Documentation/git-branch.txt b/Documentation/git-branch.txt
index ace4ad3..adaa178 100644
--- a/Documentation/git-branch.txt
+++ b/Documentation/git-branch.txt
@@ -9,7 +9,7 @@
 --------
 [verse]
 'git branch' [--color[=<when>] | --no-color] [--show-current]
-	[-v [--abbrev=<length> | --no-abbrev]]
+	[-v [--abbrev=<n> | --no-abbrev]]
 	[--column[=<options>] | --no-column] [--sort=<key>]
 	[--merged [<commit>]] [--no-merged [<commit>]]
 	[--contains [<commit>]] [--no-contains [<commit>]]
@@ -194,8 +194,10 @@
 	Be more quiet when creating or deleting a branch, suppressing
 	non-error messages.
 
---abbrev=<length>::
-	Alter the sha1's minimum display length in the output listing.
+--abbrev=<n>::
+	In the verbose listing that show the commit object name,
+	show the shortest prefix that is at least '<n>' hexdigits
+	long that uniquely refers the object.
 	The default value is 7 and can be overridden by the `core.abbrev`
 	config option.
 
diff --git a/Documentation/git-checkout.txt b/Documentation/git-checkout.txt
index afa5c11..b1a6fe4 100644
--- a/Documentation/git-checkout.txt
+++ b/Documentation/git-checkout.txt
@@ -192,7 +192,10 @@
 'origin' remote. See also `checkout.defaultRemote` in
 linkgit:git-config[1].
 +
-Use `--no-guess` to disable this.
+`--guess` is the default behavior. Use `--no-guess` to disable it.
++
+The default behavior can be set via the `checkout.guess` configuration
+variable.
 
 -l::
 	Create the new branch's reflog; see linkgit:git-branch[1] for
@@ -351,6 +354,10 @@
 <tree-ish>::
 	Tree to checkout from (when paths are given). If not specified,
 	the index will be used.
++
+As a special case, you may use `"A...B"` as a shortcut for the
+merge base of `A` and `B` if there is exactly one merge base. You can
+leave out at most one of `A` and `B`, in which case it defaults to `HEAD`.
 
 \--::
 	Do not interpret any more arguments as options.
diff --git a/Documentation/git-cherry-pick.txt b/Documentation/git-cherry-pick.txt
index 75feeef..5d75031 100644
--- a/Documentation/git-cherry-pick.txt
+++ b/Documentation/git-cherry-pick.txt
@@ -104,7 +104,7 @@
 
 -s::
 --signoff::
-	Add Signed-off-by line at the end of the commit message.
+	Add a `Signed-off-by` trailer at the end of the commit message.
 	See the signoff option in linkgit:git-commit[1] for more information.
 
 -S[<keyid>]::
diff --git a/Documentation/git-clone.txt b/Documentation/git-clone.txt
index 097e6a8..876aedc 100644
--- a/Documentation/git-clone.txt
+++ b/Documentation/git-clone.txt
@@ -183,8 +183,9 @@
 
 -o <name>::
 --origin <name>::
-	Instead of using the remote name `origin` to keep track
-	of the upstream repository, use `<name>`.
+	Instead of using the remote name `origin` to keep track of the upstream
+	repository, use `<name>`.  Overrides `clone.defaultRemoteName` from the
+	config.
 
 -b <name>::
 --branch <name>::
diff --git a/Documentation/git-commit-graph.txt b/Documentation/git-commit-graph.txt
index de6b6de..e1f48c9 100644
--- a/Documentation/git-commit-graph.txt
+++ b/Documentation/git-commit-graph.txt
@@ -39,7 +39,9 @@
 --------
 'write'::
 
-Write a commit-graph file based on the commits found in packfiles.
+Write a commit-graph file based on the commits found in packfiles. If
+the config option `core.commitGraph` is disabled, then this command will
+output a warning, then return success without writing a commit-graph file.
 +
 With the `--stdin-packs` option, generate the new commit graph by
 walking objects only in the specified pack-indexes. (Cannot be combined
diff --git a/Documentation/git-commit.txt b/Documentation/git-commit.txt
index a3baea3..17150fa 100644
--- a/Documentation/git-commit.txt
+++ b/Documentation/git-commit.txt
@@ -59,6 +59,7 @@
 If you make a commit and then find a mistake immediately after
 that, you can recover from it with 'git reset'.
 
+:git-commit: 1
 
 OPTIONS
 -------
@@ -163,14 +164,7 @@
 	message, the commit is aborted.  This has no effect when a message
 	is given by other means, e.g. with the `-m` or `-F` options.
 
--s::
---signoff::
-	Add Signed-off-by line by the committer at the end of the commit
-	log message.  The meaning of a signoff depends on the project,
-	but it typically certifies that committer has
-	the rights to submit this work under the same license and
-	agrees to a Developer Certificate of Origin
-	(see http://developercertificate.org/ for more information).
+include::signoff-option.txt[]
 
 -n::
 --no-verify::
diff --git a/Documentation/git-diff-index.txt b/Documentation/git-diff-index.txt
index f4bd815..27acb31 100644
--- a/Documentation/git-diff-index.txt
+++ b/Documentation/git-diff-index.txt
@@ -9,7 +9,7 @@
 SYNOPSIS
 --------
 [verse]
-'git diff-index' [-m] [--cached] [<common diff options>] <tree-ish> [<path>...]
+'git diff-index' [-m] [--cached] [--merge-base] [<common diff options>] <tree-ish> [<path>...]
 
 DESCRIPTION
 -----------
@@ -27,7 +27,12 @@
 	The id of a tree object to diff against.
 
 --cached::
-	do not consider the on-disk file at all
+	Do not consider the on-disk file at all.
+
+--merge-base::
+	Instead of comparing <tree-ish> directly, use the merge base
+	between <tree-ish> and HEAD instead.  <tree-ish> must be a
+	commit.
 
 -m::
 	By default, files recorded in the index but not checked
diff --git a/Documentation/git-diff-tree.txt b/Documentation/git-diff-tree.txt
index 5c8a2a5..2fc24c5 100644
--- a/Documentation/git-diff-tree.txt
+++ b/Documentation/git-diff-tree.txt
@@ -10,7 +10,7 @@
 --------
 [verse]
 'git diff-tree' [--stdin] [-m] [-s] [-v] [--no-commit-id] [--pretty]
-	      [-t] [-r] [-c | --cc] [--combined-all-paths] [--root]
+	      [-t] [-r] [-c | --cc] [--combined-all-paths] [--root] [--merge-base]
 	      [<common diff options>] <tree-ish> [<tree-ish>] [<path>...]
 
 DESCRIPTION
@@ -43,6 +43,11 @@
 	When `--root` is specified the initial commit will be shown as a big
 	creation event. This is equivalent to a diff against the NULL tree.
 
+--merge-base::
+	Instead of comparing the <tree-ish>s directly, use the merge
+	base between the two <tree-ish>s as the "before" side.  There
+	must be two <tree-ish>s given and they must both be commits.
+
 --stdin::
 	When `--stdin` is specified, the command does not take
 	<tree-ish> arguments from the command line.  Instead, it
diff --git a/Documentation/git-diff.txt b/Documentation/git-diff.txt
index 727f24d..7f4c8a8 100644
--- a/Documentation/git-diff.txt
+++ b/Documentation/git-diff.txt
@@ -10,8 +10,8 @@
 --------
 [verse]
 'git diff' [<options>] [<commit>] [--] [<path>...]
-'git diff' [<options>] --cached [<commit>] [--] [<path>...]
-'git diff' [<options>] <commit> [<commit>...] <commit> [--] [<path>...]
+'git diff' [<options>] --cached [--merge-base] [<commit>] [--] [<path>...]
+'git diff' [<options>] [--merge-base] <commit> [<commit>...] <commit> [--] [<path>...]
 'git diff' [<options>] <commit>...<commit> [--] [<path>...]
 'git diff' [<options>] <blob> <blob>
 'git diff' [<options>] --no-index [--] <path> <path>
@@ -40,7 +40,7 @@
 	or when running the command outside a working tree
 	controlled by Git. This form implies `--exit-code`.
 
-'git diff' [<options>] --cached [<commit>] [--] [<path>...]::
+'git diff' [<options>] --cached [--merge-base] [<commit>] [--] [<path>...]::
 
 	This form is to view the changes you staged for the next
 	commit relative to the named <commit>.  Typically you
@@ -49,6 +49,10 @@
 	If HEAD does not exist (e.g. unborn branches) and
 	<commit> is not given, it shows all staged changes.
 	--staged is a synonym of --cached.
++
+If --merge-base is given, instead of using <commit>, use the merge base
+of <commit> and HEAD.  `git diff --merge-base A` is equivalent to
+`git diff $(git merge-base A HEAD)`.
 
 'git diff' [<options>] <commit> [--] [<path>...]::
 
@@ -58,23 +62,27 @@
 	branch name to compare with the tip of a different
 	branch.
 
-'git diff' [<options>] <commit> <commit> [--] [<path>...]::
+'git diff' [<options>] [--merge-base] <commit> <commit> [--] [<path>...]::
 
 	This is to view the changes between two arbitrary
 	<commit>.
++
+If --merge-base is given, use the merge base of the two commits for the
+"before" side.  `git diff --merge-base A B` is equivalent to
+`git diff $(git merge-base A B) B`.
 
 'git diff' [<options>] <commit> <commit>... <commit> [--] [<path>...]::
 
 	This form is to view the results of a merge commit.  The first
 	listed <commit> must be the merge itself; the remaining two or
 	more commits should be its parents.  A convenient way to produce
-	the desired set of revisions is to use the {caret}@ suffix.
+	the desired set of revisions is to use the `^@` suffix.
 	For instance, if `master` names a merge commit, `git diff master
 	master^@` gives the same combined diff as `git show master`.
 
 'git diff' [<options>] <commit>..<commit> [--] [<path>...]::
 
-	This is synonymous to the earlier form (without the "..") for
+	This is synonymous to the earlier form (without the `..`) for
 	viewing the changes between two arbitrary <commit>.  If <commit> on
 	one side is omitted, it will have the same effect as
 	using HEAD instead.
@@ -83,20 +91,20 @@
 
 	This form is to view the changes on the branch containing
 	and up to the second <commit>, starting at a common ancestor
-	of both <commit>.  "git diff A\...B" is equivalent to
-	"git diff $(git merge-base A B) B".  You can omit any one
+	of both <commit>.  `git diff A...B` is equivalent to
+	`git diff $(git merge-base A B) B`.  You can omit any one
 	of <commit>, which has the same effect as using HEAD instead.
 
 Just in case you are doing something exotic, it should be
 noted that all of the <commit> in the above description, except
-in the last two forms that use ".." notations, can be any
-<tree>.
+in the `--merge-base` case and in the last two forms that use `..`
+notations, can be any <tree>.
 
 For a more complete list of ways to spell <commit>, see
 "SPECIFYING REVISIONS" section in linkgit:gitrevisions[7].
 However, "diff" is about comparing two _endpoints_, not ranges,
-and the range notations ("<commit>..<commit>" and
-"<commit>\...<commit>") do not mean a range as defined in the
+and the range notations (`<commit>..<commit>` and
+`<commit>...<commit>`) do not mean a range as defined in the
 "SPECIFYING RANGES" section in linkgit:gitrevisions[7].
 
 'git diff' [<options>] <blob> <blob>::
@@ -144,9 +152,9 @@
 +
 <1> Changes in the working tree not yet staged for the next commit.
 <2> Changes between the index and your last commit; what you
-    would be committing if you run "git commit" without "-a" option.
+    would be committing if you run `git commit` without `-a` option.
 <3> Changes in the working tree since your last commit; what you
-    would be committing if you run "git commit -a"
+    would be committing if you run `git commit -a`
 
 Comparing with arbitrary commits::
 +
diff --git a/Documentation/git-for-each-repo.txt b/Documentation/git-for-each-repo.txt
new file mode 100644
index 0000000..94bd19d
--- /dev/null
+++ b/Documentation/git-for-each-repo.txt
@@ -0,0 +1,59 @@
+git-for-each-repo(1)
+====================
+
+NAME
+----
+git-for-each-repo - Run a Git command on a list of repositories
+
+
+SYNOPSIS
+--------
+[verse]
+'git for-each-repo' --config=<config> [--] <arguments>
+
+
+DESCRIPTION
+-----------
+Run a Git command on a list of repositories. The arguments after the
+known options or `--` indicator are used as the arguments for the Git
+subprocess.
+
+THIS COMMAND IS EXPERIMENTAL. THE BEHAVIOR MAY CHANGE.
+
+For example, we could run maintenance on each of a list of repositories
+stored in a `maintenance.repo` config variable using
+
+-------------
+git for-each-repo --config=maintenance.repo maintenance run
+-------------
+
+This will run `git -C <repo> maintenance run` for each value `<repo>`
+in the multi-valued config variable `maintenance.repo`.
+
+
+OPTIONS
+-------
+--config=<config>::
+	Use the given config variable as a multi-valued list storing
+	absolute path names. Iterate on that list of paths to run
+	the given arguments.
++
+These config values are loaded from system, global, and local Git config,
+as available. If `git for-each-repo` is run in a directory that is not a
+Git repository, then only the system and global config is used.
+
+
+SUBPROCESS BEHAVIOR
+-------------------
+
+If any `git -C <repo> <arguments>` subprocess returns a non-zero exit code,
+then the `git for-each-repo` process returns that exit code without running
+more subprocesses.
+
+Each `git -C <repo> <arguments>` subprocess inherits the standard file
+descriptors `stdin`, `stdout`, and `stderr`.
+
+
+GIT
+---
+Part of the linkgit:git[1] suite
diff --git a/Documentation/git-format-patch.txt b/Documentation/git-format-patch.txt
index 0f81d04..3e49bf2 100644
--- a/Documentation/git-format-patch.txt
+++ b/Documentation/git-format-patch.txt
@@ -28,6 +28,7 @@
 		   [--no-notes | --notes[=<ref>]]
 		   [--interdiff=<previous>]
 		   [--range-diff=<previous> [--creation-factor=<percent>]]
+		   [--filename-max-length=<n>]
 		   [--progress]
 		   [<common diff options>]
 		   [ <since> | <revision range> ]
@@ -119,7 +120,7 @@
 
 -s::
 --signoff::
-	Add `Signed-off-by:` line to the commit message, using
+	Add a `Signed-off-by` trailer to the commit message, using
 	the committer identity of yourself.
 	See the signoff option in linkgit:git-commit[1] for more information.
 
@@ -200,6 +201,13 @@
 	allows for useful naming of a patch series, and can be
 	combined with the `--numbered` option.
 
+--filename-max-length=<n>::
+	Instead of the standard 64 bytes, chomp the generated output
+	filenames at around '<n>' bytes (too short a value will be
+	silently raised to a reasonable length).  Defaults to the
+	value of the `format.filenameMaxLength` configuration
+	variable, or 64 if unconfigured.
+
 --rfc::
 	Alias for `--subject-prefix="RFC PATCH"`. RFC means "Request For
 	Comments"; use this when sending an experimental patch for
diff --git a/Documentation/git-grep.txt b/Documentation/git-grep.txt
index 6077ff0..4e0ba82 100644
--- a/Documentation/git-grep.txt
+++ b/Documentation/git-grep.txt
@@ -241,7 +241,7 @@
 --show-function::
 	Show the preceding line that contains the function name of
 	the match, unless the matching line is a function name itself.
-	The name is determined in the same way as 'git diff' works out
+	The name is determined in the same way as `git diff` works out
 	patch hunk headers (see 'Defining a custom hunk-header' in
 	linkgit:gitattributes[5]).
 
@@ -266,7 +266,9 @@
 	Show the surrounding text from the previous line containing a
 	function name up to the one before the next function name,
 	effectively showing the whole function in which the match was
-	found.
+	found. The function names are determined in the same way as
+	`git diff` works out patch hunk headers (see 'Defining a
+	custom hunk-header' in linkgit:gitattributes[5]).
 
 --threads <num>::
 	Number of grep worker threads to use.
diff --git a/Documentation/git-log.txt b/Documentation/git-log.txt
index 2b8ac5f..dd189a3 100644
--- a/Documentation/git-log.txt
+++ b/Documentation/git-log.txt
@@ -77,20 +77,7 @@
 	Intended to speed up tools that read log messages from `git log`
 	output by allowing them to allocate space in advance.
 
--L <start>,<end>:<file>::
--L :<funcname>:<file>::
-	Trace the evolution of the line range given by "<start>,<end>"
-	(or the function name regex <funcname>) within the <file>.  You may
-	not give any pathspec limiters.  This is currently limited to
-	a walk starting from a single revision, i.e., you may only
-	give zero or one positive revision arguments, and
-	<start> and <end> (or <funcname>) must exist in the starting revision.
-	You can specify this option more than once. Implies `--patch`.
-	Patch output can be suppressed using `--no-patch`, but other diff formats
-	(namely `--raw`, `--numstat`, `--shortstat`, `--dirstat`, `--summary`,
-	`--name-only`, `--name-status`, `--check`) are not currently implemented.
-+
-include::line-range-format.txt[]
+include::line-range-options.txt[]
 
 <revision range>::
 	Show only commits in the specified revision range.  When no
diff --git a/Documentation/git-ls-files.txt b/Documentation/git-ls-files.txt
index 3cb2ebb..cbcf526 100644
--- a/Documentation/git-ls-files.txt
+++ b/Documentation/git-ls-files.txt
@@ -19,7 +19,7 @@
 		[--exclude-standard]
 		[--error-unmatch] [--with-tree=<tree-ish>]
 		[--full-name] [--recurse-submodules]
-		[--abbrev] [--] [<file>...]
+		[--abbrev[=<n>]] [--] [<file>...]
 
 DESCRIPTION
 -----------
@@ -153,7 +153,8 @@
 
 --abbrev[=<n>]::
 	Instead of showing the full 40-byte hexadecimal object
-	lines, show only a partial prefix.
+	lines, show the shortest prefix that is at least '<n>'
+	hexdigits long that uniquely refers the object.
 	Non default number of digits can be specified with --abbrev=<n>.
 
 --debug::
diff --git a/Documentation/git-ls-tree.txt b/Documentation/git-ls-tree.txt
index a751571..db02d6d 100644
--- a/Documentation/git-ls-tree.txt
+++ b/Documentation/git-ls-tree.txt
@@ -62,7 +62,8 @@
 
 --abbrev[=<n>]::
 	Instead of showing the full 40-byte hexadecimal object
-	lines, show only a partial prefix.
+	lines, show the shortest prefix that is at least '<n>'
+	hexdigits long that uniquely refers the object.
 	Non default number of digits can be specified with --abbrev=<n>.
 
 --full-name::
diff --git a/Documentation/git-maintenance.txt b/Documentation/git-maintenance.txt
index 6abcb82..6fec1eb 100644
--- a/Documentation/git-maintenance.txt
+++ b/Documentation/git-maintenance.txt
@@ -29,6 +29,32 @@
 SUBCOMMANDS
 -----------
 
+register::
+	Initialize Git config values so any scheduled maintenance will
+	start running on this repository. This adds the repository to the
+	`maintenance.repo` config variable in the current user's global
+	config and enables some recommended configuration values for
+	`maintenance.<task>.schedule`. The tasks that are enabled are safe
+	for running in the background without disrupting foreground
+	processes.
++
+The `register` subcomand will also set the `maintenance.strategy` config
+value to `incremental`, if this value is not previously set. The
+`incremental` strategy uses the following schedule for each maintenance
+task:
++
+--
+* `gc`: disabled.
+* `commit-graph`: hourly.
+* `prefetch`: hourly.
+* `loose-objects`: daily.
+* `incremental-repack`: daily.
+--
++
+`git maintenance register` will also disable foreground maintenance by
+setting `maintenance.auto = false` in the current repository. This config
+setting will remain after a `git maintenance unregister` command.
+
 run::
 	Run one or more maintenance tasks. If one or more `--task` options
 	are specified, then those tasks are run in that order. Otherwise,
@@ -36,6 +62,22 @@
 	config options are true. By default, only `maintenance.gc.enabled`
 	is true.
 
+start::
+	Start running maintenance on the current repository. This performs
+	the same config updates as the `register` subcommand, then updates
+	the background scheduler to run `git maintenance run --scheduled`
+	on an hourly basis.
+
+stop::
+	Halt the background maintenance schedule. The current repository
+	is not removed from the list of maintained repositories, in case
+	the background maintenance is restarted later.
+
+unregister::
+	Remove the current repository from background maintenance. This
+	only removes the repository from the configured list. It does not
+	stop the background maintenance processes from running.
+
 TASKS
 -----
 
@@ -47,6 +89,21 @@
 	`commit-graph-chain` file. They will be deleted by a later run based
 	on the expiration delay.
 
+prefetch::
+	The `prefetch` task updates the object directory with the latest
+	objects from all registered remotes. For each remote, a `git fetch`
+	command is run. The refmap is custom to avoid updating local or remote
+	branches (those in `refs/heads` or `refs/remotes`). Instead, the
+	remote refs are stored in `refs/prefetch/<remote>/`. Also, tags are
+	not updated.
++
+This is done to avoid disrupting the remote-tracking branches. The end users
+expect these refs to stay unmoved unless they initiate a fetch.  With prefetch
+task, however, the objects necessary to complete a later real fetch would
+already be obtained, so the real fetch would go faster.  In the ideal case,
+it will just become an update to bunch of remote-tracking branches without
+any object transfer.
+
 gc::
 	Clean up unnecessary files and optimize the local repository. "GC"
 	stands for "garbage collection," but this task performs many
@@ -55,6 +112,39 @@
 	be disruptive in some situations, as it deletes stale data. See
 	linkgit:git-gc[1] for more details on garbage collection in Git.
 
+loose-objects::
+	The `loose-objects` job cleans up loose objects and places them into
+	pack-files. In order to prevent race conditions with concurrent Git
+	commands, it follows a two-step process. First, it deletes any loose
+	objects that already exist in a pack-file; concurrent Git processes
+	will examine the pack-file for the object data instead of the loose
+	object. Second, it creates a new pack-file (starting with "loose-")
+	containing a batch of loose objects. The batch size is limited to 50
+	thousand objects to prevent the job from taking too long on a
+	repository with many loose objects. The `gc` task writes unreachable
+	objects as loose objects to be cleaned up by a later step only if
+	they are not re-added to a pack-file; for this reason it is not
+	advisable to enable both the `loose-objects` and `gc` tasks at the
+	same time.
+
+incremental-repack::
+	The `incremental-repack` job repacks the object directory
+	using the `multi-pack-index` feature. In order to prevent race
+	conditions with concurrent Git commands, it follows a two-step
+	process. First, it calls `git multi-pack-index expire` to delete
+	pack-files unreferenced by the `multi-pack-index` file. Second, it
+	calls `git multi-pack-index repack` to select several small
+	pack-files and repack them into a bigger one, and then update the
+	`multi-pack-index` entries that refer to the small pack-files to
+	refer to the new pack-file. This prepares those small pack-files
+	for deletion upon the next run of `git multi-pack-index expire`.
+	The selection of the small pack-files is such that the expected
+	size of the big pack-file is at least the batch size; see the
+	`--batch-size` option for the `repack` subcommand in
+	linkgit:git-multi-pack-index[1]. The default batch-size is zero,
+	which is a special case that attempts to repack all pack-files
+	into a single pack-file.
+
 OPTIONS
 -------
 --auto::
@@ -62,7 +152,18 @@
 	only if certain thresholds are met. For example, the `gc` task
 	runs when the number of loose objects exceeds the number stored
 	in the `gc.auto` config setting, or when the number of pack-files
-	exceeds the `gc.autoPackLimit` config setting.
+	exceeds the `gc.autoPackLimit` config setting. Not compatible with
+	the `--schedule` option.
+
+--schedule::
+	When combined with the `run` subcommand, run maintenance tasks
+	only if certain time conditions are met, as specified by the
+	`maintenance.<task>.schedule` config value for each `<task>`.
+	This config value specifies a number of seconds since the last
+	time that task ran, according to the `maintenance.<task>.lastRun`
+	config value. The tasks that are tested are those provided by
+	the `--task=<task>` option(s) or those with
+	`maintenance.<task>.enabled` set to true.
 
 --quiet::
 	Do not report progress or other information over `stderr`.
@@ -74,6 +175,50 @@
 	`maintenance.<task>.enabled` configured as `true` are considered.
 	See the 'TASKS' section for the list of accepted `<task>` values.
 
+
+TROUBLESHOOTING
+---------------
+The `git maintenance` command is designed to simplify the repository
+maintenance patterns while minimizing user wait time during Git commands.
+A variety of configuration options are available to allow customizing this
+process. The default maintenance options focus on operations that complete
+quickly, even on large repositories.
+
+Users may find some cases where scheduled maintenance tasks do not run as
+frequently as intended. Each `git maintenance run` command takes a lock on
+the repository's object database, and this prevents other concurrent
+`git maintenance run` commands from running on the same repository. Without
+this safeguard, competing processes could leave the repository in an
+unpredictable state.
+
+The background maintenance schedule runs `git maintenance run` processes
+on an hourly basis. Each run executes the "hourly" tasks. At midnight,
+that process also executes the "daily" tasks. At midnight on the first day
+of the week, that process also executes the "weekly" tasks. A single
+process iterates over each registered repository, performing the scheduled
+tasks for that frequency. Depending on the number of registered
+repositories and their sizes, this process may take longer than an hour.
+In this case, multiple `git maintenance run` commands may run on the same
+repository at the same time, colliding on the object database lock. This
+results in one of the two tasks not running.
+
+If you find that some maintenance windows are taking longer than one hour
+to complete, then consider reducing the complexity of your maintenance
+tasks. For example, the `gc` task is much slower than the
+`incremental-repack` task. However, this comes at a cost of a slightly
+larger object database. Consider moving more expensive tasks to be run
+less frequently.
+
+Expert users may consider scheduling their own maintenance tasks using a
+different schedule than is available through `git maintenance start` and
+Git configuration options. These users should be aware of the object
+database lock and how concurrent `git maintenance run` commands behave.
+Further, the `git gc` command should not be combined with
+`git maintenance run` commands. `git gc` modifies the object database
+but does not take the lock in the same way as `git maintenance run`. If
+possible, use `git maintenance run --task=gc` instead of `git gc`.
+
+
 GIT
 ---
 Part of the linkgit:git[1] suite
diff --git a/Documentation/git-p4.txt b/Documentation/git-p4.txt
index dab9609..ec233ac 100644
--- a/Documentation/git-p4.txt
+++ b/Documentation/git-p4.txt
@@ -417,7 +417,7 @@
 ~~~~~~~~~~~~~~~~~~
 
 The `p4-post-changelist` hook is invoked after the submit has
-successfully occured in P4. It takes no parameters and is meant
+successfully occurred in P4. It takes no parameters and is meant
 primarily for notification and cannot affect the outcome of the
 git p4 submit action.
 
diff --git a/Documentation/git-parse-remote.txt b/Documentation/git-parse-remote.txt
deleted file mode 100644
index a45ea1e..0000000
--- a/Documentation/git-parse-remote.txt
+++ /dev/null
@@ -1,23 +0,0 @@
-git-parse-remote(1)
-===================
-
-NAME
-----
-git-parse-remote - Routines to help parsing remote repository access parameters
-
-
-SYNOPSIS
---------
-[verse]
-'. "$(git --exec-path)/git-parse-remote"'
-
-DESCRIPTION
------------
-This script is included in various scripts to supply
-routines to parse files under $GIT_DIR/remotes/ and
-$GIT_DIR/branches/ and configuration variables that are related
-to fetching, pulling and pushing.
-
-GIT
----
-Part of the linkgit:git[1] suite
diff --git a/Documentation/git-push.txt b/Documentation/git-push.txt
index 3b80534..ab103c8 100644
--- a/Documentation/git-push.txt
+++ b/Documentation/git-push.txt
@@ -13,7 +13,7 @@
 	   [--repo=<repository>] [-f | --force] [-d | --delete] [--prune] [-v | --verbose]
 	   [-u | --set-upstream] [-o <string> | --push-option=<string>]
 	   [--[no-]signed|--signed=(true|false|if-asked)]
-	   [--force-with-lease[=<refname>[:<expect>]]]
+	   [--force-with-lease[=<refname>[:<expect>]] [--force-if-includes]]
 	   [--no-verify] [<repository> [<refspec>...]]
 
 DESCRIPTION
@@ -320,6 +320,14 @@
 force push changes to `master` if the remote version is still at
 `base`, regardless of what your local `remotes/origin/master` has been
 updated to in the background.
++
+Alternatively, specifying `--force-if-includes` as an ancillary option
+along with `--force-with-lease[=<refname>]` (i.e., without saying what
+exact commit the ref on the remote side must be pointing at, or which
+refs on the remote side are being protected) at the time of "push" will
+verify if updates from the remote-tracking refs that may have been
+implicitly updated in the background are integrated locally before
+allowing a forced update.
 
 -f::
 --force::
@@ -341,6 +349,22 @@
 origin +master` to force a push to the `master` branch). See the
 `<refspec>...` section above for details.
 
+--[no-]force-if-includes::
+	Force an update only if the tip of the remote-tracking ref
+	has been integrated locally.
++
+This option enables a check that verifies if the tip of the
+remote-tracking ref is reachable from one of the "reflog" entries of
+the local branch based in it for a rewrite. The check ensures that any
+updates from the remote have been incorporated locally by rejecting the
+forced update if that is not the case.
++
+If the option is passed without specifying `--force-with-lease`, or
+specified along with `--force-with-lease=<refname>:<expect>`, it is
+a "no-op".
++
+Specifying `--no-force-if-includes` disables this behavior.
+
 --repo=<repository>::
 	This option is equivalent to the <repository> argument. If both
 	are specified, the command-line argument takes precedence.
diff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt
index 38e1548..a0487b5 100644
--- a/Documentation/git-rebase.txt
+++ b/Documentation/git-rebase.txt
@@ -496,7 +496,7 @@
 See also INCOMPATIBLE OPTIONS below.
 
 --signoff::
-	Add a Signed-off-by: trailer to all the rebased commits. Note
+	Add a `Signed-off-by` trailer to all the rebased commits. Note
 	that if `--interactive` is given then only commits marked to be
 	picked, edited or reworded will have the trailer added.
 +
diff --git a/Documentation/git-remote.txt b/Documentation/git-remote.txt
index ea73386..31c29c9 100644
--- a/Documentation/git-remote.txt
+++ b/Documentation/git-remote.txt
@@ -203,6 +203,17 @@
 `remote.origin.fetch` configuration variables.  (See
 linkgit:git-config[1]).
 
+EXIT STATUS
+-----------
+
+On success, the exit status is `0`.
+
+When subcommands such as 'add', 'rename', and 'remove' can't find the
+remote in question, the exit status is `2`. When the remote already
+exists, the exit status is `3`.
+
+On any other error, the exit status may be any other non-zero value.
+
 EXAMPLES
 --------
 
diff --git a/Documentation/git-restore.txt b/Documentation/git-restore.txt
index 84c6c40..55bde91 100644
--- a/Documentation/git-restore.txt
+++ b/Documentation/git-restore.txt
@@ -40,6 +40,10 @@
 +
 If not specified, the contents are restored from `HEAD` if `--staged` is
 given, otherwise from the index.
++
+As a special case, you may use `"A...B"` as a shortcut for the
+merge base of `A` and `B` if there is exactly one merge base. You can
+leave out at most one of `A` and `B`, in which case it defaults to `HEAD`.
 
 -p::
 --patch::
diff --git a/Documentation/git-rev-parse.txt b/Documentation/git-rev-parse.txt
index 19b12b6..5013daa 100644
--- a/Documentation/git-rev-parse.txt
+++ b/Documentation/git-rev-parse.txt
@@ -109,6 +109,10 @@
 annotated tag that points at a commit).  To make sure that `$VAR`
 names an existing object of any type, `git rev-parse "$VAR^{object}"`
 can be used.
++
+Note that if you are verifying a name from an untrusted source, it is
+wise to use `--end-of-options` so that the name argument is not mistaken
+for another option.
 
 -q::
 --quiet::
@@ -446,7 +450,7 @@
 * Print the commit object name from the revision in the $REV shell variable:
 +
 ------------
-$ git rev-parse --verify $REV^{commit}
+$ git rev-parse --verify --end-of-options $REV^{commit}
 ------------
 +
 This will error out if $REV is empty or not a valid revision.
@@ -454,7 +458,7 @@
 * Similar to above:
 +
 ------------
-$ git rev-parse --default master --verify $REV
+$ git rev-parse --default master --verify --end-of-options $REV
 ------------
 +
 but if $REV is empty, the commit object name from master will be printed.
diff --git a/Documentation/git-revert.txt b/Documentation/git-revert.txt
index 044276e..bb92a4a 100644
--- a/Documentation/git-revert.txt
+++ b/Documentation/git-revert.txt
@@ -99,7 +99,7 @@
 
 -s::
 --signoff::
-	Add Signed-off-by line at the end of the commit message.
+	Add a `Signed-off-by` trailer at the end of the commit message.
 	See the signoff option in linkgit:git-commit[1] for more information.
 
 --strategy=<strategy>::
diff --git a/Documentation/git-send-email.txt b/Documentation/git-send-email.txt
index 0a69810..b7bbbea 100644
--- a/Documentation/git-send-email.txt
+++ b/Documentation/git-send-email.txt
@@ -313,7 +313,7 @@
 	the value of `sendemail.identity`.
 
 --[no-]signed-off-by-cc::
-	If this is set, add emails found in Signed-off-by: or Cc: lines to the
+	If this is set, add emails found in the `Signed-off-by` trailer or Cc: lines to the
 	cc list. Default is the value of `sendemail.signedoffbycc` configuration
 	value; if that is unspecified, default to --signed-off-by-cc.
 
@@ -340,7 +340,7 @@
   except for self (use 'self' for that).
 - 'bodycc' will avoid including anyone mentioned in Cc lines in the
   patch body (commit message) except for self (use 'self' for that).
-- 'sob' will avoid including anyone mentioned in Signed-off-by lines except
+- 'sob' will avoid including anyone mentioned in the Signed-off-by trailers except
   for self (use 'self' for that).
 - 'misc-by' will avoid including anyone mentioned in Acked-by,
   Reviewed-by, Tested-by and other "-by" lines in the patch body,
diff --git a/Documentation/git-svn.txt b/Documentation/git-svn.txt
index 6624a14..67b143c 100644
--- a/Documentation/git-svn.txt
+++ b/Documentation/git-svn.txt
@@ -701,7 +701,7 @@
 
 --use-log-author::
 	When retrieving svn commits into Git (as part of 'fetch', 'rebase', or
-	'dcommit' operations), look for the first `From:` or `Signed-off-by:` line
+	'dcommit' operations), look for the first `From:` line or `Signed-off-by` trailer
 	in the log message and use that as the author string.
 +
 [verse]
@@ -710,7 +710,7 @@
 --add-author-from::
 	When committing to svn from Git (as part of 'set-tree' or 'dcommit'
 	operations), if the existing log message doesn't already have a
-	`From:` or `Signed-off-by:` line, append a `From:` line based on the
+	`From:` or `Signed-off-by` trailer, append a `From:` line based on the
 	Git commit's author string.  If you use this, then `--use-log-author`
 	will retrieve a valid author string for all commits.
 +
diff --git a/Documentation/git-switch.txt b/Documentation/git-switch.txt
index 3759c3a..5c438cd 100644
--- a/Documentation/git-switch.txt
+++ b/Documentation/git-switch.txt
@@ -103,6 +103,9 @@
 `checkout.defaultRemote` in linkgit:git-config[1].
 +
 `--guess` is the default behavior. Use `--no-guess` to disable it.
++
+The default behavior can be set via the `checkout.guess` configuration
+variable.
 
 -f::
 --force::
diff --git a/Documentation/git-worktree.txt b/Documentation/git-worktree.txt
index 32e8440..af06128 100644
--- a/Documentation/git-worktree.txt
+++ b/Documentation/git-worktree.txt
@@ -96,8 +96,9 @@
 
 List details of each working tree.  The main working tree is listed first,
 followed by each of the linked working trees.  The output details include
-whether the working tree is bare, the revision currently checked out, and the
-branch currently checked out (or "detached HEAD" if none).
+whether the working tree is bare, the revision currently checked out, the
+branch currently checked out (or "detached HEAD" if none), and "locked" if
+the worktree is locked.
 
 lock::
 
diff --git a/Documentation/gitattributes.txt b/Documentation/gitattributes.txt
index 2d0a037..e84e104 100644
--- a/Documentation/gitattributes.txt
+++ b/Documentation/gitattributes.txt
@@ -802,6 +802,9 @@
 
 - `ada` suitable for source code in the Ada language.
 
+- `bash` suitable for source code in the Bourne-Again SHell language.
+  Covers a superset of POSIX shell function definitions.
+
 - `bibtex` suitable for files with BibTeX coded references.
 
 - `cpp` suitable for source code in the C and C++ languages.
diff --git a/Documentation/githooks.txt b/Documentation/githooks.txt
index 6e461ac..ffccfc7 100644
--- a/Documentation/githooks.txt
+++ b/Documentation/githooks.txt
@@ -164,7 +164,7 @@
 file.
 
 The default 'commit-msg' hook, when enabled, detects duplicate
-"Signed-off-by" lines, and aborts the commit if one is found.
+`Signed-off-by` trailers, and aborts the commit if one is found.
 
 post-commit
 ~~~~~~~~~~~
@@ -655,7 +655,7 @@
 This hook is invoked by `git-p4 submit`.
 
 The `p4-post-changelist` hook is invoked after the submit has
-successfully occured in P4. It takes no parameters and is meant
+successfully occurred in P4. It takes no parameters and is meant
 primarily for notification and cannot affect the outcome of the
 git p4 submit action.
 
diff --git a/Documentation/gitk.txt b/Documentation/gitk.txt
index c653ebb..d50e9ed 100644
--- a/Documentation/gitk.txt
+++ b/Documentation/gitk.txt
@@ -98,25 +98,7 @@
 	(See "History simplification" in linkgit:git-log[1] for a more
 	detailed explanation.)
 
--L<start>,<end>:<file>::
--L:<funcname>:<file>::
-
-	Trace the evolution of the line range given by "<start>,<end>"
-	(or the function name regex <funcname>) within the <file>.  You may
-	not give any pathspec limiters.  This is currently limited to
-	a walk starting from a single revision, i.e., you may only
-	give zero or one positive revision arguments, and
-	<start> and <end> (or <funcname>) must exist in the starting revision.
-	You can specify this option more than once. Implies `--patch`.
-	Patch output can be suppressed using `--no-patch`, but other diff formats
-	(namely `--raw`, `--numstat`, `--shortstat`, `--dirstat`, `--summary`,
-	`--name-only`, `--name-status`, `--check`) are not currently implemented.
-+
-*Note:* gitk (unlike linkgit:git-log[1]) currently only understands
-this option if you specify it "glued together" with its argument.  Do
-*not* put a space after `-L`.
-+
-include::line-range-format.txt[]
+include::line-range-options.txt[]
 
 <revision range>::
 
diff --git a/Documentation/line-range-format.txt b/Documentation/line-range-format.txt
index 829676f..9b51e9f 100644
--- a/Documentation/line-range-format.txt
+++ b/Documentation/line-range-format.txt
@@ -1,30 +1,32 @@
-<start> and <end> can take one of these forms:
+'<start>' and '<end>' can take one of these forms:
 
 - number
 +
-If <start> or <end> is a number, it specifies an
+If '<start>' or '<end>' is a number, it specifies an
 absolute line number (lines count from 1).
 +
 
-- /regex/
+- `/regex/`
 +
 This form will use the first line matching the given
-POSIX regex. If <start> is a regex, it will search from the end of
+POSIX regex. If '<start>' is a regex, it will search from the end of
 the previous `-L` range, if any, otherwise from the start of file.
-If <start> is ``^/regex/'', it will search from the start of file.
-If <end> is a regex, it will search
-starting at the line given by <start>.
+If '<start>' is `^/regex/`, it will search from the start of file.
+If '<end>' is a regex, it will search
+starting at the line given by '<start>'.
 +
 
 - +offset or -offset
 +
-This is only valid for <end> and will specify a number
-of lines before or after the line given by <start>.
+This is only valid for '<end>' and will specify a number
+of lines before or after the line given by '<start>'.
 
 +
-If ``:<funcname>'' is given in place of <start> and <end>, it is a
+If `:<funcname>` is given in place of '<start>' and '<end>', it is a
 regular expression that denotes the range from the first funcname line
-that matches <funcname>, up to the next funcname line. ``:<funcname>''
+that matches '<funcname>', up to the next funcname line. `:<funcname>`
 searches from the end of the previous `-L` range, if any, otherwise
-from the start of file. ``^:<funcname>'' searches from the start of
-file.
+from the start of file. `^:<funcname>` searches from the start of
+file. The function names are determined in the same way as `git diff`
+works out patch hunk headers (see 'Defining a custom hunk-header'
+in linkgit:gitattributes[5]).
diff --git a/Documentation/line-range-options.txt b/Documentation/line-range-options.txt
new file mode 100644
index 0000000..8e295a6
--- /dev/null
+++ b/Documentation/line-range-options.txt
@@ -0,0 +1,15 @@
+-L<start>,<end>:<file>::
+-L:<funcname>:<file>::
+
+	Trace the evolution of the line range given by '<start>,<end>',
+	or by the function name regex '<funcname>', within the '<file>'. You may
+	not give any pathspec limiters.  This is currently limited to
+	a walk starting from a single revision, i.e., you may only
+	give zero or one positive revision arguments, and
+	'<start>' and '<end>' (or '<funcname>') must exist in the starting revision.
+	You can specify this option more than once. Implies `--patch`.
+	Patch output can be suppressed using `--no-patch`, but other diff formats
+	(namely `--raw`, `--numstat`, `--shortstat`, `--dirstat`, `--summary`,
+	`--name-only`, `--name-status`, `--check`) are not currently implemented.
++
+include::line-range-format.txt[]
diff --git a/Documentation/merge-options.txt b/Documentation/merge-options.txt
index 80d4831..eb0aabd 100644
--- a/Documentation/merge-options.txt
+++ b/Documentation/merge-options.txt
@@ -77,16 +77,7 @@
 With --no-log do not list one-line descriptions from the
 actual commits being merged.
 
---signoff::
---no-signoff::
-	Add Signed-off-by line by the committer at the end of the commit
-	log message.  The meaning of a signoff depends on the project,
-	but it typically certifies that committer has
-	the rights to submit this work under the same license and
-	agrees to a Developer Certificate of Origin
-	(see http://developercertificate.org/ for more information).
-+
-With --no-signoff do not add a Signed-off-by line.
+include::signoff-option.txt[]
 
 --stat::
 -n::
diff --git a/Documentation/pretty-options.txt b/Documentation/pretty-options.txt
index 17c5aac..27ddaf8 100644
--- a/Documentation/pretty-options.txt
+++ b/Documentation/pretty-options.txt
@@ -16,9 +16,9 @@
 
 --abbrev-commit::
 	Instead of showing the full 40-byte hexadecimal commit object
-	name, show only a partial prefix.  Non default number of
-	digits can be specified with "--abbrev=<n>" (which also modifies
-	diff output, if it is displayed).
+	name, show a prefix that names the object uniquely.
+	"--abbrev=<n>" (which also modifies diff output, if it is displayed)
+	option can be used to specify the minimum length of the prefix.
 +
 This should make "--pretty=oneline" a whole lot more readable for
 people using 80-column terminals.
diff --git a/Documentation/signoff-option.txt b/Documentation/signoff-option.txt
new file mode 100644
index 0000000..12aa233
--- /dev/null
+++ b/Documentation/signoff-option.txt
@@ -0,0 +1,18 @@
+ifdef::git-commit[]
+-s::
+endif::git-commit[]
+--signoff::
+--no-signoff::
+	Add a `Signed-off-by` trailer by the committer at the end of the commit
+	log message.  The meaning of a signoff depends on the project
+	to which you're committing.  For example, it may certify that
+	the committer has the rights to submit the work under the
+	project's license or agrees to some contributor representation,
+	such as a Developer Certificate of Origin.
+	(See http://developercertificate.org for the one used by the
+	Linux kernel and Git projects.)  Consult the documentation or
+	leadership of the project to which you're contributing to
+	understand how the signoffs are used in that project.
++
+The --no-signoff option can be used to countermand an earlier --signoff
+option on the command line.
diff --git a/Documentation/technical/directory-rename-detection.txt b/Documentation/technical/directory-rename-detection.txt
index 844629c..49b83ef 100644
--- a/Documentation/technical/directory-rename-detection.txt
+++ b/Documentation/technical/directory-rename-detection.txt
@@ -18,7 +18,8 @@
 More interesting possibilities exist, though, such as:
 
   * one side of history renames x -> z, and the other renames some file to
-    x/e, causing the need for the merge to do a transitive rename.
+    x/e, causing the need for the merge to do a transitive rename so that
+    the rename ends up at z/e.
 
   * one side of history renames x -> z, but also renames all files within x.
     For example, x/a -> z/alpha, x/b -> z/bravo, etc.
@@ -35,7 +36,7 @@
     directory itself contained inner directories that were renamed to yet
     other locations).
 
-  * combinations of the above; see t/t6043-merge-rename-directories.sh for
+  * combinations of the above; see t/t6423-merge-rename-directories.sh for
     various interesting cases.
 
 Limitations -- applicability of directory renames
@@ -62,19 +63,19 @@
 Limitations -- detailed rules and testcases
 -------------------------------------------
 
-t/t6043-merge-rename-directories.sh contains extensive tests and commentary
+t/t6423-merge-rename-directories.sh contains extensive tests and commentary
 which generate and explore the rules listed above.  It also lists a few
 additional rules:
 
   a) If renames split a directory into two or more others, the directory
      with the most renames, "wins".
 
-  b) Avoid directory-rename-detection for a path, if that path is the
-     source of a rename on either side of a merge.
-
-  c) Only apply implicit directory renames to directories if the other side
+  b) Only apply implicit directory renames to directories if the other side
      of history is the one doing the renaming.
 
+  c) Do not perform directory rename detection for directories which had no
+     new paths added to them.
+
 Limitations -- support in different commands
 --------------------------------------------
 
diff --git a/GIT-VERSION-GEN b/GIT-VERSION-GEN
index ca6ccb4..82bcd13 100755
--- a/GIT-VERSION-GEN
+++ b/GIT-VERSION-GEN
@@ -1,7 +1,7 @@
 #!/bin/sh
 
 GVF=GIT-VERSION-FILE
-DEF_VER=v2.29.2
+DEF_VER=v2.29.GIT
 
 LF='
 '
diff --git a/Makefile b/Makefile
index 1fb0ec1..45bce31 100644
--- a/Makefile
+++ b/Makefile
@@ -613,7 +613,6 @@
 SCRIPT_SH += git-web--browse.sh
 
 SCRIPT_LIB += git-mergetool--lib
-SCRIPT_LIB += git-parse-remote
 SCRIPT_LIB += git-rebase--preserve-merges
 SCRIPT_LIB += git-sh-i18n
 SCRIPT_LIB += git-sh-setup
@@ -694,6 +693,7 @@
 TEST_BUILTINS_OBJS += test-bloom.o
 TEST_BUILTINS_OBJS += test-chmtime.o
 TEST_BUILTINS_OBJS += test-config.o
+TEST_BUILTINS_OBJS += test-crontab.o
 TEST_BUILTINS_OBJS += test-ctype.o
 TEST_BUILTINS_OBJS += test-date.o
 TEST_BUILTINS_OBJS += test-delta.o
@@ -704,6 +704,7 @@
 TEST_BUILTINS_OBJS += test-dump-split-index.o
 TEST_BUILTINS_OBJS += test-dump-untracked-cache.o
 TEST_BUILTINS_OBJS += test-example-decorate.o
+TEST_BUILTINS_OBJS += test-fast-rebase.o
 TEST_BUILTINS_OBJS += test-genrandom.o
 TEST_BUILTINS_OBJS += test-genzeros.o
 TEST_BUILTINS_OBJS += test-hash-speed.o
@@ -921,6 +922,8 @@
 LIB_OBJS += match-trees.o
 LIB_OBJS += mem-pool.o
 LIB_OBJS += merge-blobs.o
+LIB_OBJS += merge-ort.o
+LIB_OBJS += merge-ort-wrappers.o
 LIB_OBJS += merge-recursive.o
 LIB_OBJS += merge.o
 LIB_OBJS += mergesort.o
@@ -1000,6 +1003,7 @@
 LIB_OBJS += strbuf.o
 LIB_OBJS += streaming.o
 LIB_OBJS += string-list.o
+LIB_OBJS += strmap.o
 LIB_OBJS += strvec.o
 LIB_OBJS += sub-process.o
 LIB_OBJS += submodule-config.o
@@ -1089,6 +1093,7 @@
 BUILTIN_OBJS += builtin/fetch.o
 BUILTIN_OBJS += builtin/fmt-merge-msg.o
 BUILTIN_OBJS += builtin/for-each-ref.o
+BUILTIN_OBJS += builtin/for-each-repo.o
 BUILTIN_OBJS += builtin/fsck.o
 BUILTIN_OBJS += builtin/gc.o
 BUILTIN_OBJS += builtin/get-tar-commit-id.o
@@ -2577,7 +2582,6 @@
 	--keyword=__ --keyword=N__ --keyword="__n:1,2"
 LOCALIZED_C = $(C_OBJ:o=c) $(LIB_H) $(GENERATED_H)
 LOCALIZED_SH = $(SCRIPT_SH)
-LOCALIZED_SH += git-parse-remote.sh
 LOCALIZED_SH += git-rebase--preserve-merges.sh
 LOCALIZED_SH += git-sh-setup.sh
 LOCALIZED_PERL = $(SCRIPT_PERL)
@@ -2768,6 +2772,9 @@
 ifdef GIT_TEST_INDEX_VERSION
 	@echo GIT_TEST_INDEX_VERSION=\''$(subst ','\'',$(subst ','\'',$(GIT_TEST_INDEX_VERSION)))'\' >>$@+
 endif
+ifdef GIT_TEST_PERL_FATAL_WARNINGS
+	@echo GIT_TEST_PERL_FATAL_WARNINGS=\''$(subst ','\'',$(subst ','\'',$(GIT_TEST_PERL_FATAL_WARNINGS)))'\' >>$@+
+endif
 	@if cmp $@+ $@ >/dev/null 2>&1; then $(RM) $@+; else mv $@+ $@; fi
 
 ### Detect Python interpreter path changes
@@ -3050,9 +3057,6 @@
 
 ### Maintainer's dist rules
 
-# Allow tweaking to hide local environment effects, like perm bits.
-# With GNU tar, "--mode=u+rwX,og+rX,og-w" would be a good idea, for example.
-TAR_DIST_EXTRA_OPTS =
 GIT_TARNAME = git-$(GIT_VERSION)
 GIT_ARCHIVE_EXTRA_FILES = \
 	--prefix=$(GIT_TARNAME)/ \
@@ -3102,11 +3106,15 @@
 htmldocs = git-htmldocs-$(GIT_VERSION)
 manpages = git-manpages-$(GIT_VERSION)
 .PHONY: dist-doc distclean
-dist-doc:
+dist-doc: git$X
 	$(RM) -r .doc-tmp-dir
 	mkdir .doc-tmp-dir
 	$(MAKE) -C Documentation WEBDOC_DEST=../.doc-tmp-dir install-webdoc
-	cd .doc-tmp-dir && $(TAR) cf ../$(htmldocs).tar $(TAR_DIST_EXTRA_OPTS) .
+	./git -C .doc-tmp-dir init
+	./git -C .doc-tmp-dir add .
+	./git -C .doc-tmp-dir commit -m htmldocs
+	./git -C .doc-tmp-dir archive --format=tar --prefix=./ HEAD^{tree} \
+		> $(htmldocs).tar
 	gzip -n -9 -f $(htmldocs).tar
 	:
 	$(RM) -r .doc-tmp-dir
@@ -3116,7 +3124,11 @@
 		man5dir=../.doc-tmp-dir/man5 \
 		man7dir=../.doc-tmp-dir/man7 \
 		install
-	cd .doc-tmp-dir && $(TAR) cf ../$(manpages).tar $(TAR_DIST_EXTRA_OPTS) .
+	./git -C .doc-tmp-dir init
+	./git -C .doc-tmp-dir add .
+	./git -C .doc-tmp-dir commit -m manpages
+	./git -C .doc-tmp-dir archive --format=tar --prefix=./ HEAD^{tree} \
+		> $(manpages).tar
 	gzip -n -9 -f $(manpages).tar
 	$(RM) -r .doc-tmp-dir
 
diff --git a/RelNotes b/RelNotes
index 01daa17..dc8c04b 120000
--- a/RelNotes
+++ b/RelNotes
@@ -1 +1 @@
-Documentation/RelNotes/2.29.2.txt
\ No newline at end of file
+Documentation/RelNotes/2.30.0.txt
\ No newline at end of file
diff --git a/add-interactive.c b/add-interactive.c
index 555c4ab..a14c0fe 100644
--- a/add-interactive.c
+++ b/add-interactive.c
@@ -557,7 +557,7 @@
 		if (ps)
 			clear_pathspec(&rev.prune_data);
 	}
-	hashmap_free_entries(&s.file_map, struct pathname_entry, ent);
+	hashmap_clear_and_free(&s.file_map, struct pathname_entry, ent);
 	if (unmerged_count)
 		*unmerged_count = s.unmerged_count;
 	if (binary_count)
diff --git a/add-patch.c b/add-patch.c
index bd94bd3..be4cf6e 100644
--- a/add-patch.c
+++ b/add-patch.c
@@ -1695,6 +1695,14 @@
 	if (mode == ADD_P_STASH)
 		s.mode = &patch_mode_stash;
 	else if (mode == ADD_P_RESET) {
+		/*
+		 * NEEDSWORK: Instead of comparing to the literal "HEAD",
+		 * compare the commit objects instead so that other ways of
+		 * saying the same thing (such as "@") are also handled
+		 * appropriately.
+		 *
+		 * This applies to the cases below too.
+		 */
 		if (!revision || !strcmp(revision, "HEAD"))
 			s.mode = &patch_mode_reset_head;
 		else
diff --git a/advice.c b/advice.c
index f0a3d32..1647423 100644
--- a/advice.c
+++ b/advice.c
@@ -11,6 +11,7 @@
 int advice_push_fetch_first = 1;
 int advice_push_needs_force = 1;
 int advice_push_unqualified_ref_name = 1;
+int advice_push_ref_needs_update = 1;
 int advice_status_hints = 1;
 int advice_status_u_option = 1;
 int advice_status_ahead_behind_warning = 1;
@@ -72,6 +73,7 @@
 	{ "pushFetchFirst", &advice_push_fetch_first },
 	{ "pushNeedsForce", &advice_push_needs_force },
 	{ "pushUnqualifiedRefName", &advice_push_unqualified_ref_name },
+	{ "pushRefNeedsUpdate", &advice_push_ref_needs_update },
 	{ "statusHints", &advice_status_hints },
 	{ "statusUoption", &advice_status_u_option },
 	{ "statusAheadBehindWarning", &advice_status_ahead_behind_warning },
@@ -116,6 +118,7 @@
 	[ADVICE_PUSH_ALREADY_EXISTS]			= { "pushAlreadyExists", 1 },
 	[ADVICE_PUSH_FETCH_FIRST]			= { "pushFetchFirst", 1 },
 	[ADVICE_PUSH_NEEDS_FORCE]			= { "pushNeedsForce", 1 },
+	[ADVICE_PUSH_REF_NEEDS_UPDATE]			= { "pushRefNeedsUpdate", 1 },
 
 	/* make this an alias for backward compatibility */
 	[ADVICE_PUSH_UPDATE_REJECTED_ALIAS]		= { "pushNonFastForward", 1 },
diff --git a/advice.h b/advice.h
index 16f2c11..bc24329 100644
--- a/advice.h
+++ b/advice.h
@@ -11,6 +11,7 @@
 extern int advice_push_fetch_first;
 extern int advice_push_needs_force;
 extern int advice_push_unqualified_ref_name;
+extern int advice_push_ref_needs_update;
 extern int advice_status_hints;
 extern int advice_status_u_option;
 extern int advice_status_ahead_behind_warning;
@@ -60,6 +61,7 @@
 	ADVICE_PUSH_UNQUALIFIED_REF_NAME,
 	ADVICE_PUSH_UPDATE_REJECTED_ALIAS,
 	ADVICE_PUSH_UPDATE_REJECTED,
+	ADVICE_PUSH_REF_NEEDS_UPDATE,
 	ADVICE_RESET_QUIET_WARNING,
 	ADVICE_RESOLVE_CONFLICT,
 	ADVICE_RM_HINTS,
diff --git a/apply.c b/apply.c
index 76dba93..359ceb6 100644
--- a/apply.c
+++ b/apply.c
@@ -4699,8 +4699,13 @@
 			reverse_patches(patch);
 		if (use_patch(state, patch)) {
 			patch_stats(state, patch);
-			*listp = patch;
-			listp = &patch->next;
+			if (!list || !state->apply_in_reverse) {
+				*listp = patch;
+				listp = &patch->next;
+			} else {
+				patch->next = list;
+				list = patch;
+			}
 
 			if ((patch->new_name &&
 			     ends_with_path_components(patch->new_name,
diff --git a/archive-tar.c b/archive-tar.c
index f1a1447..a971fdc 100644
--- a/archive-tar.c
+++ b/archive-tar.c
@@ -374,7 +374,8 @@
 		ar = xcalloc(1, sizeof(*ar));
 		ar->name = xmemdupz(name, namelen);
 		ar->write_archive = write_tar_filter_archive;
-		ar->flags = ARCHIVER_WANT_COMPRESSION_LEVELS;
+		ar->flags = ARCHIVER_WANT_COMPRESSION_LEVELS |
+			    ARCHIVER_HIGH_COMPRESSION_LEVELS;
 		ALLOC_GROW(tar_filters, nr_tar_filters + 1, alloc_tar_filters);
 		tar_filters[nr_tar_filters++] = ar;
 	}
diff --git a/archive.c b/archive.c
index 3c1541a..5919d9e 100644
--- a/archive.c
+++ b/archive.c
@@ -529,10 +529,12 @@
 	return 0;
 }
 
-#define OPT__COMPR(s, v, h, p) \
-	OPT_SET_INT_F(s, NULL, v, h, p, PARSE_OPT_NONEG)
-#define OPT__COMPR_HIDDEN(s, v, p) \
-	OPT_SET_INT_F(s, NULL, v, "", p, PARSE_OPT_NONEG | PARSE_OPT_HIDDEN)
+static int number_callback(const struct option *opt, const char *arg, int unset)
+{
+	BUG_ON_OPT_NEG(unset);
+	*(int *)opt->value = strtol(arg, NULL, 10);
+	return 0;
+}
 
 static int parse_archive_args(int argc, const char **argv,
 		const struct archiver **ar, struct archiver_args *args,
@@ -561,16 +563,8 @@
 		OPT_BOOL(0, "worktree-attributes", &worktree_attributes,
 			N_("read .gitattributes in working directory")),
 		OPT__VERBOSE(&verbose, N_("report archived files on stderr")),
-		OPT__COMPR('0', &compression_level, N_("store only"), 0),
-		OPT__COMPR('1', &compression_level, N_("compress faster"), 1),
-		OPT__COMPR_HIDDEN('2', &compression_level, 2),
-		OPT__COMPR_HIDDEN('3', &compression_level, 3),
-		OPT__COMPR_HIDDEN('4', &compression_level, 4),
-		OPT__COMPR_HIDDEN('5', &compression_level, 5),
-		OPT__COMPR_HIDDEN('6', &compression_level, 6),
-		OPT__COMPR_HIDDEN('7', &compression_level, 7),
-		OPT__COMPR_HIDDEN('8', &compression_level, 8),
-		OPT__COMPR('9', &compression_level, N_("compress better"), 9),
+		OPT_NUMBER_CALLBACK(&compression_level,
+			N_("set compression level"), number_callback),
 		OPT_GROUP(""),
 		OPT_BOOL('l', "list", &list,
 			N_("list supported archive formats")),
@@ -617,7 +611,9 @@
 
 	args->compression_level = Z_DEFAULT_COMPRESSION;
 	if (compression_level != -1) {
-		if ((*ar)->flags & ARCHIVER_WANT_COMPRESSION_LEVELS)
+		int levels_ok = (*ar)->flags & ARCHIVER_WANT_COMPRESSION_LEVELS;
+		int high_ok = (*ar)->flags & ARCHIVER_HIGH_COMPRESSION_LEVELS;
+		if (levels_ok && (compression_level <= 9 || high_ok))
 			args->compression_level = compression_level;
 		else {
 			die(_("Argument not supported for format '%s': -%d"),
@@ -662,6 +658,7 @@
 	rc = ar->write_archive(ar, &args);
 
 	string_list_clear_func(&args.extra_files, extra_file_info_clear);
+	free(args.refname);
 
 	return rc;
 }
diff --git a/archive.h b/archive.h
index 82b2260..33551b7 100644
--- a/archive.h
+++ b/archive.h
@@ -8,7 +8,7 @@
 
 struct archiver_args {
 	struct repository *repo;
-	const char *refname;
+	char *refname;
 	const char *prefix;
 	const char *base;
 	size_t baselen;
@@ -36,6 +36,7 @@
 
 #define ARCHIVER_WANT_COMPRESSION_LEVELS 1
 #define ARCHIVER_REMOTE 2
+#define ARCHIVER_HIGH_COMPRESSION_LEVELS 4
 struct archiver {
 	const char *name;
 	int (*write_archive)(const struct archiver *, struct archiver_args *);
diff --git a/attr.c b/attr.c
index a826b2e..4ef85d6 100644
--- a/attr.c
+++ b/attr.c
@@ -52,13 +52,6 @@
 	pthread_mutex_unlock(&map->mutex);
 }
 
-/*
- * The global dictionary of all interned attributes.  This
- * is a singleton object which is shared between threads.
- * Access to this dictionary must be surrounded with a mutex.
- */
-static struct attr_hashmap g_attr_hashmap;
-
 /* The container for objects stored in "struct attr_hashmap" */
 struct attr_hash_entry {
 	struct hashmap_entry ent;
@@ -80,11 +73,14 @@
 	return (a->keylen != b->keylen) || strncmp(a->key, b->key, a->keylen);
 }
 
-/* Initialize an 'attr_hashmap' object */
-static void attr_hashmap_init(struct attr_hashmap *map)
-{
-	hashmap_init(&map->map, attr_hash_entry_cmp, NULL, 0);
-}
+/*
+ * The global dictionary of all interned attributes.  This
+ * is a singleton object which is shared between threads.
+ * Access to this dictionary must be surrounded with a mutex.
+ */
+static struct attr_hashmap g_attr_hashmap = {
+	HASHMAP_INIT(attr_hash_entry_cmp, NULL)
+};
 
 /*
  * Retrieve the 'value' stored in a hashmap given the provided 'key'.
@@ -96,9 +92,6 @@
 	struct attr_hash_entry k;
 	struct attr_hash_entry *e;
 
-	if (!map->map.tablesize)
-		attr_hashmap_init(map);
-
 	hashmap_entry_init(&k.ent, memhash(key, keylen));
 	k.key = key;
 	k.keylen = keylen;
@@ -114,9 +107,6 @@
 {
 	struct attr_hash_entry *e;
 
-	if (!map->map.tablesize)
-		attr_hashmap_init(map);
-
 	e = xmalloc(sizeof(struct attr_hash_entry));
 	hashmap_entry_init(&e->ent, memhash(key, keylen));
 	e->key = key;
diff --git a/bisect.c b/bisect.c
index f5b1368..d8c2c8f 100644
--- a/bisect.c
+++ b/bisect.c
@@ -103,8 +103,10 @@
 	return count;
 }
 
-static inline int halfway(struct commit_list *p, int nr)
+static inline int approx_halfway(struct commit_list *p, int nr)
 {
+	int diff;
+
 	/*
 	 * Don't short-cut something we are not going to return!
 	 */
@@ -113,13 +115,22 @@
 	if (DEBUG_BISECT)
 		return 0;
 	/*
-	 * 2 and 3 are halfway of 5.
+	 * For small number of commits 2 and 3 are halfway of 5, and
 	 * 3 is halfway of 6 but 2 and 4 are not.
 	 */
-	switch (2 * weight(p) - nr) {
+	diff = 2 * weight(p) - nr;
+	switch (diff) {
 	case -1: case 0: case 1:
 		return 1;
 	default:
+		/*
+		 * For large number of commits we are not so strict, it's
+		 * good enough if it's within ~0.1% of the halfway point,
+		 * e.g. 5000 is exactly halfway of 10000, but we consider
+		 * the values [4996, 5004] as halfway as well.
+		 */
+		if (abs(diff) < nr / 1024)
+			return 1;
 		return 0;
 	}
 }
@@ -321,8 +332,9 @@
 		weight_set(p, count_distance(p));
 		clear_distance(list);
 
-		/* Does it happen to be at exactly half-way? */
-		if (!(bisect_flags & FIND_BISECTION_ALL) && halfway(p, nr))
+		/* Does it happen to be at half-way? */
+		if (!(bisect_flags & FIND_BISECTION_ALL) &&
+		      approx_halfway(p, nr))
 			return p;
 		counted++;
 	}
@@ -362,8 +374,9 @@
 			else
 				weight_set(p, weight(q));
 
-			/* Does it happen to be at exactly half-way? */
-			if (!(bisect_flags & FIND_BISECTION_ALL) && halfway(p, nr))
+			/* Does it happen to be at half-way? */
+			if (!(bisect_flags & FIND_BISECTION_ALL) &&
+			      approx_halfway(p, nr))
 				return p;
 		}
 	}
@@ -1090,7 +1103,7 @@
 		  nr), nr, steps_msg);
 	free(steps_msg);
 	/* Clean up objects used, as they will be reused. */
-	clear_commit_marks_all(ALL_REV_FLAGS);
+	repo_clear_commit_marks(r, ALL_REV_FLAGS);
 
 	return bisect_checkout(bisect_rev, no_checkout);
 }
diff --git a/blame.c b/blame.c
index 686845b..a5044fc 100644
--- a/blame.c
+++ b/blame.c
@@ -435,7 +435,7 @@
 
 static void free_fingerprint(struct fingerprint *f)
 {
-	hashmap_free(&f->map);
+	hashmap_clear(&f->map);
 	free(f->entries);
 }
 
@@ -2670,7 +2670,7 @@
 		if (obj->flags & UNINTERESTING)
 			continue;
 		obj = deref_tag(revs->repo, obj, NULL, 0);
-		if (obj->type != OBJ_COMMIT)
+		if (!obj || obj->type != OBJ_COMMIT)
 			die("Non commit %s?", revs->pending.objects[i].name);
 		if (found)
 			die("More than one commit to dig from %s and %s?",
@@ -2701,7 +2701,7 @@
 	/* Is that sole rev a committish? */
 	obj = revs->pending.objects[0].item;
 	obj = deref_tag(revs->repo, obj, NULL, 0);
-	if (obj->type != OBJ_COMMIT)
+	if (!obj || obj->type != OBJ_COMMIT)
 		return NULL;
 
 	/* Do we have HEAD? */
@@ -2737,7 +2737,7 @@
 		if (!(obj->flags & UNINTERESTING))
 			continue;
 		obj = deref_tag(revs->repo, obj, NULL, 0);
-		if (obj->type != OBJ_COMMIT)
+		if (!obj || obj->type != OBJ_COMMIT)
 			die("Non commit %s?", revs->pending.objects[i].name);
 		if (found)
 			die("More than one commit to dig up from, %s and %s?",
@@ -2764,7 +2764,6 @@
 }
 
 void setup_scoreboard(struct blame_scoreboard *sb,
-		      const char *path,
 		      struct blame_origin **orig)
 {
 	const char *final_commit_name = NULL;
@@ -2803,7 +2802,7 @@
 		setup_work_tree();
 		sb->final = fake_working_tree_commit(sb->repo,
 						     &sb->revs->diffopt,
-						     path, sb->contents_from);
+						     sb->path, sb->contents_from);
 		add_pending_object(sb->revs, &(sb->final->object), ":");
 	}
 
@@ -2846,12 +2845,12 @@
 		sb->final_buf_size = o->file.size;
 	}
 	else {
-		o = get_origin(sb->final, path);
+		o = get_origin(sb->final, sb->path);
 		if (fill_blob_sha1_and_mode(sb->repo, o))
-			die(_("no such path %s in %s"), path, final_commit_name);
+			die(_("no such path %s in %s"), sb->path, final_commit_name);
 
 		if (sb->revs->diffopt.flags.allow_textconv &&
-		    textconv_object(sb->repo, path, o->mode, &o->blob_oid, 1, (char **) &sb->final_buf,
+		    textconv_object(sb->repo, sb->path, o->mode, &o->blob_oid, 1, (char **) &sb->final_buf,
 				    &sb->final_buf_size))
 			;
 		else
@@ -2861,7 +2860,7 @@
 		if (!sb->final_buf)
 			die(_("cannot read blob %s for path %s"),
 			    oid_to_hex(&o->blob_oid),
-			    path);
+			    sb->path);
 	}
 	sb->num_read_blob++;
 	prepare_lines(sb);
@@ -2888,8 +2887,7 @@
 	return new_head;
 }
 
-void setup_blame_bloom_data(struct blame_scoreboard *sb,
-			    const char *path)
+void setup_blame_bloom_data(struct blame_scoreboard *sb)
 {
 	struct blame_bloom_data *bd;
 	struct bloom_filter_settings *bs;
@@ -2909,7 +2907,7 @@
 	bd->nr = 0;
 	ALLOC_ARRAY(bd->keys, bd->alloc);
 
-	add_bloom_key(bd, path);
+	add_bloom_key(bd, sb->path);
 
 	sb->bloom_data = bd;
 }
diff --git a/blame.h b/blame.h
index b6bbee4..38bde53 100644
--- a/blame.h
+++ b/blame.h
@@ -181,10 +181,8 @@
 
 void init_scoreboard(struct blame_scoreboard *sb);
 void setup_scoreboard(struct blame_scoreboard *sb,
-		      const char *path,
 		      struct blame_origin **orig);
-void setup_blame_bloom_data(struct blame_scoreboard *sb,
-			    const char *path);
+void setup_blame_bloom_data(struct blame_scoreboard *sb);
 void cleanup_scoreboard(struct blame_scoreboard *sb);
 
 struct blame_entry *blame_entry_prepend(struct blame_entry *head,
diff --git a/block-sha1/sha1.c b/block-sha1/sha1.c
index 22b125c..8681031 100644
--- a/block-sha1/sha1.c
+++ b/block-sha1/sha1.c
@@ -203,7 +203,7 @@
 	ctx->H[4] = 0xc3d2e1f0;
 }
 
-void blk_SHA1_Update(blk_SHA_CTX *ctx, const void *data, unsigned long len)
+void blk_SHA1_Update(blk_SHA_CTX *ctx, const void *data, size_t len)
 {
 	unsigned int lenW = ctx->size & 63;
 
diff --git a/block-sha1/sha1.h b/block-sha1/sha1.h
index 4df6747..9fb0441 100644
--- a/block-sha1/sha1.h
+++ b/block-sha1/sha1.h
@@ -13,7 +13,7 @@
 } blk_SHA_CTX;
 
 void blk_SHA1_Init(blk_SHA_CTX *ctx);
-void blk_SHA1_Update(blk_SHA_CTX *ctx, const void *dataIn, unsigned long len);
+void blk_SHA1_Update(blk_SHA_CTX *ctx, const void *dataIn, size_t len);
 void blk_SHA1_Final(unsigned char hashout[20], blk_SHA_CTX *ctx);
 
 #define platform_SHA_CTX	blk_SHA_CTX
diff --git a/bloom.c b/bloom.c
index 68c7320..b176f28 100644
--- a/bloom.c
+++ b/bloom.c
@@ -229,10 +229,9 @@
 	diffcore_std(&diffopt);
 
 	if (diff_queued_diff.nr <= settings->max_changed_paths) {
-		struct hashmap pathmap;
+		struct hashmap pathmap = HASHMAP_INIT(pathmap_cmp, NULL);
 		struct pathmap_hash_entry *e;
 		struct hashmap_iter iter;
-		hashmap_init(&pathmap, pathmap_cmp, NULL, 0);
 
 		for (i = 0; i < diff_queued_diff.nr; i++) {
 			const char *path = diff_queued_diff.queue[i]->two->path;
@@ -287,7 +286,7 @@
 		}
 
 	cleanup:
-		hashmap_free_entries(&pathmap, struct pathmap_hash_entry, entry);
+		hashmap_clear_and_free(&pathmap, struct pathmap_hash_entry, entry);
 	} else {
 		for (i = 0; i < diff_queued_diff.nr; i++)
 			diff_free_filepair(diff_queued_diff.queue[i]);
diff --git a/builtin.h b/builtin.h
index 53fb290..b6ce981 100644
--- a/builtin.h
+++ b/builtin.h
@@ -155,6 +155,7 @@
 int cmd_fetch_pack(int argc, const char **argv, const char *prefix);
 int cmd_fmt_merge_msg(int argc, const char **argv, const char *prefix);
 int cmd_for_each_ref(int argc, const char **argv, const char *prefix);
+int cmd_for_each_repo(int argc, const char **argv, const char *prefix);
 int cmd_format_patch(int argc, const char **argv, const char *prefix);
 int cmd_fsck(int argc, const char **argv, const char *prefix);
 int cmd_gc(int argc, const char **argv, const char *prefix);
diff --git a/builtin/am.c b/builtin/am.c
index 4949535..f22c73a 100644
--- a/builtin/am.c
+++ b/builtin/am.c
@@ -98,8 +98,6 @@
 	char *author_name;
 	char *author_email;
 	char *author_date;
-	char *committer_name;
-	char *committer_email;
 	char *msg;
 	size_t msg_len;
 
@@ -132,8 +130,6 @@
  */
 static void am_state_init(struct am_state *state)
 {
-	const char *committer;
-	struct ident_split id;
 	int gpgsign;
 
 	memset(state, 0, sizeof(*state));
@@ -154,14 +150,6 @@
 
 	if (!git_config_get_bool("commit.gpgsign", &gpgsign))
 		state->sign_commit = gpgsign ? "" : NULL;
-
-	committer = git_committer_info(IDENT_STRICT);
-	if (split_ident_line(&id, committer, strlen(committer)) < 0)
-		die(_("invalid committer: %s"), committer);
-	state->committer_name =
-		xmemdupz(id.name_begin, id.name_end - id.name_begin);
-	state->committer_email =
-		xmemdupz(id.mail_begin, id.mail_end - id.mail_begin);
 }
 
 /**
@@ -173,8 +161,6 @@
 	free(state->author_name);
 	free(state->author_email);
 	free(state->author_date);
-	free(state->committer_name);
-	free(state->committer_email);
 	free(state->msg);
 	strvec_clear(&state->git_apply_opts);
 }
@@ -1594,8 +1580,9 @@
 			IDENT_STRICT);
 
 	if (state->committer_date_is_author_date)
-		committer = fmt_ident(state->committer_name,
-				      state->committer_email, WANT_COMMITTER_IDENT,
+		committer = fmt_ident(getenv("GIT_COMMITTER_NAME"),
+				      getenv("GIT_COMMITTER_EMAIL"),
+				      WANT_COMMITTER_IDENT,
 				      state->ignore_date ? NULL
 							 : state->author_date,
 				      IDENT_STRICT);
@@ -2237,7 +2224,7 @@
 			N_("allow fall back on 3way merging if needed")),
 		OPT__QUIET(&state.quiet, N_("be quiet")),
 		OPT_SET_INT('s', "signoff", &state.signoff,
-			N_("add a Signed-off-by line to the commit message"),
+			N_("add a Signed-off-by trailer to the commit message"),
 			SIGNOFF_EXPLICIT),
 		OPT_BOOL('u', "utf8", &state.utf8,
 			N_("recode into utf8 (default)")),
diff --git a/builtin/bisect--helper.c b/builtin/bisect--helper.c
index 7512b88..709eb71 100644
--- a/builtin/bisect--helper.c
+++ b/builtin/bisect--helper.c
@@ -20,9 +20,6 @@
 static GIT_PATH_FUNC(git_path_bisect_first_parent, "BISECT_FIRST_PARENT")
 
 static const char * const git_bisect_helper_usage[] = {
-	N_("git bisect--helper --next-all"),
-	N_("git bisect--helper --write-terms <bad_term> <good_term>"),
-	N_("git bisect--helper --bisect-clean-state"),
 	N_("git bisect--helper --bisect-reset [<commit>]"),
 	N_("git bisect--helper --bisect-write [--no-log] <state> <revision> <good_term> <bad_term>"),
 	N_("git bisect--helper --bisect-check-and-set-terms <command> <good_term> <bad_term>"),
@@ -32,7 +29,8 @@
 					    " [--no-checkout] [--first-parent] [<bad> [<good>...]] [--] [<paths>...]"),
 	N_("git bisect--helper --bisect-next"),
 	N_("git bisect--helper --bisect-auto-next"),
-	N_("git bisect--helper --bisect-autostart"),
+	N_("git bisect--helper --bisect-state (bad|new) [<rev>]"),
+	N_("git bisect--helper --bisect-state (good|old) [<rev>...]"),
 	NULL
 };
 
@@ -85,6 +83,19 @@
 	return res;
 }
 
+/*
+ * return code BISECT_INTERNAL_SUCCESS_MERGE_BASE
+ * and BISECT_INTERNAL_SUCCESS_1ST_BAD_FOUND are codes
+ * that indicate special success.
+ */
+
+static int is_bisect_success(enum bisect_error res)
+{
+	return !res ||
+		res == BISECT_INTERNAL_SUCCESS_1ST_BAD_FOUND ||
+		res == BISECT_INTERNAL_SUCCESS_MERGE_BASE;
+}
+
 static int write_in_file(const char *path, const char *mode, const char *format, va_list args)
 {
 	FILE *fp = NULL;
@@ -174,30 +185,6 @@
 	return res;
 }
 
-static int is_expected_rev(const char *expected_hex)
-{
-	struct strbuf actual_hex = STRBUF_INIT;
-	int res = 0;
-	if (strbuf_read_file(&actual_hex, git_path_bisect_expected_rev(), 0) >= 40) {
-		strbuf_trim(&actual_hex);
-		res = !strcmp(actual_hex.buf, expected_hex);
-	}
-	strbuf_release(&actual_hex);
-	return res;
-}
-
-static void check_expected_revs(const char **revs, int rev_nr)
-{
-	int i;
-
-	for (i = 0; i < rev_nr; i++) {
-		if (!is_expected_rev(revs[i])) {
-			unlink_or_warn(git_path_bisect_ancestors_ok());
-			unlink_or_warn(git_path_bisect_expected_rev());
-		}
-	}
-}
-
 static int bisect_reset(const char *commit)
 {
 	struct strbuf branch = STRBUF_INIT;
@@ -609,12 +596,13 @@
 	return bisect_next(terms, prefix);
 }
 
-static int bisect_start(struct bisect_terms *terms, const char **argv, int argc)
+static enum bisect_error bisect_start(struct bisect_terms *terms, const char **argv, int argc)
 {
 	int no_checkout = 0;
 	int first_parent_only = 0;
 	int i, has_double_dash = 0, must_write_terms = 0, bad_seen = 0;
-	int flags, pathspec_pos, res = 0;
+	int flags, pathspec_pos;
+	enum bisect_error res = BISECT_OK;
 	struct string_list revs = STRING_LIST_INIT_DUP;
 	struct string_list states = STRING_LIST_INIT_DUP;
 	struct strbuf start_head = STRBUF_INIT;
@@ -753,14 +741,7 @@
 	 * Get rid of any old bisect state.
 	 */
 	if (bisect_clean_state())
-		return -1;
-
-	/*
-	 * In case of mistaken revs or checkout error, or signals received,
-	 * "bisect_auto_next" below may exit or misbehave.
-	 * We have to trap this to be able to clean up using
-	 * "bisect_clean_state".
-	 */
+		return BISECT_FAILED;
 
 	/*
 	 * Write new start state
@@ -777,7 +758,7 @@
 		}
 		if (update_ref(NULL, "BISECT_HEAD", &oid, NULL, 0,
 			       UPDATE_REFS_MSG_ON_ERR)) {
-			res = -1;
+			res = BISECT_FAILED;
 			goto finish;
 		}
 	}
@@ -789,25 +770,31 @@
 	for (i = 0; i < states.nr; i++)
 		if (bisect_write(states.items[i].string,
 				 revs.items[i].string, terms, 1)) {
-			res = -1;
+			res = BISECT_FAILED;
 			goto finish;
 		}
 
 	if (must_write_terms && write_terms(terms->term_bad,
 					    terms->term_good)) {
-		res = -1;
+		res = BISECT_FAILED;
 		goto finish;
 	}
 
 	res = bisect_append_log_quoted(argv);
 	if (res)
-		res = -1;
+		res = BISECT_FAILED;
 
 finish:
 	string_list_clear(&revs, 0);
 	string_list_clear(&states, 0);
 	strbuf_release(&start_head);
 	strbuf_release(&bisect_names);
+	if (res)
+		return res;
+
+	res = bisect_auto_next(terms, NULL);
+	if (!is_bisect_success(res))
+		bisect_clean_state();
 	return res;
 }
 
@@ -843,14 +830,84 @@
 	return res;
 }
 
+static enum bisect_error bisect_state(struct bisect_terms *terms, const char **argv,
+				      int argc)
+{
+	const char *state;
+	int i, verify_expected = 1;
+	struct object_id oid, expected;
+	struct strbuf buf = STRBUF_INIT;
+	struct oid_array revs = OID_ARRAY_INIT;
+
+	if (!argc)
+		return error(_("Please call `--bisect-state` with at least one argument"));
+
+	if (bisect_autostart(terms))
+		return BISECT_FAILED;
+
+	state = argv[0];
+	if (check_and_set_terms(terms, state) ||
+	    !one_of(state, terms->term_good, terms->term_bad, "skip", NULL))
+		return BISECT_FAILED;
+
+	argv++;
+	argc--;
+	if (argc > 1 && !strcmp(state, terms->term_bad))
+		return error(_("'git bisect %s' can take only one argument."), terms->term_bad);
+
+	if (argc == 0) {
+		const char *head = "BISECT_HEAD";
+		enum get_oid_result res_head = get_oid(head, &oid);
+
+		if (res_head == MISSING_OBJECT) {
+			head = "HEAD";
+			res_head = get_oid(head, &oid);
+		}
+
+		if (res_head)
+			error(_("Bad rev input: %s"), head);
+		oid_array_append(&revs, &oid);
+	}
+
+	/*
+	 * All input revs must be checked before executing bisect_write()
+	 * to discard junk revs.
+	 */
+
+	for (; argc; argc--, argv++) {
+		if (get_oid(*argv, &oid)){
+			error(_("Bad rev input: %s"), *argv);
+			oid_array_clear(&revs);
+			return BISECT_FAILED;
+		}
+		oid_array_append(&revs, &oid);
+	}
+
+	if (strbuf_read_file(&buf, git_path_bisect_expected_rev(), 0) < the_hash_algo->hexsz ||
+	    get_oid_hex(buf.buf, &expected) < 0)
+		verify_expected = 0; /* Ignore invalid file contents */
+	strbuf_release(&buf);
+
+	for (i = 0; i < revs.nr; i++) {
+		if (bisect_write(state, oid_to_hex(&revs.oid[i]), terms, 0)) {
+			oid_array_clear(&revs);
+			return BISECT_FAILED;
+		}
+		if (verify_expected && !oideq(&revs.oid[i], &expected)) {
+			unlink_or_warn(git_path_bisect_ancestors_ok());
+			unlink_or_warn(git_path_bisect_expected_rev());
+			verify_expected = 0;
+		}
+	}
+
+	oid_array_clear(&revs);
+	return bisect_auto_next(terms, NULL);
+}
+
 int cmd_bisect__helper(int argc, const char **argv, const char *prefix)
 {
 	enum {
-		NEXT_ALL = 1,
-		WRITE_TERMS,
-		BISECT_CLEAN_STATE,
-		CHECK_EXPECTED_REVS,
-		BISECT_RESET,
+		BISECT_RESET = 1,
 		BISECT_WRITE,
 		CHECK_AND_SET_TERMS,
 		BISECT_NEXT_CHECK,
@@ -858,18 +915,11 @@
 		BISECT_START,
 		BISECT_AUTOSTART,
 		BISECT_NEXT,
-		BISECT_AUTO_NEXT
+		BISECT_AUTO_NEXT,
+		BISECT_STATE
 	} cmdmode = 0;
 	int res = 0, nolog = 0;
 	struct option options[] = {
-		OPT_CMDMODE(0, "next-all", &cmdmode,
-			 N_("perform 'git bisect next'"), NEXT_ALL),
-		OPT_CMDMODE(0, "write-terms", &cmdmode,
-			 N_("write the terms to .git/BISECT_TERMS"), WRITE_TERMS),
-		OPT_CMDMODE(0, "bisect-clean-state", &cmdmode,
-			 N_("cleanup the bisection state"), BISECT_CLEAN_STATE),
-		OPT_CMDMODE(0, "check-expected-revs", &cmdmode,
-			 N_("check for expected revs"), CHECK_EXPECTED_REVS),
 		OPT_CMDMODE(0, "bisect-reset", &cmdmode,
 			 N_("reset the bisection state"), BISECT_RESET),
 		OPT_CMDMODE(0, "bisect-write", &cmdmode,
@@ -886,8 +936,8 @@
 			 N_("find the next bisection commit"), BISECT_NEXT),
 		OPT_CMDMODE(0, "bisect-auto-next", &cmdmode,
 			 N_("verify the next bisection state then checkout the next bisection commit"), BISECT_AUTO_NEXT),
-		OPT_CMDMODE(0, "bisect-autostart", &cmdmode,
-			 N_("start the bisection if it has not yet been started"), BISECT_AUTOSTART),
+		OPT_CMDMODE(0, "bisect-state", &cmdmode,
+			 N_("mark the state of ref (or refs)"), BISECT_STATE),
 		OPT_BOOL(0, "no-log", &nolog,
 			 N_("no log for BISECT_WRITE")),
 		OPT_END()
@@ -902,20 +952,6 @@
 		usage_with_options(git_bisect_helper_usage, options);
 
 	switch (cmdmode) {
-	case NEXT_ALL:
-		res = bisect_next_all(the_repository, prefix);
-		break;
-	case WRITE_TERMS:
-		if (argc != 2)
-			return error(_("--write-terms requires two arguments"));
-		return write_terms(argv[0], argv[1]);
-	case BISECT_CLEAN_STATE:
-		if (argc != 0)
-			return error(_("--bisect-clean-state requires no arguments"));
-		return bisect_clean_state();
-	case CHECK_EXPECTED_REVS:
-		check_expected_revs(argv, argc);
-		return 0;
 	case BISECT_RESET:
 		if (argc > 1)
 			return error(_("--bisect-reset requires either no argument or a commit"));
@@ -959,11 +995,10 @@
 		get_terms(&terms);
 		res = bisect_auto_next(&terms, prefix);
 		break;
-	case BISECT_AUTOSTART:
-		if (argc)
-			return error(_("--bisect-autostart does not accept arguments"));
+	case BISECT_STATE:
 		set_terms(&terms, "bad", "good");
-		res = bisect_autostart(&terms);
+		get_terms(&terms);
+		res = bisect_state(&terms, argv, argc);
 		break;
 	default:
 		BUG("unknown subcommand %d", cmdmode);
diff --git a/builtin/blame.c b/builtin/blame.c
index bb0f293..6f7e324 100644
--- a/builtin/blame.c
+++ b/builtin/blame.c
@@ -820,6 +820,8 @@
 		if (kind != OBJ_TAG)
 			return -1;
 		obj = deref_tag(r, parse_object(r, &oid), NULL, 0);
+		if (!obj)
+			return -1;
 		oidcpy(&oid, &obj->oid);
 	}
 }
@@ -889,7 +891,8 @@
 		OPT_STRING(0, "contents", &contents_from, N_("file"), N_("Use <file>'s contents as the final image")),
 		OPT_CALLBACK_F('C', NULL, &opt, N_("score"), N_("Find line copies within and across files"), PARSE_OPT_OPTARG, blame_copy_callback),
 		OPT_CALLBACK_F('M', NULL, &opt, N_("score"), N_("Find line movements within and across files"), PARSE_OPT_OPTARG, blame_move_callback),
-		OPT_STRING_LIST('L', NULL, &range_list, N_("n,m"), N_("Process only line range n,m, counting from 1")),
+		OPT_STRING_LIST('L', NULL, &range_list, N_("range"),
+				N_("Process only line range <start>,<end> or function :<funcname>")),
 		OPT__ABBREV(&abbrev),
 		OPT_END()
 	};
@@ -1080,17 +1083,18 @@
 	sb.contents_from = contents_from;
 	sb.reverse = reverse;
 	sb.repo = the_repository;
+	sb.path = path;
 	build_ignorelist(&sb, &ignore_revs_file_list, &ignore_rev_list);
 	string_list_clear(&ignore_revs_file_list, 0);
 	string_list_clear(&ignore_rev_list, 0);
-	setup_scoreboard(&sb, path, &o);
+	setup_scoreboard(&sb, &o);
 
 	/*
 	 * Changed-path Bloom filters are disabled when looking
 	 * for copies.
 	 */
 	if (!(opt & PICKAXE_BLAME_COPY))
-		setup_blame_bloom_data(&sb, path);
+		setup_blame_bloom_data(&sb);
 
 	lno = sb.num_lines;
 
@@ -1109,7 +1113,7 @@
 		if ((!lno && (top || bottom)) || lno < bottom)
 			die(Q_("file %s has only %lu line",
 			       "file %s has only %lu lines",
-			       lno), path, lno);
+			       lno), sb.path, lno);
 		if (bottom < 1)
 			bottom = 1;
 		if (top < 1 || lno < top)
@@ -1134,7 +1138,6 @@
 	string_list_clear(&range_list, 0);
 
 	sb.ent = NULL;
-	sb.path = path;
 
 	if (blame_move_score)
 		sb.move_score = blame_move_score;
diff --git a/builtin/checkout-index.c b/builtin/checkout-index.c
index a854fd1..4bbfc92 100644
--- a/builtin/checkout-index.c
+++ b/builtin/checkout-index.c
@@ -79,6 +79,14 @@
 		return errs > 0 ? -1 : 0;
 	}
 
+	/*
+	 * At this point we know we didn't try to check anything out. If it was
+	 * because we did find an entry but it was stage 0, that's not an
+	 * error.
+	 */
+	if (has_same_name && checkout_stage == CHECKOUT_ALL)
+		return 0;
+
 	if (!state.quiet) {
 		fprintf(stderr, "git checkout-index: %s ", name);
 		if (!has_same_name)
@@ -159,6 +167,7 @@
 	int prefix_length;
 	int force = 0, quiet = 0, not_new = 0;
 	int index_opt = 0;
+	int err = 0;
 	struct option builtin_checkout_index_options[] = {
 		OPT_BOOL('a', "all", &all,
 			N_("check out all files in the index")),
@@ -223,7 +232,7 @@
 		if (read_from_stdin)
 			die("git checkout-index: don't mix '--stdin' and explicit filenames");
 		p = prefix_path(prefix, prefix_length, arg);
-		checkout_file(p, prefix);
+		err |= checkout_file(p, prefix);
 		free(p);
 	}
 
@@ -245,13 +254,16 @@
 				strbuf_swap(&buf, &unquoted);
 			}
 			p = prefix_path(prefix, prefix_length, buf.buf);
-			checkout_file(p, prefix);
+			err |= checkout_file(p, prefix);
 			free(p);
 		}
 		strbuf_release(&unquoted);
 		strbuf_release(&buf);
 	}
 
+	if (err)
+		return 1;
+
 	if (all)
 		checkout_all(prefix, prefix_length);
 
diff --git a/builtin/checkout.c b/builtin/checkout.c
index 0951f8f..9b82119 100644
--- a/builtin/checkout.c
+++ b/builtin/checkout.c
@@ -471,6 +471,19 @@
 
 	if (opts->patch_mode) {
 		const char *patch_mode;
+		const char *rev = new_branch_info->name;
+		char rev_oid[GIT_MAX_HEXSZ + 1];
+
+		/*
+		 * Since rev can be in the form of `<a>...<b>` (which is not
+		 * recognized by diff-index), we will always replace the name
+		 * with the hex of the commit (whether it's in `...` form or
+		 * not) for the run_add_interactive() machinery to work
+		 * properly. However, there is special logic for the HEAD case
+		 * so we mustn't replace that.
+		 */
+		if (rev && strcmp(rev, "HEAD"))
+			rev = oid_to_hex_r(rev_oid, &new_branch_info->commit->object.oid);
 
 		if (opts->checkout_index && opts->checkout_worktree)
 			patch_mode = "--patch=checkout";
@@ -481,7 +494,7 @@
 		else
 			BUG("either flag must have been set, worktree=%d, index=%d",
 			    opts->checkout_worktree, opts->checkout_index);
-		return run_add_interactive(new_branch_info->name, patch_mode, &opts->pathspec);
+		return run_add_interactive(rev, patch_mode, &opts->pathspec);
 	}
 
 	repo_hold_locked_index(the_repository, &lock_file, LOCK_DIE_ON_ERROR);
@@ -1029,7 +1042,7 @@
 		describe_detached_head(_("Previous HEAD position was"), old_commit);
 
 	/* Clean up objects used, as they will be reused. */
-	clear_commit_marks_all(ALL_REV_FLAGS);
+	repo_clear_commit_marks(the_repository, ALL_REV_FLAGS);
 }
 
 static int switch_branches(const struct checkout_opts *opts,
@@ -1093,11 +1106,16 @@
 
 static int git_checkout_config(const char *var, const char *value, void *cb)
 {
+	struct checkout_opts *opts = cb;
+
 	if (!strcmp(var, "diff.ignoresubmodules")) {
-		struct checkout_opts *opts = cb;
 		handle_ignore_submodules_arg(&opts->diff_options, value);
 		return 0;
 	}
+	if (!strcmp(var, "checkout.guess")) {
+		opts->dwim_new_local_branch = git_config_bool(var, value);
+		return 0;
+	}
 
 	if (starts_with(var, "submodule."))
 		return git_default_submodule_config(var, value, NULL);
diff --git a/builtin/clone.c b/builtin/clone.c
index 391aa41..a084192 100644
--- a/builtin/clone.c
+++ b/builtin/clone.c
@@ -53,6 +53,7 @@
 static int deepen;
 static char *option_template, *option_depth, *option_since;
 static char *option_origin = NULL;
+static char *remote_name = NULL;
 static char *option_branch = NULL;
 static struct string_list option_not = STRING_LIST_INIT_NODUP;
 static const char *real_git_dir;
@@ -721,7 +722,7 @@
 		if (!option_bare) {
 			update_ref(msg, "HEAD", &our->old_oid, NULL, 0,
 				   UPDATE_REFS_DIE_ON_ERR);
-			install_branch_config(0, head, option_origin, our->name);
+			install_branch_config(0, head, remote_name, our->name);
 		}
 	} else if (our) {
 		struct commit *c = lookup_commit_reference(the_repository,
@@ -851,8 +852,26 @@
 	return err;
 }
 
+static int git_clone_config(const char *k, const char *v, void *cb)
+{
+	if (!strcmp(k, "clone.defaultremotename")) {
+		free(remote_name);
+		remote_name = xstrdup(v);
+	}
+	return git_default_config(k, v, cb);
+}
+
 static int write_one_config(const char *key, const char *value, void *data)
 {
+	/*
+	 * give git_clone_config a chance to write config values back to the
+	 * environment, since git_config_set_multivar_gently only deals with
+	 * config-file writes
+	 */
+	int apply_failed = git_clone_config(key, value, data);
+	if (apply_failed)
+		return apply_failed;
+
 	return git_config_set_multivar_gently(key,
 					      value ? value : "true",
 					      CONFIG_REGEX_NONE, 0);
@@ -905,12 +924,12 @@
 		}
 		/* Configure the remote */
 		if (value.len) {
-			strbuf_addf(&key, "remote.%s.fetch", option_origin);
+			strbuf_addf(&key, "remote.%s.fetch", remote_name);
 			git_config_set_multivar(key.buf, value.buf, "^$", 0);
 			strbuf_reset(&key);
 
 			if (option_mirror) {
-				strbuf_addf(&key, "remote.%s.mirror", option_origin);
+				strbuf_addf(&key, "remote.%s.mirror", remote_name);
 				git_config_set(key.buf, "true");
 				strbuf_reset(&key);
 			}
@@ -963,6 +982,9 @@
 	struct strvec ref_prefixes = STRVEC_INIT;
 
 	packet_trace_identity("clone");
+
+	git_config(git_clone_config, NULL);
+
 	argc = parse_options(argc, argv, prefix, builtin_clone_options,
 			     builtin_clone_usage, 0);
 
@@ -991,9 +1013,6 @@
 		option_no_checkout = 1;
 	}
 
-	if (!option_origin)
-		option_origin = "origin";
-
 	repo_name = argv[0];
 
 	path = get_repo_path(repo_name, &is_bundle);
@@ -1124,9 +1143,30 @@
 	if (real_git_dir)
 		git_dir = real_git_dir;
 
+	/*
+	 * additional config can be injected with -c, make sure it's included
+	 * after init_db, which clears the entire config environment.
+	 */
 	write_config(&option_config);
 
-	git_config(git_default_config, NULL);
+	/*
+	 * re-read config after init_db and write_config to pick up any config
+	 * injected by --template and --config, respectively.
+	 */
+	git_config(git_clone_config, NULL);
+
+	/*
+	 * apply the remote name provided by --origin only after this second
+	 * call to git_config, to ensure it overrides all config-based values.
+	 */
+	if (option_origin != NULL)
+		remote_name = xstrdup(option_origin);
+
+	if (remote_name == NULL)
+		remote_name = xstrdup("origin");
+
+	if (!valid_remote_name(remote_name))
+		die(_("'%s' is not a valid remote name"), remote_name);
 
 	if (option_bare) {
 		if (option_mirror)
@@ -1135,15 +1175,15 @@
 
 		git_config_set("core.bare", "true");
 	} else {
-		strbuf_addf(&branch_top, "refs/remotes/%s/", option_origin);
+		strbuf_addf(&branch_top, "refs/remotes/%s/", remote_name);
 	}
 
-	strbuf_addf(&key, "remote.%s.url", option_origin);
+	strbuf_addf(&key, "remote.%s.url", remote_name);
 	git_config_set(key.buf, repo);
 	strbuf_reset(&key);
 
 	if (option_no_tags) {
-		strbuf_addf(&key, "remote.%s.tagOpt", option_origin);
+		strbuf_addf(&key, "remote.%s.tagOpt", remote_name);
 		git_config_set(key.buf, "--no-tags");
 		strbuf_reset(&key);
 	}
@@ -1154,7 +1194,7 @@
 	if (option_sparse_checkout && git_sparse_checkout_init(dir))
 		return 1;
 
-	remote = remote_get(option_origin);
+	remote = remote_get(remote_name);
 
 	refspec_appendf(&remote->fetch, "+%s*:%s*", src_ref_prefix,
 			branch_top.buf);
@@ -1266,7 +1306,7 @@
 
 			if (!our_head_points_at)
 				die(_("Remote branch %s not found in upstream %s"),
-				    option_branch, option_origin);
+				    option_branch, remote_name);
 		}
 		else
 			our_head_points_at = remote_head_points_at;
@@ -1274,7 +1314,7 @@
 	else {
 		if (option_branch)
 			die(_("Remote branch %s not found in upstream %s"),
-					option_branch, option_origin);
+					option_branch, remote_name);
 
 		warning(_("You appear to have cloned an empty repository."));
 		mapped_refs = NULL;
@@ -1286,7 +1326,7 @@
 			const char *branch = git_default_branch_name();
 			char *ref = xstrfmt("refs/heads/%s", branch);
 
-			install_branch_config(0, branch, option_origin, ref);
+			install_branch_config(0, branch, remote_name, ref);
 			free(ref);
 		}
 	}
@@ -1295,7 +1335,7 @@
 			remote_head_points_at, &branch_top);
 
 	if (filter_options.choice)
-		partial_clone_register(option_origin, &filter_options);
+		partial_clone_register(remote_name, &filter_options);
 
 	if (is_local)
 		clone_local(path, git_dir);
@@ -1327,6 +1367,7 @@
 	junk_mode = JUNK_LEAVE_REPO;
 	err = checkout(submodule_progress);
 
+	free(remote_name);
 	strbuf_release(&reflog_msg);
 	strbuf_release(&branch_top);
 	strbuf_release(&key);
diff --git a/builtin/commit.c b/builtin/commit.c
index 1dfd799..505fe60 100644
--- a/builtin/commit.c
+++ b/builtin/commit.c
@@ -1507,7 +1507,7 @@
 		OPT_STRING(0, "fixup", &fixup_message, N_("commit"), N_("use autosquash formatted message to fixup specified commit")),
 		OPT_STRING(0, "squash", &squash_message, N_("commit"), N_("use autosquash formatted message to squash specified commit")),
 		OPT_BOOL(0, "reset-author", &renew_authorship, N_("the commit is authored by me now (used with -C/-c/--amend)")),
-		OPT_BOOL('s', "signoff", &signoff, N_("add Signed-off-by:")),
+		OPT_BOOL('s', "signoff", &signoff, N_("add a Signed-off-by trailer")),
 		OPT_FILENAME('t', "template", &template_file, N_("use specified template file")),
 		OPT_BOOL('e', "edit", &edit_flag, N_("force edit of commit")),
 		OPT_CLEANUP(&cleanup_arg),
diff --git a/builtin/credential-store.c b/builtin/credential-store.c
index 5331ab1..ae3c1ba 100644
--- a/builtin/credential-store.c
+++ b/builtin/credential-store.c
@@ -1,4 +1,5 @@
 #include "builtin.h"
+#include "config.h"
 #include "lockfile.h"
 #include "credential.h"
 #include "string-list.h"
@@ -58,8 +59,11 @@
 static void rewrite_credential_file(const char *fn, struct credential *c,
 				    struct strbuf *extra)
 {
-	if (hold_lock_file_for_update(&credential_lock, fn, 0) < 0)
-		die_errno("unable to get credential storage lock");
+	int timeout_ms = 1000;
+
+	git_config_get_int("credentialstore.locktimeoutms", &timeout_ms);
+	if (hold_lock_file_for_update_timeout(&credential_lock, fn, 0, timeout_ms) < 0)
+		die_errno(_("unable to get credential storage lock in %d ms"), timeout_ms);
 	if (extra)
 		print_line(extra);
 	parse_credential_file(fn, c, NULL, print_line);
diff --git a/builtin/credential.c b/builtin/credential.c
index 879acfb..d75dcdc 100644
--- a/builtin/credential.c
+++ b/builtin/credential.c
@@ -1,6 +1,7 @@
 #include "git-compat-util.h"
 #include "credential.h"
 #include "builtin.h"
+#include "config.h"
 
 static const char usage_msg[] =
 	"git credential [fill|approve|reject]";
@@ -10,6 +11,8 @@
 	const char *op;
 	struct credential c = CREDENTIAL_INIT;
 
+	git_config(git_default_config, NULL);
+
 	if (argc != 2 || !strcmp(argv[1], "-h"))
 		usage(usage_msg);
 	op = argv[1];
diff --git a/builtin/diff-index.c b/builtin/diff-index.c
index 93ec642..7f5281c 100644
--- a/builtin/diff-index.c
+++ b/builtin/diff-index.c
@@ -15,7 +15,7 @@
 int cmd_diff_index(int argc, const char **argv, const char *prefix)
 {
 	struct rev_info rev;
-	int cached = 0;
+	unsigned int option = 0;
 	int i;
 	int result;
 
@@ -32,7 +32,9 @@
 		const char *arg = argv[i];
 
 		if (!strcmp(arg, "--cached"))
-			cached = 1;
+			option |= DIFF_INDEX_CACHED;
+		else if (!strcmp(arg, "--merge-base"))
+			option |= DIFF_INDEX_MERGE_BASE;
 		else
 			usage(diff_cache_usage);
 	}
@@ -46,7 +48,7 @@
 	if (rev.pending.nr != 1 ||
 	    rev.max_count != -1 || rev.min_age != -1 || rev.max_age != -1)
 		usage(diff_cache_usage);
-	if (!cached) {
+	if (!(option & DIFF_INDEX_CACHED)) {
 		setup_work_tree();
 		if (read_cache_preload(&rev.diffopt.pathspec) < 0) {
 			perror("read_cache_preload");
@@ -56,7 +58,7 @@
 		perror("read_cache");
 		return -1;
 	}
-	result = run_diff_index(&rev, cached);
+	result = run_diff_index(&rev, option);
 	UNLEAK(rev);
 	return diff_result_code(&rev.diffopt, result);
 }
diff --git a/builtin/diff-tree.c b/builtin/diff-tree.c
index 802363d..9fc95e9 100644
--- a/builtin/diff-tree.c
+++ b/builtin/diff-tree.c
@@ -111,6 +111,7 @@
 	struct setup_revision_opt s_r_opt;
 	struct userformat_want w;
 	int read_stdin = 0;
+	int merge_base = 0;
 
 	if (argc == 2 && !strcmp(argv[1], "-h"))
 		usage(diff_tree_usage);
@@ -143,9 +144,18 @@
 			read_stdin = 1;
 			continue;
 		}
+		if (!strcmp(arg, "--merge-base")) {
+			merge_base = 1;
+			continue;
+		}
 		usage(diff_tree_usage);
 	}
 
+	if (read_stdin && merge_base)
+		die(_("--stdin and --merge-base are mutually exclusive"));
+	if (merge_base && opt->pending.nr != 2)
+		die(_("--merge-base only works with two commits"));
+
 	/*
 	 * NOTE!  We expect "a..b" to expand to "^a b" but it is
 	 * perfectly valid for revision range parser to yield "b ^a",
@@ -165,7 +175,12 @@
 	case 2:
 		tree1 = opt->pending.objects[0].item;
 		tree2 = opt->pending.objects[1].item;
-		if (tree2->flags & UNINTERESTING) {
+		if (merge_base) {
+			struct object_id oid;
+
+			diff_get_merge_base(opt, &oid);
+			tree1 = lookup_object(the_repository, &oid);
+		} else if (tree2->flags & UNINTERESTING) {
 			SWAP(tree2, tree1);
 		}
 		diff_tree_oid(&tree1->oid, &tree2->oid, "", &opt->diffopt);
diff --git a/builtin/diff.c b/builtin/diff.c
index cd4083f..780c338 100644
--- a/builtin/diff.c
+++ b/builtin/diff.c
@@ -26,7 +26,7 @@
 static const char builtin_diff_usage[] =
 "git diff [<options>] [<commit>] [--] [<path>...]\n"
 "   or: git diff [<options>] --cached [<commit>] [--] [<path>...]\n"
-"   or: git diff [<options>] <commit> [<commit>...] <commit> [--] [<path>...]\n"
+"   or: git diff [<options>] <commit> [--merge-base] [<commit>...] <commit> [--] [<path>...]\n"
 "   or: git diff [<options>] <commit>...<commit>] [--] [<path>...]\n"
 "   or: git diff [<options>] <blob> <blob>]\n"
 "   or: git diff [<options>] --no-index [--] <path> <path>]\n"
@@ -134,11 +134,13 @@
 static int builtin_diff_index(struct rev_info *revs,
 			      int argc, const char **argv)
 {
-	int cached = 0;
+	unsigned int option = 0;
 	while (1 < argc) {
 		const char *arg = argv[1];
 		if (!strcmp(arg, "--cached") || !strcmp(arg, "--staged"))
-			cached = 1;
+			option |= DIFF_INDEX_CACHED;
+		else if (!strcmp(arg, "--merge-base"))
+			option |= DIFF_INDEX_MERGE_BASE;
 		else
 			usage(builtin_diff_usage);
 		argv++; argc--;
@@ -151,7 +153,7 @@
 	    revs->max_count != -1 || revs->min_age != -1 ||
 	    revs->max_age != -1)
 		usage(builtin_diff_usage);
-	if (!cached) {
+	if (!(option & DIFF_INDEX_CACHED)) {
 		setup_work_tree();
 		if (read_cache_preload(&revs->diffopt.pathspec) < 0) {
 			perror("read_cache_preload");
@@ -161,7 +163,7 @@
 		perror("read_cache");
 		return -1;
 	}
-	return run_diff_index(revs, cached);
+	return run_diff_index(revs, option);
 }
 
 static int builtin_diff_tree(struct rev_info *revs,
@@ -170,19 +172,34 @@
 			     struct object_array_entry *ent1)
 {
 	const struct object_id *(oid[2]);
-	int swap = 0;
+	struct object_id mb_oid;
+	int merge_base = 0;
 
-	if (argc > 1)
-		usage(builtin_diff_usage);
+	while (1 < argc) {
+		const char *arg = argv[1];
+		if (!strcmp(arg, "--merge-base"))
+			merge_base = 1;
+		else
+			usage(builtin_diff_usage);
+		argv++; argc--;
+	}
 
-	/*
-	 * We saw two trees, ent0 and ent1.  If ent1 is uninteresting,
-	 * swap them.
-	 */
-	if (ent1->item->flags & UNINTERESTING)
-		swap = 1;
-	oid[swap] = &ent0->item->oid;
-	oid[1 - swap] = &ent1->item->oid;
+	if (merge_base) {
+		diff_get_merge_base(revs, &mb_oid);
+		oid[0] = &mb_oid;
+		oid[1] = &revs->pending.objects[1].item->oid;
+	} else {
+		int swap = 0;
+
+		/*
+		 * We saw two trees, ent0 and ent1.  If ent1 is uninteresting,
+		 * swap them.
+		 */
+		if (ent1->item->flags & UNINTERESTING)
+			swap = 1;
+		oid[swap] = &ent0->item->oid;
+		oid[1 - swap] = &ent1->item->oid;
+	}
 	diff_tree_oid(oid[0], oid[1], "", &revs->diffopt);
 	log_tree_diff_flush(revs);
 	return 0;
diff --git a/builtin/difftool.c b/builtin/difftool.c
index 7ac432b..6e18e62 100644
--- a/builtin/difftool.c
+++ b/builtin/difftool.c
@@ -342,7 +342,10 @@
 	const char *workdir, *tmp;
 	int ret = 0, i;
 	FILE *fp;
-	struct hashmap working_tree_dups, submodules, symlinks2;
+	struct hashmap working_tree_dups = HASHMAP_INIT(working_tree_entry_cmp,
+							NULL);
+	struct hashmap submodules = HASHMAP_INIT(pair_cmp, NULL);
+	struct hashmap symlinks2 = HASHMAP_INIT(pair_cmp, NULL);
 	struct hashmap_iter iter;
 	struct pair_entry *entry;
 	struct index_state wtindex;
@@ -383,10 +386,6 @@
 	rdir_len = rdir.len;
 	wtdir_len = wtdir.len;
 
-	hashmap_init(&working_tree_dups, working_tree_entry_cmp, NULL, 0);
-	hashmap_init(&submodules, pair_cmp, NULL, 0);
-	hashmap_init(&symlinks2, pair_cmp, NULL, 0);
-
 	child.no_stdin = 1;
 	child.git_cmd = 1;
 	child.use_shell = 0;
diff --git a/builtin/fast-import.c b/builtin/fast-import.c
index 1bf50a7..dd4d09c 100644
--- a/builtin/fast-import.c
+++ b/builtin/fast-import.c
@@ -150,7 +150,7 @@
 	char *buf;
 };
 
-typedef void (*mark_set_inserter_t)(struct mark_set *s, struct object_id *oid, uintmax_t mark);
+typedef void (*mark_set_inserter_t)(struct mark_set **s, struct object_id *oid, uintmax_t mark);
 typedef void (*each_mark_fn_t)(uintmax_t mark, void *obj, void *cbp);
 
 /* Configured limits on output */
@@ -526,13 +526,15 @@
 	return r;
 }
 
-static void insert_mark(struct mark_set *s, uintmax_t idnum, struct object_entry *oe)
+static void insert_mark(struct mark_set **top, uintmax_t idnum, struct object_entry *oe)
 {
+	struct mark_set *s = *top;
+
 	while ((idnum >> s->shift) >= 1024) {
 		s = mem_pool_calloc(&fi_mem_pool, 1, sizeof(struct mark_set));
-		s->shift = marks->shift + 10;
-		s->data.sets[0] = marks;
-		marks = s;
+		s->shift = (*top)->shift + 10;
+		s->data.sets[0] = *top;
+		*top = s;
 	}
 	while (s->shift) {
 		uintmax_t i = idnum >> s->shift;
@@ -944,7 +946,7 @@
 
 	e = insert_object(&oid);
 	if (mark)
-		insert_mark(marks, mark, e);
+		insert_mark(&marks, mark, e);
 	if (e->idx.offset) {
 		duplicate_count_by_type[type]++;
 		return 1;
@@ -1142,7 +1144,7 @@
 	e = insert_object(&oid);
 
 	if (mark)
-		insert_mark(marks, mark, e);
+		insert_mark(&marks, mark, e);
 
 	if (e->idx.offset) {
 		duplicate_count_by_type[OBJ_BLOB]++;
@@ -1717,7 +1719,7 @@
 	}
 }
 
-static void insert_object_entry(struct mark_set *s, struct object_id *oid, uintmax_t mark)
+static void insert_object_entry(struct mark_set **s, struct object_id *oid, uintmax_t mark)
 {
 	struct object_entry *e;
 	e = find_object(oid);
@@ -1734,12 +1736,12 @@
 	insert_mark(s, mark, e);
 }
 
-static void insert_oid_entry(struct mark_set *s, struct object_id *oid, uintmax_t mark)
+static void insert_oid_entry(struct mark_set **s, struct object_id *oid, uintmax_t mark)
 {
 	insert_mark(s, mark, xmemdupz(oid, sizeof(*oid)));
 }
 
-static void read_mark_file(struct mark_set *s, FILE *f, mark_set_inserter_t inserter)
+static void read_mark_file(struct mark_set **s, FILE *f, mark_set_inserter_t inserter)
 {
 	char line[512];
 	while (fgets(line, sizeof(line), f)) {
@@ -1772,7 +1774,7 @@
 		goto done; /* Marks file does not exist */
 	else
 		die_errno("cannot read '%s'", import_marks_file);
-	read_mark_file(marks, f, insert_object_entry);
+	read_mark_file(&marks, f, insert_object_entry);
 	fclose(f);
 done:
 	import_marks_file_done = 1;
@@ -3228,7 +3230,7 @@
 		die(_("Expected 'to' command, got %s"), command_buf.buf);
 	e = find_object(&b.oid);
 	assert(e);
-	insert_mark(marks, next_mark, e);
+	insert_mark(&marks, next_mark, e);
 }
 
 static char* make_fast_import_path(const char *path)
@@ -3321,13 +3323,14 @@
 	*f = '\0';
 	f++;
 	ms = xcalloc(1, sizeof(*ms));
-	string_list_insert(list, s)->util = ms;
 
 	fp = fopen(f, "r");
 	if (!fp)
 		die_errno("cannot read '%s'", f);
-	read_mark_file(ms, fp, insert_oid_entry);
+	read_mark_file(&ms, fp, insert_oid_entry);
 	fclose(fp);
+
+	string_list_insert(list, s)->util = ms;
 }
 
 static int parse_one_option(const char *option)
@@ -3396,7 +3399,6 @@
 		option_rewrite_submodules(arg, &sub_marks_to);
 	} else if (skip_prefix(feature, "rewrite-submodules-from=", &arg)) {
 		option_rewrite_submodules(arg, &sub_marks_from);
-	} else if (skip_prefix(feature, "rewrite-submodules-from=", &arg)) {
 	} else if (!strcmp(feature, "get-mark")) {
 		; /* Don't die - this feature is supported */
 	} else if (!strcmp(feature, "cat-blob")) {
diff --git a/builtin/fetch.c b/builtin/fetch.c
index f9c3c49..ecf8537 100644
--- a/builtin/fetch.c
+++ b/builtin/fetch.c
@@ -393,7 +393,7 @@
 		item = refname_hash_add(&remote_refs, ref->name, &ref->old_oid);
 		string_list_insert(&remote_refs_list, ref->name);
 	}
-	hashmap_free_entries(&existing_refs, struct refname_hash_entry, ent);
+	hashmap_clear_and_free(&existing_refs, struct refname_hash_entry, ent);
 
 	/*
 	 * We may have a final lightweight tag that needs to be
@@ -428,7 +428,7 @@
 		**tail = rm;
 		*tail = &rm->next;
 	}
-	hashmap_free_entries(&remote_refs, struct refname_hash_entry, ent);
+	hashmap_clear_and_free(&remote_refs, struct refname_hash_entry, ent);
 	string_list_clear(&remote_refs_list, 0);
 	oidset_clear(&fetch_oids);
 }
@@ -573,7 +573,7 @@
 		}
 	}
 	if (existing_refs_populated)
-		hashmap_free_entries(&existing_refs, struct refname_hash_entry, ent);
+		hashmap_clear_and_free(&existing_refs, struct refname_hash_entry, ent);
 
 	return ref_map;
 }
diff --git a/builtin/for-each-repo.c b/builtin/for-each-repo.c
new file mode 100644
index 0000000..5bba623
--- /dev/null
+++ b/builtin/for-each-repo.c
@@ -0,0 +1,58 @@
+#include "cache.h"
+#include "config.h"
+#include "builtin.h"
+#include "parse-options.h"
+#include "run-command.h"
+#include "string-list.h"
+
+static const char * const for_each_repo_usage[] = {
+	N_("git for-each-repo --config=<config> <command-args>"),
+	NULL
+};
+
+static int run_command_on_repo(const char *path,
+			       void *cbdata)
+{
+	int i;
+	struct child_process child = CHILD_PROCESS_INIT;
+	struct strvec *args = (struct strvec *)cbdata;
+
+	child.git_cmd = 1;
+	strvec_pushl(&child.args, "-C", path, NULL);
+
+	for (i = 0; i < args->nr; i++)
+		strvec_push(&child.args, args->v[i]);
+
+	return run_command(&child);
+}
+
+int cmd_for_each_repo(int argc, const char **argv, const char *prefix)
+{
+	static const char *config_key = NULL;
+	int i, result = 0;
+	const struct string_list *values;
+	struct strvec args = STRVEC_INIT;
+
+	const struct option options[] = {
+		OPT_STRING(0, "config", &config_key, N_("config"),
+			   N_("config key storing a list of repository paths")),
+		OPT_END()
+	};
+
+	argc = parse_options(argc, argv, prefix, options, for_each_repo_usage,
+			     PARSE_OPT_STOP_AT_NON_OPTION);
+
+	if (!config_key)
+		die(_("missing --config=<config>"));
+
+	for (i = 0; i < argc; i++)
+		strvec_push(&args, argv[i]);
+
+	values = repo_config_get_value_multi(the_repository,
+					     config_key);
+
+	for (i = 0; !result && i < values->nr; i++)
+		result = run_command_on_repo(values->items[i].string, &args);
+
+	return result;
+}
diff --git a/builtin/gc.c b/builtin/gc.c
index 0909593..3e8d76f 100644
--- a/builtin/gc.c
+++ b/builtin/gc.c
@@ -29,6 +29,9 @@
 #include "tree.h"
 #include "promisor-remote.h"
 #include "refs.h"
+#include "remote.h"
+#include "object-store.h"
+#include "exec-cmd.h"
 
 #define FAILED_RUN "failed to run %s"
 
@@ -531,7 +534,7 @@
 	const char *name;
 	pid_t pid;
 	int daemonized = 0;
-	int keep_base_pack = -1;
+	int keep_largest_pack = -1;
 	timestamp_t dummy;
 
 	struct option builtin_gc_options[] = {
@@ -545,7 +548,7 @@
 		OPT_BOOL_F(0, "force", &force,
 			   N_("force running gc even if there may be another gc running"),
 			   PARSE_OPT_NOCOMPLETE),
-		OPT_BOOL(0, "keep-largest-pack", &keep_base_pack,
+		OPT_BOOL(0, "keep-largest-pack", &keep_largest_pack,
 			 N_("repack all other packs except the largest pack")),
 		OPT_END()
 	};
@@ -622,8 +625,8 @@
 	} else {
 		struct string_list keep_pack = STRING_LIST_INIT_NODUP;
 
-		if (keep_base_pack != -1) {
-			if (keep_base_pack)
+		if (keep_largest_pack != -1) {
+			if (keep_largest_pack)
 				find_base_packs(&keep_pack, 0);
 		} else if (big_pack_threshold) {
 			find_base_packs(&keep_pack, big_pack_threshold);
@@ -701,14 +704,51 @@
 	return 0;
 }
 
-static const char * const builtin_maintenance_run_usage[] = {
-	N_("git maintenance run [--auto] [--[no-]quiet] [--task=<task>]"),
+static const char *const builtin_maintenance_run_usage[] = {
+	N_("git maintenance run [--auto] [--[no-]quiet] [--task=<task>] [--schedule]"),
 	NULL
 };
 
+enum schedule_priority {
+	SCHEDULE_NONE = 0,
+	SCHEDULE_WEEKLY = 1,
+	SCHEDULE_DAILY = 2,
+	SCHEDULE_HOURLY = 3,
+};
+
+static enum schedule_priority parse_schedule(const char *value)
+{
+	if (!value)
+		return SCHEDULE_NONE;
+	if (!strcasecmp(value, "hourly"))
+		return SCHEDULE_HOURLY;
+	if (!strcasecmp(value, "daily"))
+		return SCHEDULE_DAILY;
+	if (!strcasecmp(value, "weekly"))
+		return SCHEDULE_WEEKLY;
+	return SCHEDULE_NONE;
+}
+
+static int maintenance_opt_schedule(const struct option *opt, const char *arg,
+				    int unset)
+{
+	enum schedule_priority *priority = opt->value;
+
+	if (unset)
+		die(_("--no-schedule is not allowed"));
+
+	*priority = parse_schedule(arg);
+
+	if (!*priority)
+		die(_("unrecognized --schedule argument '%s'"), arg);
+
+	return 0;
+}
+
 struct maintenance_run_opts {
 	int auto_flag;
 	int quiet;
+	enum schedule_priority schedule;
 };
 
 /* Remember to update object flag allocation in object.h */
@@ -737,9 +777,15 @@
 	commit = lookup_commit(the_repository, oid);
 	if (!commit)
 		return 0;
-	if (parse_commit(commit))
+	if (parse_commit(commit) ||
+	    commit_graph_position(commit) != COMMIT_NOT_FROM_GRAPH)
 		return 0;
 
+	data->num_not_in_graph++;
+
+	if (data->num_not_in_graph >= data->limit)
+		return 1;
+
 	commit_list_append(commit, &stack);
 
 	while (!result && stack) {
@@ -786,7 +832,7 @@
 
 	result = for_each_ref(dfs_on_ref, &data);
 
-	clear_commit_marks_all(SEEN);
+	repo_clear_commit_marks(the_repository, SEEN);
 
 	return result;
 }
@@ -807,6 +853,10 @@
 
 static int maintenance_task_commit_graph(struct maintenance_run_opts *opts)
 {
+	prepare_repo_settings(the_repository);
+	if (!the_repository->settings.core_commit_graph)
+		return 0;
+
 	close_object_store(the_repository->objects);
 	if (run_write_commit_graph(opts)) {
 		error(_("failed to write commit-graph"));
@@ -816,6 +866,51 @@
 	return 0;
 }
 
+static int fetch_remote(const char *remote, struct maintenance_run_opts *opts)
+{
+	struct child_process child = CHILD_PROCESS_INIT;
+
+	child.git_cmd = 1;
+	strvec_pushl(&child.args, "fetch", remote, "--prune", "--no-tags",
+		     "--no-write-fetch-head", "--recurse-submodules=no",
+		     "--refmap=", NULL);
+
+	if (opts->quiet)
+		strvec_push(&child.args, "--quiet");
+
+	strvec_pushf(&child.args, "+refs/heads/*:refs/prefetch/%s/*", remote);
+
+	return !!run_command(&child);
+}
+
+static int append_remote(struct remote *remote, void *cbdata)
+{
+	struct string_list *remotes = (struct string_list *)cbdata;
+
+	string_list_append(remotes, remote->name);
+	return 0;
+}
+
+static int maintenance_task_prefetch(struct maintenance_run_opts *opts)
+{
+	int result = 0;
+	struct string_list_item *item;
+	struct string_list remotes = STRING_LIST_INIT_DUP;
+
+	if (for_each_remote(append_remote, &remotes)) {
+		error(_("failed to fill remotes"));
+		result = 1;
+		goto cleanup;
+	}
+
+	for_each_string_list_item(item, &remotes)
+		result |= fetch_remote(item->string, opts);
+
+cleanup:
+	string_list_clear(&remotes, 0);
+	return result;
+}
+
 static int maintenance_task_gc(struct maintenance_run_opts *opts)
 {
 	struct child_process child = CHILD_PROCESS_INIT;
@@ -834,6 +929,268 @@
 	return run_command(&child);
 }
 
+static int prune_packed(struct maintenance_run_opts *opts)
+{
+	struct child_process child = CHILD_PROCESS_INIT;
+
+	child.git_cmd = 1;
+	strvec_push(&child.args, "prune-packed");
+
+	if (opts->quiet)
+		strvec_push(&child.args, "--quiet");
+
+	return !!run_command(&child);
+}
+
+struct write_loose_object_data {
+	FILE *in;
+	int count;
+	int batch_size;
+};
+
+static int loose_object_auto_limit = 100;
+
+static int loose_object_count(const struct object_id *oid,
+			       const char *path,
+			       void *data)
+{
+	int *count = (int*)data;
+	if (++(*count) >= loose_object_auto_limit)
+		return 1;
+	return 0;
+}
+
+static int loose_object_auto_condition(void)
+{
+	int count = 0;
+
+	git_config_get_int("maintenance.loose-objects.auto",
+			   &loose_object_auto_limit);
+
+	if (!loose_object_auto_limit)
+		return 0;
+	if (loose_object_auto_limit < 0)
+		return 1;
+
+	return for_each_loose_file_in_objdir(the_repository->objects->odb->path,
+					     loose_object_count,
+					     NULL, NULL, &count);
+}
+
+static int bail_on_loose(const struct object_id *oid,
+			 const char *path,
+			 void *data)
+{
+	return 1;
+}
+
+static int write_loose_object_to_stdin(const struct object_id *oid,
+				       const char *path,
+				       void *data)
+{
+	struct write_loose_object_data *d = (struct write_loose_object_data *)data;
+
+	fprintf(d->in, "%s\n", oid_to_hex(oid));
+
+	return ++(d->count) > d->batch_size;
+}
+
+static int pack_loose(struct maintenance_run_opts *opts)
+{
+	struct repository *r = the_repository;
+	int result = 0;
+	struct write_loose_object_data data;
+	struct child_process pack_proc = CHILD_PROCESS_INIT;
+
+	/*
+	 * Do not start pack-objects process
+	 * if there are no loose objects.
+	 */
+	if (!for_each_loose_file_in_objdir(r->objects->odb->path,
+					   bail_on_loose,
+					   NULL, NULL, NULL))
+		return 0;
+
+	pack_proc.git_cmd = 1;
+
+	strvec_push(&pack_proc.args, "pack-objects");
+	if (opts->quiet)
+		strvec_push(&pack_proc.args, "--quiet");
+	strvec_pushf(&pack_proc.args, "%s/pack/loose", r->objects->odb->path);
+
+	pack_proc.in = -1;
+
+	if (start_command(&pack_proc)) {
+		error(_("failed to start 'git pack-objects' process"));
+		return 1;
+	}
+
+	data.in = xfdopen(pack_proc.in, "w");
+	data.count = 0;
+	data.batch_size = 50000;
+
+	for_each_loose_file_in_objdir(r->objects->odb->path,
+				      write_loose_object_to_stdin,
+				      NULL,
+				      NULL,
+				      &data);
+
+	fclose(data.in);
+
+	if (finish_command(&pack_proc)) {
+		error(_("failed to finish 'git pack-objects' process"));
+		result = 1;
+	}
+
+	return result;
+}
+
+static int maintenance_task_loose_objects(struct maintenance_run_opts *opts)
+{
+	return prune_packed(opts) || pack_loose(opts);
+}
+
+static int incremental_repack_auto_condition(void)
+{
+	struct packed_git *p;
+	int enabled;
+	int incremental_repack_auto_limit = 10;
+	int count = 0;
+
+	if (git_config_get_bool("core.multiPackIndex", &enabled) ||
+	    !enabled)
+		return 0;
+
+	git_config_get_int("maintenance.incremental-repack.auto",
+			   &incremental_repack_auto_limit);
+
+	if (!incremental_repack_auto_limit)
+		return 0;
+	if (incremental_repack_auto_limit < 0)
+		return 1;
+
+	for (p = get_packed_git(the_repository);
+	     count < incremental_repack_auto_limit && p;
+	     p = p->next) {
+		if (!p->multi_pack_index)
+			count++;
+	}
+
+	return count >= incremental_repack_auto_limit;
+}
+
+static int multi_pack_index_write(struct maintenance_run_opts *opts)
+{
+	struct child_process child = CHILD_PROCESS_INIT;
+
+	child.git_cmd = 1;
+	strvec_pushl(&child.args, "multi-pack-index", "write", NULL);
+
+	if (opts->quiet)
+		strvec_push(&child.args, "--no-progress");
+
+	if (run_command(&child))
+		return error(_("failed to write multi-pack-index"));
+
+	return 0;
+}
+
+static int multi_pack_index_expire(struct maintenance_run_opts *opts)
+{
+	struct child_process child = CHILD_PROCESS_INIT;
+
+	child.git_cmd = 1;
+	strvec_pushl(&child.args, "multi-pack-index", "expire", NULL);
+
+	if (opts->quiet)
+		strvec_push(&child.args, "--no-progress");
+
+	close_object_store(the_repository->objects);
+
+	if (run_command(&child))
+		return error(_("'git multi-pack-index expire' failed"));
+
+	return 0;
+}
+
+#define TWO_GIGABYTES (INT32_MAX)
+
+static off_t get_auto_pack_size(void)
+{
+	/*
+	 * The "auto" value is special: we optimize for
+	 * one large pack-file (i.e. from a clone) and
+	 * expect the rest to be small and they can be
+	 * repacked quickly.
+	 *
+	 * The strategy we select here is to select a
+	 * size that is one more than the second largest
+	 * pack-file. This ensures that we will repack
+	 * at least two packs if there are three or more
+	 * packs.
+	 */
+	off_t max_size = 0;
+	off_t second_largest_size = 0;
+	off_t result_size;
+	struct packed_git *p;
+	struct repository *r = the_repository;
+
+	reprepare_packed_git(r);
+	for (p = get_all_packs(r); p; p = p->next) {
+		if (p->pack_size > max_size) {
+			second_largest_size = max_size;
+			max_size = p->pack_size;
+		} else if (p->pack_size > second_largest_size)
+			second_largest_size = p->pack_size;
+	}
+
+	result_size = second_largest_size + 1;
+
+	/* But limit ourselves to a batch size of 2g */
+	if (result_size > TWO_GIGABYTES)
+		result_size = TWO_GIGABYTES;
+
+	return result_size;
+}
+
+static int multi_pack_index_repack(struct maintenance_run_opts *opts)
+{
+	struct child_process child = CHILD_PROCESS_INIT;
+
+	child.git_cmd = 1;
+	strvec_pushl(&child.args, "multi-pack-index", "repack", NULL);
+
+	if (opts->quiet)
+		strvec_push(&child.args, "--no-progress");
+
+	strvec_pushf(&child.args, "--batch-size=%"PRIuMAX,
+				  (uintmax_t)get_auto_pack_size());
+
+	close_object_store(the_repository->objects);
+
+	if (run_command(&child))
+		return error(_("'git multi-pack-index repack' failed"));
+
+	return 0;
+}
+
+static int maintenance_task_incremental_repack(struct maintenance_run_opts *opts)
+{
+	prepare_repo_settings(the_repository);
+	if (!the_repository->settings.core_multi_pack_index) {
+		warning(_("skipping incremental-repack task because core.multiPackIndex is disabled"));
+		return 0;
+	}
+
+	if (multi_pack_index_write(opts))
+		return 1;
+	if (multi_pack_index_expire(opts))
+		return 1;
+	if (multi_pack_index_repack(opts))
+		return 1;
+	return 0;
+}
+
 typedef int maintenance_task_fn(struct maintenance_run_opts *opts);
 
 /*
@@ -849,11 +1206,16 @@
 	maintenance_auto_fn *auto_condition;
 	unsigned enabled:1;
 
+	enum schedule_priority schedule;
+
 	/* -1 if not selected. */
 	int selected_order;
 };
 
 enum maintenance_task_label {
+	TASK_PREFETCH,
+	TASK_LOOSE_OBJECTS,
+	TASK_INCREMENTAL_REPACK,
 	TASK_GC,
 	TASK_COMMIT_GRAPH,
 
@@ -862,6 +1224,20 @@
 };
 
 static struct maintenance_task tasks[] = {
+	[TASK_PREFETCH] = {
+		"prefetch",
+		maintenance_task_prefetch,
+	},
+	[TASK_LOOSE_OBJECTS] = {
+		"loose-objects",
+		maintenance_task_loose_objects,
+		loose_object_auto_condition,
+	},
+	[TASK_INCREMENTAL_REPACK] = {
+		"incremental-repack",
+		maintenance_task_incremental_repack,
+		incremental_repack_auto_condition,
+	},
 	[TASK_GC] = {
 		"gc",
 		maintenance_task_gc,
@@ -877,10 +1253,8 @@
 
 static int compare_tasks_by_selection(const void *a_, const void *b_)
 {
-	const struct maintenance_task *a, *b;
-
-	a = (const struct maintenance_task *)&a_;
-	b = (const struct maintenance_task *)&b_;
+	const struct maintenance_task *a = a_;
+	const struct maintenance_task *b = b_;
 
 	return b->selected_order - a->selected_order;
 }
@@ -927,6 +1301,9 @@
 		     !tasks[i].auto_condition()))
 			continue;
 
+		if (opts->schedule && tasks[i].schedule < opts->schedule)
+			continue;
+
 		trace2_region_enter("maintenance", tasks[i].name, r);
 		if (tasks[i].fn(opts)) {
 			error(_("task '%s' failed"), tasks[i].name);
@@ -939,21 +1316,54 @@
 	return result;
 }
 
-static void initialize_task_config(void)
+static void initialize_maintenance_strategy(void)
+{
+	char *config_str;
+
+	if (git_config_get_string("maintenance.strategy", &config_str))
+		return;
+
+	if (!strcasecmp(config_str, "incremental")) {
+		tasks[TASK_GC].schedule = SCHEDULE_NONE;
+		tasks[TASK_COMMIT_GRAPH].enabled = 1;
+		tasks[TASK_COMMIT_GRAPH].schedule = SCHEDULE_HOURLY;
+		tasks[TASK_PREFETCH].enabled = 1;
+		tasks[TASK_PREFETCH].schedule = SCHEDULE_HOURLY;
+		tasks[TASK_INCREMENTAL_REPACK].enabled = 1;
+		tasks[TASK_INCREMENTAL_REPACK].schedule = SCHEDULE_DAILY;
+		tasks[TASK_LOOSE_OBJECTS].enabled = 1;
+		tasks[TASK_LOOSE_OBJECTS].schedule = SCHEDULE_DAILY;
+	}
+}
+
+static void initialize_task_config(int schedule)
 {
 	int i;
 	struct strbuf config_name = STRBUF_INIT;
 	gc_config();
 
+	if (schedule)
+		initialize_maintenance_strategy();
+
 	for (i = 0; i < TASK__COUNT; i++) {
 		int config_value;
+		char *config_str;
 
-		strbuf_setlen(&config_name, 0);
+		strbuf_reset(&config_name);
 		strbuf_addf(&config_name, "maintenance.%s.enabled",
 			    tasks[i].name);
 
 		if (!git_config_get_bool(config_name.buf, &config_value))
 			tasks[i].enabled = config_value;
+
+		strbuf_reset(&config_name);
+		strbuf_addf(&config_name, "maintenance.%s.schedule",
+			    tasks[i].name);
+
+		if (!git_config_get_string(config_name.buf, &config_str)) {
+			tasks[i].schedule = parse_schedule(config_str);
+			free(config_str);
+		}
 	}
 
 	strbuf_release(&config_name);
@@ -997,6 +1407,9 @@
 	struct option builtin_maintenance_run_options[] = {
 		OPT_BOOL(0, "auto", &opts.auto_flag,
 			 N_("run tasks based on the state of the repository")),
+		OPT_CALLBACK(0, "schedule", &opts.schedule, N_("frequency"),
+			     N_("run tasks based on frequency"),
+			     maintenance_opt_schedule),
 		OPT_BOOL(0, "quiet", &opts.quiet,
 			 N_("do not report progress or other information over stderr")),
 		OPT_CALLBACK_F(0, "task", NULL, N_("task"),
@@ -1007,7 +1420,6 @@
 	memset(&opts, 0, sizeof(opts));
 
 	opts.quiet = !isatty(2);
-	initialize_task_config();
 
 	for (i = 0; i < TASK__COUNT; i++)
 		tasks[i].selected_order = -1;
@@ -1017,13 +1429,196 @@
 			     builtin_maintenance_run_usage,
 			     PARSE_OPT_STOP_AT_NON_OPTION);
 
+	if (opts.auto_flag && opts.schedule)
+		die(_("use at most one of --auto and --schedule=<frequency>"));
+
+	initialize_task_config(opts.schedule);
+
 	if (argc != 0)
 		usage_with_options(builtin_maintenance_run_usage,
 				   builtin_maintenance_run_options);
 	return maintenance_run_tasks(&opts);
 }
 
-static const char builtin_maintenance_usage[] = N_("git maintenance run [<options>]");
+static int maintenance_register(void)
+{
+	char *config_value;
+	struct child_process config_set = CHILD_PROCESS_INIT;
+	struct child_process config_get = CHILD_PROCESS_INIT;
+
+	/* There is no current repository, so skip registering it */
+	if (!the_repository || !the_repository->gitdir)
+		return 0;
+
+	/* Disable foreground maintenance */
+	git_config_set("maintenance.auto", "false");
+
+	/* Set maintenance strategy, if unset */
+	if (!git_config_get_string("maintenance.strategy", &config_value))
+		free(config_value);
+	else
+		git_config_set("maintenance.strategy", "incremental");
+
+	config_get.git_cmd = 1;
+	strvec_pushl(&config_get.args, "config", "--global", "--get", "maintenance.repo",
+		     the_repository->worktree ? the_repository->worktree
+					      : the_repository->gitdir,
+			 NULL);
+	config_get.out = -1;
+
+	if (start_command(&config_get))
+		return error(_("failed to run 'git config'"));
+
+	/* We already have this value in our config! */
+	if (!finish_command(&config_get))
+		return 0;
+
+	config_set.git_cmd = 1;
+	strvec_pushl(&config_set.args, "config", "--add", "--global", "maintenance.repo",
+		     the_repository->worktree ? the_repository->worktree
+					      : the_repository->gitdir,
+		     NULL);
+
+	return run_command(&config_set);
+}
+
+static int maintenance_unregister(void)
+{
+	struct child_process config_unset = CHILD_PROCESS_INIT;
+
+	if (!the_repository || !the_repository->gitdir)
+		return error(_("no current repository to unregister"));
+
+	config_unset.git_cmd = 1;
+	strvec_pushl(&config_unset.args, "config", "--global", "--unset",
+		     "maintenance.repo",
+		     the_repository->worktree ? the_repository->worktree
+					      : the_repository->gitdir,
+		     NULL);
+
+	return run_command(&config_unset);
+}
+
+#define BEGIN_LINE "# BEGIN GIT MAINTENANCE SCHEDULE"
+#define END_LINE "# END GIT MAINTENANCE SCHEDULE"
+
+static int update_background_schedule(int run_maintenance)
+{
+	int result = 0;
+	int in_old_region = 0;
+	struct child_process crontab_list = CHILD_PROCESS_INIT;
+	struct child_process crontab_edit = CHILD_PROCESS_INIT;
+	FILE *cron_list, *cron_in;
+	const char *crontab_name;
+	struct strbuf line = STRBUF_INIT;
+	struct lock_file lk;
+	char *lock_path = xstrfmt("%s/schedule", the_repository->objects->odb->path);
+
+	if (hold_lock_file_for_update(&lk, lock_path, LOCK_NO_DEREF) < 0)
+		return error(_("another process is scheduling background maintenance"));
+
+	crontab_name = getenv("GIT_TEST_CRONTAB");
+	if (!crontab_name)
+		crontab_name = "crontab";
+
+	strvec_split(&crontab_list.args, crontab_name);
+	strvec_push(&crontab_list.args, "-l");
+	crontab_list.in = -1;
+	crontab_list.out = dup(lk.tempfile->fd);
+	crontab_list.git_cmd = 0;
+
+	if (start_command(&crontab_list)) {
+		result = error(_("failed to run 'crontab -l'; your system might not support 'cron'"));
+		goto cleanup;
+	}
+
+	/* Ignore exit code, as an empty crontab will return error. */
+	finish_command(&crontab_list);
+
+	/*
+	 * Read from the .lock file, filtering out the old
+	 * schedule while appending the new schedule.
+	 */
+	cron_list = fdopen(lk.tempfile->fd, "r");
+	rewind(cron_list);
+
+	strvec_split(&crontab_edit.args, crontab_name);
+	crontab_edit.in = -1;
+	crontab_edit.git_cmd = 0;
+
+	if (start_command(&crontab_edit)) {
+		result = error(_("failed to run 'crontab'; your system might not support 'cron'"));
+		goto cleanup;
+	}
+
+	cron_in = fdopen(crontab_edit.in, "w");
+	if (!cron_in) {
+		result = error(_("failed to open stdin of 'crontab'"));
+		goto done_editing;
+	}
+
+	while (!strbuf_getline_lf(&line, cron_list)) {
+		if (!in_old_region && !strcmp(line.buf, BEGIN_LINE))
+			in_old_region = 1;
+		if (in_old_region)
+			continue;
+		fprintf(cron_in, "%s\n", line.buf);
+		if (in_old_region && !strcmp(line.buf, END_LINE))
+			in_old_region = 0;
+	}
+
+	if (run_maintenance) {
+		struct strbuf line_format = STRBUF_INIT;
+		const char *exec_path = git_exec_path();
+
+		fprintf(cron_in, "%s\n", BEGIN_LINE);
+		fprintf(cron_in,
+			"# The following schedule was created by Git\n");
+		fprintf(cron_in, "# Any edits made in this region might be\n");
+		fprintf(cron_in,
+			"# replaced in the future by a Git command.\n\n");
+
+		strbuf_addf(&line_format,
+			    "%%s %%s * * %%s \"%s/git\" --exec-path=\"%s\" for-each-repo --config=maintenance.repo maintenance run --schedule=%%s\n",
+			    exec_path, exec_path);
+		fprintf(cron_in, line_format.buf, "0", "1-23", "*", "hourly");
+		fprintf(cron_in, line_format.buf, "0", "0", "1-6", "daily");
+		fprintf(cron_in, line_format.buf, "0", "0", "0", "weekly");
+		strbuf_release(&line_format);
+
+		fprintf(cron_in, "\n%s\n", END_LINE);
+	}
+
+	fflush(cron_in);
+	fclose(cron_in);
+	close(crontab_edit.in);
+
+done_editing:
+	if (finish_command(&crontab_edit)) {
+		result = error(_("'crontab' died"));
+		goto cleanup;
+	}
+	fclose(cron_list);
+
+cleanup:
+	rollback_lock_file(&lk);
+	return result;
+}
+
+static int maintenance_start(void)
+{
+	if (maintenance_register())
+		warning(_("failed to add repo to global config"));
+
+	return update_background_schedule(1);
+}
+
+static int maintenance_stop(void)
+{
+	return update_background_schedule(0);
+}
+
+static const char builtin_maintenance_usage[] =	N_("git maintenance <subcommand> [<options>]");
 
 int cmd_maintenance(int argc, const char **argv, const char *prefix)
 {
@@ -1033,6 +1628,14 @@
 
 	if (!strcmp(argv[1], "run"))
 		return maintenance_run(argc - 1, argv + 1, prefix);
+	if (!strcmp(argv[1], "start"))
+		return maintenance_start();
+	if (!strcmp(argv[1], "stop"))
+		return maintenance_stop();
+	if (!strcmp(argv[1], "register"))
+		return maintenance_register();
+	if (!strcmp(argv[1], "unregister"))
+		return maintenance_unregister();
 
 	die(_("invalid subcommand: %s"), argv[1]);
 }
diff --git a/builtin/grep.c b/builtin/grep.c
index c803738..e58e575 100644
--- a/builtin/grep.c
+++ b/builtin/grep.c
@@ -670,6 +670,17 @@
 				     NULL, 0);
 		obj_read_unlock();
 
+		if (!real_obj) {
+			char hex[GIT_MAX_HEXSZ + 1];
+			const char *name = list->objects[i].name;
+
+			if (!name) {
+				oid_to_hex_r(hex, &list->objects[i].item->oid);
+				name = hex;
+			}
+			die(_("invalid object '%s' given."), name);
+		}
+
 		/* load the gitmodules file for this rev */
 		if (recurse_submodules) {
 			submodule_free(opt->repo);
diff --git a/builtin/index-pack.c b/builtin/index-pack.c
index 0d03cb4..4b8d86e 100644
--- a/builtin/index-pack.c
+++ b/builtin/index-pack.c
@@ -1597,7 +1597,7 @@
 
 	/* The address of the 4-byte offset table */
 	idx1 = (((const uint32_t *)((const uint8_t *)p->index_data + p->crc_offset))
-		+ p->num_objects /* CRC32 table */
+		+ (size_t)p->num_objects /* CRC32 table */
 		);
 
 	/* The address of the 8-byte offset table */
diff --git a/builtin/log.c b/builtin/log.c
index 0a7ed4b..08204e3 100644
--- a/builtin/log.c
+++ b/builtin/log.c
@@ -37,6 +37,7 @@
 
 #define MAIL_DEFAULT_WRAP 72
 #define COVER_FROM_AUTO_MAX_SUBJECT_LEN 100
+#define FORMAT_PATCH_NAME_MAX_DEFAULT 64
 
 /* Set a default date-time format for git log ("log.date" config variable) */
 static const char *default_date_mode = NULL;
@@ -50,6 +51,7 @@
 static int decoration_given;
 static int use_mailmap_config = 1;
 static const char *fmt_patch_subject_prefix = "PATCH";
+static int fmt_patch_name_max = FORMAT_PATCH_NAME_MAX_DEFAULT;
 static const char *fmt_pretty;
 
 static const char * const builtin_log_usage[] = {
@@ -150,6 +152,7 @@
 	rev->abbrev_commit = default_abbrev_commit;
 	rev->show_root_diff = default_show_root;
 	rev->subject_prefix = fmt_patch_subject_prefix;
+	rev->patch_name_max = fmt_patch_name_max;
 	rev->show_signature = default_show_signature;
 	rev->encode_email_headers = default_encode_email_headers;
 	rev->diffopt.flags.allow_textconv = 1;
@@ -183,8 +186,8 @@
 				N_("pattern"), N_("do not decorate refs that match <pattern>")),
 		OPT_CALLBACK_F(0, "decorate", NULL, NULL, N_("decorate options"),
 			       PARSE_OPT_OPTARG, decorate_callback),
-		OPT_CALLBACK('L', NULL, &line_cb, "n,m:file",
-			     N_("Process line range n,m in file, counting from 1"),
+		OPT_CALLBACK('L', NULL, &line_cb, "range:file",
+			     N_("Trace the evolution of line range <start>,<end> or function :<funcname> in <file>"),
 			     log_line_range_callback),
 		OPT_END()
 	};
@@ -206,6 +209,9 @@
 	if (argc > 1)
 		die(_("unrecognized argument: %s"), argv[1]);
 
+	if (rev->line_level_traverse && rev->prune_data.nr)
+		die(_("-L<range>:<file> cannot be used with pathspec"));
+
 	memset(&w, 0, sizeof(w));
 	userformat_find_requirements(NULL, &w);
 
@@ -454,6 +460,10 @@
 		return git_config_string(&fmt_pretty, var, value);
 	if (!strcmp(var, "format.subjectprefix"))
 		return git_config_string(&fmt_patch_subject_prefix, var, value);
+	if (!strcmp(var, "format.filenamemaxlength")) {
+		fmt_patch_name_max = git_config_int(var, value);
+		return 0;
+	}
 	if (!strcmp(var, "format.encodeemailheaders")) {
 		default_encode_email_headers = git_config_bool(var, value);
 		return 0;
@@ -955,15 +965,9 @@
 			 struct rev_info *rev, int quiet)
 {
 	struct strbuf filename = STRBUF_INIT;
-	int suffix_len = strlen(rev->patch_suffix) + 1;
 
 	if (output_directory) {
 		strbuf_addstr(&filename, output_directory);
-		if (filename.len >=
-		    PATH_MAX - FORMAT_PATCH_NAME_MAX - suffix_len) {
-			strbuf_release(&filename);
-			return error(_("name of output directory is too long"));
-		}
 		strbuf_complete(&filename, '/');
 	}
 
@@ -1153,7 +1157,7 @@
 	}
 }
 
-static void make_cover_letter(struct rev_info *rev, int use_stdout,
+static void make_cover_letter(struct rev_info *rev, int use_separate_file,
 			      struct commit *origin,
 			      int nr, struct commit **list,
 			      const char *branch_name,
@@ -1173,7 +1177,7 @@
 
 	committer = git_committer_info(0);
 
-	if (!use_stdout &&
+	if (use_separate_file &&
 	    open_next_file(NULL, rev->numbered_files ? NULL : "cover-letter", rev, quiet))
 		die(_("failed to create cover-letter file"));
 
@@ -1738,7 +1742,7 @@
 		OPT_CALLBACK_F('N', "no-numbered", &numbered, NULL,
 			    N_("use [PATCH] even with multiple patches"),
 			    PARSE_OPT_NOARG | PARSE_OPT_NONEG, no_numbered_callback),
-		OPT_BOOL('s', "signoff", &do_signoff, N_("add Signed-off-by:")),
+		OPT_BOOL('s', "signoff", &do_signoff, N_("add a Signed-off-by trailer")),
 		OPT_BOOL(0, "stdout", &use_stdout,
 			    N_("print patches to standard out")),
 		OPT_BOOL(0, "cover-letter", &cover_letter,
@@ -1751,6 +1755,8 @@
 			    N_("start numbering patches at <n> instead of 1")),
 		OPT_INTEGER('v', "reroll-count", &reroll_count,
 			    N_("mark the series as Nth re-roll")),
+		OPT_INTEGER(0, "filename-max-length", &fmt_patch_name_max,
+			    N_("max length of output filename")),
 		OPT_CALLBACK_F(0, "rfc", &rev, NULL,
 			    N_("Use [RFC PATCH] instead of [PATCH]"),
 			    PARSE_OPT_NOARG | PARSE_OPT_NONEG, rfc_callback),
@@ -1851,6 +1857,10 @@
 			     PARSE_OPT_KEEP_ARGV0 | PARSE_OPT_KEEP_UNKNOWN |
 			     PARSE_OPT_KEEP_DASHDASH);
 
+	/* Make sure "0000-$sub.patch" gives non-negative length for $sub */
+	if (fmt_patch_name_max <= strlen("0000-") + strlen(fmt_patch_suffix))
+		fmt_patch_name_max = strlen("0000-") + strlen(fmt_patch_suffix);
+
 	if (cover_from_description_arg)
 		cover_from_description_mode = parse_cover_from_description(cover_from_description_arg);
 
@@ -1935,6 +1945,7 @@
 	rev.diffopt.output_format |= DIFF_FORMAT_PATCH;
 
 	rev.zero_commit = zero_commit;
+	rev.patch_name_max = fmt_patch_name_max;
 
 	if (!rev.diffopt.flags.text && !no_binary_diff)
 		rev.diffopt.flags.binary = 1;
@@ -1942,20 +1953,27 @@
 	if (rev.show_notes)
 		load_display_notes(&rev.notes_opt);
 
-	if (!output_directory && !use_stdout)
-		output_directory = config_output_directory;
+	if (use_stdout + rev.diffopt.close_file + !!output_directory > 1)
+		die(_("--stdout, --output, and --output-directory are mutually exclusive"));
 
-	if (!use_stdout)
-		output_directory = set_outdir(prefix, output_directory);
-	else
+	if (use_stdout) {
 		setup_pager();
-
-	if (output_directory) {
+	} else if (rev.diffopt.close_file) {
+		/*
+		 * The diff code parsed --output; it has already opened the
+		 * file, but but we must instruct it not to close after each
+		 * diff.
+		 */
+		rev.diffopt.close_file = 0;
+	} else {
 		int saved;
+
+		if (!output_directory)
+			output_directory = config_output_directory;
+		output_directory = set_outdir(prefix, output_directory);
+
 		if (rev.diffopt.use_color != GIT_COLOR_ALWAYS)
 			rev.diffopt.use_color = GIT_COLOR_NEVER;
-		if (use_stdout)
-			die(_("standard output, or directory, which one?"));
 		/*
 		 * We consider <outdir> as 'outside of gitdir', therefore avoid
 		 * applying adjust_shared_perm in s-c-l-d.
@@ -2117,7 +2135,7 @@
 	if (cover_letter) {
 		if (thread)
 			gen_message_id(&rev, "cover");
-		make_cover_letter(&rev, use_stdout,
+		make_cover_letter(&rev, !!output_directory,
 				  origin, nr, list, branch_name, quiet);
 		print_bases(&bases, rev.diffopt.file);
 		print_signature(rev.diffopt.file);
@@ -2172,7 +2190,7 @@
 			gen_message_id(&rev, oid_to_hex(&commit->object.oid));
 		}
 
-		if (!use_stdout &&
+		if (output_directory &&
 		    open_next_file(rev.numbered_files ? NULL : commit, NULL, &rev, quiet))
 			die(_("failed to create output files"));
 		shown = log_tree_commit(&rev, commit);
@@ -2185,7 +2203,7 @@
 		 * the log; when using one file per patch, we do
 		 * not want the extra blank line.
 		 */
-		if (!use_stdout)
+		if (output_directory)
 			rev.shown_one = 0;
 		if (shown) {
 			print_bases(&bases, rev.diffopt.file);
@@ -2196,7 +2214,7 @@
 			else
 				print_signature(rev.diffopt.file);
 		}
-		if (!use_stdout)
+		if (output_directory)
 			fclose(rev.diffopt.file);
 	}
 	stop_progress(&progress);
diff --git a/builtin/merge-tree.c b/builtin/merge-tree.c
index e72714a..de85207 100644
--- a/builtin/merge-tree.c
+++ b/builtin/merge-tree.c
@@ -109,6 +109,7 @@
 	xdemitconf_t xecfg;
 	xdemitcb_t ecb;
 
+	memset(&xpp, 0, sizeof(xpp));
 	xpp.flags = 0;
 	memset(&xecfg, 0, sizeof(xecfg));
 	xecfg.ctxlen = 3;
diff --git a/builtin/merge.c b/builtin/merge.c
index 9d5359e..1cff730 100644
--- a/builtin/merge.c
+++ b/builtin/merge.c
@@ -28,6 +28,7 @@
 #include "rerere.h"
 #include "help.h"
 #include "merge-recursive.h"
+#include "merge-ort-wrappers.h"
 #include "resolve-undo.h"
 #include "remote.h"
 #include "fmt-merge-msg.h"
@@ -88,6 +89,7 @@
 static struct strategy all_strategy[] = {
 	{ "recursive",  DEFAULT_TWOHEAD | NO_TRIVIAL },
 	{ "octopus",    DEFAULT_OCTOPUS },
+	{ "ort",        NO_TRIVIAL },
 	{ "resolve",    0 },
 	{ "ours",       NO_FAST_FORWARD | NO_TRIVIAL },
 	{ "subtree",    NO_FAST_FORWARD | NO_TRIVIAL },
@@ -159,10 +161,17 @@
 	struct strategy *ret;
 	static struct cmdnames main_cmds, other_cmds;
 	static int loaded;
+	char *default_strategy = getenv("GIT_TEST_MERGE_ALGORITHM");
 
 	if (!name)
 		return NULL;
 
+	if (default_strategy &&
+	    !strcmp(default_strategy, "ort") &&
+	    !strcmp(name, "recursive")) {
+		name = "ort";
+	}
+
 	for (i = 0; i < ARRAY_SIZE(all_strategy); i++)
 		if (!strcmp(name, all_strategy[i].name))
 			return &all_strategy[i];
@@ -289,7 +298,7 @@
 	  N_("GPG sign commit"), PARSE_OPT_OPTARG, NULL, (intptr_t) "" },
 	OPT_AUTOSTASH(&autostash),
 	OPT_BOOL(0, "overwrite-ignore", &overwrite_ignore, N_("update ignored files (default)")),
-	OPT_BOOL(0, "signoff", &signoff, N_("add Signed-off-by:")),
+	OPT_BOOL(0, "signoff", &signoff, N_("add a Signed-off-by trailer")),
 	OPT_BOOL(0, "no-verify", &no_verify, N_("bypass pre-merge-commit and commit-msg hooks")),
 	OPT_END()
 };
@@ -701,7 +710,8 @@
 	if (refresh_and_write_cache(REFRESH_QUIET, SKIP_IF_UNCHANGED, 0) < 0)
 		return error(_("Unable to write index."));
 
-	if (!strcmp(strategy, "recursive") || !strcmp(strategy, "subtree")) {
+	if (!strcmp(strategy, "recursive") || !strcmp(strategy, "subtree") ||
+	    !strcmp(strategy, "ort")) {
 		struct lock_file lock = LOCK_INIT;
 		int clean, x;
 		struct commit *result;
@@ -732,8 +742,12 @@
 			commit_list_insert(j->item, &reversed);
 
 		hold_locked_index(&lock, LOCK_DIE_ON_ERROR);
-		clean = merge_recursive(&o, head,
-				remoteheads->item, reversed, &result);
+		if (!strcmp(strategy, "ort"))
+			clean = merge_ort_recursive(&o, head, remoteheads->item,
+						    reversed, &result);
+		else
+			clean = merge_recursive(&o, head, remoteheads->item,
+						reversed, &result);
 		if (clean < 0)
 			exit(128);
 		if (write_locked_index(&the_index, &lock,
@@ -1264,6 +1278,12 @@
 	if (branch)
 		skip_prefix(branch, "refs/heads/", &branch);
 
+	if (!pull_twohead) {
+		char *default_strategy = getenv("GIT_TEST_MERGE_ALGORITHM");
+		if (default_strategy && !strcmp(default_strategy, "ort"))
+			pull_twohead = "ort";
+	}
+
 	init_diff_ui_defaults();
 	git_config(git_merge_config, NULL);
 
diff --git a/builtin/pack-redundant.c b/builtin/pack-redundant.c
index 178e340..3e70f2a 100644
--- a/builtin/pack-redundant.c
+++ b/builtin/pack-redundant.c
@@ -236,7 +236,7 @@
 
 static void cmp_two_packs(struct pack_list *p1, struct pack_list *p2)
 {
-	unsigned long p1_off = 0, p2_off = 0, p1_step, p2_step;
+	size_t p1_off = 0, p2_off = 0, p1_step, p2_step;
 	const unsigned char *p1_base, *p2_base;
 	struct llist_item *p1_hint = NULL, *p2_hint = NULL;
 	const unsigned int hashsz = the_hash_algo->rawsz;
@@ -280,7 +280,7 @@
 static size_t sizeof_union(struct packed_git *p1, struct packed_git *p2)
 {
 	size_t ret = 0;
-	unsigned long p1_off = 0, p2_off = 0, p1_step, p2_step;
+	size_t p1_off = 0, p2_off = 0, p1_step, p2_step;
 	const unsigned char *p1_base, *p2_base;
 	const unsigned int hashsz = the_hash_algo->rawsz;
 
@@ -499,7 +499,7 @@
 static struct pack_list * add_pack(struct packed_git *p)
 {
 	struct pack_list l;
-	unsigned long off = 0, step;
+	size_t off = 0, step;
 	const unsigned char *base;
 
 	if (!p->pack_local && !(alt_odb || verbose))
diff --git a/builtin/pull.c b/builtin/pull.c
index 425950f..aa56ebc 100644
--- a/builtin/pull.c
+++ b/builtin/pull.c
@@ -142,7 +142,7 @@
 		N_("add (at most <n>) entries from shortlog to merge commit message"),
 		PARSE_OPT_OPTARG),
 	OPT_PASSTHRU(0, "signoff", &opt_signoff, NULL,
-		N_("add Signed-off-by:"),
+		N_("add a Signed-off-by trailer"),
 		PARSE_OPT_OPTARG),
 	OPT_PASSTHRU(0, "squash", &opt_squash, NULL,
 		N_("create a single commit instead of doing a merge"),
@@ -345,18 +345,18 @@
 		return parse_config_rebase("pull.rebase", value, 1);
 
 	if (opt_verbosity >= 0 && !opt_ff) {
-		warning(_("Pulling without specifying how to reconcile divergent branches is\n"
-			"discouraged. You can squelch this message by running one of the following\n"
-			"commands sometime before your next pull:\n"
-			"\n"
-			"  git config pull.rebase false  # merge (the default strategy)\n"
-			"  git config pull.rebase true   # rebase\n"
-			"  git config pull.ff only       # fast-forward only\n"
-			"\n"
-			"You can replace \"git config\" with \"git config --global\" to set a default\n"
-			"preference for all repositories. You can also pass --rebase, --no-rebase,\n"
-			"or --ff-only on the command line to override the configured default per\n"
-			"invocation.\n"));
+		advise(_("Pulling without specifying how to reconcile divergent branches is\n"
+			 "discouraged. You can squelch this message by running one of the following\n"
+			 "commands sometime before your next pull:\n"
+			 "\n"
+			 "  git config pull.rebase false  # merge (the default strategy)\n"
+			 "  git config pull.rebase true   # rebase\n"
+			 "  git config pull.ff only       # fast-forward only\n"
+			 "\n"
+			 "You can replace \"git config\" with \"git config --global\" to set a default\n"
+			 "preference for all repositories. You can also pass --rebase, --no-rebase,\n"
+			 "or --ff-only on the command line to override the configured default per\n"
+			 "invocation.\n"));
 	}
 
 	return REBASE_FALSE;
@@ -852,21 +852,42 @@
 
 /**
  * Given the current HEAD oid, the merge head returned from git-fetch and the
- * fork point calculated by get_rebase_fork_point(), runs git-rebase with the
- * appropriate arguments and returns its exit status.
+ * fork point calculated by get_rebase_fork_point(), compute the <newbase> and
+ * <upstream> arguments to use for the upcoming git-rebase invocation.
  */
-static int run_rebase(const struct object_id *curr_head,
+static int get_rebase_newbase_and_upstream(struct object_id *newbase,
+		struct object_id *upstream,
+		const struct object_id *curr_head,
 		const struct object_id *merge_head,
 		const struct object_id *fork_point)
 {
-	int ret;
 	struct object_id oct_merge_base;
-	struct strvec args = STRVEC_INIT;
 
 	if (!get_octopus_merge_base(&oct_merge_base, curr_head, merge_head, fork_point))
 		if (!is_null_oid(fork_point) && oideq(&oct_merge_base, fork_point))
 			fork_point = NULL;
 
+	if (fork_point && !is_null_oid(fork_point))
+		oidcpy(upstream, fork_point);
+	else
+		oidcpy(upstream, merge_head);
+
+	oidcpy(newbase, merge_head);
+
+	return 0;
+}
+
+/**
+ * Given the <newbase> and <upstream> calculated by
+ * get_rebase_newbase_and_upstream(), runs git-rebase with the
+ * appropriate arguments and returns its exit status.
+ */
+static int run_rebase(const struct object_id *newbase,
+		const struct object_id *upstream)
+{
+	int ret;
+	struct strvec args = STRVEC_INIT;
+
 	strvec_push(&args, "rebase");
 
 	/* Shared options */
@@ -894,12 +915,9 @@
 		warning(_("ignoring --verify-signatures for rebase"));
 
 	strvec_push(&args, "--onto");
-	strvec_push(&args, oid_to_hex(merge_head));
+	strvec_push(&args, oid_to_hex(newbase));
 
-	if (fork_point && !is_null_oid(fork_point))
-		strvec_push(&args, oid_to_hex(fork_point));
-	else
-		strvec_push(&args, oid_to_hex(merge_head));
+	strvec_push(&args, oid_to_hex(upstream));
 
 	ret = run_command_v_opt(args.v, RUN_GIT_CMD);
 	strvec_clear(&args);
@@ -1011,9 +1029,15 @@
 	if (opt_rebase) {
 		int ret = 0;
 		int ran_ff = 0;
+
+		struct object_id newbase;
+		struct object_id upstream;
+		get_rebase_newbase_and_upstream(&newbase, &upstream, &curr_head,
+						merge_heads.oid, &rebase_fork_point);
+
 		if ((recurse_submodules == RECURSE_SUBMODULES_ON ||
 		     recurse_submodules == RECURSE_SUBMODULES_ON_DEMAND) &&
-		    submodule_touches_in_range(the_repository, &rebase_fork_point, &curr_head))
+		    submodule_touches_in_range(the_repository, &upstream, &curr_head))
 			die(_("cannot rebase with locally recorded submodule modifications"));
 		if (!autostash) {
 			struct commit_list *list = NULL;
@@ -1034,7 +1058,7 @@
 			free_commit_list(list);
 		}
 		if (!ran_ff)
-			ret = run_rebase(&curr_head, merge_heads.oid, &rebase_fork_point);
+			ret = run_rebase(&newbase, &upstream);
 
 		if (!ret && (recurse_submodules == RECURSE_SUBMODULES_ON ||
 			     recurse_submodules == RECURSE_SUBMODULES_ON_DEMAND))
diff --git a/builtin/push.c b/builtin/push.c
index 6da3a8e..03adb58 100644
--- a/builtin/push.c
+++ b/builtin/push.c
@@ -290,6 +290,12 @@
 	   "or update a remote ref to make it point at a non-commit object,\n"
 	   "without using the '--force' option.\n");
 
+static const char message_advice_ref_needs_update[] =
+	N_("Updates were rejected because the tip of the remote-tracking\n"
+	   "branch has been updated since the last checkout. You may want\n"
+	   "to integrate those changes locally (e.g., 'git pull ...')\n"
+	   "before forcing an update.\n");
+
 static void advise_pull_before_push(void)
 {
 	if (!advice_push_non_ff_current || !advice_push_update_rejected)
@@ -325,6 +331,13 @@
 	advise(_(message_advice_ref_needs_force));
 }
 
+static void advise_ref_needs_update(void)
+{
+	if (!advice_push_ref_needs_update || !advice_push_update_rejected)
+		return;
+	advise(_(message_advice_ref_needs_update));
+}
+
 static int push_with_options(struct transport *transport, struct refspec *rs,
 			     int flags)
 {
@@ -374,6 +387,8 @@
 		advise_ref_fetch_first();
 	} else if (reject_reasons & REJECT_NEEDS_FORCE) {
 		advise_ref_needs_force();
+	} else if (reject_reasons & REJECT_REF_NEEDS_UPDATE) {
+		advise_ref_needs_update();
 	}
 
 	return 1;
@@ -510,6 +525,12 @@
 		if (!v)
 			return config_error_nonbool(k);
 		return color_parse(v, push_colors[slot]);
+	} else if (!strcmp(k, "push.useforceifincludes")) {
+		if (git_config_bool(k, v))
+			*flags |= TRANSPORT_PUSH_FORCE_IF_INCLUDES;
+		else
+			*flags &= ~TRANSPORT_PUSH_FORCE_IF_INCLUDES;
+		return 0;
 	}
 
 	return git_default_config(k, v, NULL);
@@ -541,6 +562,9 @@
 		OPT_CALLBACK_F(0, CAS_OPT_NAME, &cas, N_("<refname>:<expect>"),
 			       N_("require old value of ref to be at this value"),
 			       PARSE_OPT_OPTARG | PARSE_OPT_LITERAL_ARGHELP, parseopt_push_cas_option),
+		OPT_BIT(0, TRANS_OPT_FORCE_IF_INCLUDES, &flags,
+			N_("require remote updates to be integrated locally"),
+			TRANSPORT_PUSH_FORCE_IF_INCLUDES),
 		OPT_CALLBACK(0, "recurse-submodules", &recurse_submodules, "(check|on-demand|no)",
 			     N_("control recursive pushing of submodules"), option_parse_recurse_submodules),
 		OPT_BOOL_F( 0 , "thin", &thin, N_("use thin pack"), PARSE_OPT_NOCOMPLETE),
@@ -625,6 +649,9 @@
 	if ((flags & TRANSPORT_PUSH_ALL) && (flags & TRANSPORT_PUSH_MIRROR))
 		die(_("--all and --mirror are incompatible"));
 
+	if (!is_empty_cas(&cas) && (flags & TRANSPORT_PUSH_FORCE_IF_INCLUDES))
+		cas.use_force_if_includes = 1;
+
 	for_each_string_list_item(item, push_options)
 		if (strchr(item->string, '\n'))
 			die(_("push options must not have new line characters"));
diff --git a/builtin/rebase.c b/builtin/rebase.c
index eeca533..19c7b37 100644
--- a/builtin/rebase.c
+++ b/builtin/rebase.c
@@ -119,6 +119,7 @@
 	struct replay_opts replay = REPLAY_OPTS_INIT;
 
 	replay.action = REPLAY_INTERACTIVE_REBASE;
+	replay.strategy = NULL;
 	sequencer_init_config(&replay);
 
 	replay.signoff = opts->signoff;
@@ -136,7 +137,12 @@
 					opts->committer_date_is_author_date;
 	replay.ignore_date = opts->ignore_date;
 	replay.gpg_sign = xstrdup_or_null(opts->gpg_sign_opt);
-	replay.strategy = opts->strategy;
+	if (opts->strategy)
+		replay.strategy = opts->strategy;
+	else if (!replay.strategy && replay.default_strategy) {
+		replay.strategy = replay.default_strategy;
+		replay.default_strategy = NULL;
+	}
 
 	if (opts->strategy_opts)
 		parse_strategy_opts(&replay, opts->strategy_opts);
@@ -270,15 +276,14 @@
 }
 
 static int get_revision_ranges(struct commit *upstream, struct commit *onto,
-			       struct object_id *orig_head, const char **head_hash,
-			       char **revisions, char **shortrevisions)
+			       struct object_id *orig_head, char **revisions,
+			       char **shortrevisions)
 {
 	struct commit *base_rev = upstream ? upstream : onto;
 	const char *shorthead;
 
-	*head_hash = find_unique_abbrev(orig_head, GIT_MAX_HEXSZ);
 	*revisions = xstrfmt("%s...%s", oid_to_hex(&base_rev->object.oid),
-						   *head_hash);
+			     oid_to_hex(orig_head));
 
 	shorthead = find_unique_abbrev(orig_head, DEFAULT_ABBREV);
 
@@ -296,7 +301,8 @@
 }
 
 static int init_basic_state(struct replay_opts *opts, const char *head_name,
-			    struct commit *onto, const char *orig_head)
+			    struct commit *onto,
+			    const struct object_id *orig_head)
 {
 	FILE *interactive;
 
@@ -327,7 +333,6 @@
 static int do_interactive_rebase(struct rebase_options *opts, unsigned flags)
 {
 	int ret;
-	const char *head_hash = NULL;
 	char *revisions = NULL, *shortrevisions = NULL;
 	struct strvec make_script_args = STRVEC_INIT;
 	struct todo_list todo_list = TODO_LIST_INIT;
@@ -335,12 +340,12 @@
 	struct string_list commands = STRING_LIST_INIT_DUP;
 
 	if (get_revision_ranges(opts->upstream, opts->onto, &opts->orig_head,
-				&head_hash, &revisions, &shortrevisions))
+				&revisions, &shortrevisions))
 		return -1;
 
 	if (init_basic_state(&replay,
 			     opts->head_name ? opts->head_name : "detached HEAD",
-			     opts->onto, head_hash)) {
+			     opts->onto, &opts->orig_head)) {
 		free(revisions);
 		free(shortrevisions);
 
@@ -370,8 +375,9 @@
 
 		split_exec_commands(opts->cmd, &commands);
 		ret = complete_action(the_repository, &replay, flags,
-			shortrevisions, opts->onto_name, opts->onto, head_hash,
-			&commands, opts->autosquash, &todo_list);
+			shortrevisions, opts->onto_name, opts->onto,
+			&opts->orig_head, &commands, opts->autosquash,
+			&todo_list);
 	}
 
 	string_list_clear(&commands, 0);
@@ -1324,7 +1330,7 @@
 			N_("do not show diffstat of what changed upstream"),
 			PARSE_OPT_NOARG, NULL, REBASE_DIFFSTAT },
 		OPT_BOOL(0, "signoff", &options.signoff,
-			 N_("add a Signed-off-by: line to each commit")),
+			 N_("add a Signed-off-by trailer to each commit")),
 		OPT_BOOL(0, "committer-date-is-author-date",
 			 &options.committer_date_is_author_date,
 			 N_("make committer date match author date")),
@@ -1771,6 +1777,11 @@
 			    options.default_backend);
 	}
 
+	if (options.type == REBASE_MERGE &&
+	    !options.strategy &&
+	    getenv("GIT_TEST_MERGE_ALGORITHM"))
+		options.strategy = xstrdup(getenv("GIT_TEST_MERGE_ALGORITHM"));
+
 	switch (options.type) {
 	case REBASE_MERGE:
 	case REBASE_PRESERVE_MERGES:
diff --git a/builtin/receive-pack.c b/builtin/receive-pack.c
index bb9909c..f1f0f7b 100644
--- a/builtin/receive-pack.c
+++ b/builtin/receive-pack.c
@@ -977,15 +977,25 @@
 	int new_report = 0;
 	int code = 0;
 	int once = 0;
+	int response = 0;
 
 	for (;;) {
 		struct object_id old_oid, new_oid;
 		const char *head;
 		const char *refname;
 		char *p;
+		enum packet_read_status status;
 
-		if (packet_reader_read(reader) != PACKET_READ_NORMAL)
+		status = packet_reader_read(reader);
+		if (status != PACKET_READ_NORMAL) {
+			/* Check whether proc-receive exited abnormally */
+			if (status == PACKET_READ_EOF && !response) {
+				strbuf_addstr(errmsg, "proc-receive exited abnormally");
+				return -1;
+			}
 			break;
+		}
+		response++;
 
 		head = reader->line;
 		p = strchr(head, ' ');
@@ -1145,31 +1155,49 @@
 	if (use_push_options)
 		strbuf_addstr(&cap, " push-options");
 	if (cap.len) {
-		packet_write_fmt(proc.in, "version=1%c%s\n", '\0', cap.buf + 1);
+		code = packet_write_fmt_gently(proc.in, "version=1%c%s\n", '\0', cap.buf + 1);
 		strbuf_release(&cap);
 	} else {
-		packet_write_fmt(proc.in, "version=1\n");
+		code = packet_write_fmt_gently(proc.in, "version=1\n");
 	}
-	packet_flush(proc.in);
+	if (!code)
+		code = packet_flush_gently(proc.in);
 
-	for (;;) {
-		int linelen;
+	if (!code)
+		for (;;) {
+			int linelen;
+			enum packet_read_status status;
 
-		if (packet_reader_read(&reader) != PACKET_READ_NORMAL)
-			break;
+			status = packet_reader_read(&reader);
+			if (status != PACKET_READ_NORMAL) {
+				/* Check whether proc-receive exited abnormally */
+				if (status == PACKET_READ_EOF)
+					code = -1;
+				break;
+			}
 
-		if (reader.pktlen > 8 && starts_with(reader.line, "version=")) {
-			version = atoi(reader.line + 8);
-			linelen = strlen(reader.line);
-			if (linelen < reader.pktlen) {
-				const char *feature_list = reader.line + linelen + 1;
-				if (parse_feature_request(feature_list, "push-options"))
-					hook_use_push_options = 1;
+			if (reader.pktlen > 8 && starts_with(reader.line, "version=")) {
+				version = atoi(reader.line + 8);
+				linelen = strlen(reader.line);
+				if (linelen < reader.pktlen) {
+					const char *feature_list = reader.line + linelen + 1;
+					if (parse_feature_request(feature_list, "push-options"))
+						hook_use_push_options = 1;
+				}
 			}
 		}
+
+	if (code) {
+		strbuf_addstr(&errmsg, "fail to negotiate version with proc-receive hook");
+		goto cleanup;
 	}
 
-	if (version != 1) {
+	switch (version) {
+	case 0:
+		/* fallthrough */
+	case 1:
+		break;
+	default:
 		strbuf_addf(&errmsg, "proc-receive version '%d' is not supported",
 			    version);
 		code = -1;
@@ -1180,20 +1208,36 @@
 	for (cmd = commands; cmd; cmd = cmd->next) {
 		if (!cmd->run_proc_receive || cmd->skip_update || cmd->error_string)
 			continue;
-		packet_write_fmt(proc.in, "%s %s %s",
-				 oid_to_hex(&cmd->old_oid),
-				 oid_to_hex(&cmd->new_oid),
-				 cmd->ref_name);
+		code = packet_write_fmt_gently(proc.in, "%s %s %s",
+					       oid_to_hex(&cmd->old_oid),
+					       oid_to_hex(&cmd->new_oid),
+					       cmd->ref_name);
+		if (code)
+			break;
 	}
-	packet_flush(proc.in);
+	if (!code)
+		code = packet_flush_gently(proc.in);
+	if (code) {
+		strbuf_addstr(&errmsg, "fail to write commands to proc-receive hook");
+		goto cleanup;
+	}
 
 	/* Send push options */
 	if (hook_use_push_options) {
 		struct string_list_item *item;
 
-		for_each_string_list_item(item, push_options)
-			packet_write_fmt(proc.in, "%s", item->string);
-		packet_flush(proc.in);
+		for_each_string_list_item(item, push_options) {
+			code = packet_write_fmt_gently(proc.in, "%s", item->string);
+			if (code)
+				break;
+		}
+		if (!code)
+			code = packet_flush_gently(proc.in);
+		if (code) {
+			strbuf_addstr(&errmsg,
+				      "fail to write push-options to proc-receive hook");
+			goto cleanup;
+		}
 	}
 
 	/* Read result from proc-receive */
diff --git a/builtin/remote.c b/builtin/remote.c
index 64b4b55..c1b211b 100644
--- a/builtin/remote.c
+++ b/builtin/remote.c
@@ -191,11 +191,12 @@
 	url = argv[1];
 
 	remote = remote_get(name);
-	if (remote_is_configured(remote, 1))
-		die(_("remote %s already exists."), name);
+	if (remote_is_configured(remote, 1)) {
+		error(_("remote %s already exists."), name);
+		exit(3);
+	}
 
-	strbuf_addf(&buf2, "refs/heads/test:refs/remotes/%s/test", name);
-	if (!valid_fetch_refspec(buf2.buf))
+	if (!valid_remote_name(name))
 		die(_("'%s' is not a valid remote name"), name);
 
 	strbuf_addf(&buf, "remote.%s.url", name);
@@ -686,21 +687,23 @@
 	rename.remote_branches = &remote_branches;
 
 	oldremote = remote_get(rename.old_name);
-	if (!remote_is_configured(oldremote, 1))
-		die(_("No such remote: '%s'"), rename.old_name);
+	if (!remote_is_configured(oldremote, 1)) {
+		error(_("No such remote: '%s'"), rename.old_name);
+		exit(2);
+	}
 
 	if (!strcmp(rename.old_name, rename.new_name) && oldremote->origin != REMOTE_CONFIG)
 		return migrate_file(oldremote);
 
 	newremote = remote_get(rename.new_name);
-	if (remote_is_configured(newremote, 1))
-		die(_("remote %s already exists."), rename.new_name);
+	if (remote_is_configured(newremote, 1)) {
+		error(_("remote %s already exists."), rename.new_name);
+		exit(3);
+	}
 
-	strbuf_addf(&buf, "refs/heads/test:refs/remotes/%s/test", rename.new_name);
-	if (!valid_fetch_refspec(buf.buf))
+	if (!valid_remote_name(rename.new_name))
 		die(_("'%s' is not a valid remote name"), rename.new_name);
 
-	strbuf_reset(&buf);
 	strbuf_addf(&buf, "remote.%s", rename.old_name);
 	strbuf_addf(&buf2, "remote.%s", rename.new_name);
 	if (git_config_rename_section(buf.buf, buf2.buf) < 1)
@@ -829,8 +832,10 @@
 		usage_with_options(builtin_remote_rm_usage, options);
 
 	remote = remote_get(argv[1]);
-	if (!remote_is_configured(remote, 1))
-		die(_("No such remote: '%s'"), argv[1]);
+	if (!remote_is_configured(remote, 1)) {
+		error(_("No such remote: '%s'"), argv[1]);
+		exit(2);
+	}
 
 	known_remotes.to_delete = remote;
 	for_each_remote(add_known_remote, &known_remotes);
@@ -1511,8 +1516,10 @@
 	strbuf_addf(&key, "remote.%s.fetch", remotename);
 
 	remote = remote_get(remotename);
-	if (!remote_is_configured(remote, 1))
-		die(_("No such remote '%s'"), remotename);
+	if (!remote_is_configured(remote, 1)) {
+		error(_("No such remote '%s'"), remotename);
+		exit(2);
+	}
 
 	if (!add_mode && remove_all_fetch_refspecs(key.buf)) {
 		strbuf_release(&key);
@@ -1565,8 +1572,10 @@
 	remotename = argv[0];
 
 	remote = remote_get(remotename);
-	if (!remote_is_configured(remote, 1))
-		die(_("No such remote '%s'"), remotename);
+	if (!remote_is_configured(remote, 1)) {
+		error(_("No such remote '%s'"), remotename);
+		exit(2);
+	}
 
 	url_nr = 0;
 	if (push_mode) {
@@ -1633,8 +1642,10 @@
 		oldurl = newurl;
 
 	remote = remote_get(remotename);
-	if (!remote_is_configured(remote, 1))
-		die(_("No such remote '%s'"), remotename);
+	if (!remote_is_configured(remote, 1)) {
+		error(_("No such remote '%s'"), remotename);
+		exit(2);
+	}
 
 	if (push_mode) {
 		strbuf_addf(&name_buf, "remote.%s.pushurl", remotename);
diff --git a/builtin/repack.c b/builtin/repack.c
index 01e7767..279be11 100644
--- a/builtin/repack.c
+++ b/builtin/repack.c
@@ -202,6 +202,37 @@
 	return 0;
 }
 
+static struct {
+	const char *name;
+	unsigned optional:1;
+} exts[] = {
+	{".pack"},
+	{".idx"},
+	{".bitmap", 1},
+	{".promisor", 1},
+};
+
+static unsigned populate_pack_exts(char *name)
+{
+	struct stat statbuf;
+	struct strbuf path = STRBUF_INIT;
+	unsigned ret = 0;
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(exts); i++) {
+		strbuf_reset(&path);
+		strbuf_addf(&path, "%s-%s%s", packtmp, name, exts[i].name);
+
+		if (stat(path.buf, &statbuf))
+			continue;
+
+		ret |= (1 << i);
+	}
+
+	strbuf_release(&path);
+	return ret;
+}
+
 static void repack_promisor_objects(const struct pack_objects_args *args,
 				    struct string_list *names)
 {
@@ -230,11 +261,12 @@
 
 	out = xfdopen(cmd.out, "r");
 	while (strbuf_getline_lf(&line, out) != EOF) {
+		struct string_list_item *item;
 		char *promisor_name;
 		int fd;
 		if (line.len != the_hash_algo->hexsz)
 			die(_("repack: Expecting full hex object ID lines only from pack-objects."));
-		string_list_append(names, line.buf);
+		item = string_list_append(names, line.buf);
 
 		/*
 		 * pack-objects creates the .pack and .idx files, but not the
@@ -253,6 +285,9 @@
 		if (fd < 0)
 			die_errno(_("unable to create '%s'"), promisor_name);
 		close(fd);
+
+		item->util = (void *)(uintptr_t)populate_pack_exts(item->string);
+
 		free(promisor_name);
 	}
 	fclose(out);
@@ -265,22 +300,13 @@
 
 int cmd_repack(int argc, const char **argv, const char *prefix)
 {
-	struct {
-		const char *name;
-		unsigned optional:1;
-	} exts[] = {
-		{".pack"},
-		{".idx"},
-		{".bitmap", 1},
-		{".promisor", 1},
-	};
 	struct child_process cmd = CHILD_PROCESS_INIT;
 	struct string_list_item *item;
 	struct string_list names = STRING_LIST_INIT_DUP;
 	struct string_list rollback = STRING_LIST_INIT_NODUP;
 	struct string_list existing_packs = STRING_LIST_INIT_DUP;
 	struct strbuf line = STRBUF_INIT;
-	int i, ext, ret, failed;
+	int i, ext, ret;
 	FILE *out;
 
 	/* variables to be filled by option parsing */
@@ -429,113 +455,42 @@
 	if (!names.nr && !po_args.quiet)
 		printf_ln(_("Nothing new to pack."));
 
+	for_each_string_list_item(item, &names) {
+		item->util = (void *)(uintptr_t)populate_pack_exts(item->string);
+	}
+
 	close_object_store(the_repository->objects);
 
 	/*
 	 * Ok we have prepared all new packfiles.
-	 * First see if there are packs of the same name and if so
-	 * if we can move them out of the way (this can happen if we
-	 * repacked immediately after packing fully.
 	 */
-	failed = 0;
 	for_each_string_list_item(item, &names) {
 		for (ext = 0; ext < ARRAY_SIZE(exts); ext++) {
 			char *fname, *fname_old;
 
-			fname = mkpathdup("%s/pack-%s%s", packdir,
-						item->string, exts[ext].name);
-			if (!file_exists(fname)) {
-				free(fname);
-				continue;
-			}
-
-			fname_old = mkpathdup("%s/old-%s%s", packdir,
-						item->string, exts[ext].name);
-			if (file_exists(fname_old))
-				if (unlink(fname_old))
-					failed = 1;
-
-			if (!failed && rename(fname, fname_old)) {
-				free(fname);
-				free(fname_old);
-				failed = 1;
-				break;
-			} else {
-				string_list_append(&rollback, fname);
-				free(fname_old);
-			}
-		}
-		if (failed)
-			break;
-	}
-	if (failed) {
-		struct string_list rollback_failure = STRING_LIST_INIT_DUP;
-		for_each_string_list_item(item, &rollback) {
-			char *fname, *fname_old;
-			fname = mkpathdup("%s/%s", packdir, item->string);
-			fname_old = mkpathdup("%s/old-%s", packdir, item->string);
-			if (rename(fname_old, fname))
-				string_list_append(&rollback_failure, fname);
-			free(fname);
-			free(fname_old);
-		}
-
-		if (rollback_failure.nr) {
-			int i;
-			fprintf(stderr,
-				_("WARNING: Some packs in use have been renamed by\n"
-				  "WARNING: prefixing old- to their name, in order to\n"
-				  "WARNING: replace them with the new version of the\n"
-				  "WARNING: file.  But the operation failed, and the\n"
-				  "WARNING: attempt to rename them back to their\n"
-				  "WARNING: original names also failed.\n"
-				  "WARNING: Please rename them in %s manually:\n"), packdir);
-			for (i = 0; i < rollback_failure.nr; i++)
-				fprintf(stderr, "WARNING:   old-%s -> %s\n",
-					rollback_failure.items[i].string,
-					rollback_failure.items[i].string);
-		}
-		exit(1);
-	}
-
-	/* Now the ones with the same name are out of the way... */
-	for_each_string_list_item(item, &names) {
-		for (ext = 0; ext < ARRAY_SIZE(exts); ext++) {
-			char *fname, *fname_old;
-			struct stat statbuffer;
-			int exists = 0;
 			fname = mkpathdup("%s/pack-%s%s",
 					packdir, item->string, exts[ext].name);
 			fname_old = mkpathdup("%s-%s%s",
 					packtmp, item->string, exts[ext].name);
-			if (!stat(fname_old, &statbuffer)) {
-				statbuffer.st_mode &= ~(S_IWUSR | S_IWGRP | S_IWOTH);
-				chmod(fname_old, statbuffer.st_mode);
-				exists = 1;
-			}
-			if (exists || !exts[ext].optional) {
+
+			if (((uintptr_t)item->util) & (1 << ext)) {
+				struct stat statbuffer;
+				if (!stat(fname_old, &statbuffer)) {
+					statbuffer.st_mode &= ~(S_IWUSR | S_IWGRP | S_IWOTH);
+					chmod(fname_old, statbuffer.st_mode);
+				}
+
 				if (rename(fname_old, fname))
 					die_errno(_("renaming '%s' failed"), fname_old);
-			}
+			} else if (!exts[ext].optional)
+				die(_("missing required file: %s"), fname_old);
+			else if (unlink(fname) < 0 && errno != ENOENT)
+				die_errno(_("could not unlink: %s"), fname);
+
 			free(fname);
 			free(fname_old);
 		}
 	}
-
-	/* Remove the "old-" files */
-	for_each_string_list_item(item, &names) {
-		for (ext = 0; ext < ARRAY_SIZE(exts); ext++) {
-			char *fname;
-			fname = mkpathdup("%s/old-%s%s",
-					  packdir,
-					  item->string,
-					  exts[ext].name);
-			if (remove_path(fname))
-				warning(_("failed to remove '%s'"), fname);
-			free(fname);
-		}
-	}
-
 	/* End of pack replacement. */
 
 	reprepare_packed_git(the_repository);
diff --git a/builtin/rev-parse.c b/builtin/rev-parse.c
index ed200c8..69ba732 100644
--- a/builtin/rev-parse.c
+++ b/builtin/rev-parse.c
@@ -595,6 +595,7 @@
 	struct object_context unused;
 	struct strbuf buf = STRBUF_INIT;
 	const int hexsz = the_hash_algo->hexsz;
+	int seen_end_of_options = 0;
 
 	if (argc > 1 && !strcmp("--parseopt", argv[1]))
 		return cmd_parseopt(argc - 1, argv + 1, prefix);
@@ -622,21 +623,29 @@
 	for (i = 1; i < argc; i++) {
 		const char *arg = argv[i];
 
-		if (!strcmp(arg, "--local-env-vars")) {
-			int i;
-			for (i = 0; local_repo_env[i]; i++)
-				printf("%s\n", local_repo_env[i]);
+		if (as_is) {
+			if (show_file(arg, output_prefix) && as_is < 2)
+				verify_filename(prefix, arg, 0);
 			continue;
 		}
-		if (!strcmp(arg, "--resolve-git-dir")) {
-			const char *gitdir = argv[++i];
-			if (!gitdir)
-				die("--resolve-git-dir requires an argument");
-			gitdir = resolve_gitdir(gitdir);
-			if (!gitdir)
-				die("not a gitdir '%s'", argv[i]);
-			puts(gitdir);
-			continue;
+
+		if (!seen_end_of_options) {
+			if (!strcmp(arg, "--local-env-vars")) {
+				int i;
+				for (i = 0; local_repo_env[i]; i++)
+					printf("%s\n", local_repo_env[i]);
+				continue;
+			}
+			if (!strcmp(arg, "--resolve-git-dir")) {
+				const char *gitdir = argv[++i];
+				if (!gitdir)
+					die("--resolve-git-dir requires an argument");
+				gitdir = resolve_gitdir(gitdir);
+				if (!gitdir)
+					die("not a gitdir '%s'", argv[i]);
+				puts(gitdir);
+				continue;
+			}
 		}
 
 		/* The rest of the options require a git repository. */
@@ -646,41 +655,36 @@
 			did_repo_setup = 1;
 		}
 
-		if (!strcmp(arg, "--git-path")) {
-			if (!argv[i + 1])
-				die("--git-path requires an argument");
-			strbuf_reset(&buf);
-			puts(relative_path(git_path("%s", argv[i + 1]),
-					   prefix, &buf));
-			i++;
-			continue;
-		}
-		if (as_is) {
-			if (show_file(arg, output_prefix) && as_is < 2)
-				verify_filename(prefix, arg, 0);
-			continue;
-		}
-		if (!strcmp(arg,"-n")) {
-			if (++i >= argc)
-				die("-n requires an argument");
-			if ((filter & DO_FLAGS) && (filter & DO_REVS)) {
-				show(arg);
-				show(argv[i]);
-			}
-			continue;
-		}
-		if (starts_with(arg, "-n")) {
-			if ((filter & DO_FLAGS) && (filter & DO_REVS))
-				show(arg);
+		if (!strcmp(arg, "--")) {
+			as_is = 2;
+			/* Pass on the "--" if we show anything but files.. */
+			if (filter & (DO_FLAGS | DO_REVS))
+				show_file(arg, 0);
 			continue;
 		}
 
-		if (*arg == '-') {
-			if (!strcmp(arg, "--")) {
-				as_is = 2;
-				/* Pass on the "--" if we show anything but files.. */
-				if (filter & (DO_FLAGS | DO_REVS))
-					show_file(arg, 0);
+		if (!seen_end_of_options && *arg == '-') {
+			if (!strcmp(arg, "--git-path")) {
+				if (!argv[i + 1])
+					die("--git-path requires an argument");
+				strbuf_reset(&buf);
+				puts(relative_path(git_path("%s", argv[i + 1]),
+						   prefix, &buf));
+				i++;
+				continue;
+			}
+			if (!strcmp(arg,"-n")) {
+				if (++i >= argc)
+					die("-n requires an argument");
+				if ((filter & DO_FLAGS) && (filter & DO_REVS)) {
+					show(arg);
+					show(argv[i]);
+				}
+				continue;
+			}
+			if (starts_with(arg, "-n")) {
+				if ((filter & DO_FLAGS) && (filter & DO_REVS))
+					show(arg);
 				continue;
 			}
 			if (!strcmp(arg, "--default")) {
@@ -937,6 +941,12 @@
 				puts(the_hash_algo->name);
 				continue;
 			}
+			if (!strcmp(arg, "--end-of-options")) {
+				seen_end_of_options = 1;
+				if (filter & (DO_FLAGS | DO_REVS))
+					show_file(arg, 0);
+				continue;
+			}
 			if (show_flag(arg) && verify)
 				die_no_single_rev(quiet);
 			continue;
diff --git a/builtin/revert.c b/builtin/revert.c
index f61cc5d..314a86c 100644
--- a/builtin/revert.c
+++ b/builtin/revert.c
@@ -107,7 +107,7 @@
 		OPT_BOOL('n', "no-commit", &opts->no_commit, N_("don't automatically commit")),
 		OPT_BOOL('e', "edit", &opts->edit, N_("edit the commit message")),
 		OPT_NOOP_NOARG('r', NULL),
-		OPT_BOOL('s', "signoff", &opts->signoff, N_("add Signed-off-by:")),
+		OPT_BOOL('s', "signoff", &opts->signoff, N_("add a Signed-off-by trailer")),
 		OPT_CALLBACK('m', "mainline", opts, N_("parent-number"),
 			     N_("select mainline parent"), option_parse_m),
 		OPT_RERERE_AUTOUPDATE(&opts->allow_rerere_auto),
@@ -172,6 +172,11 @@
 				NULL);
 	}
 
+	if (!opts->strategy && opts->default_strategy) {
+		opts->strategy = opts->default_strategy;
+		opts->default_strategy = NULL;
+	}
+
 	if (opts->allow_ff)
 		verify_opt_compatible(me, "--ff",
 				"--signoff", opts->signoff,
@@ -202,6 +207,8 @@
 	/* These option values will be free()d */
 	opts->gpg_sign = xstrdup_or_null(opts->gpg_sign);
 	opts->strategy = xstrdup_or_null(opts->strategy);
+	if (!opts->strategy && getenv("GIT_TEST_MERGE_ALGORITHM"))
+		opts->strategy = xstrdup(getenv("GIT_TEST_MERGE_ALGORITHM"));
 
 	if (cmd == 'q') {
 		int ret = sequencer_remove_state(opts);
diff --git a/builtin/send-pack.c b/builtin/send-pack.c
index 7af148d..a7e0166 100644
--- a/builtin/send-pack.c
+++ b/builtin/send-pack.c
@@ -71,6 +71,11 @@
 			msg = "stale info";
 			break;
 
+		case REF_STATUS_REJECT_REMOTE_UPDATED:
+			res = "error";
+			msg = "remote ref updated since checkout";
+			break;
+
 		case REF_STATUS_REJECT_ALREADY_EXISTS:
 			res = "error";
 			msg = "already exists";
@@ -173,6 +178,7 @@
 	int progress = -1;
 	int from_stdin = 0;
 	struct push_cas_option cas = {0};
+	int force_if_includes = 0;
 	struct packet_reader reader;
 
 	struct option options[] = {
@@ -198,6 +204,8 @@
 		OPT_CALLBACK_F(0, CAS_OPT_NAME, &cas, N_("<refname>:<expect>"),
 		  N_("require old value of ref to be at this value"),
 		  PARSE_OPT_OPTARG, parseopt_push_cas_option),
+		OPT_BOOL(0, TRANS_OPT_FORCE_IF_INCLUDES, &force_if_includes,
+			 N_("require remote updates to be integrated locally")),
 		OPT_END()
 	};
 
@@ -299,6 +307,9 @@
 	if (!is_empty_cas(&cas))
 		apply_push_cas(&cas, remote, remote_refs);
 
+	if (!is_empty_cas(&cas) && force_if_includes)
+		cas.use_force_if_includes = 1;
+
 	set_ref_status_for_push(remote_refs, args.send_mirror,
 		args.force_update);
 
diff --git a/builtin/shortlog.c b/builtin/shortlog.c
index 0a5c496..c52e4cc 100644
--- a/builtin/shortlog.c
+++ b/builtin/shortlog.c
@@ -10,6 +10,7 @@
 #include "shortlog.h"
 #include "parse-options.h"
 #include "trailer.h"
+#include "strmap.h"
 
 static char const * const shortlog_usage[] = {
 	N_("git shortlog [<options>] [<revision-range>] [[--] <path>...]"),
@@ -169,60 +170,6 @@
 	strbuf_release(&oneline);
 }
 
-struct strset_item {
-	struct hashmap_entry ent;
-	char value[FLEX_ARRAY];
-};
-
-struct strset {
-	struct hashmap map;
-};
-
-#define STRSET_INIT { { NULL } }
-
-static int strset_item_hashcmp(const void *hash_data,
-			       const struct hashmap_entry *entry,
-			       const struct hashmap_entry *entry_or_key,
-			       const void *keydata)
-{
-	const struct strset_item *a, *b;
-
-	a = container_of(entry, const struct strset_item, ent);
-	if (keydata)
-		return strcmp(a->value, keydata);
-
-	b = container_of(entry_or_key, const struct strset_item, ent);
-	return strcmp(a->value, b->value);
-}
-
-/*
- * Adds "str" to the set if it was not already present; returns true if it was
- * already there.
- */
-static int strset_check_and_add(struct strset *ss, const char *str)
-{
-	unsigned int hash = strhash(str);
-	struct strset_item *item;
-
-	if (!ss->map.table)
-		hashmap_init(&ss->map, strset_item_hashcmp, NULL, 0);
-
-	if (hashmap_get_from_hash(&ss->map, hash, str))
-		return 1;
-
-	FLEX_ALLOC_STR(item, value, str);
-	hashmap_entry_init(&item->ent, hash);
-	hashmap_add(&ss->map, &item->ent);
-	return 0;
-}
-
-static void strset_clear(struct strset *ss)
-{
-	if (!ss->map.table)
-		return;
-	hashmap_free_entries(&ss->map, struct strset_item, ent);
-}
-
 static void insert_records_from_trailers(struct shortlog *log,
 					 struct strset *dups,
 					 struct commit *commit,
@@ -253,7 +200,7 @@
 		if (!parse_ident(log, &ident, value))
 			value = ident.buf;
 
-		if (strset_check_and_add(dups, value))
+		if (!strset_add(dups, value))
 			continue;
 		insert_one_record(log, value, oneline);
 	}
@@ -291,7 +238,7 @@
 				      log->email ? "%aN <%aE>" : "%aN",
 				      &ident, &ctx);
 		if (!HAS_MULTI_BITS(log->groups) ||
-		    !strset_check_and_add(&dups, ident.buf))
+		    strset_add(&dups, ident.buf))
 			insert_one_record(log, ident.buf, oneline_str);
 	}
 	if (log->groups & SHORTLOG_GROUP_COMMITTER) {
@@ -300,7 +247,7 @@
 				      log->email ? "%cN <%cE>" : "%cN",
 				      &ident, &ctx);
 		if (!HAS_MULTI_BITS(log->groups) ||
-		    !strset_check_and_add(&dups, ident.buf))
+		    strset_add(&dups, ident.buf))
 			insert_one_record(log, ident.buf, oneline_str);
 	}
 	if (log->groups & SHORTLOG_GROUP_TRAILER) {
diff --git a/builtin/stash.c b/builtin/stash.c
index 3f811f3..e1f8235 100644
--- a/builtin/stash.c
+++ b/builtin/stash.c
@@ -419,7 +419,7 @@
 			ret = apply_cached(&out);
 			strbuf_release(&out);
 			if (ret)
-				return error(_("conflicts in index."
+				return error(_("conflicts in index. "
 					       "Try without --index."));
 
 			discard_cache();
@@ -534,11 +534,22 @@
 	return ret;
 }
 
+static int reject_reflog_ent(struct object_id *ooid, struct object_id *noid,
+			     const char *email, timestamp_t timestamp, int tz,
+			     const char *message, void *cb_data)
+{
+	return 1;
+}
+
+static int reflog_is_empty(const char *refname)
+{
+	return !for_each_reflog_ent(refname, reject_reflog_ent, NULL);
+}
+
 static int do_drop_stash(struct stash_info *info, int quiet)
 {
 	int ret;
 	struct child_process cp_reflog = CHILD_PROCESS_INIT;
-	struct child_process cp = CHILD_PROCESS_INIT;
 
 	/*
 	 * reflog does not provide a simple function for deleting refs. One will
@@ -559,19 +570,7 @@
 			     info->revision.buf);
 	}
 
-	/*
-	 * This could easily be replaced by get_oid, but currently it will throw
-	 * a fatal error when a reflog is empty, which we can not recover from.
-	 */
-	cp.git_cmd = 1;
-	/* Even though --quiet is specified, rev-parse still outputs the hash */
-	cp.no_stdout = 1;
-	strvec_pushl(&cp.args, "rev-parse", "--verify", "--quiet", NULL);
-	strvec_pushf(&cp.args, "%s@{0}", ref_stash);
-	ret = run_command(&cp);
-
-	/* do_clear_stash if we just dropped the last stash entry */
-	if (ret)
+	if (reflog_is_empty(ref_stash))
 		do_clear_stash();
 
 	return 0;
diff --git a/builtin/worktree.c b/builtin/worktree.c
index 99abaee..197fd24 100644
--- a/builtin/worktree.c
+++ b/builtin/worktree.c
@@ -304,9 +304,9 @@
 	}
 
 	if (locked)
-		die(_("'%s' is a missing but locked worktree;\nuse '%s -f -f' to override, or 'unlock' and 'prune' or 'remove' to clear"), cmd, path);
+		die(_("'%s' is a missing but locked worktree;\nuse '%s -f -f' to override, or 'unlock' and 'prune' or 'remove' to clear"), path, cmd);
 	else
-		die(_("'%s' is a missing but already registered worktree;\nuse '%s -f' to override, or 'prune' or 'remove' to clear"), cmd, path);
+		die(_("'%s' is a missing but already registered worktree;\nuse '%s -f' to override, or 'prune' or 'remove' to clear"), path, cmd);
 }
 
 static int add_worktree(const char *path, const char *refname,
@@ -676,8 +676,11 @@
 		} else
 			strbuf_addstr(&sb, "(error)");
 	}
-	printf("%s\n", sb.buf);
 
+	if (!is_main_worktree(wt) && worktree_lock_reason(wt))
+		strbuf_addstr(&sb, " locked");
+
+	printf("%s\n", sb.buf);
 	strbuf_release(&sb);
 }
 
diff --git a/cache.h b/cache.h
index c0072d4..e986cf4 100644
--- a/cache.h
+++ b/cache.h
@@ -1960,7 +1960,6 @@
 void stat_validity_update(struct stat_validity *sv, int fd);
 
 int versioncmp(const char *s1, const char *s2);
-void sleep_millisec(int millisec);
 
 /*
  * Create a directory and (if share is nonzero) adjust its permissions
diff --git a/ci/print-test-failures.sh b/ci/print-test-failures.sh
index 92a983a..c70d6cd 100755
--- a/ci/print-test-failures.sh
+++ b/ci/print-test-failures.sh
@@ -48,7 +48,7 @@
 			;;
 		github-actions)
 			mkdir -p failed-test-artifacts
-			echo "::set-env name=FAILED_TEST_ARTIFACTS::t/failed-test-artifacts"
+			echo "FAILED_TEST_ARTIFACTS=t/failed-test-artifacts" >>$GITHUB_ENV
 			cp "${TEST_EXIT%.exit}.out" failed-test-artifacts/
 			tar czf failed-test-artifacts/"$test_name".trash.tar.gz "$trash_dir"
 			continue
diff --git a/command-list.txt b/command-list.txt
index 0e3204e..9379b02 100644
--- a/command-list.txt
+++ b/command-list.txt
@@ -94,6 +94,7 @@
 git-filter-branch                       ancillarymanipulators
 git-fmt-merge-msg                       purehelpers
 git-for-each-ref                        plumbinginterrogators
+git-for-each-repo                       plumbinginterrogators
 git-format-patch                        mainporcelain
 git-fsck                                ancillaryinterrogators          complete
 git-gc                                  mainporcelain
@@ -135,7 +136,6 @@
 git-pack-objects                        plumbingmanipulators
 git-pack-redundant                      plumbinginterrogators
 git-pack-refs                           ancillarymanipulators
-git-parse-remote                        synchelpers
 git-patch-id                            purehelpers
 git-prune                               ancillarymanipulators   complete
 git-prune-packed                        plumbingmanipulators
diff --git a/commit-graph.c b/commit-graph.c
index cb042bd..6f62a07 100644
--- a/commit-graph.c
+++ b/commit-graph.c
@@ -2008,7 +2008,7 @@
 
 static void sort_and_scan_merged_commits(struct write_commit_graph_context *ctx)
 {
-	uint32_t i;
+	uint32_t i, dedup_i = 0;
 
 	if (ctx->report_progress)
 		ctx->progress = start_delayed_progress(
@@ -2023,17 +2023,27 @@
 
 		if (i && oideq(&ctx->commits.list[i - 1]->object.oid,
 			  &ctx->commits.list[i]->object.oid)) {
-			die(_("unexpected duplicate commit id %s"),
-			    oid_to_hex(&ctx->commits.list[i]->object.oid));
+			/*
+			 * Silently ignore duplicates. These were likely
+			 * created due to a commit appearing in multiple
+			 * layers of the chain, which is unexpected but
+			 * not invalid. We should make sure there is a
+			 * unique copy in the new layer.
+			 */
 		} else {
 			unsigned int num_parents;
 
+			ctx->commits.list[dedup_i] = ctx->commits.list[i];
+			dedup_i++;
+
 			num_parents = commit_list_count(ctx->commits.list[i]->parents);
 			if (num_parents > 2)
 				ctx->num_extra_edges += num_parents - 1;
 		}
 	}
 
+	ctx->commits.nr = dedup_i;
+
 	stop_progress(&ctx->progress);
 }
 
@@ -2150,6 +2160,11 @@
 	int replace = 0;
 	struct bloom_filter_settings bloom_settings = DEFAULT_BLOOM_FILTER_SETTINGS;
 
+	prepare_repo_settings(the_repository);
+	if (!the_repository->settings.core_commit_graph) {
+		warning(_("attempting to write a commit-graph, but 'core.commitGraph' is disabled"));
+		return 0;
+	}
 	if (!commit_graph_compatible(the_repository))
 		return 0;
 
diff --git a/commit.c b/commit.c
index f53429c..fe1fa3d 100644
--- a/commit.c
+++ b/commit.c
@@ -1586,7 +1586,7 @@
 
 /*
  * Inspect the given string and determine the true "end" of the log message, in
- * order to find where to put a new Signed-off-by: line.  Ignored are
+ * order to find where to put a new Signed-off-by trailer.  Ignored are
  * trailing comment lines and blank lines.  To support "git commit -s
  * --amend" on an existing commit, we also ignore "Conflicts:".  To
  * support "git commit -v", we truncate at cut lines.
diff --git a/compat/bswap.h b/compat/bswap.h
index c0bb744..512f6f4 100644
--- a/compat/bswap.h
+++ b/compat/bswap.h
@@ -74,7 +74,7 @@
 }
 #endif
 
-#elif defined(_MSC_VER) && (defined(_M_IX86) || defined(_M_X64))
+#elif defined(_MSC_VER) && (defined(_M_IX86) || defined(_M_X64) || defined(_M_ARM64))
 
 #include <stdlib.h>
 
diff --git a/config.c b/config.c
index 2bdff44..8f324ed 100644
--- a/config.c
+++ b/config.c
@@ -1963,7 +1963,7 @@
 		free(entry->key);
 		string_list_clear(&entry->value_list, 1);
 	}
-	hashmap_free_entries(&cs->config_hash, struct config_set_element, ent);
+	hashmap_clear_and_free(&cs->config_hash, struct config_set_element, ent);
 	cs->hash_initialized = 0;
 	free(cs->list.items);
 	cs->list.nr = 0;
diff --git a/config.mak.dev b/config.mak.dev
index 89b218d..022fb58 100644
--- a/config.mak.dev
+++ b/config.mak.dev
@@ -1,5 +1,6 @@
 ifeq ($(filter no-error,$(DEVOPTS)),)
 DEVELOPER_CFLAGS += -Werror
+SPARSE_FLAGS += -Wsparse-error
 endif
 ifneq ($(filter pedantic,$(DEVOPTS)),)
 DEVELOPER_CFLAGS += -pedantic
@@ -15,6 +16,7 @@
 DEVELOPER_CFLAGS += -Wstrict-prototypes
 DEVELOPER_CFLAGS += -Wunused
 DEVELOPER_CFLAGS += -Wvla
+DEVELOPER_CFLAGS += -fno-common
 
 ifndef COMPILER_FEATURES
 COMPILER_FEATURES := $(shell ./detect-compiler $(CC))
@@ -45,3 +47,5 @@
 DEVELOPER_CFLAGS += -Wno-uninitialized
 endif
 endif
+
+GIT_TEST_PERL_FATAL_WARNINGS = YesPlease
diff --git a/config.mak.uname b/config.mak.uname
index c7eba69..5b30a91 100644
--- a/config.mak.uname
+++ b/config.mak.uname
@@ -541,11 +541,6 @@
 	# removing the directory at OS releases J06.21 and L17.02.
 	# Default to the older rm until those two releases are deprecated.
 	RM = /bin/rm -f
-	# As detected by './configure'.
-	# Missdetected, hence commented out, see below.
-	#NO_CURL = YesPlease
-	# Added manually, see above.
-	NEEDS_SSL_WITH_CURL = YesPlease
 	NEEDS_CRYPTO_WITH_SSL = YesPlease
 	HAVE_DEV_TTY = YesPlease
 	HAVE_LIBCHARSET_H = YesPlease
@@ -636,7 +631,6 @@
 	prefix =
 	INSTALL = /bin/install
 	EXTLIBS += /mingw/lib/libz.a
-	NO_R_TO_GCC_LINKER = YesPlease
 	INTERNAL_QSORT = YesPlease
 	HAVE_LIBCHARSET_H = YesPlease
 	NO_GETTEXT = YesPlease
@@ -669,7 +663,6 @@
 			-fstack-protector-strong
 		EXTLIBS += -lntdll
 		INSTALL = /bin/install
-		NO_R_TO_GCC_LINKER = YesPlease
 		INTERNAL_QSORT = YesPlease
 		HAVE_LIBCHARSET_H = YesPlease
 		NO_GETTEXT =
@@ -695,7 +688,6 @@
 	NO_MKDTEMP = YesPlease
 	NO_NSEC = YesPlease
 	NO_PTHREADS = YesPlease
-	NO_R_TO_GCC_LINKER = YesPlease
 	NO_STRCASESTR = YesPlease
 	NO_STRLCPY = YesPlease
 endif
diff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash
index 0a96ad8..1ed0362 100644
--- a/contrib/completion/git-completion.bash
+++ b/contrib/completion/git-completion.bash
@@ -416,14 +416,13 @@
 	local options
 	eval "options=\${$var-}"
 
-	local completion_helper
-	if [ "$GIT_COMPLETION_SHOW_ALL" = "1" ]; then
-		completion_helper="--git-completion-helper-all"
-	else
-		completion_helper="--git-completion-helper"
-	fi
-
 	if [ -z "$options" ]; then
+		local completion_helper
+		if [ "$GIT_COMPLETION_SHOW_ALL" = "1" ]; then
+			completion_helper="--git-completion-helper-all"
+		else
+			completion_helper="--git-completion-helper"
+		fi
 		# leading and trailing spaces are significant to make
 		# option removal work correctly.
 		options=" $incl $(__git ${cmd/_/ } $completion_helper) " || return
@@ -1121,26 +1120,44 @@
 # __git_aliased_command requires 1 argument
 __git_aliased_command ()
 {
-	local word cmdline=$(__git config --get "alias.$1")
-	for word in $cmdline; do
-		case "$word" in
-		\!gitk|gitk)
-			echo "gitk"
+	local cur=$1 last list word cmdline
+
+	while [[ -n "$cur" ]]; do
+		if [[ "$list" == *" $cur "* ]]; then
+			# loop detected
 			return
-			;;
-		\!*)	: shell command alias ;;
-		-*)	: option ;;
-		*=*)	: setting env ;;
-		git)	: git itself ;;
-		\(\))   : skip parens of shell function definition ;;
-		{)	: skip start of shell helper function ;;
-		:)	: skip null command ;;
-		\'*)	: skip opening quote after sh -c ;;
-		*)
-			echo "$word"
-			return
-		esac
+		fi
+
+		cmdline=$(__git config --get "alias.$cur")
+		list=" $cur $list"
+		last=$cur
+		cur=
+
+		for word in $cmdline; do
+			case "$word" in
+			\!gitk|gitk)
+				cur="gitk"
+				break
+				;;
+			\!*)	: shell command alias ;;
+			-*)	: option ;;
+			*=*)	: setting env ;;
+			git)	: git itself ;;
+			\(\))   : skip parens of shell function definition ;;
+			{)	: skip start of shell helper function ;;
+			:)	: skip null command ;;
+			\'*)	: skip opening quote after sh -c ;;
+			*)
+				cur="$word"
+				break
+			esac
+		done
 	done
+
+	cur=$last
+	if [[ "$cur" != "$1" ]]; then
+		echo "$cur"
+	fi
 }
 
 # Check whether one of the given words is present on the command line,
@@ -1467,14 +1484,15 @@
 # Helper function to decide whether or not we should enable DWIM logic for
 # git-switch and git-checkout.
 #
-# To decide between the following rules in priority order
-# 1) the last provided of "--guess" or "--no-guess" explicitly enable or
-#    disable completion of DWIM logic respectively.
-# 2) If the --no-track option is provided, take this as a hint to disable the
-#    DWIM completion logic
-# 3) If GIT_COMPLETION_CHECKOUT_NO_GUESS is set, disable the DWIM completion
-#    logic, as requested by the user.
-# 4) Enable DWIM logic otherwise.
+# To decide between the following rules in decreasing priority order:
+# - the last provided of "--guess" or "--no-guess" explicitly enable or
+#   disable completion of DWIM logic respectively.
+# - If checkout.guess is false, disable completion of DWIM logic.
+# - If the --no-track option is provided, take this as a hint to disable the
+#   DWIM completion logic
+# - If GIT_COMPLETION_CHECKOUT_NO_GUESS is set, disable the DWIM completion
+#   logic, as requested by the user.
+# - Enable DWIM logic otherwise.
 #
 __git_checkout_default_dwim_mode ()
 {
@@ -1485,11 +1503,17 @@
 	fi
 
 	# --no-track disables DWIM, but with lower priority than
-	# --guess/--no-guess
+	# --guess/--no-guess/checkout.guess
 	if [ -n "$(__git_find_on_cmdline "--no-track")" ]; then
 		dwim_opt=""
 	fi
 
+	# checkout.guess = false disables DWIM, but with lower priority than
+	# --guess/--no-guess
+	if [ "$(__git config --type=bool checkout.guess)" = "false" ]; then
+		dwim_opt=""
+	fi
+
 	# Find the last provided --guess or --no-guess
 	last_option="$(__git_find_last_on_cmdline "--guess --no-guess")"
 	case "$last_option" in
@@ -1688,8 +1712,13 @@
 			--submodule --submodule= --ignore-submodules
 			--indent-heuristic --no-indent-heuristic
 			--textconv --no-textconv
+			--patch --no-patch
 "
 
+__git_diff_difftool_options="--cached --staged --pickaxe-all --pickaxe-regex
+			--base --ours --theirs --no-index --relative --merge-base
+			$__git_diff_common_options"
+
 _git_diff ()
 {
 	__git_has_doubledash && return
@@ -1712,10 +1741,7 @@
 		return
 		;;
 	--*)
-		__gitcomp "--cached --staged --pickaxe-all --pickaxe-regex
-			--base --ours --theirs --no-index
-			$__git_diff_common_options
-			"
+		__gitcomp "$__git_diff_difftool_options"
 		return
 		;;
 	esac
@@ -1737,11 +1763,7 @@
 		return
 		;;
 	--*)
-		__gitcomp_builtin difftool "$__git_diff_common_options
-					--base --cached --ours --theirs
-					--pickaxe-all --pickaxe-regex
-					--relative --staged
-					"
+		__gitcomp_builtin difftool "$__git_diff_difftool_options"
 		return
 		;;
 	esac
@@ -2031,11 +2053,9 @@
 			--no-walk --no-walk= --do-walk
 			--parents --children
 			--expand-tabs --expand-tabs= --no-expand-tabs
-			--patch
 			$merge
 			$__git_diff_common_options
 			--pickaxe-all --pickaxe-regex
-			--patch --no-patch
 			"
 		return
 		;;
@@ -2938,7 +2958,7 @@
 		;;
 	--*)
 		__gitcomp "--pretty= --format= --abbrev-commit --no-abbrev-commit
-			--oneline --show-signature --patch
+			--oneline --show-signature
 			--expand-tabs --expand-tabs= --no-expand-tabs
 			$__git_diff_common_options
 			"
@@ -3021,7 +3041,10 @@
 		list,--*)
 			__gitcomp "--name-status --oneline --patch-with-stat"
 			;;
-		show,--*|branch,--*)
+		show,--*)
+			__gitcomp "$__git_diff_common_options"
+			;;
+		branch,--*)
 			;;
 		branch,*)
 			if [ $cword -eq 3 ]; then
@@ -3458,88 +3481,8 @@
 	__git_complete_revlist
 }
 
-if [[ -n ${ZSH_VERSION-} ]] &&
-   # Don't define these functions when sourced from 'git-completion.zsh',
-   # it has its own implementations.
-   [[ -z ${GIT_SOURCING_ZSH_COMPLETION-} ]]; then
-	echo "WARNING: this script is deprecated, please see git-completion.zsh" 1>&2
-
-	autoload -U +X compinit && compinit
-
-	__gitcomp ()
-	{
-		emulate -L zsh
-
-		local cur_="${3-$cur}"
-
-		case "$cur_" in
-		--*=)
-			;;
-		*)
-			local c IFS=$' \t\n'
-			local -a array
-			for c in ${=1}; do
-				c="$c${4-}"
-				case $c in
-				--*=*|*.) ;;
-				*) c="$c " ;;
-				esac
-				array[${#array[@]}+1]="$c"
-			done
-			compset -P '*[=:]'
-			compadd -Q -S '' -p "${2-}" -a -- array && _ret=0
-			;;
-		esac
-	}
-
-	__gitcomp_direct ()
-	{
-		emulate -L zsh
-
-		local IFS=$'\n'
-		compset -P '*[=:]'
-		compadd -Q -- ${=1} && _ret=0
-	}
-
-	__gitcomp_nl ()
-	{
-		emulate -L zsh
-
-		local IFS=$'\n'
-		compset -P '*[=:]'
-		compadd -Q -S "${4- }" -p "${2-}" -- ${=1} && _ret=0
-	}
-
-	__gitcomp_file_direct ()
-	{
-		emulate -L zsh
-
-		local IFS=$'\n'
-		compset -P '*[=:]'
-		compadd -f -- ${=1} && _ret=0
-	}
-
-	__gitcomp_file ()
-	{
-		emulate -L zsh
-
-		local IFS=$'\n'
-		compset -P '*[=:]'
-		compadd -p "${2-}" -f -- ${=1} && _ret=0
-	}
-
-	_git ()
-	{
-		local _ret=1 cur cword prev
-		cur=${words[CURRENT]}
-		prev=${words[CURRENT-1]}
-		let cword=CURRENT-1
-		emulate ksh -c __${service}_main
-		let _ret && _default && _ret=0
-		return _ret
-	}
-
-	compdef _git git gitk
+if [[ -n ${ZSH_VERSION-} && -z ${GIT_SOURCING_ZSH_COMPLETION-} ]]; then
+	echo "ERROR: this script is obsolete, please see git-completion.zsh" 1>&2
 	return
 fi
 
@@ -3561,18 +3504,6 @@
 		|| complete -o default -o nospace -F $wrapper $1
 }
 
-# wrapper for backwards compatibility
-_git ()
-{
-	__git_wrap__git_main
-}
-
-# wrapper for backwards compatibility
-_gitk ()
-{
-	__git_wrap__gitk_main
-}
-
 __git_complete git __git_main
 __git_complete gitk __gitk_main
 
@@ -3580,6 +3511,6 @@
 # when the user has tab-completed the executable name and consequently
 # included the '.exe' suffix.
 #
-if [ Cygwin = "$(uname -o 2>/dev/null)" ]; then
-__git_complete git.exe __git_main
+if [ "$OSTYPE" = cygwin ]; then
+	__git_complete git.exe __git_main
 fi
diff --git a/contrib/completion/git-completion.zsh b/contrib/completion/git-completion.zsh
index ce47e86..e0fda27 100644
--- a/contrib/completion/git-completion.zsh
+++ b/contrib/completion/git-completion.zsh
@@ -2,26 +2,24 @@
 
 # zsh completion wrapper for git
 #
-# Copyright (c) 2012-2013 Felipe Contreras <felipe.contreras@gmail.com>
+# Copyright (c) 2012-2020 Felipe Contreras <felipe.contreras@gmail.com>
 #
-# You need git's bash completion script installed somewhere, by default it
-# would be the location bash-completion uses.
+# The recommended way to install this script is to make a copy of it as a
+# file named '_git' inside any directory in your fpath.
 #
-# If your script is somewhere else, you can configure it on your ~/.zshrc:
-#
-#  zstyle ':completion:*:*:git:*' script ~/.git-completion.zsh
-#
-# The recommended way to install this script is to make a copy of it in
-# ~/.zsh/ directory as ~/.zsh/git-completion.zsh and then add the following
-# to your ~/.zshrc file:
+# For example, create a directory '~/.zsh/', copy this file to '~/.zsh/_git',
+# and then add the following to your ~/.zshrc file:
 #
 #  fpath=(~/.zsh $fpath)
-
-complete ()
-{
-	# do nothing
-	return 0
-}
+#
+# You need git's bash completion script installed. By default bash-completion's
+# location will be used (e.g. pkg-config --variable=completionsdir bash-completion).
+#
+# If your bash completion script is somewhere else, you can specify the
+# location in your ~/.zshrc:
+#
+#  zstyle ':completion:*:*:git:*' script ~/.git-completion.bash
+#
 
 zstyle -T ':completion:*:*:git:*' tag-order && \
 	zstyle ':completion:*:*:git:*' tag-order 'common-commands'
@@ -29,18 +27,26 @@
 zstyle -s ":completion:*:*:git:*" script script
 if [ -z "$script" ]; then
 	local -a locations
-	local e
+	local e bash_completion
+
+	bash_completion=$(pkg-config --variable=completionsdir bash-completion 2>/dev/null) ||
+		bash_completion='/usr/share/bash-completion/completions/'
+
 	locations=(
-		$(dirname ${funcsourcetrace[1]%:*})/git-completion.bash
-		'/etc/bash_completion.d/git' # fedora, old debian
-		'/usr/share/bash-completion/completions/git' # arch, ubuntu, new debian
-		'/usr/share/bash-completion/git' # gentoo
+		"$(dirname ${funcsourcetrace[1]%:*})"/git-completion.bash
+		"$HOME/.local/share/bash-completion/completions/git"
+		"$bash_completion/git"
+		'/etc/bash_completion.d/git' # old debian
 		)
 	for e in $locations; do
 		test -f $e && script="$e" && break
 	done
 fi
+
+local old_complete="$functions[complete]"
+functions[complete]=:
 GIT_SOURCING_ZSH_COMPLETION=y . "$script"
+functions[complete]="$old_complete"
 
 __gitcomp ()
 {
@@ -51,13 +57,35 @@
 	case "$cur_" in
 	--*=)
 		;;
+	--no-*)
+		local c IFS=$' \t\n'
+		local -a array
+		for c in ${=1}; do
+			if [[ $c == "--" ]]; then
+				continue
+			fi
+			c="$c${4-}"
+			case $c in
+			--*=|*.) ;;
+			*) c="$c " ;;
+			esac
+			array+=("$c")
+		done
+		compset -P '*[=:]'
+		compadd -Q -S '' -p "${2-}" -a -- array && _ret=0
+		;;
 	*)
 		local c IFS=$' \t\n'
 		local -a array
 		for c in ${=1}; do
+			if [[ $c == "--" ]]; then
+				c="--no-...${4-}"
+				array+=("$c ")
+				break
+			fi
 			c="$c${4-}"
 			case $c in
-			--*=*|*.) ;;
+			--*=|*.) ;;
 			*) c="$c " ;;
 			esac
 			array+=("$c")
@@ -72,44 +100,57 @@
 {
 	emulate -L zsh
 
-	local IFS=$'\n'
 	compset -P '*[=:]'
-	compadd -Q -- ${=1} && _ret=0
+	compadd -Q -S '' -- ${(f)1} && _ret=0
 }
 
 __gitcomp_nl ()
 {
 	emulate -L zsh
 
-	local IFS=$'\n'
 	compset -P '*[=:]'
-	compadd -Q -S "${4- }" -p "${2-}" -- ${=1} && _ret=0
-}
-
-__gitcomp_nl_append ()
-{
-	emulate -L zsh
-
-	local IFS=$'\n'
-	compadd -Q -S "${4- }" -p "${2-}" -- ${=1} && _ret=0
-}
-
-__gitcomp_file_direct ()
-{
-	emulate -L zsh
-
-	local IFS=$'\n'
-	compset -P '*[=:]'
-	compadd -f -- ${=1} && _ret=0
+	compadd -Q -S "${4- }" -p "${2-}" -- ${(f)1} && _ret=0
 }
 
 __gitcomp_file ()
 {
 	emulate -L zsh
 
-	local IFS=$'\n'
-	compset -P '*[=:]'
-	compadd -p "${2-}" -f -- ${=1} && _ret=0
+	compadd -f -p "${2-}" -- ${(f)1} && _ret=0
+}
+
+__gitcomp_direct_append ()
+{
+	__gitcomp_direct "$@"
+}
+
+__gitcomp_nl_append ()
+{
+	__gitcomp_nl "$@"
+}
+
+__gitcomp_file_direct ()
+{
+	__gitcomp_file "$1" ""
+}
+
+_git_zsh ()
+{
+	__gitcomp "v1.1"
+}
+
+__git_complete_command ()
+{
+	emulate -L zsh
+
+	local command="$1"
+	local completion_func="_git_${command//-/_}"
+	if (( $+functions[$completion_func] )); then
+		emulate ksh -c $completion_func
+		return 0
+	else
+		return 1
+	fi
 }
 
 __git_zsh_bash_func ()
@@ -118,14 +159,12 @@
 
 	local command=$1
 
-	local completion_func="_git_${command//-/_}"
-	declare -f $completion_func >/dev/null && $completion_func && return
+	__git_complete_command "$command" && return
 
 	local expansion=$(__git_aliased_command "$command")
 	if [ -n "$expansion" ]; then
 		words[1]=$expansion
-		completion_func="_git_${expansion//-/_}"
-		declare -f $completion_func >/dev/null && $completion_func
+		__git_complete_command "$expansion"
 	fi
 }
 
@@ -162,8 +201,9 @@
 __git_zsh_cmd_alias ()
 {
 	local -a list
-	list=(${${${(0)"$(git config -z --get-regexp '^alias\.')"}#alias.}%$'\n'*})
-	_describe -t alias-commands 'aliases' list $* && _ret=0
+	list=(${${(0)"$(git config -z --get-regexp '^alias\.*')"}#alias.})
+	list=(${(f)"$(printf "%s:alias for '%s'\n" ${(f@)list})"})
+	_describe -t alias-commands 'aliases' list && _ret=0
 }
 
 __git_zsh_cmd_all ()
@@ -201,10 +241,13 @@
 
 	case $state in
 	(command)
-		_alternative \
-                         'alias-commands:alias:__git_zsh_cmd_alias' \
-                         'common-commands:common:__git_zsh_cmd_common' \
-                         'all-commands:all:__git_zsh_cmd_all' && _ret=0
+		_tags common-commands alias-commands all-commands
+		while _tags; do
+			_requested common-commands && __git_zsh_cmd_common
+			_requested alias-commands && __git_zsh_cmd_alias
+			_requested all-commands && __git_zsh_cmd_all
+			let _ret || break
+		done
 		;;
 	(arg)
 		local command="${words[1]}" __git_dir
@@ -235,8 +278,12 @@
 
 	if (( $+functions[__${service}_zsh_main] )); then
 		__${service}_zsh_main
-	else
+	elif (( $+functions[__${service}_main] )); then
 		emulate ksh -c __${service}_main
+	elif (( $+functions[_${service}] )); then
+		emulate ksh -c _${service}
+	elif ((	$+functions[_${service//-/_}] )); then
+		emulate ksh -c _${service//-/_}
 	fi
 
 	let _ret && _default && _ret=0
diff --git a/contrib/completion/git-prompt.sh b/contrib/completion/git-prompt.sh
index 16260ba..4640a15 100644
--- a/contrib/completion/git-prompt.sh
+++ b/contrib/completion/git-prompt.sh
@@ -97,7 +97,8 @@
 # If you would like a colored hint about the current dirty state, set
 # GIT_PS1_SHOWCOLORHINTS to a nonempty value. The colors are based on
 # the colored output of "git status -sb" and are available only when
-# using __git_ps1 for PROMPT_COMMAND or precmd.
+# using __git_ps1 for PROMPT_COMMAND or precmd in Bash,
+# but always available in Zsh.
 #
 # If you would like __git_ps1 to do nothing in the case when the current
 # directory is set up to be ignored by git, then set
@@ -137,6 +138,7 @@
 	done <<< "$output"
 
 	# parse configuration values
+	local option
 	for option in ${GIT_PS1_SHOWUPSTREAM}; do
 		case "$option" in
 		git|svn) upstream="$option" ;;
@@ -553,9 +555,11 @@
 
 	local z="${GIT_PS1_STATESEPARATOR-" "}"
 
-	# NO color option unless in PROMPT_COMMAND mode
-	if [ $pcmode = yes ] && [ -n "${GIT_PS1_SHOWCOLORHINTS-}" ]; then
-		__git_ps1_colorize_gitstring
+	# NO color option unless in PROMPT_COMMAND mode or it's Zsh
+	if [ -n "${GIT_PS1_SHOWCOLORHINTS-}" ]; then
+		if [ $pcmode = yes ] || [ -n "${ZSH_VERSION-}" ]; then
+			__git_ps1_colorize_gitstring
+		fi
 	fi
 
 	b=${b##refs/heads/}
diff --git a/contrib/git-resurrect.sh b/contrib/git-resurrect.sh
index 8c171dd..d843df3 100755
--- a/contrib/git-resurrect.sh
+++ b/contrib/git-resurrect.sh
@@ -27,7 +27,7 @@
 
 search_reflog () {
 	sed -ne 's~^\([^ ]*\) .*	checkout: moving from '"$1"' .*~\1~p' \
-                < "$GIT_DIR"/logs/HEAD
+		< "$GIT_DIR"/logs/HEAD
 }
 
 search_reflog_merges () {
@@ -37,19 +37,18 @@
 	)
 }
 
-_x40="[0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f]"
-_x40="$_x40$_x40$_x40$_x40$_x40$_x40$_x40$_x40"
+oid_pattern=$(git hash-object --stdin </dev/null | sed -e 's/./[0-9a-f]/g')
 
 search_merges () {
-        git rev-list --all --grep="Merge branch '$1'" \
-                --pretty=tformat:"%P %s" |
-        sed -ne "/^$_x40 \($_x40\) Merge .*/ {s//\1/p;$early_exit}"
+	git rev-list --all --grep="Merge branch '$1'" \
+		--pretty=tformat:"%P %s" |
+	sed -ne "/^$oid_pattern \($oid_pattern\) Merge .*/ {s//\1/p;$early_exit}"
 }
 
 search_merge_targets () {
 	git rev-list --all --grep="Merge branch '[^']*' into $branch\$" \
 		--pretty=tformat:"%H %s" --all |
-	sed -ne "/^\($_x40\) Merge .*/ {s//\1/p;$early_exit} "
+	sed -ne "/^\($oid_pattern\) Merge .*/ {s//\1/p;$early_exit} "
 }
 
 dry_run=
diff --git a/csum-file.h b/csum-file.h
index f9cbd31..e54d53d 100644
--- a/csum-file.h
+++ b/csum-file.h
@@ -62,4 +62,11 @@
 	hashwrite(f, &data, sizeof(data));
 }
 
+static inline size_t hashwrite_be64(struct hashfile *f, uint64_t data)
+{
+	data = htonll(data);
+	hashwrite(f, &data, sizeof(data));
+	return sizeof(data);
+}
+
 #endif
diff --git a/diff-lib.c b/diff-lib.c
index f95c6de..b73cc18 100644
--- a/diff-lib.c
+++ b/diff-lib.c
@@ -13,6 +13,7 @@
 #include "submodule.h"
 #include "dir.h"
 #include "fsmonitor.h"
+#include "commit-reach.h"
 
 /*
  * diff-files
@@ -97,6 +98,8 @@
 
 	diff_set_mnemonic_prefix(&revs->diffopt, "i/", "w/");
 
+	refresh_fsmonitor(istate);
+
 	if (diff_unmerged_stage < 0)
 		diff_unmerged_stage = 2;
 	entries = istate->cache_nr;
@@ -197,8 +200,17 @@
 		if (ce_uptodate(ce) || ce_skip_worktree(ce))
 			continue;
 
-		/* If CE_VALID is set, don't look at workdir for file removal */
-		if (ce->ce_flags & CE_VALID) {
+		/*
+		 * When CE_VALID is set (via "update-index --assume-unchanged"
+		 * or via adding paths while core.ignorestat is set to true),
+		 * the user has promised that the working tree file for that
+		 * path will not be modified.  When CE_FSMONITOR_VALID is true,
+		 * the fsmonitor knows that the path hasn't been modified since
+		 * we refreshed the cached stat information.  In either case,
+		 * we do not have to stat to see if the path has been removed
+		 * or modified.
+		 */
+		if (ce->ce_flags & (CE_VALID | CE_FSMONITOR_VALID)) {
 			changed = 0;
 			newmode = ce->ce_mode;
 		} else {
@@ -510,16 +522,74 @@
 	return unpack_trees(1, &t, &opts);
 }
 
-int run_diff_index(struct rev_info *revs, int cached)
+void diff_get_merge_base(const struct rev_info *revs, struct object_id *mb)
+{
+	int i;
+	struct commit *mb_child[2] = {0};
+	struct commit_list *merge_bases;
+
+	for (i = 0; i < revs->pending.nr; i++) {
+		struct object *obj = revs->pending.objects[i].item;
+		if (obj->flags)
+			die(_("--merge-base does not work with ranges"));
+		if (obj->type != OBJ_COMMIT)
+			die(_("--merge-base only works with commits"));
+	}
+
+	/*
+	 * This check must go after the for loop above because A...B
+	 * ranges produce three pending commits, resulting in a
+	 * misleading error message.
+	 */
+	if (revs->pending.nr < 1 || revs->pending.nr > 2)
+		BUG("unexpected revs->pending.nr: %d", revs->pending.nr);
+
+	for (i = 0; i < revs->pending.nr; i++)
+		mb_child[i] = lookup_commit_reference(the_repository, &revs->pending.objects[i].item->oid);
+	if (revs->pending.nr == 1) {
+		struct object_id oid;
+
+		if (get_oid("HEAD", &oid))
+			die(_("unable to get HEAD"));
+
+		mb_child[1] = lookup_commit_reference(the_repository, &oid);
+	}
+
+	merge_bases = repo_get_merge_bases(the_repository, mb_child[0], mb_child[1]);
+	if (!merge_bases)
+		die(_("no merge base found"));
+	if (merge_bases->next)
+		die(_("multiple merge bases found"));
+
+	oidcpy(mb, &merge_bases->item->object.oid);
+
+	free_commit_list(merge_bases);
+}
+
+int run_diff_index(struct rev_info *revs, unsigned int option)
 {
 	struct object_array_entry *ent;
+	int cached = !!(option & DIFF_INDEX_CACHED);
+	int merge_base = !!(option & DIFF_INDEX_MERGE_BASE);
+	struct object_id oid;
+	const char *name;
+	char merge_base_hex[GIT_MAX_HEXSZ + 1];
 
 	if (revs->pending.nr != 1)
 		BUG("run_diff_index must be passed exactly one tree");
 
 	trace_performance_enter();
 	ent = revs->pending.objects;
-	if (diff_cache(revs, &ent->item->oid, ent->name, cached))
+
+	if (merge_base) {
+		diff_get_merge_base(revs, &oid);
+		name = oid_to_hex_r(merge_base_hex, &oid);
+	} else {
+		oidcpy(&oid, &ent->item->oid);
+		name = ent->name;
+	}
+
+	if (diff_cache(revs, &oid, name, cached))
 		exit(128);
 
 	diff_set_mnemonic_prefix(&revs->diffopt, "c/", cached ? "i/" : "w/");
@@ -536,10 +606,12 @@
 
 	repo_init_revisions(opt->repo, &revs, NULL);
 	copy_pathspec(&revs.prune_data, &opt->pathspec);
+	diff_setup_done(&revs.diffopt);
 	revs.diffopt = *opt;
 
 	if (diff_cache(&revs, tree_oid, NULL, 1))
 		exit(128);
+	clear_pathspec(&revs.prune_data);
 	return 0;
 }
 
diff --git a/diff.c b/diff.c
index 2bb2f8f..643f4f3 100644
--- a/diff.c
+++ b/diff.c
@@ -3587,6 +3587,8 @@
 		if (header.len && !o->flags.suppress_diff_headers)
 			ecbdata.header = &header;
 		xpp.flags = o->xdl_opts;
+		xpp.ignore_regex = o->ignore_regex;
+		xpp.ignore_regex_nr = o->ignore_regex_nr;
 		xpp.anchors = o->anchors;
 		xpp.anchors_nr = o->anchors_nr;
 		xecfg.ctxlen = o->context;
@@ -3716,6 +3718,8 @@
 		memset(&xpp, 0, sizeof(xpp));
 		memset(&xecfg, 0, sizeof(xecfg));
 		xpp.flags = o->xdl_opts;
+		xpp.ignore_regex = o->ignore_regex;
+		xpp.ignore_regex_nr = o->ignore_regex_nr;
 		xpp.anchors = o->anchors;
 		xpp.anchors_nr = o->anchors_nr;
 		xecfg.ctxlen = o->context;
@@ -4111,6 +4115,9 @@
 
 void diff_free_filespec_data(struct diff_filespec *s)
 {
+	if (!s)
+		return;
+
 	diff_free_filespec_blob(s);
 	FREE_AND_NULL(s->cnt_data);
 }
@@ -5203,6 +5210,22 @@
 	return 0;
 }
 
+static int diff_opt_ignore_regex(const struct option *opt,
+				 const char *arg, int unset)
+{
+	struct diff_options *options = opt->value;
+	regex_t *regex;
+
+	BUG_ON_OPT_NEG(unset);
+	regex = xmalloc(sizeof(*regex));
+	if (regcomp(regex, arg, REG_EXTENDED | REG_NEWLINE))
+		return error(_("invalid regex given to -I: '%s'"), arg);
+	ALLOC_GROW(options->ignore_regex, options->ignore_regex_nr + 1,
+		   options->ignore_regex_alloc);
+	options->ignore_regex[options->ignore_regex_nr++] = regex;
+	return 0;
+}
+
 static int diff_opt_pickaxe_regex(const struct option *opt,
 				  const char *arg, int unset)
 {
@@ -5491,6 +5514,9 @@
 		OPT_BIT_F(0, "ignore-blank-lines", &options->xdl_opts,
 			  N_("ignore changes whose lines are all blank"),
 			  XDF_IGNORE_BLANK_LINES, PARSE_OPT_NONEG),
+		OPT_CALLBACK_F('I', "ignore-matching-lines", options, N_("<regex>"),
+			       N_("ignore changes whose all lines match <regex>"),
+			       0, diff_opt_ignore_regex),
 		OPT_BIT(0, "indent-heuristic", &options->xdl_opts,
 			N_("heuristic to shift diff hunk boundaries for easy reading"),
 			XDF_INDENT_HEURISTIC),
@@ -6289,9 +6315,9 @@
 			if (o->color_moved == COLOR_MOVED_ZEBRA_DIM)
 				dim_moved_lines(o);
 
-			hashmap_free_entries(&add_lines, struct moved_entry,
+			hashmap_clear_and_free(&add_lines, struct moved_entry,
 						ent);
-			hashmap_free_entries(&del_lines, struct moved_entry,
+			hashmap_clear_and_free(&del_lines, struct moved_entry,
 						ent);
 		}
 
diff --git a/diff.h b/diff.h
index 11de52e..9665e22 100644
--- a/diff.h
+++ b/diff.h
@@ -234,6 +234,10 @@
 	 */
 	const char *pickaxe;
 
+	/* -I<regex> */
+	regex_t **ignore_regex;
+	size_t ignore_regex_nr, ignore_regex_alloc;
+
 	const char *single_follow;
 	const char *a_prefix, *b_prefix;
 	const char *line_prefix;
@@ -578,12 +582,17 @@
  */
 const char *diff_aligned_abbrev(const struct object_id *sha1, int);
 
+void diff_get_merge_base(const struct rev_info *revs, struct object_id *mb);
+
 /* do not report anything on removed paths */
 #define DIFF_SILENT_ON_REMOVED 01
 /* report racily-clean paths as modified */
 #define DIFF_RACY_IS_MODIFIED 02
 int run_diff_files(struct rev_info *revs, unsigned int option);
-int run_diff_index(struct rev_info *revs, int cached);
+
+#define DIFF_INDEX_CACHED 01
+#define DIFF_INDEX_MERGE_BASE 02
+int run_diff_index(struct rev_info *revs, unsigned int option);
 
 int do_diff_cache(const struct object_id *, struct diff_options *);
 int diff_flush_patch_id(struct diff_options *, struct object_id *, int, int);
diff --git a/diffcore-rename.c b/diffcore-rename.c
index 99e63e9..d367a6d 100644
--- a/diffcore-rename.c
+++ b/diffcore-rename.c
@@ -407,7 +407,7 @@
 		renames += find_identical_files(&file_table, i, options);
 
 	/* Free the hash data structure and entries */
-	hashmap_free_entries(&file_table, struct file_similarity, entry);
+	hashmap_clear_and_free(&file_table, struct file_similarity, entry);
 
 	return renames;
 }
diff --git a/dir.c b/dir.c
index 7838711..d637461 100644
--- a/dir.c
+++ b/dir.c
@@ -817,8 +817,8 @@
 
 clear_hashmaps:
 	warning(_("disabling cone pattern matching"));
-	hashmap_free_entries(&pl->parent_hashmap, struct pattern_entry, ent);
-	hashmap_free_entries(&pl->recursive_hashmap, struct pattern_entry, ent);
+	hashmap_clear_and_free(&pl->parent_hashmap, struct pattern_entry, ent);
+	hashmap_clear_and_free(&pl->recursive_hashmap, struct pattern_entry, ent);
 	pl->use_cone_patterns = 0;
 }
 
@@ -921,8 +921,8 @@
 		free(pl->patterns[i]);
 	free(pl->patterns);
 	free(pl->filebuf);
-	hashmap_free_entries(&pl->recursive_hashmap, struct pattern_entry, ent);
-	hashmap_free_entries(&pl->parent_hashmap, struct pattern_entry, ent);
+	hashmap_clear_and_free(&pl->recursive_hashmap, struct pattern_entry, ent);
+	hashmap_clear_and_free(&pl->parent_hashmap, struct pattern_entry, ent);
 
 	memset(pl, 0, sizeof(*pl));
 }
@@ -1040,9 +1040,9 @@
  * an index if 'istate' is non-null), parse it and store the
  * exclude rules in "pl".
  *
- * If "ss" is not NULL, compute SHA-1 of the exclude file and fill
+ * If "oid_stat" is not NULL, compute oid of the exclude file and fill
  * stat data from disk (only valid if add_patterns returns zero). If
- * ss_valid is non-zero, "ss" must contain good value as input.
+ * oid_stat.valid is non-zero, "oid_stat" must contain good value as input.
  */
 static int add_patterns(const char *fname, const char *base, int baselen,
 			struct pattern_list *pl, struct index_state *istate,
@@ -1090,7 +1090,7 @@
 			int pos;
 			if (oid_stat->valid &&
 			    !match_stat_data_racy(istate, &oid_stat->stat, &st))
-				; /* no content change, ss->sha1 still good */
+				; /* no content change, oid_stat->oid still good */
 			else if (istate &&
 				 (pos = index_name_pos(istate, fname, strlen(fname))) >= 0 &&
 				 !ce_stage(istate->cache[pos]) &&
diff --git a/fmt-merge-msg.c b/fmt-merge-msg.c
index bd22e1e..9a664a4 100644
--- a/fmt-merge-msg.c
+++ b/fmt-merge-msg.c
@@ -626,8 +626,10 @@
 	void *current_branch_to_free;
 	struct merge_parents merge_parents;
 
-	if (!suppress_dest_pattern_seen)
+	if (!suppress_dest_pattern_seen) {
+		string_list_append(&suppress_dest_patterns, "main");
 		string_list_append(&suppress_dest_patterns, "master");
+	}
 
 	memset(&merge_parents, 0, sizeof(merge_parents));
 
diff --git a/git-add--interactive.perl b/git-add--interactive.perl
index 8a72018..e713fe3 100755
--- a/git-add--interactive.perl
+++ b/git-add--interactive.perl
@@ -1830,6 +1830,13 @@
 				$arg = shift @ARGV or die __("missing --");
 				if ($arg ne '--') {
 					$patch_mode_revision = $arg;
+
+					# NEEDSWORK: Instead of comparing to the literal "HEAD",
+					# compare the commit objects instead so that other ways of
+					# saying the same thing (such as "@") are also handled
+					# appropriately.
+					#
+					# This applies to the cases below too.
 					$patch_mode = ($arg eq 'HEAD' ?
 						       'reset_head' : 'reset_nothead');
 					$arg = shift @ARGV or die __("missing --");
diff --git a/git-bisect.sh b/git-bisect.sh
index ea7e684..1f3f6e9 100755
--- a/git-bisect.sh
+++ b/git-bisect.sh
@@ -39,37 +39,6 @@
 TERM_BAD=bad
 TERM_GOOD=good
 
-bisect_head()
-{
-	if git rev-parse --verify -q BISECT_HEAD > /dev/null
-	then
-		echo BISECT_HEAD
-	else
-		echo HEAD
-	fi
-}
-
-bisect_start() {
-	git bisect--helper --bisect-start $@ || exit
-
-	#
-	# Change state.
-	# In case of mistaken revs or checkout error, or signals received,
-	# "bisect_auto_next" below may exit or misbehave.
-	# We have to trap this to be able to clean up using
-	# "bisect_clean_state".
-	#
-	trap 'git bisect--helper --bisect-clean-state' 0
-	trap 'exit 255' 1 2 3 15
-
-	#
-	# Check if we can proceed to the next bisect state.
-	#
-	git bisect--helper --bisect-auto-next || exit
-
-	trap '-' 0
-}
-
 bisect_skip() {
 	all=''
 	for arg in "$@"
@@ -82,43 +51,7 @@
 		esac
 		all="$all $revs"
 	done
-	eval bisect_state 'skip' $all
-}
-
-bisect_state() {
-	git bisect--helper --bisect-autostart || exit
-	state=$1
-	git bisect--helper --check-and-set-terms $state $TERM_GOOD $TERM_BAD || exit
-	get_terms
-	case "$#,$state" in
-	0,*)
-		die "Please call 'bisect_state' with at least one argument." ;;
-	1,"$TERM_BAD"|1,"$TERM_GOOD"|1,skip)
-		bisected_head=$(bisect_head)
-		rev=$(git rev-parse --verify "$bisected_head") ||
-			die "$(eval_gettext "Bad rev input: \$bisected_head")"
-		git bisect--helper --bisect-write "$state" "$rev" "$TERM_GOOD" "$TERM_BAD" || exit
-		git bisect--helper --check-expected-revs "$rev" ;;
-	2,"$TERM_BAD"|*,"$TERM_GOOD"|*,skip)
-		shift
-		hash_list=''
-		for rev in "$@"
-		do
-			sha=$(git rev-parse --verify "$rev^{commit}") ||
-				die "$(eval_gettext "Bad rev input: \$rev")"
-			hash_list="$hash_list $sha"
-		done
-		for rev in $hash_list
-		do
-			git bisect--helper --bisect-write "$state" "$rev" "$TERM_GOOD" "$TERM_BAD" || exit
-		done
-		git bisect--helper --check-expected-revs $hash_list ;;
-	*,"$TERM_BAD")
-		die "$(eval_gettext "'git bisect \$TERM_BAD' can take only one argument.")" ;;
-	*)
-		usage ;;
-	esac
-	git bisect--helper --bisect-auto-next
+	eval git bisect--helper --bisect-state 'skip' $all
 }
 
 bisect_visualize() {
@@ -163,8 +96,7 @@
 		get_terms
 		case "$command" in
 		start)
-			cmd="bisect_start $rev $tail"
-			eval "$cmd" ;;
+			eval "git bisect--helper --bisect-start $rev $tail" ;;
 		"$TERM_GOOD"|"$TERM_BAD"|skip)
 			git bisect--helper --bisect-write "$command" "$rev" "$TERM_GOOD" "$TERM_BAD" || exit;;
 		terms)
@@ -209,8 +141,7 @@
 			state="$TERM_GOOD"
 		fi
 
-		# We have to use a subshell because "bisect_state" can exit.
-		( bisect_state $state >"$GIT_DIR/BISECT_RUN" )
+		git bisect--helper --bisect-state $state >"$GIT_DIR/BISECT_RUN"
 		res=$?
 
 		cat "$GIT_DIR/BISECT_RUN"
@@ -225,7 +156,7 @@
 		if [ $res -ne 0 ]
 		then
 			eval_gettextln "bisect run failed:
-'bisect_state \$state' exited with error code \$res" >&2
+'bisect-state \$state' exited with error code \$res" >&2
 			exit $res
 		fi
 
@@ -264,9 +195,9 @@
 	help)
 		git bisect -h ;;
 	start)
-		bisect_start "$@" ;;
+		git bisect--helper --bisect-start "$@" ;;
 	bad|good|new|old|"$TERM_BAD"|"$TERM_GOOD")
-		bisect_state "$cmd" "$@" ;;
+		git bisect--helper --bisect-state "$cmd" "$@" ;;
 	skip)
 		bisect_skip "$@" ;;
 	next)
diff --git a/git-compat-util.h b/git-compat-util.h
index 7a0fb7a..7d509c5 100644
--- a/git-compat-util.h
+++ b/git-compat-util.h
@@ -489,11 +489,13 @@
 #define error_errno(...) (error_errno(__VA_ARGS__), const_error())
 #endif
 
-void set_die_routine(NORETURN_PTR void (*routine)(const char *err, va_list params));
-void set_error_routine(void (*routine)(const char *err, va_list params));
-extern void (*get_error_routine(void))(const char *err, va_list params);
-void set_warn_routine(void (*routine)(const char *warn, va_list params));
-extern void (*get_warn_routine(void))(const char *warn, va_list params);
+typedef void (*report_fn)(const char *, va_list params);
+
+void set_die_routine(NORETURN_PTR report_fn routine);
+void set_error_routine(report_fn routine);
+report_fn get_error_routine(void);
+void set_warn_routine(report_fn routine);
+report_fn get_warn_routine(void);
 void set_die_is_recursing_routine(int (*routine)(void));
 
 int starts_with(const char *str, const char *prefix);
@@ -1352,4 +1354,6 @@
 	((uintptr_t)&(ptr)->member - (uintptr_t)(ptr))
 #endif /* !__GNUC__ */
 
+void sleep_millisec(int millisec);
+
 #endif
diff --git a/git-mergetool--lib.sh b/git-mergetool--lib.sh
index 2defef2..7225abd 100644
--- a/git-mergetool--lib.sh
+++ b/git-mergetool--lib.sh
@@ -138,6 +138,10 @@
 	merge_cmd () {
 		( eval $merge_tool_cmd )
 	}
+
+	list_tool_variants () {
+		echo "$tool"
+	}
 }
 
 setup_tool () {
diff --git a/git-p4.py b/git-p4.py
index 4433ca5..6ae5bbf 100755
--- a/git-p4.py
+++ b/git-p4.py
@@ -1668,7 +1668,7 @@
     Submit after inspect the message file.
 
     The `p4-post-changelist` hook is invoked after the submit has successfully
-    occured in P4. It takes no parameters and is meant primarily for notification
+    occurred in P4. It takes no parameters and is meant primarily for notification
     and cannot affect the outcome of the git p4 submit action.
     """
 
@@ -4186,7 +4186,7 @@
 
         # create a master branch and check out a work tree
         if gitBranchExists(self.branch):
-            system([ "git", "branch", "master", self.branch ])
+            system([ "git", "branch", currentGitBranch(), self.branch ])
             if not self.cloneBare:
                 system([ "git", "checkout", "-f" ])
         else:
diff --git a/git-parse-remote.sh b/git-parse-remote.sh
deleted file mode 100644
index d3c3998..0000000
--- a/git-parse-remote.sh
+++ /dev/null
@@ -1,101 +0,0 @@
-# This is a shell library to calculate the remote repository and
-# upstream branch that should be pulled by "git pull" from the current
-# branch.
-
-# git-ls-remote could be called from outside a git managed repository;
-# this would fail in that case and would issue an error message.
-GIT_DIR=$(git rev-parse -q --git-dir) || :;
-
-get_default_remote () {
-	curr_branch=$(git symbolic-ref -q HEAD)
-	curr_branch="${curr_branch#refs/heads/}"
-	origin=$(git config --get "branch.$curr_branch.remote")
-	echo ${origin:-origin}
-}
-
-get_remote_merge_branch () {
-	case "$#" in
-	0|1)
-	    origin="$1"
-	    default=$(get_default_remote)
-	    test -z "$origin" && origin=$default
-	    curr_branch=$(git symbolic-ref -q HEAD) &&
-	    [ "$origin" = "$default" ] &&
-	    echo $(git for-each-ref --format='%(upstream)' $curr_branch)
-	    ;;
-	*)
-	    repo=$1
-	    shift
-	    ref=$1
-	    # FIXME: It should return the tracking branch
-	    #        Currently only works with the default mapping
-	    case "$ref" in
-	    +*)
-		ref=$(expr "z$ref" : 'z+\(.*\)')
-		;;
-	    esac
-	    expr "z$ref" : 'z.*:' >/dev/null || ref="${ref}:"
-	    remote=$(expr "z$ref" : 'z\([^:]*\):')
-	    case "$remote" in
-	    '' | HEAD ) remote=HEAD ;;
-	    heads/*) remote=${remote#heads/} ;;
-	    refs/heads/*) remote=${remote#refs/heads/} ;;
-	    refs/* | tags/* | remotes/* ) remote=
-	    esac
-	    [ -n "$remote" ] && case "$repo" in
-		.)
-		    echo "refs/heads/$remote"
-		    ;;
-		*)
-		    echo "refs/remotes/$repo/$remote"
-		    ;;
-	    esac
-	esac
-}
-
-error_on_missing_default_upstream () {
-	cmd="$1"
-	op_type="$2"
-	op_prep="$3" # FIXME: op_prep is no longer used
-	example="$4"
-	branch_name=$(git symbolic-ref -q HEAD)
-	display_branch_name="${branch_name#refs/heads/}"
-	# If there's only one remote, use that in the suggestion
-	remote="$(gettext "<remote>")"
-	branch="$(gettext "<branch>")"
-	if test $(git remote | wc -l) = 1
-	then
-		remote=$(git remote)
-	fi
-
-	if test -z "$branch_name"
-	then
-		gettextln "You are not currently on a branch."
-	else
-		gettextln "There is no tracking information for the current branch."
-	fi
-	case "$op_type" in
-	rebase)
-		gettextln "Please specify which branch you want to rebase against."
-		;;
-	merge)
-		gettextln "Please specify which branch you want to merge with."
-		;;
-	*)
-		echo >&2 "BUG: unknown operation type: $op_type"
-		exit 1
-		;;
-	esac
-	eval_gettextln "See git-\${cmd}(1) for details."
-	echo
-	echo "    $example"
-	echo
-	if test -n "$branch_name"
-	then
-		gettextln "If you wish to set tracking information for this branch you can do so with:"
-		echo
-		echo "    git branch --set-upstream-to=$remote/$branch $display_branch_name"
-		echo
-	fi
-	exit 1
-}
diff --git a/git-submodule.sh b/git-submodule.sh
index 7ce5287..eb90f18 100755
--- a/git-submodule.sh
+++ b/git-submodule.sh
@@ -20,7 +20,6 @@
 OPTIONS_SPEC=
 SUBDIRECTORY_OK=Yes
 . git-sh-setup
-. git-parse-remote
 require_work_tree
 wt_prefix=$(git rev-parse --show-prefix)
 cd_to_toplevel
@@ -413,16 +412,18 @@
 	test -z "$rev"
 )
 
+# usage: fetch_in_submodule <module_path> [<depth>] [<sha1>]
+# Because arguments are positional, use an empty string to omit <depth>
+# but include <sha1>.
 fetch_in_submodule () (
 	sanitize_submodule_env &&
 	cd "$1" &&
-	case "$2" in
-	'')
-		git fetch ;;
-	*)
-		shift
-		git fetch $(get_default_remote) "$@" ;;
-	esac
+	if test $# -eq 3
+	then
+		echo "$3" | git fetch --stdin ${2:+"$2"}
+	else
+		git fetch ${2:+"$2"}
+	fi
 )
 
 #
@@ -576,7 +577,7 @@
 				fetch_in_submodule "$sm_path" $depth ||
 				die "$(eval_gettext "Unable to fetch in submodule path '\$sm_path'")"
 			fi
-			remote_name=$(sanitize_submodule_env; cd "$sm_path" && get_default_remote)
+			remote_name=$(sanitize_submodule_env; cd "$sm_path" && git submodule--helper print-default-remote)
 			sha1=$(sanitize_submodule_env; cd "$sm_path" &&
 				git rev-parse --verify "${remote_name}/${branch}") ||
 			die "$(eval_gettext "Unable to find current \${remote_name}/\${branch} revision in submodule path '\$sm_path'")"
@@ -602,7 +603,7 @@
 				# Now we tried the usual fetch, but $sha1 may
 				# not be reachable from any of the refs
 				is_tip_reachable "$sm_path" "$sha1" ||
-				fetch_in_submodule "$sm_path" $depth "$sha1" ||
+				fetch_in_submodule "$sm_path" "$depth" "$sha1" ||
 				die "$(eval_gettext "Fetched in submodule path '\$displaypath', but it did not contain \$sha1. Direct fetching of that commit failed.")"
 			fi
 
diff --git a/git-svn.perl b/git-svn.perl
index 58f5a7a..70cb5e2 100755
--- a/git-svn.perl
+++ b/git-svn.perl
@@ -2,7 +2,7 @@
 # Copyright (C) 2006, Eric Wong <normalperson@yhbt.net>
 # License: GPL v2 or later
 use 5.008;
-use warnings;
+use warnings $ENV{GIT_PERL_FATAL_WARNINGS} ? qw(FATAL all) : ();
 use strict;
 use vars qw/	$AUTHOR $VERSION
 		$oid $oid_short $oid_length
diff --git a/git.c b/git.c
index 4bdcdad..4b7bd77 100644
--- a/git.c
+++ b/git.c
@@ -516,6 +516,7 @@
 	{ "fetch-pack", cmd_fetch_pack, RUN_SETUP | NO_PARSEOPT },
 	{ "fmt-merge-msg", cmd_fmt_merge_msg, RUN_SETUP },
 	{ "for-each-ref", cmd_for_each_ref, RUN_SETUP },
+	{ "for-each-repo", cmd_for_each_repo, RUN_SETUP_GENTLY },
 	{ "format-patch", cmd_format_patch, RUN_SETUP },
 	{ "fsck", cmd_fsck, RUN_SETUP },
 	{ "fsck-objects", cmd_fsck, RUN_SETUP },
diff --git a/hashmap.c b/hashmap.c
index 09813e1..5009471 100644
--- a/hashmap.c
+++ b/hashmap.c
@@ -92,8 +92,9 @@
 }
 
 static inline int entry_equals(const struct hashmap *map,
-		const struct hashmap_entry *e1, const struct hashmap_entry *e2,
-		const void *keydata)
+			       const struct hashmap_entry *e1,
+			       const struct hashmap_entry *e2,
+			       const void *keydata)
 {
 	return (e1 == e2) ||
 	       (e1->hash == e2->hash &&
@@ -101,7 +102,7 @@
 }
 
 static inline unsigned int bucket(const struct hashmap *map,
-		const struct hashmap_entry *key)
+				  const struct hashmap_entry *key)
 {
 	return key->hash & (map->tablesize - 1);
 }
@@ -113,6 +114,7 @@
 
 static void rehash(struct hashmap *map, unsigned int newsize)
 {
+	/* map->table MUST NOT be NULL when this function is called */
 	unsigned int i, oldsize = map->tablesize;
 	struct hashmap_entry **oldtable = map->table;
 
@@ -133,6 +135,7 @@
 static inline struct hashmap_entry **find_entry_ptr(const struct hashmap *map,
 		const struct hashmap_entry *key, const void *keydata)
 {
+	/* map->table MUST NOT be NULL when this function is called */
 	struct hashmap_entry **e = &map->table[bucket(map, key)];
 	while (*e && !entry_equals(map, *e, key, keydata))
 		e = &(*e)->next;
@@ -148,7 +151,7 @@
 }
 
 void hashmap_init(struct hashmap *map, hashmap_cmp_fn equals_function,
-		const void *cmpfn_data, size_t initial_size)
+		  const void *cmpfn_data, size_t initial_size)
 {
 	unsigned int size = HASHMAP_INITIAL_SIZE;
 
@@ -171,22 +174,37 @@
 	map->do_count_items = 1;
 }
 
-void hashmap_free_(struct hashmap *map, ssize_t entry_offset)
+static void free_individual_entries(struct hashmap *map, ssize_t entry_offset)
+{
+	struct hashmap_iter iter;
+	struct hashmap_entry *e;
+
+	hashmap_iter_init(map, &iter);
+	while ((e = hashmap_iter_next(&iter)))
+		/*
+		 * like container_of, but using caller-calculated
+		 * offset (caller being hashmap_clear_and_free)
+		 */
+		free((char *)e - entry_offset);
+}
+
+void hashmap_partial_clear_(struct hashmap *map, ssize_t entry_offset)
 {
 	if (!map || !map->table)
 		return;
-	if (entry_offset >= 0) { /* called by hashmap_free_entries */
-		struct hashmap_iter iter;
-		struct hashmap_entry *e;
+	if (entry_offset >= 0)  /* called by hashmap_clear_entries */
+		free_individual_entries(map, entry_offset);
+	memset(map->table, 0, map->tablesize * sizeof(struct hashmap_entry *));
+	map->shrink_at = 0;
+	map->private_size = 0;
+}
 
-		hashmap_iter_init(map, &iter);
-		while ((e = hashmap_iter_next(&iter)))
-			/*
-			 * like container_of, but using caller-calculated
-			 * offset (caller being hashmap_free_entries)
-			 */
-			free((char *)e - entry_offset);
-	}
+void hashmap_clear_(struct hashmap *map, ssize_t entry_offset)
+{
+	if (!map || !map->table)
+		return;
+	if (entry_offset >= 0)  /* called by hashmap_clear_and_free */
+		free_individual_entries(map, entry_offset);
 	free(map->table);
 	memset(map, 0, sizeof(*map));
 }
@@ -195,11 +213,13 @@
 				const struct hashmap_entry *key,
 				const void *keydata)
 {
+	if (!map->table)
+		return NULL;
 	return *find_entry_ptr(map, key, keydata);
 }
 
 struct hashmap_entry *hashmap_get_next(const struct hashmap *map,
-			const struct hashmap_entry *entry)
+				       const struct hashmap_entry *entry)
 {
 	struct hashmap_entry *e = entry->next;
 	for (; e; e = e->next)
@@ -210,8 +230,12 @@
 
 void hashmap_add(struct hashmap *map, struct hashmap_entry *entry)
 {
-	unsigned int b = bucket(map, entry);
+	unsigned int b;
 
+	if (!map->table)
+		alloc_table(map, HASHMAP_INITIAL_SIZE);
+
+	b = bucket(map, entry);
 	/* add entry */
 	entry->next = map->table[b];
 	map->table[b] = entry;
@@ -225,11 +249,15 @@
 }
 
 struct hashmap_entry *hashmap_remove(struct hashmap *map,
-					const struct hashmap_entry *key,
-					const void *keydata)
+				     const struct hashmap_entry *key,
+				     const void *keydata)
 {
 	struct hashmap_entry *old;
-	struct hashmap_entry **e = find_entry_ptr(map, key, keydata);
+	struct hashmap_entry **e;
+
+	if (!map->table)
+		return NULL;
+	e = find_entry_ptr(map, key, keydata);
 	if (!*e)
 		return NULL;
 
@@ -249,7 +277,7 @@
 }
 
 struct hashmap_entry *hashmap_put(struct hashmap *map,
-				struct hashmap_entry *entry)
+				  struct hashmap_entry *entry)
 {
 	struct hashmap_entry *old = hashmap_remove(map, entry, NULL);
 	hashmap_add(map, entry);
diff --git a/hashmap.h b/hashmap.h
index b011b39..7251687 100644
--- a/hashmap.h
+++ b/hashmap.h
@@ -96,7 +96,7 @@
  *         }
  *
  *         if (!strcmp("end", action)) {
- *             hashmap_free_entries(&map, struct long2string, ent);
+ *             hashmap_clear_and_free(&map, struct long2string, ent);
  *             break;
  *         }
  *     }
@@ -210,6 +210,9 @@
 
 /* hashmap functions */
 
+#define HASHMAP_INIT(fn, data) { .cmpfn = fn, .cmpfn_data = data, \
+				 .do_count_items = 1 }
+
 /*
  * Initializes a hashmap structure.
  *
@@ -228,24 +231,72 @@
  * prevent expensive resizing. If 0, the table is dynamically resized.
  */
 void hashmap_init(struct hashmap *map,
-			 hashmap_cmp_fn equals_function,
-			 const void *equals_function_data,
-			 size_t initial_size);
+		  hashmap_cmp_fn equals_function,
+		  const void *equals_function_data,
+		  size_t initial_size);
 
-/* internal function for freeing hashmap */
-void hashmap_free_(struct hashmap *map, ssize_t offset);
+/* internal functions for clearing or freeing hashmap */
+void hashmap_partial_clear_(struct hashmap *map, ssize_t offset);
+void hashmap_clear_(struct hashmap *map, ssize_t offset);
 
 /*
- * Frees a hashmap structure and allocated memory, leaves entries undisturbed
+ * Frees a hashmap structure and allocated memory for the table, but does not
+ * free the entries nor anything they point to.
+ *
+ * Usage note:
+ *
+ * Many callers will need to iterate over all entries and free the data each
+ * entry points to; in such a case, they can free the entry itself while at it.
+ * Thus, you might see:
+ *
+ *    hashmap_for_each_entry(map, hashmap_iter, e, hashmap_entry_name) {
+ *      free(e->somefield);
+ *      free(e);
+ *    }
+ *    hashmap_clear(map);
+ *
+ * instead of
+ *
+ *    hashmap_for_each_entry(map, hashmap_iter, e, hashmap_entry_name) {
+ *      free(e->somefield);
+ *    }
+ *    hashmap_clear_and_free(map, struct my_entry_struct, hashmap_entry_name);
+ *
+ * to avoid the implicit extra loop over the entries.  However, if there are
+ * no special fields in your entry that need to be freed beyond the entry
+ * itself, it is probably simpler to avoid the explicit loop and just call
+ * hashmap_clear_and_free().
  */
-#define hashmap_free(map) hashmap_free_(map, -1)
+#define hashmap_clear(map) hashmap_clear_(map, -1)
 
 /*
- * Frees @map and all entries.  @type is the struct type of the entry
- * where @member is the hashmap_entry struct used to associate with @map
+ * Similar to hashmap_clear(), except that the table is no deallocated; it
+ * is merely zeroed out but left the same size as before.  If the hashmap
+ * will be reused, this avoids the overhead of deallocating and
+ * reallocating map->table.  As with hashmap_clear(), you may need to free
+ * the entries yourself before calling this function.
  */
-#define hashmap_free_entries(map, type, member) \
-	hashmap_free_(map, offsetof(type, member));
+#define hashmap_partial_clear(map) hashmap_partial_clear_(map, -1)
+
+/*
+ * Similar to hashmap_clear() but also frees all entries.  @type is the
+ * struct type of the entry where @member is the hashmap_entry struct used
+ * to associate with @map.
+ *
+ * See usage note above hashmap_clear().
+ */
+#define hashmap_clear_and_free(map, type, member) \
+	hashmap_clear_(map, offsetof(type, member))
+
+/*
+ * Similar to hashmap_partial_clear() but also frees all entries.  @type is
+ * the struct type of the entry where @member is the hashmap_entry struct
+ * used to associate with @map.
+ *
+ * See usage note above hashmap_clear().
+ */
+#define hashmap_partial_clear_and_free(map, type, member) \
+	hashmap_partial_clear_(map, offsetof(type, member))
 
 /* hashmap_entry functions */
 
@@ -261,7 +312,7 @@
  * and if it is on stack, you can just let it go out of scope).
  */
 static inline void hashmap_entry_init(struct hashmap_entry *e,
-					unsigned int hash)
+				      unsigned int hash)
 {
 	e->hash = hash;
 	e->next = NULL;
@@ -303,8 +354,8 @@
  * to `hashmap_cmp_fn` to decide whether the entry matches the key.
  */
 struct hashmap_entry *hashmap_get(const struct hashmap *map,
-				const struct hashmap_entry *key,
-				const void *keydata);
+				  const struct hashmap_entry *key,
+				  const void *keydata);
 
 /*
  * Returns the hashmap entry for the specified hash code and key data,
@@ -337,7 +388,7 @@
  * call to `hashmap_get` or `hashmap_get_next`.
  */
 struct hashmap_entry *hashmap_get_next(const struct hashmap *map,
-			const struct hashmap_entry *entry);
+				       const struct hashmap_entry *entry);
 
 /*
  * Adds a hashmap entry. This allows to add duplicate entries (i.e.
@@ -357,7 +408,7 @@
  * Returns the replaced entry, or NULL if not found (i.e. the entry was added).
  */
 struct hashmap_entry *hashmap_put(struct hashmap *map,
-				struct hashmap_entry *entry);
+				  struct hashmap_entry *entry);
 
 /*
  * Adds or replaces a hashmap entry contained within @keyvar,
@@ -379,8 +430,8 @@
  * Argument explanation is the same as in `hashmap_get`.
  */
 struct hashmap_entry *hashmap_remove(struct hashmap *map,
-					const struct hashmap_entry *key,
-					const void *keydata);
+				     const struct hashmap_entry *key,
+				     const void *keydata);
 
 /*
  * Removes a hashmap entry contained within @keyvar,
@@ -422,7 +473,7 @@
 
 /* Initializes the iterator and returns the first entry, if any. */
 static inline struct hashmap_entry *hashmap_iter_first(struct hashmap *map,
-		struct hashmap_iter *iter)
+						       struct hashmap_iter *iter)
 {
 	hashmap_iter_init(map, iter);
 	return hashmap_iter_next(iter);
diff --git a/line-log.c b/line-log.c
index 68eeb42..75c8b1a 100644
--- a/line-log.c
+++ b/line-log.c
@@ -481,7 +481,7 @@
 		if (obj->flags & UNINTERESTING)
 			continue;
 		obj = deref_tag(revs->repo, obj, NULL, 0);
-		if (obj->type != OBJ_COMMIT)
+		if (!obj || obj->type != OBJ_COMMIT)
 			die("Non commit %s?", revs->pending.objects[i].name);
 		if (commit)
 			die("More than one commit to dig from: %s and %s?",
diff --git a/list-objects-filter-options.c b/list-objects-filter-options.c
index defd3df..d2d1c81 100644
--- a/list-objects-filter-options.c
+++ b/list-objects-filter-options.c
@@ -35,7 +35,7 @@
 		/* not a real filter type; just the count of all filters */
 		break;
 	}
-	BUG("list_object_filter_choice_name: invalid argument '%d'", c);
+	BUG("list_object_filter_config_name: invalid argument '%d'", c);
 }
 
 /*
diff --git a/log-tree.c b/log-tree.c
index 1927f91..fd0dde9 100644
--- a/log-tree.c
+++ b/log-tree.c
@@ -367,7 +367,7 @@
 	const char *suffix = info->patch_suffix;
 	int nr = info->nr;
 	int start_len = filename->len;
-	int max_len = start_len + FORMAT_PATCH_NAME_MAX - (strlen(suffix) + 1);
+	int max_len = start_len + info->patch_name_max - (strlen(suffix) + 1);
 
 	if (0 < info->reroll_count)
 		strbuf_addf(filename, "v%d-", info->reroll_count);
diff --git a/log-tree.h b/log-tree.h
index 8fa7928..1e8c91d 100644
--- a/log-tree.h
+++ b/log-tree.h
@@ -33,7 +33,6 @@
 			     int maybe_multipart);
 void load_ref_decorations(struct decoration_filter *filter, int flags);
 
-#define FORMAT_PATCH_NAME_MAX 64
 void fmt_output_commit(struct strbuf *, struct commit *, struct rev_info *);
 void fmt_output_subject(struct strbuf *, const char *subject, struct rev_info *);
 void fmt_output_email_subject(struct strbuf *, struct rev_info *);
diff --git a/merge-ort-wrappers.c b/merge-ort-wrappers.c
new file mode 100644
index 0000000..7eec25f
--- /dev/null
+++ b/merge-ort-wrappers.c
@@ -0,0 +1,62 @@
+#include "cache.h"
+#include "merge-ort.h"
+#include "merge-ort-wrappers.h"
+
+#include "commit.h"
+
+static int unclean(struct merge_options *opt, struct tree *head)
+{
+	/* Sanity check on repo state; index must match head */
+	struct strbuf sb = STRBUF_INIT;
+
+	if (head && repo_index_has_changes(opt->repo, head, &sb)) {
+		fprintf(stderr, _("Your local changes to the following files would be overwritten by merge:\n  %s"),
+		    sb.buf);
+		strbuf_release(&sb);
+		return -1;
+	}
+
+	return 0;
+}
+
+int merge_ort_nonrecursive(struct merge_options *opt,
+			   struct tree *head,
+			   struct tree *merge,
+			   struct tree *merge_base)
+{
+	struct merge_result result;
+
+	if (unclean(opt, head))
+		return -1;
+
+	if (oideq(&merge_base->object.oid, &merge->object.oid)) {
+		printf(_("Already up to date!"));
+		return 1;
+	}
+
+	memset(&result, 0, sizeof(result));
+	merge_incore_nonrecursive(opt, merge_base, head, merge, &result);
+	merge_switch_to_result(opt, head, &result, 1, 1);
+
+	return result.clean;
+}
+
+int merge_ort_recursive(struct merge_options *opt,
+			struct commit *side1,
+			struct commit *side2,
+			struct commit_list *merge_bases,
+			struct commit **result)
+{
+	struct tree *head = repo_get_commit_tree(opt->repo, side1);
+	struct merge_result tmp;
+
+	if (unclean(opt, head))
+		return -1;
+
+	memset(&tmp, 0, sizeof(tmp));
+	merge_incore_recursive(opt, merge_bases, side1, side2, &tmp);
+	merge_switch_to_result(opt, head, &tmp, 1, 1);
+	*result = NULL;
+
+	return tmp.clean;
+}
diff --git a/merge-ort-wrappers.h b/merge-ort-wrappers.h
new file mode 100644
index 0000000..0c4c57a
--- /dev/null
+++ b/merge-ort-wrappers.h
@@ -0,0 +1,25 @@
+#ifndef MERGE_ORT_WRAPPERS_H
+#define MERGE_ORT_WRAPPERS_H
+
+#include "merge-recursive.h"
+
+/*
+ * rename-detecting three-way merge, no recursion.
+ * Wrapper mimicking the old merge_trees() function.
+ */
+int merge_ort_nonrecursive(struct merge_options *opt,
+			   struct tree *head,
+			   struct tree *merge,
+			   struct tree *common);
+
+/*
+ * rename-detecting three-way merge with recursive ancestor consolidation.
+ * Wrapper mimicking the old merge_recursive() function.
+ */
+int merge_ort_recursive(struct merge_options *opt,
+			struct commit *h1,
+			struct commit *h2,
+			struct commit_list *ancestors,
+			struct commit **result);
+
+#endif
diff --git a/merge-ort.c b/merge-ort.c
new file mode 100644
index 0000000..b487901
--- /dev/null
+++ b/merge-ort.c
@@ -0,0 +1,52 @@
+/*
+ * "Ostensibly Recursive's Twin" merge strategy, or "ort" for short.  Meant
+ * as a drop-in replacement for the "recursive" merge strategy, allowing one
+ * to replace
+ *
+ *   git merge [-s recursive]
+ *
+ * with
+ *
+ *   git merge -s ort
+ *
+ * Note: git's parser allows the space between '-s' and its argument to be
+ * missing.  (Should I have backronymed "ham", "alsa", "kip", "nap, "alvo",
+ * "cale", "peedy", or "ins" instead of "ort"?)
+ */
+
+#include "cache.h"
+#include "merge-ort.h"
+
+void merge_switch_to_result(struct merge_options *opt,
+			    struct tree *head,
+			    struct merge_result *result,
+			    int update_worktree_and_index,
+			    int display_update_msgs)
+{
+	die("Not yet implemented");
+	merge_finalize(opt, result);
+}
+
+void merge_finalize(struct merge_options *opt,
+		    struct merge_result *result)
+{
+	die("Not yet implemented");
+}
+
+void merge_incore_nonrecursive(struct merge_options *opt,
+			       struct tree *merge_base,
+			       struct tree *side1,
+			       struct tree *side2,
+			       struct merge_result *result)
+{
+	die("Not yet implemented");
+}
+
+void merge_incore_recursive(struct merge_options *opt,
+			    struct commit_list *merge_bases,
+			    struct commit *side1,
+			    struct commit *side2,
+			    struct merge_result *result)
+{
+	die("Not yet implemented");
+}
diff --git a/merge-ort.h b/merge-ort.h
new file mode 100644
index 0000000..74adcca
--- /dev/null
+++ b/merge-ort.h
@@ -0,0 +1,58 @@
+#ifndef MERGE_ORT_H
+#define MERGE_ORT_H
+
+#include "merge-recursive.h"
+
+struct commit;
+struct tree;
+
+struct merge_result {
+	/* Whether the merge is clean */
+	int clean;
+
+	/*
+	 * Result of merge.  If !clean, represents what would go in worktree
+	 * (thus possibly including files containing conflict markers).
+	 */
+	struct tree *tree;
+
+	/*
+	 * Additional metadata used by merge_switch_to_result() or future calls
+	 * to merge_incore_*().  Includes data needed to update the index (if
+	 * !clean) and to print "CONFLICT" messages.  Not for external use.
+	 */
+	void *priv;
+};
+
+/*
+ * rename-detecting three-way merge with recursive ancestor consolidation.
+ * working tree and index are untouched.
+ */
+void merge_incore_recursive(struct merge_options *opt,
+			    struct commit_list *merge_bases,
+			    struct commit *side1,
+			    struct commit *side2,
+			    struct merge_result *result);
+
+/*
+ * rename-detecting three-way merge, no recursion.
+ * working tree and index are untouched.
+ */
+void merge_incore_nonrecursive(struct merge_options *opt,
+			       struct tree *merge_base,
+			       struct tree *side1,
+			       struct tree *side2,
+			       struct merge_result *result);
+
+/* Update the working tree and index from head to result after incore merge */
+void merge_switch_to_result(struct merge_options *opt,
+			    struct tree *head,
+			    struct merge_result *result,
+			    int update_worktree_and_index,
+			    int display_update_msgs);
+
+/* Do needed cleanup when not calling merge_switch_to_result() */
+void merge_finalize(struct merge_options *opt,
+		    struct merge_result *result);
+
+#endif
diff --git a/merge-recursive.c b/merge-recursive.c
index d021433..f736a0f 100644
--- a/merge-recursive.c
+++ b/merge-recursive.c
@@ -2651,7 +2651,7 @@
 		free(e->target_file);
 		string_list_clear(&e->source_files, 0);
 	}
-	hashmap_free_entries(&collisions, struct collision_entry, ent);
+	hashmap_clear_and_free(&collisions, struct collision_entry, ent);
 	return renames;
 }
 
@@ -2870,7 +2870,7 @@
 		strbuf_release(&e->new_dir);
 		/* possible_new_dirs already cleared in get_directory_renames */
 	}
-	hashmap_free_entries(dir_renames, struct dir_rename_entry, ent);
+	hashmap_clear_and_free(dir_renames, struct dir_rename_entry, ent);
 	free(dir_renames);
 
 	free(pairs->queue);
@@ -3497,7 +3497,7 @@
 		string_list_clear(entries, 1);
 		free(entries);
 
-		hashmap_free_entries(&opt->priv->current_file_dir_set,
+		hashmap_clear_and_free(&opt->priv->current_file_dir_set,
 					struct path_hashmap_entry, e);
 
 		if (clean < 0) {
diff --git a/mergetools/bc b/mergetools/bc
index a89086e..26c19d4 100644
--- a/mergetools/bc
+++ b/mergetools/bc
@@ -25,4 +25,5 @@
 list_tool_variants () {
 	echo bc
 	echo bc3
+	echo bc4
 }
diff --git a/midx.c b/midx.c
index 0de42ff..da03c14 100644
--- a/midx.c
+++ b/midx.c
@@ -10,6 +10,7 @@
 #include "progress.h"
 #include "trace2.h"
 #include "run-command.h"
+#include "repository.h"
 
 #define MIDX_SIGNATURE 0x4d494458 /* "MIDX" */
 #define MIDX_VERSION 1
@@ -398,15 +399,9 @@
 {
 	struct multi_pack_index *m;
 	struct multi_pack_index *m_search;
-	int config_value;
-	static int env_value = -1;
 
-	if (env_value < 0)
-		env_value = git_env_bool(GIT_TEST_MULTI_PACK_INDEX, 0);
-
-	if (!env_value &&
-	    (repo_config_get_bool(r, "core.multipackindex", &config_value) ||
-	    !config_value))
+	prepare_repo_settings(r);
+	if (!r->settings.core_multi_pack_index)
 		return 0;
 
 	for (m_search = r->objects->multi_pack_index; m_search; m_search = m_search->next)
@@ -790,9 +785,7 @@
 		if (!(offset >> 31))
 			continue;
 
-		hashwrite_be32(f, offset >> 32);
-		hashwrite_be32(f, offset & 0xffffffffUL);
-		written += 2 * sizeof(uint32_t);
+		written += hashwrite_be64(f, offset);
 
 		nr_large_offset--;
 	}
@@ -850,7 +843,7 @@
 
 	packs.pack_paths_checked = 0;
 	if (flags & MIDX_PROGRESS)
-		packs.progress = start_progress(_("Adding packfiles to multi-pack-index"), 0);
+		packs.progress = start_delayed_progress(_("Adding packfiles to multi-pack-index"), 0);
 	else
 		packs.progress = NULL;
 
@@ -980,14 +973,13 @@
 			    chunk_offsets[i]);
 
 		hashwrite_be32(f, chunk_ids[i]);
-		hashwrite_be32(f, chunk_offsets[i] >> 32);
-		hashwrite_be32(f, chunk_offsets[i]);
+		hashwrite_be64(f, chunk_offsets[i]);
 
 		written += MIDX_CHUNKLOOKUP_WIDTH;
 	}
 
 	if (flags & MIDX_PROGRESS)
-		progress = start_progress(_("Writing chunks to multi-pack-index"),
+		progress = start_delayed_progress(_("Writing chunks to multi-pack-index"),
 					  num_chunks);
 	for (i = 0; i < num_chunks; i++) {
 		if (written != chunk_offsets[i])
@@ -1129,7 +1121,7 @@
 	}
 
 	if (flags & MIDX_PROGRESS)
-		progress = start_progress(_("Looking for referenced packfiles"),
+		progress = start_delayed_progress(_("Looking for referenced packfiles"),
 					  m->num_packs);
 	for (i = 0; i < m->num_packs; i++) {
 		if (prepare_midx_pack(r, m, i))
@@ -1250,7 +1242,7 @@
 	count = xcalloc(m->num_packs, sizeof(uint32_t));
 
 	if (flags & MIDX_PROGRESS)
-		progress = start_progress(_("Counting referenced objects"),
+		progress = start_delayed_progress(_("Counting referenced objects"),
 					  m->num_objects);
 	for (i = 0; i < m->num_objects; i++) {
 		int pack_int_id = nth_midxed_pack_int_id(m, i);
@@ -1260,7 +1252,7 @@
 	stop_progress(&progress);
 
 	if (flags & MIDX_PROGRESS)
-		progress = start_progress(_("Finding and deleting unreferenced packfiles"),
+		progress = start_delayed_progress(_("Finding and deleting unreferenced packfiles"),
 					  m->num_packs);
 	for (i = 0; i < m->num_packs; i++) {
 		char *pack_name;
diff --git a/name-hash.c b/name-hash.c
index fb526a3..5d3c7b1 100644
--- a/name-hash.c
+++ b/name-hash.c
@@ -726,6 +726,6 @@
 		return;
 	istate->name_hash_initialized = 0;
 
-	hashmap_free(&istate->name_hash);
-	hashmap_free_entries(&istate->dir_hash, struct dir_entry, ent);
+	hashmap_clear(&istate->name_hash);
+	hashmap_clear_and_free(&istate->dir_hash, struct dir_entry, ent);
 }
diff --git a/notes.c b/notes.c
index 564baac..d5ac081 100644
--- a/notes.c
+++ b/notes.c
@@ -970,7 +970,7 @@
 
 	if (*load_refs && !strcmp(k, "notes.displayref")) {
 		if (!v)
-			config_error_nonbool(k);
+			return config_error_nonbool(k);
 		string_list_add_refs_by_glob(&display_notes_refs, v);
 	}
 
diff --git a/object.c b/object.c
index 3257518..68f80b0 100644
--- a/object.c
+++ b/object.c
@@ -453,12 +453,12 @@
 	}
 }
 
-void clear_commit_marks_all(unsigned int flags)
+void repo_clear_commit_marks(struct repository *r, unsigned int flags)
 {
 	int i;
 
-	for (i = 0; i < the_repository->parsed_objects->obj_hash_size; i++) {
-		struct object *obj = the_repository->parsed_objects->obj_hash[i];
+	for (i = 0; i < r->parsed_objects->obj_hash_size; i++) {
+		struct object *obj = r->parsed_objects->obj_hash[i];
 		if (obj && obj->type == OBJ_COMMIT)
 			obj->flags &= ~flags;
 	}
@@ -532,7 +532,7 @@
 	close_object_store(o);
 	o->packed_git = NULL;
 
-	hashmap_free(&o->pack_map);
+	hashmap_clear(&o->pack_map);
 }
 
 void parsed_object_pool_clear(struct parsed_object_pool *o)
diff --git a/object.h b/object.h
index 20b1880..59daadc 100644
--- a/object.h
+++ b/object.h
@@ -191,8 +191,9 @@
 void clear_object_flags(unsigned flags);
 
 /*
- * Clear the specified object flags from all in-core commit objects.
+ * Clear the specified object flags from all in-core commit objects from
+ * the specified repository.
  */
-void clear_commit_marks_all(unsigned int flags);
+void repo_clear_commit_marks(struct repository *r, unsigned int flags);
 
 #endif /* OBJECT_H */
diff --git a/oidmap.c b/oidmap.c
index 423aa01..286a04a 100644
--- a/oidmap.c
+++ b/oidmap.c
@@ -27,7 +27,7 @@
 		return;
 
 	/* TODO: make oidmap itself not depend on struct layouts */
-	hashmap_free_(&map->map, free_entries ? 0 : -1);
+	hashmap_clear_(&map->map, free_entries ? 0 : -1);
 }
 
 void *oidmap_get(const struct oidmap *map, const struct object_id *key)
diff --git a/oidset.c b/oidset.c
index 2d0ab76..5aac633 100644
--- a/oidset.c
+++ b/oidset.c
@@ -72,9 +72,10 @@
 		if (!sb.len)
 			continue;
 
-		if (parse_oid_hex(sb.buf, &oid, &p) || *p != '\0' ||
-		    (fn && fn(&oid, cbdata)))
+		if (parse_oid_hex(sb.buf, &oid, &p) || *p != '\0')
 			die("invalid object name: %s", sb.buf);
+		if (fn && fn(&oid, cbdata))
+			continue;
 		oidset_insert(set, &oid);
 	}
 	if (ferror(fp))
diff --git a/pack-check.c b/pack-check.c
index dad6d8a..4b089fe 100644
--- a/pack-check.c
+++ b/pack-check.c
@@ -39,7 +39,7 @@
 	} while (len);
 
 	index_crc = p->index_data;
-	index_crc += 2 + 256 + p->num_objects * (the_hash_algo->rawsz/4) + nr;
+	index_crc += 2 + 256 + (size_t)p->num_objects * (the_hash_algo->rawsz/4) + nr;
 
 	return data_crc != ntohl(*index_crc);
 }
@@ -164,7 +164,7 @@
 
 int verify_pack_index(struct packed_git *p)
 {
-	off_t index_size;
+	size_t len;
 	const unsigned char *index_base;
 	git_hash_ctx ctx;
 	unsigned char hash[GIT_MAX_RAWSZ];
@@ -172,14 +172,14 @@
 
 	if (open_pack_index(p))
 		return error("packfile %s index not opened", p->pack_name);
-	index_size = p->index_size;
 	index_base = p->index_data;
+	len = p->index_size - the_hash_algo->rawsz;
 
 	/* Verify SHA1 sum of the index file */
 	the_hash_algo->init_fn(&ctx);
-	the_hash_algo->update_fn(&ctx, index_base, (unsigned int)(index_size - the_hash_algo->rawsz));
+	the_hash_algo->update_fn(&ctx, index_base, len);
 	the_hash_algo->final_fn(hash, &ctx);
-	if (!hasheq(hash, index_base + index_size - the_hash_algo->rawsz))
+	if (!hasheq(hash, index_base + len))
 		err = error("Packfile index for %s hash mismatch",
 			    p->pack_name);
 	return err;
diff --git a/pack-revindex.c b/pack-revindex.c
index d28a7e4..ecdde39 100644
--- a/pack-revindex.c
+++ b/pack-revindex.c
@@ -130,7 +130,7 @@
 
 	if (p->index_version > 1) {
 		const uint32_t *off_32 =
-			(uint32_t *)(index + 8 + p->num_objects * (hashsz + 4));
+			(uint32_t *)(index + 8 + (size_t)p->num_objects * (hashsz + 4));
 		const uint32_t *off_64 = off_32 + p->num_objects;
 		for (i = 0; i < num_ent; i++) {
 			const uint32_t off = ntohl(*off_32++);
diff --git a/pack-write.c b/pack-write.c
index a6cdb3c..3513665 100644
--- a/pack-write.c
+++ b/pack-write.c
@@ -48,7 +48,6 @@
 	struct hashfile *f;
 	struct pack_idx_entry **sorted_by_sha, **list, **last;
 	off_t last_obj_offset = 0;
-	uint32_t array[256];
 	int i, fd;
 	uint32_t index_version;
 
@@ -106,10 +105,9 @@
 				break;
 			next++;
 		}
-		array[i] = htonl(next - sorted_by_sha);
+		hashwrite_be32(f, next - sorted_by_sha);
 		list = next;
 	}
-	hashwrite(f, array, 256 * 4);
 
 	/*
 	 * Write the actual SHA1 entries..
@@ -153,13 +151,10 @@
 		while (nr_large_offset) {
 			struct pack_idx_entry *obj = *list++;
 			uint64_t offset = obj->offset;
-			uint32_t split[2];
 
 			if (!need_large_offset(offset, opts))
 				continue;
-			split[0] = htonl(offset >> 32);
-			split[1] = htonl(offset & 0xffffffff);
-			hashwrite(f, split, 8);
+			hashwrite_be64(f, offset);
 			nr_large_offset--;
 		}
 	}
diff --git a/packfile.c b/packfile.c
index 0929ebe..9702b12 100644
--- a/packfile.c
+++ b/packfile.c
@@ -148,7 +148,7 @@
 		 *  - hash of the packfile
 		 *  - file checksum
 		 */
-		if (idx_size != 4 * 256 + nr * (hashsz + 4) + hashsz + hashsz)
+		if (idx_size != st_add(4 * 256 + hashsz + hashsz, st_mult(nr, hashsz + 4)))
 			return error("wrong index v1 file size in %s", path);
 	} else if (version == 2) {
 		/*
@@ -164,10 +164,10 @@
 		 * variable sized table containing 8-byte entries
 		 * for offsets larger than 2^31.
 		 */
-		unsigned long min_size = 8 + 4*256 + nr*(hashsz + 4 + 4) + hashsz + hashsz;
-		unsigned long max_size = min_size;
+		size_t min_size = st_add(8 + 4*256 + hashsz + hashsz, st_mult(nr, hashsz + 4 + 4));
+		size_t max_size = min_size;
 		if (nr)
-			max_size += (nr - 1)*8;
+			max_size = st_add(max_size, st_mult(nr - 1, 8));
 		if (idx_size < min_size || idx_size > max_size)
 			return error("wrong index v2 file size in %s", path);
 		if (idx_size != min_size &&
@@ -1933,14 +1933,14 @@
 	const unsigned int hashsz = the_hash_algo->rawsz;
 	index += 4 * 256;
 	if (p->index_version == 1) {
-		return ntohl(*((uint32_t *)(index + (hashsz + 4) * n)));
+		return ntohl(*((uint32_t *)(index + (hashsz + 4) * (size_t)n)));
 	} else {
 		uint32_t off;
-		index += 8 + p->num_objects * (hashsz + 4);
+		index += 8 + (size_t)p->num_objects * (hashsz + 4);
 		off = ntohl(*((uint32_t *)(index + 4 * n)));
 		if (!(off & 0x80000000))
 			return off;
-		index += p->num_objects * 4 + (off & 0x7fffffff) * 8;
+		index += (size_t)p->num_objects * 4 + (off & 0x7fffffff) * 8;
 		check_pack_index_ptr(p, index);
 		return get_be64(index);
 	}
diff --git a/patch-ids.c b/patch-ids.c
index 12aa6d4..21973e4 100644
--- a/patch-ids.c
+++ b/patch-ids.c
@@ -71,7 +71,7 @@
 
 int free_patch_ids(struct patch_ids *ids)
 {
-	hashmap_free_entries(&ids->patches, struct patch_id, ent);
+	hashmap_clear_and_free(&ids->patches, struct patch_id, ent);
 	return 0;
 }
 
diff --git a/perl/FromCPAN/Error.pm b/perl/FromCPAN/Error.pm
index 8b95e2d..d82b713 100644
--- a/perl/FromCPAN/Error.pm
+++ b/perl/FromCPAN/Error.pm
@@ -12,7 +12,7 @@
 package Error;
 
 use strict;
-use warnings;
+use warnings $ENV{GIT_PERL_FATAL_WARNINGS} ? qw(FATAL all) : ();
 
 use vars qw($VERSION);
 use 5.004;
diff --git a/perl/Git.pm b/perl/Git.pm
index 10df990..02eacef 100644
--- a/perl/Git.pm
+++ b/perl/Git.pm
@@ -9,7 +9,7 @@
 
 use 5.008;
 use strict;
-use warnings;
+use warnings $ENV{GIT_PERL_FATAL_WARNINGS} ? qw(FATAL all) : ();
 
 use File::Temp ();
 use File::Spec ();
diff --git a/perl/Git/I18N.pm b/perl/Git/I18N.pm
index bfb4fb6..2037f38 100644
--- a/perl/Git/I18N.pm
+++ b/perl/Git/I18N.pm
@@ -1,7 +1,7 @@
 package Git::I18N;
 use 5.008;
 use strict;
-use warnings;
+use warnings $ENV{GIT_PERL_FATAL_WARNINGS} ? qw(FATAL all) : ();
 BEGIN {
 	require Exporter;
 	if ($] < 5.008003) {
diff --git a/perl/Git/IndexInfo.pm b/perl/Git/IndexInfo.pm
index 2a7b490..9ee054f 100644
--- a/perl/Git/IndexInfo.pm
+++ b/perl/Git/IndexInfo.pm
@@ -1,6 +1,6 @@
 package Git::IndexInfo;
 use strict;
-use warnings;
+use warnings $ENV{GIT_PERL_FATAL_WARNINGS} ? qw(FATAL all) : ();
 use Git qw/command_input_pipe command_close_pipe/;
 
 sub new {
diff --git a/perl/Git/LoadCPAN.pm b/perl/Git/LoadCPAN.pm
index e5585e7..0c360bc 100644
--- a/perl/Git/LoadCPAN.pm
+++ b/perl/Git/LoadCPAN.pm
@@ -1,7 +1,7 @@
 package Git::LoadCPAN;
 use 5.008;
 use strict;
-use warnings;
+use warnings $ENV{GIT_PERL_FATAL_WARNINGS} ? qw(FATAL all) : ();
 
 =head1 NAME
 
diff --git a/perl/Git/LoadCPAN/Error.pm b/perl/Git/LoadCPAN/Error.pm
index c6d2c45..5d84c20 100644
--- a/perl/Git/LoadCPAN/Error.pm
+++ b/perl/Git/LoadCPAN/Error.pm
@@ -1,7 +1,7 @@
 package Git::LoadCPAN::Error;
 use 5.008;
 use strict;
-use warnings;
+use warnings $ENV{GIT_PERL_FATAL_WARNINGS} ? qw(FATAL all) : ();
 use Git::LoadCPAN (
 	module => 'Error',
 	import => 1,
diff --git a/perl/Git/LoadCPAN/Mail/Address.pm b/perl/Git/LoadCPAN/Mail/Address.pm
index f70a4f0..340e88a 100644
--- a/perl/Git/LoadCPAN/Mail/Address.pm
+++ b/perl/Git/LoadCPAN/Mail/Address.pm
@@ -1,7 +1,7 @@
 package Git::LoadCPAN::Mail::Address;
 use 5.008;
 use strict;
-use warnings;
+use warnings $ENV{GIT_PERL_FATAL_WARNINGS} ? qw(FATAL all) : ();
 use Git::LoadCPAN (
 	module => 'Mail::Address',
 	import => 0,
diff --git a/perl/Git/Packet.pm b/perl/Git/Packet.pm
index b75738b..d144f51 100644
--- a/perl/Git/Packet.pm
+++ b/perl/Git/Packet.pm
@@ -1,7 +1,7 @@
 package Git::Packet;
 use 5.008;
 use strict;
-use warnings;
+use warnings $ENV{GIT_PERL_FATAL_WARNINGS} ? qw(FATAL all) : ();
 BEGIN {
 	require Exporter;
 	if ($] < 5.008003) {
diff --git a/perl/Git/SVN.pm b/perl/Git/SVN.pm
index d1c352f..f6f1dc0 100644
--- a/perl/Git/SVN.pm
+++ b/perl/Git/SVN.pm
@@ -1,6 +1,6 @@
 package Git::SVN;
 use strict;
-use warnings;
+use warnings $ENV{GIT_PERL_FATAL_WARNINGS} ? qw(FATAL all) : ();
 use Fcntl qw/:DEFAULT :seek/;
 use constant rev_map_fmt => 'NH*';
 use vars qw/$_no_metadata
diff --git a/perl/Git/SVN/Editor.pm b/perl/Git/SVN/Editor.pm
index c961444..47fd048 100644
--- a/perl/Git/SVN/Editor.pm
+++ b/perl/Git/SVN/Editor.pm
@@ -1,7 +1,7 @@
 package Git::SVN::Editor;
 use vars qw/@ISA $_rmdir $_cp_similarity $_find_copies_harder $_rename_limit/;
 use strict;
-use warnings;
+use warnings $ENV{GIT_PERL_FATAL_WARNINGS} ? qw(FATAL all) : ();
 use SVN::Core;
 use SVN::Delta;
 use Carp qw/croak/;
diff --git a/perl/Git/SVN/Fetcher.pm b/perl/Git/SVN/Fetcher.pm
index 729e533..968309e 100644
--- a/perl/Git/SVN/Fetcher.pm
+++ b/perl/Git/SVN/Fetcher.pm
@@ -3,7 +3,7 @@
             $_placeholder_filename @deleted_gpath %added_placeholder
             $repo_id/;
 use strict;
-use warnings;
+use warnings $ENV{GIT_PERL_FATAL_WARNINGS} ? qw(FATAL all) : ();
 use SVN::Delta;
 use Carp qw/croak/;
 use File::Basename qw/dirname/;
diff --git a/perl/Git/SVN/GlobSpec.pm b/perl/Git/SVN/GlobSpec.pm
index a0a8d17..f2c1e1f 100644
--- a/perl/Git/SVN/GlobSpec.pm
+++ b/perl/Git/SVN/GlobSpec.pm
@@ -1,6 +1,6 @@
 package Git::SVN::GlobSpec;
 use strict;
-use warnings;
+use warnings $ENV{GIT_PERL_FATAL_WARNINGS} ? qw(FATAL all) : ();
 
 sub new {
 	my ($class, $glob, $pattern_ok) = @_;
diff --git a/perl/Git/SVN/Log.pm b/perl/Git/SVN/Log.pm
index 3858fcf..cc8b484 100644
--- a/perl/Git/SVN/Log.pm
+++ b/perl/Git/SVN/Log.pm
@@ -1,6 +1,6 @@
 package Git::SVN::Log;
 use strict;
-use warnings;
+use warnings $ENV{GIT_PERL_FATAL_WARNINGS} ? qw(FATAL all) : ();
 use Git::SVN::Utils qw(fatal);
 use Git qw(command
            command_oneline
@@ -298,7 +298,7 @@
 			get_author_info($c, $1, $2, $3);
 		} elsif (/^${esc_color}(?:tree|parent|committer) /o) {
 			# ignore
-		} elsif (/^${esc_color}:\d{6} \d{6} $::sha1_short/o) {
+		} elsif (/^${esc_color}:\d{6} \d{6} $::oid_short/o) {
 			push @{$c->{raw}}, $_;
 		} elsif (/^${esc_color}[ACRMDT]\t/) {
 			# we could add $SVN->{svn_path} here, but that requires
diff --git a/perl/Git/SVN/Memoize/YAML.pm b/perl/Git/SVN/Memoize/YAML.pm
index 9676b8f..8fcf664 100644
--- a/perl/Git/SVN/Memoize/YAML.pm
+++ b/perl/Git/SVN/Memoize/YAML.pm
@@ -1,5 +1,5 @@
 package Git::SVN::Memoize::YAML;
-use warnings;
+use warnings $ENV{GIT_PERL_FATAL_WARNINGS} ? qw(FATAL all) : ();
 use strict;
 use YAML::Any ();
 
diff --git a/perl/Git/SVN/Migration.pm b/perl/Git/SVN/Migration.pm
index dc90f6a..ed96ac5 100644
--- a/perl/Git/SVN/Migration.pm
+++ b/perl/Git/SVN/Migration.pm
@@ -33,7 +33,7 @@
 #              possible if noMetadata or useSvmProps are set; but should
 #              be no problem for users that use the (sensible) defaults.
 use strict;
-use warnings;
+use warnings $ENV{GIT_PERL_FATAL_WARNINGS} ? qw(FATAL all) : ();
 use Carp qw/croak/;
 use File::Path qw/mkpath/;
 use File::Basename qw/dirname basename/;
diff --git a/perl/Git/SVN/Prompt.pm b/perl/Git/SVN/Prompt.pm
index e940b08..de158e8 100644
--- a/perl/Git/SVN/Prompt.pm
+++ b/perl/Git/SVN/Prompt.pm
@@ -1,6 +1,6 @@
 package Git::SVN::Prompt;
 use strict;
-use warnings;
+use warnings $ENV{GIT_PERL_FATAL_WARNINGS} ? qw(FATAL all) : ();
 require SVN::Core;
 use vars qw/$_no_auth_cache $_username/;
 
diff --git a/perl/Git/SVN/Ra.pm b/perl/Git/SVN/Ra.pm
index 2cfe055..912e035 100644
--- a/perl/Git/SVN/Ra.pm
+++ b/perl/Git/SVN/Ra.pm
@@ -1,7 +1,7 @@
 package Git::SVN::Ra;
 use vars qw/@ISA $config_dir $_ignore_refs_regex $_log_window_size/;
 use strict;
-use warnings;
+use warnings $ENV{GIT_PERL_FATAL_WARNINGS} ? qw(FATAL all) : ();
 use Memoize;
 use Git::SVN::Utils qw(
 	canonicalize_url
diff --git a/perl/Git/SVN/Utils.pm b/perl/Git/SVN/Utils.pm
index 3d1a093..5ca09ab 100644
--- a/perl/Git/SVN/Utils.pm
+++ b/perl/Git/SVN/Utils.pm
@@ -1,7 +1,7 @@
 package Git::SVN::Utils;
 
 use strict;
-use warnings;
+use warnings $ENV{GIT_PERL_FATAL_WARNINGS} ? qw(FATAL all) : ();
 
 use SVN::Core;
 
diff --git a/pkt-line.c b/pkt-line.c
index 844c253..d633005 100644
--- a/pkt-line.c
+++ b/pkt-line.c
@@ -461,9 +461,11 @@
 	enum sideband_type sideband_type;
 
 	while (1) {
-		len = packet_read(in_stream, NULL, NULL, buf, LARGE_PACKET_MAX,
-				  0);
-		if (!demultiplex_sideband(me, buf, len, 0, &scratch,
+		int status = packet_read_with_status(in_stream, NULL, NULL,
+						     buf, LARGE_PACKET_MAX,
+						     &len,
+						     PACKET_READ_GENTLE_ON_EOF);
+		if (!demultiplex_sideband(me, status, buf, len, 0, &scratch,
 					  &sideband_type))
 			continue;
 		switch (sideband_type) {
@@ -471,6 +473,9 @@
 			write_or_die(out, buf + 1, len - 1);
 			break;
 		default: /* errors: message already written */
+			if (scratch.len > 0)
+				BUG("unhandled incomplete sideband: '%s'",
+				    scratch.buf);
 			return sideband_type;
 		}
 	}
@@ -517,9 +522,9 @@
 							 reader->options);
 		if (!reader->use_sideband)
 			break;
-		if (demultiplex_sideband(reader->me, reader->buffer,
-					 reader->pktlen, 1, &scratch,
-					 &sideband_type))
+		if (demultiplex_sideband(reader->me, reader->status,
+					 reader->buffer, reader->pktlen, 1,
+					 &scratch, &sideband_type))
 			break;
 	}
 
diff --git a/range-diff.c b/range-diff.c
index 24dc435..b9950f1 100644
--- a/range-diff.c
+++ b/range-diff.c
@@ -232,11 +232,9 @@
 
 static void find_exact_matches(struct string_list *a, struct string_list *b)
 {
-	struct hashmap map;
+	struct hashmap map = HASHMAP_INIT((hashmap_cmp_fn)patch_util_cmp, NULL);
 	int i;
 
-	hashmap_init(&map, (hashmap_cmp_fn)patch_util_cmp, NULL, 0);
-
 	/* First, add the patches of a to a hash map */
 	for (i = 0; i < a->nr; i++) {
 		struct patch_util *util = a->items[i].util;
@@ -266,7 +264,7 @@
 		}
 	}
 
-	hashmap_free(&map);
+	hashmap_clear(&map);
 }
 
 static void diffsize_consume(void *data, char *line, unsigned long len)
diff --git a/ref-filter.c b/ref-filter.c
index c62f6b4..aa260bf 100644
--- a/ref-filter.c
+++ b/ref-filter.c
@@ -1097,14 +1097,19 @@
 
 static char *copy_subject(const char *buf, unsigned long len)
 {
-	char *r = xmemdupz(buf, len);
+	struct strbuf sb = STRBUF_INIT;
 	int i;
 
-	for (i = 0; i < len; i++)
-		if (r[i] == '\n')
-			r[i] = ' ';
+	for (i = 0; i < len; i++) {
+		if (buf[i] == '\r' && i + 1 < len && buf[i + 1] == '\n')
+			continue; /* ignore CR in CRLF */
 
-	return r;
+		if (buf[i] == '\n')
+			strbuf_addch(&sb, ' ');
+		else
+			strbuf_addch(&sb, buf[i]);
+	}
+	return strbuf_detach(&sb, NULL);
 }
 
 static void grab_date(const char *buf, struct atom_value *v, const char *atomname)
@@ -1228,20 +1233,23 @@
 
 	/* subject is first non-empty line */
 	*sub = buf;
-	/* subject goes to first empty line */
-	while (buf < *sig && *buf && *buf != '\n') {
-		eol = strchrnul(buf, '\n');
-		if (*eol)
-			eol++;
-		buf = eol;
+	/* subject goes to first empty line before signature begins */
+	if ((eol = strstr(*sub, "\n\n"))) {
+		eol = eol < *sig ? eol : *sig;
+	/* check if message uses CRLF */
+	} else if (! (eol = strstr(*sub, "\r\n\r\n"))) {
+		/* treat whole message as subject */
+		eol = strrchr(*sub, '\0');
 	}
+	buf = eol;
 	*sublen = buf - *sub;
 	/* drop trailing newline, if present */
-	if (*sublen && (*sub)[*sublen - 1] == '\n')
+	while (*sublen && ((*sub)[*sublen - 1] == '\n' ||
+			   (*sub)[*sublen - 1] == '\r'))
 		*sublen -= 1;
 
 	/* skip any empty lines */
-	while (*buf == '\n')
+	while (*buf == '\n' || *buf == '\r')
 		buf++;
 	*body = buf;
 	*bodylen = strlen(buf);
@@ -2222,7 +2230,7 @@
 	used_atom_cnt = 0;
 
 	if (ref_to_worktree_map.worktrees) {
-		hashmap_free_entries(&(ref_to_worktree_map.map),
+		hashmap_clear_and_free(&(ref_to_worktree_map.map),
 					struct ref_to_worktree_entry, ent);
 		free_worktrees(ref_to_worktree_map.worktrees);
 		ref_to_worktree_map.worktrees = NULL;
diff --git a/refs.c b/refs.c
index fa01153..392f0bb 100644
--- a/refs.c
+++ b/refs.c
@@ -567,8 +567,11 @@
 	const char *config_key = "init.defaultbranch";
 	const char *config_display_key = "init.defaultBranch";
 	char *ret = NULL, *full_ref;
+	const char *env = getenv("GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME");
 
-	if (repo_config_get_string(r, config_key, &ret) < 0)
+	if (env && *env)
+		ret = xstrdup(env);
+	else if (repo_config_get_string(r, config_key, &ret) < 0)
 		die(_("could not retrieve `%s`"), config_display_key);
 
 	if (!ret)
diff --git a/refspec.c b/refspec.c
index 8af357a..c49347c 100644
--- a/refspec.c
+++ b/refspec.c
@@ -245,6 +245,16 @@
 	return ret;
 }
 
+int valid_remote_name(const char *name)
+{
+	int result;
+	struct strbuf refspec = STRBUF_INIT;
+	strbuf_addf(&refspec, "refs/heads/test:refs/remotes/%s/test", name);
+	result = valid_fetch_refspec(refspec.buf);
+	strbuf_release(&refspec);
+	return result;
+}
+
 void refspec_ref_prefixes(const struct refspec *rs,
 			  struct strvec *ref_prefixes)
 {
diff --git a/refspec.h b/refspec.h
index 9551832..8b79891 100644
--- a/refspec.h
+++ b/refspec.h
@@ -64,6 +64,7 @@
 void refspec_clear(struct refspec *rs);
 
 int valid_fetch_refspec(const char *refspec);
+int valid_remote_name(const char *name);
 
 struct strvec;
 /*
diff --git a/remote-curl.c b/remote-curl.c
index 32cc4a0..0290b04 100644
--- a/remote-curl.c
+++ b/remote-curl.c
@@ -44,7 +44,8 @@
 		from_promisor : 1,
 
 		atomic : 1,
-		object_format : 1;
+		object_format : 1,
+		force_if_includes : 1;
 	const struct git_hash_algo *hash_algo;
 };
 static struct options options;
@@ -131,6 +132,14 @@
 		string_list_append(&cas_options, val.buf);
 		strbuf_release(&val);
 		return 0;
+	} else if (!strcmp(name, TRANS_OPT_FORCE_IF_INCLUDES)) {
+		if (!strcmp(value, "true"))
+			options.force_if_includes = 1;
+		else if (!strcmp(value, "false"))
+			options.force_if_includes = 0;
+		else
+			return -1;
+		return 0;
 	} else if (!strcmp(name, "cloning")) {
 		if (!strcmp(value, "true"))
 			options.cloning = 1;
@@ -1318,6 +1327,9 @@
 		strvec_push(&args, cas_option->string);
 	strvec_push(&args, url.buf);
 
+	if (options.force_if_includes)
+		strvec_push(&args, "--force-if-includes");
+
 	strvec_push(&args, "--stdin");
 	for (i = 0; i < nr_spec; i++)
 		packet_buf_write(&preamble, "%s\n", specs[i]);
diff --git a/remote.c b/remote.c
index 8be67f0..8a6dbbb 100644
--- a/remote.c
+++ b/remote.c
@@ -1568,12 +1568,23 @@
 		 * with the remote-tracking branch to find the value
 		 * to expect, but we did not have such a tracking
 		 * branch.
+		 *
+		 * If the tip of the remote-tracking ref is unreachable
+		 * from any reflog entry of its local ref indicating a
+		 * possible update since checkout; reject the push.
 		 */
 		if (ref->expect_old_sha1) {
 			if (!oideq(&ref->old_oid, &ref->old_oid_expect))
 				reject_reason = REF_STATUS_REJECT_STALE;
+			else if (ref->check_reachable && ref->unreachable)
+				reject_reason =
+					REF_STATUS_REJECT_REMOTE_UPDATED;
 			else
-				/* If the ref isn't stale then force the update. */
+				/*
+				 * If the ref isn't stale, and is reachable
+				 * from from one of the reflog entries of
+				 * the local branch, force the update.
+				 */
 				force_ref_update = 1;
 		}
 
@@ -2351,12 +2362,13 @@
 
 /*
  * Look at remote.fetch refspec and see if we have a remote
- * tracking branch for the refname there.  Fill its current
- * value in sha1[].
+ * tracking branch for the refname there. Fill the name of
+ * the remote-tracking branch in *dst_refname, and the name
+ * of the commit object at its tip in oid[].
  * If we cannot do so, return negative to signal an error.
  */
 static int remote_tracking(struct remote *remote, const char *refname,
-			   struct object_id *oid)
+			   struct object_id *oid, char **dst_refname)
 {
 	char *dst;
 
@@ -2365,9 +2377,150 @@
 		return -1; /* no tracking ref for refname at remote */
 	if (read_ref(dst, oid))
 		return -1; /* we know what the tracking ref is but we cannot read it */
+
+	*dst_refname = dst;
 	return 0;
 }
 
+/*
+ * The struct "reflog_commit_array" and related helper functions
+ * are used for collecting commits into an array during reflog
+ * traversals in "check_and_collect_until()".
+ */
+struct reflog_commit_array {
+	struct commit **item;
+	size_t nr, alloc;
+};
+
+#define REFLOG_COMMIT_ARRAY_INIT { NULL, 0, 0 }
+
+/* Append a commit to the array. */
+static void append_commit(struct reflog_commit_array *arr,
+			  struct commit *commit)
+{
+	ALLOC_GROW(arr->item, arr->nr + 1, arr->alloc);
+	arr->item[arr->nr++] = commit;
+}
+
+/* Free and reset the array. */
+static void free_commit_array(struct reflog_commit_array *arr)
+{
+	FREE_AND_NULL(arr->item);
+	arr->nr = arr->alloc = 0;
+}
+
+struct check_and_collect_until_cb_data {
+	struct commit *remote_commit;
+	struct reflog_commit_array *local_commits;
+	timestamp_t remote_reflog_timestamp;
+};
+
+/* Get the timestamp of the latest entry. */
+static int peek_reflog(struct object_id *o_oid, struct object_id *n_oid,
+		       const char *ident, timestamp_t timestamp,
+		       int tz, const char *message, void *cb_data)
+{
+	timestamp_t *ts = cb_data;
+	*ts = timestamp;
+	return 1;
+}
+
+static int check_and_collect_until(struct object_id *o_oid,
+				   struct object_id *n_oid,
+				   const char *ident, timestamp_t timestamp,
+				   int tz, const char *message, void *cb_data)
+{
+	struct commit *commit;
+	struct check_and_collect_until_cb_data *cb = cb_data;
+
+	/* An entry was found. */
+	if (oideq(n_oid, &cb->remote_commit->object.oid))
+		return 1;
+
+	if ((commit = lookup_commit_reference(the_repository, n_oid)))
+		append_commit(cb->local_commits, commit);
+
+	/*
+	 * If the reflog entry timestamp is older than the remote ref's
+	 * latest reflog entry, there is no need to check or collect
+	 * entries older than this one.
+	 */
+	if (timestamp < cb->remote_reflog_timestamp)
+		return -1;
+
+	return 0;
+}
+
+#define MERGE_BASES_BATCH_SIZE 8
+
+/*
+ * Iterate through the reflog of the local ref to check if there is an entry
+ * for the given remote-tracking ref; runs until the timestamp of an entry is
+ * older than latest timestamp of remote-tracking ref's reflog. Any commits
+ * are that seen along the way are collected into an array to check if the
+ * remote-tracking ref is reachable from any of them.
+ */
+static int is_reachable_in_reflog(const char *local, const struct ref *remote)
+{
+	timestamp_t date;
+	struct commit *commit;
+	struct commit **chunk;
+	struct check_and_collect_until_cb_data cb;
+	struct reflog_commit_array arr = REFLOG_COMMIT_ARRAY_INIT;
+	size_t size = 0;
+	int ret = 0;
+
+	commit = lookup_commit_reference(the_repository, &remote->old_oid);
+	if (!commit)
+		goto cleanup_return;
+
+	/*
+	 * Get the timestamp from the latest entry
+	 * of the remote-tracking ref's reflog.
+	 */
+	for_each_reflog_ent_reverse(remote->tracking_ref, peek_reflog, &date);
+
+	cb.remote_commit = commit;
+	cb.local_commits = &arr;
+	cb.remote_reflog_timestamp = date;
+	ret = for_each_reflog_ent_reverse(local, check_and_collect_until, &cb);
+
+	/* We found an entry in the reflog. */
+	if (ret > 0)
+		goto cleanup_return;
+
+	/*
+	 * Check if the remote commit is reachable from any
+	 * of the commits in the collected array, in batches.
+	 */
+	for (chunk = arr.item; chunk < arr.item + arr.nr; chunk += size) {
+		size = arr.item + arr.nr - chunk;
+		if (MERGE_BASES_BATCH_SIZE < size)
+			size = MERGE_BASES_BATCH_SIZE;
+
+		if ((ret = in_merge_bases_many(commit, size, chunk)))
+			break;
+	}
+
+cleanup_return:
+	free_commit_array(&arr);
+	return ret;
+}
+
+/*
+ * Check for reachability of a remote-tracking
+ * ref in the reflog entries of its local ref.
+ */
+static void check_if_includes_upstream(struct ref *remote)
+{
+	struct ref *local = get_local_ref(remote->name);
+	if (!local)
+		return;
+
+	if (is_reachable_in_reflog(local->name, remote) <= 0)
+		remote->unreachable = 1;
+}
+
 static void apply_cas(struct push_cas_option *cas,
 		      struct remote *remote,
 		      struct ref *ref)
@@ -2382,8 +2535,12 @@
 		ref->expect_old_sha1 = 1;
 		if (!entry->use_tracking)
 			oidcpy(&ref->old_oid_expect, &entry->expect);
-		else if (remote_tracking(remote, ref->name, &ref->old_oid_expect))
+		else if (remote_tracking(remote, ref->name,
+					 &ref->old_oid_expect,
+					 &ref->tracking_ref))
 			oidclr(&ref->old_oid_expect);
+		else
+			ref->check_reachable = cas->use_force_if_includes;
 		return;
 	}
 
@@ -2392,8 +2549,12 @@
 		return;
 
 	ref->expect_old_sha1 = 1;
-	if (remote_tracking(remote, ref->name, &ref->old_oid_expect))
+	if (remote_tracking(remote, ref->name,
+			    &ref->old_oid_expect,
+			    &ref->tracking_ref))
 		oidclr(&ref->old_oid_expect);
+	else
+		ref->check_reachable = cas->use_force_if_includes;
 }
 
 void apply_push_cas(struct push_cas_option *cas,
@@ -2401,6 +2562,15 @@
 		    struct ref *remote_refs)
 {
 	struct ref *ref;
-	for (ref = remote_refs; ref; ref = ref->next)
+	for (ref = remote_refs; ref; ref = ref->next) {
 		apply_cas(cas, remote, ref);
+
+		/*
+		 * If "compare-and-swap" is in "use_tracking[_for_rest]"
+		 * mode, and if "--force-if-includes" was specified, run
+		 * the check.
+		 */
+		if (ref->check_reachable)
+			check_if_includes_upstream(ref);
+	}
 }
diff --git a/remote.h b/remote.h
index d0e3f51..3211abd 100644
--- a/remote.h
+++ b/remote.h
@@ -107,12 +107,20 @@
 	struct object_id new_oid;
 	struct object_id old_oid_expect; /* used by expect-old */
 	char *symref;
+	char *tracking_ref;
 	unsigned int
 		force:1,
 		forced_update:1,
 		expect_old_sha1:1,
 		exact_oid:1,
-		deletion:1;
+		deletion:1,
+		/* Need to check if local reflog reaches the remote tip. */
+		check_reachable:1,
+		/*
+		 * Store the result of the check enabled by "check_reachable";
+		 * implies the local reflog does not reach the remote tip.
+		 */
+		unreachable:1;
 
 	enum {
 		REF_NOT_MATCHED = 0, /* initial value */
@@ -142,6 +150,7 @@
 		REF_STATUS_REJECT_NEEDS_FORCE,
 		REF_STATUS_REJECT_STALE,
 		REF_STATUS_REJECT_SHALLOW,
+		REF_STATUS_REJECT_REMOTE_UPDATED,
 		REF_STATUS_UPTODATE,
 		REF_STATUS_REMOTE_REJECT,
 		REF_STATUS_EXPECTING_REPORT,
@@ -348,6 +357,7 @@
 
 struct push_cas_option {
 	unsigned use_tracking_for_rest:1;
+	unsigned use_force_if_includes:1;
 	struct push_cas {
 		struct object_id expect;
 		unsigned use_tracking:1;
diff --git a/repo-settings.c b/repo-settings.c
index 88ccce2..f7fff0f 100644
--- a/repo-settings.c
+++ b/repo-settings.c
@@ -1,6 +1,7 @@
 #include "cache.h"
 #include "config.h"
 #include "repository.h"
+#include "midx.h"
 
 #define UPDATE_DEFAULT_BOOL(s,v) do { if (s == -1) { s = v; } } while(0)
 
@@ -52,6 +53,11 @@
 		r->settings.pack_use_sparse = value;
 	UPDATE_DEFAULT_BOOL(r->settings.pack_use_sparse, 1);
 
+	value = git_env_bool(GIT_TEST_MULTI_PACK_INDEX, 0);
+	if (value || !repo_config_get_bool(r, "core.multipackindex", &value))
+		r->settings.core_multi_pack_index = value;
+	UPDATE_DEFAULT_BOOL(r->settings.core_multi_pack_index, 1);
+
 	if (!repo_config_get_bool(r, "feature.manyfiles", &value) && value) {
 		UPDATE_DEFAULT_BOOL(r->settings.index_version, 4);
 		UPDATE_DEFAULT_BOOL(r->settings.core_untracked_cache, UNTRACKED_CACHE_WRITE);
diff --git a/repository.h b/repository.h
index bacf843..b385ca3 100644
--- a/repository.h
+++ b/repository.h
@@ -39,6 +39,8 @@
 
 	int pack_use_sparse;
 	enum fetch_negotiation_setting fetch_negotiation_algorithm;
+
+	int core_multi_pack_index;
 };
 
 struct repository {
diff --git a/revision.c b/revision.c
index aa62212..c6e169e 100644
--- a/revision.c
+++ b/revision.c
@@ -124,11 +124,6 @@
 	return strcmp(e1->path, e2->path);
 }
 
-static void paths_and_oids_init(struct hashmap *map)
-{
-	hashmap_init(map, path_and_oids_cmp, NULL, 0);
-}
-
 static void paths_and_oids_clear(struct hashmap *map)
 {
 	struct hashmap_iter iter;
@@ -139,7 +134,7 @@
 		free(entry->path);
 	}
 
-	hashmap_free_entries(map, struct path_and_oids_entry, ent);
+	hashmap_clear_and_free(map, struct path_and_oids_entry, ent);
 }
 
 static void paths_and_oids_insert(struct hashmap *map,
@@ -213,7 +208,7 @@
 				     struct oidset *trees)
 {
 	unsigned has_interesting = 0, has_uninteresting = 0;
-	struct hashmap map;
+	struct hashmap map = HASHMAP_INIT(path_and_oids_cmp, NULL);
 	struct hashmap_iter map_iter;
 	struct path_and_oids_entry *entry;
 	struct object_id *oid;
@@ -237,8 +232,6 @@
 	if (!has_uninteresting || !has_interesting)
 		return;
 
-	paths_and_oids_init(&map);
-
 	oidset_iter_init(trees, &iter);
 	while ((oid = oidset_iter_next(&iter))) {
 		struct tree *tree = lookup_tree(r, oid);
diff --git a/revision.h b/revision.h
index f6bf860..086ff10 100644
--- a/revision.h
+++ b/revision.h
@@ -238,6 +238,7 @@
 	const char	*extra_headers;
 	const char	*log_reencode;
 	const char	*subject_prefix;
+	int		patch_name_max;
 	int		no_inline;
 	int		show_log_size;
 	struct string_list *mailmap;
diff --git a/run-command.c b/run-command.c
index 2ee59ac..ea4d0fb 100644
--- a/run-command.c
+++ b/run-command.c
@@ -7,6 +7,7 @@
 #include "strbuf.h"
 #include "string-list.h"
 #include "quote.h"
+#include "config.h"
 
 void child_process_init(struct child_process *child)
 {
@@ -1868,8 +1869,13 @@
 
 int run_auto_maintenance(int quiet)
 {
+	int enabled;
 	struct child_process maint = CHILD_PROCESS_INIT;
 
+	if (!git_config_get_bool("maintenance.auto", &enabled) &&
+	    !enabled)
+		return 0;
+
 	maint.git_cmd = 1;
 	strvec_pushl(&maint.args, "maintenance", "run", "--auto", NULL);
 	strvec_push(&maint.args, quiet ? "--quiet" : "--no-quiet");
diff --git a/send-pack.c b/send-pack.c
index c969807..d2701bf 100644
--- a/send-pack.c
+++ b/send-pack.c
@@ -85,6 +85,7 @@
 	po.in = -1;
 	po.out = args->stateless_rpc ? -1 : fd;
 	po.git_cmd = 1;
+	po.clean_on_exit = 1;
 	if (start_command(&po))
 		die_errno("git pack-objects failed");
 
@@ -299,6 +300,7 @@
 	case REF_STATUS_REJECT_FETCH_FIRST:
 	case REF_STATUS_REJECT_NEEDS_FORCE:
 	case REF_STATUS_REJECT_STALE:
+	case REF_STATUS_REJECT_REMOTE_UPDATED:
 	case REF_STATUS_REJECT_NODELETE:
 		return CHECK_REF_STATUS_REJECTED;
 	case REF_STATUS_UPTODATE:
diff --git a/sequencer.c b/sequencer.c
index d76cbde..8909a46 100644
--- a/sequencer.c
+++ b/sequencer.c
@@ -14,7 +14,8 @@
 #include "diff.h"
 #include "revision.h"
 #include "rerere.h"
-#include "merge-recursive.h"
+#include "merge-ort.h"
+#include "merge-ort-wrappers.h"
 #include "refs.h"
 #include "strvec.h"
 #include "quote.h"
@@ -204,6 +205,20 @@
 		return 0;
 	}
 
+	if (!opts->default_strategy && !strcmp(k, "pull.twohead")) {
+		int ret = git_config_string((const char**)&opts->default_strategy, k, v);
+		if (ret == 0) {
+			/*
+			 * pull.twohead is allowed to be multi-valued; we only
+			 * care about the first value.
+			 */
+			char *tmp = strchr(opts->default_strategy, ' ');
+			if (tmp)
+				*tmp = '\0';
+		}
+		return ret;
+	}
+
 	status = git_gpg_config(k, v, NULL);
 	if (status)
 		return status;
@@ -314,9 +329,8 @@
 		}
 	}
 
-	free(opts->committer_name);
-	free(opts->committer_email);
 	free(opts->gpg_sign);
+	free(opts->default_strategy);
 	free(opts->strategy);
 	for (i = 0; i < opts->xopts_nr; i++)
 		free(opts->xopts[i]);
@@ -595,8 +609,9 @@
 			      struct replay_opts *opts)
 {
 	struct merge_options o;
+	struct merge_result result;
 	struct tree *next_tree, *base_tree, *head_tree;
-	int clean;
+	int clean, show_output;
 	int i;
 	struct lock_file index_lock = LOCK_INIT;
 
@@ -620,12 +635,27 @@
 	for (i = 0; i < opts->xopts_nr; i++)
 		parse_merge_opt(&o, opts->xopts[i]);
 
-	clean = merge_trees(&o,
-			    head_tree,
-			    next_tree, base_tree);
-	if (is_rebase_i(opts) && clean <= 0)
-		fputs(o.obuf.buf, stdout);
-	strbuf_release(&o.obuf);
+	if (opts->strategy && !strcmp(opts->strategy, "ort")) {
+		memset(&result, 0, sizeof(result));
+		merge_incore_nonrecursive(&o, base_tree, head_tree, next_tree,
+					    &result);
+		show_output = !is_rebase_i(opts) || !result.clean;
+		/*
+		 * TODO: merge_switch_to_result will update index/working tree;
+		 * we only really want to do that if !result.clean || this is
+		 * the final patch to be picked.  But determining this is the
+		 * final patch would take some work, and "head_tree" would need
+		 * to be replace with the tree the index matched before we
+		 * started doing any picks.
+		 */
+		merge_switch_to_result(&o, head_tree, &result, 1, show_output);
+		clean = result.clean;
+	} else {
+		clean = merge_trees(&o, head_tree, next_tree, base_tree);
+		if (is_rebase_i(opts) && clean <= 0)
+			fputs(o.obuf.buf, stdout);
+		strbuf_release(&o.obuf);
+	}
 	if (clean < 0) {
 		rollback_lock_file(&index_lock);
 		return clean;
@@ -1460,8 +1490,8 @@
 		} else {
 			reset_ident_date();
 		}
-		committer = fmt_ident(opts->committer_name,
-				      opts->committer_email,
+		committer = fmt_ident(getenv("GIT_COMMITTER_NAME"),
+				      getenv("GIT_COMMITTER_EMAIL"),
 				      WANT_COMMITTER_IDENT,
 				      opts->ignore_date ? NULL : date.buf,
 				      IDENT_STRICT);
@@ -1991,7 +2021,10 @@
 
 	if (is_rebase_i(opts) && write_author_script(msg.message) < 0)
 		res = -1;
-	else if (!opts->strategy || !strcmp(opts->strategy, "recursive") || command == TODO_REVERT) {
+	else if (!opts->strategy ||
+		 !strcmp(opts->strategy, "recursive") ||
+		 !strcmp(opts->strategy, "ort") ||
+		 command == TODO_REVERT) {
 		res = do_recursive_merge(r, base, next, base_label, next_label,
 					 &head, &msgbuf, opts);
 		if (res < 0)
@@ -2653,7 +2686,7 @@
 		}
 
 		if (read_oneliner(&buf, rebase_path_squash_onto(), 0)) {
-			if (get_oid_hex(buf.buf, &opts->squash_onto) < 0) {
+			if (get_oid_committish(buf.buf, &opts->squash_onto) < 0) {
 				ret = error(_("unusable squash-onto"));
 				goto done_rebase_i;
 			}
@@ -2692,7 +2725,7 @@
 }
 
 int write_basic_state(struct replay_opts *opts, const char *head_name,
-		      struct commit *onto, const char *orig_head)
+		      struct commit *onto, const struct object_id *orig_head)
 {
 	if (head_name)
 		write_file(rebase_path_head_name(), "%s\n", head_name);
@@ -2700,7 +2733,8 @@
 		write_file(rebase_path_onto(), "%s\n",
 			   oid_to_hex(&onto->object.oid));
 	if (orig_head)
-		write_file(rebase_path_orig_head(), "%s\n", orig_head);
+		write_file(rebase_path_orig_head(), "%s\n",
+			   oid_to_hex(orig_head));
 
 	if (opts->quiet)
 		write_file(rebase_path_quiet(), "%s", "");
@@ -3485,7 +3519,9 @@
 	struct commit_list *bases, *j, *reversed = NULL;
 	struct commit_list *to_merge = NULL, **tail = &to_merge;
 	const char *strategy = !opts->xopts_nr &&
-		(!opts->strategy || !strcmp(opts->strategy, "recursive")) ?
+		(!opts->strategy ||
+		 !strcmp(opts->strategy, "recursive") ||
+		 !strcmp(opts->strategy, "ort")) ?
 		NULL : opts->strategy;
 	struct merge_options o;
 	int merge_arg_len, oneline_offset, can_fast_forward, ret, k;
@@ -3677,7 +3713,9 @@
 		strvec_push(&cmd.args, "-F");
 		strvec_push(&cmd.args, git_path_merge_msg(r));
 		if (opts->gpg_sign)
-			strvec_push(&cmd.args, opts->gpg_sign);
+			strvec_pushf(&cmd.args, "-S%s", opts->gpg_sign);
+		else
+			strvec_push(&cmd.args, "--no-gpg-sign");
 
 		/* Add the tips to be merged */
 		for (j = to_merge; j; j = j->next)
@@ -3689,7 +3727,6 @@
 				NULL, 0);
 		rollback_lock_file(&lock);
 
-		rollback_lock_file(&lock);
 		ret = run_command(&cmd);
 
 		/* force re-reading of the cache */
@@ -3722,7 +3759,20 @@
 	o.branch2 = ref_name.buf;
 	o.buffer_output = 2;
 
-	ret = merge_recursive(&o, head_commit, merge_commit, reversed, &i);
+	if (opts->strategy && !strcmp(opts->strategy, "ort")) {
+		/*
+		 * TODO: Should use merge_incore_recursive() and
+		 * merge_switch_to_result(), skipping the call to
+		 * merge_switch_to_result() when we don't actually need to
+		 * update the index and working copy immediately.
+		 */
+		ret = merge_ort_recursive(&o,
+					  head_commit, merge_commit, reversed,
+					  &i);
+	} else {
+		ret = merge_recursive(&o, head_commit, merge_commit, reversed,
+				      &i);
+	}
 	if (ret <= 0)
 		fputs(o.obuf.buf, stdout);
 	strbuf_release(&o.obuf);
@@ -3965,21 +4015,17 @@
 
 static int checkout_onto(struct repository *r, struct replay_opts *opts,
 			 const char *onto_name, const struct object_id *onto,
-			 const char *orig_head)
+			 const struct object_id *orig_head)
 {
-	struct object_id oid;
 	const char *action = reflog_message(opts, "start", "checkout %s", onto_name);
 
-	if (get_oid(orig_head, &oid))
-		return error(_("%s: not a valid OID"), orig_head);
-
 	if (run_git_checkout(r, opts, oid_to_hex(onto), action)) {
 		apply_autostash(rebase_path_autostash());
 		sequencer_remove_state(opts);
 		return error(_("could not detach HEAD"));
 	}
 
-	return update_ref(NULL, "ORIG_HEAD", &oid, NULL, 0, UPDATE_REFS_MSG_ON_ERR);
+	return update_ref(NULL, "ORIG_HEAD", orig_head, NULL, 0, UPDATE_REFS_MSG_ON_ERR);
 }
 
 static int stopped_at_head(struct repository *r)
@@ -4467,22 +4513,6 @@
 	return 0;
 }
 
-static int init_committer(struct replay_opts *opts)
-{
-	struct ident_split id;
-	const char *committer;
-
-	committer = git_committer_info(IDENT_STRICT);
-	if (split_ident_line(&id, committer, strlen(committer)) < 0)
-		return error(_("invalid committer '%s'"), committer);
-	opts->committer_name =
-		xmemdupz(id.name_begin, id.name_end - id.name_begin);
-	opts->committer_email =
-		xmemdupz(id.mail_begin, id.mail_end - id.mail_begin);
-
-	return 0;
-}
-
 int sequencer_continue(struct repository *r, struct replay_opts *opts)
 {
 	struct todo_list todo_list = TODO_LIST_INIT;
@@ -4494,9 +4524,6 @@
 	if (read_populate_opts(opts))
 		return -1;
 	if (is_rebase_i(opts)) {
-		if (opts->committer_date_is_author_date && init_committer(opts))
-			return -1;
-
 		if ((res = read_populate_todo(r, &todo_list, opts)))
 			goto release_todo_list;
 
@@ -5058,7 +5085,7 @@
 
 	oidmap_free(&commit2todo, 1);
 	oidmap_free(&state.commit2label, 1);
-	hashmap_free_entries(&state.labels, struct labels_entry, entry);
+	hashmap_clear_and_free(&state.labels, struct labels_entry, entry);
 	strbuf_release(&state.buf);
 
 	return 0;
@@ -5314,7 +5341,7 @@
 
 int complete_action(struct repository *r, struct replay_opts *opts, unsigned flags,
 		    const char *shortrevisions, const char *onto_name,
-		    struct commit *onto, const char *orig_head,
+		    struct commit *onto, const struct object_id *orig_head,
 		    struct string_list *commands, unsigned autosquash,
 		    struct todo_list *todo_list)
 {
@@ -5391,9 +5418,6 @@
 
 	res = -1;
 
-	if (opts->committer_date_is_author_date && init_committer(opts))
-		goto cleanup;
-
 	if (checkout_onto(r, opts, onto_name, &oid, orig_head))
 		goto cleanup;
 
@@ -5577,7 +5601,7 @@
 	for (i = 0; i < todo_list->nr; i++)
 		free(subjects[i]);
 	free(subjects);
-	hashmap_free_entries(&subject2item, struct subject2item_entry, entry);
+	hashmap_clear_and_free(&subject2item, struct subject2item_entry, entry);
 
 	clear_commit_todo_item(&commit_todo);
 
diff --git a/sequencer.h b/sequencer.h
index b2a501e..f8b2e4a 100644
--- a/sequencer.h
+++ b/sequencer.h
@@ -50,13 +50,12 @@
 
 	int mainline;
 
-	char *committer_name;
-	char *committer_email;
 	char *gpg_sign;
 	enum commit_msg_cleanup_mode default_msg_cleanup;
 	int explicit_cleanup;
 
 	/* Merge strategy */
+	char *default_strategy;  /* from config options */
 	char *strategy;
 	char **xopts;
 	size_t xopts_nr, xopts_alloc;
@@ -163,8 +162,9 @@
 				 struct string_list *commands);
 int complete_action(struct repository *r, struct replay_opts *opts, unsigned flags,
 		    const char *shortrevisions, const char *onto_name,
-		    struct commit *onto, const char *orig_head, struct string_list *commands,
-		    unsigned autosquash, struct todo_list *todo_list);
+		    struct commit *onto, const struct object_id *orig_head,
+		    struct string_list *commands, unsigned autosquash,
+		    struct todo_list *todo_list);
 int todo_list_rearrange_squash(struct todo_list *todo_list);
 
 /*
@@ -226,7 +226,7 @@
 		       int allow_missing);
 void parse_strategy_opts(struct replay_opts *opts, char *raw_opts);
 int write_basic_state(struct replay_opts *opts, const char *head_name,
-		      struct commit *onto, const char *orig_head);
+		      struct commit *onto, const struct object_id *orig_head);
 void sequencer_post_commit_cleanup(struct repository *r, int verbose);
 int sequencer_get_last_command(struct repository* r,
 			       enum replay_action *action);
diff --git a/sideband.c b/sideband.c
index 0a60662..6f9e026 100644
--- a/sideband.c
+++ b/sideband.c
@@ -3,6 +3,7 @@
 #include "config.h"
 #include "sideband.h"
 #include "help.h"
+#include "pkt-line.h"
 
 struct keyword_entry {
 	/*
@@ -114,7 +115,8 @@
 #define ANSI_SUFFIX "\033[K"
 #define DUMB_SUFFIX "        "
 
-int demultiplex_sideband(const char *me, char *buf, int len,
+int demultiplex_sideband(const char *me, int status,
+			 char *buf, int len,
 			 int die_on_error,
 			 struct strbuf *scratch,
 			 enum sideband_type *sideband_type)
@@ -130,17 +132,30 @@
 			suffix = DUMB_SUFFIX;
 	}
 
-	if (len == 0) {
-		*sideband_type = SIDEBAND_FLUSH;
-		goto cleanup;
-	}
-	if (len < 1) {
+	if (status == PACKET_READ_EOF) {
 		strbuf_addf(scratch,
-			    "%s%s: protocol error: no band designator",
+			    "%s%s: unexpected disconnect while reading sideband packet",
 			    scratch->len ? "\n" : "", me);
 		*sideband_type = SIDEBAND_PROTOCOL_ERROR;
 		goto cleanup;
 	}
+
+	if (len < 0)
+		BUG("negative length on non-eof packet read");
+
+	if (len == 0) {
+		if (status == PACKET_READ_NORMAL) {
+			strbuf_addf(scratch,
+				    "%s%s: protocol error: missing sideband designator",
+				    scratch->len ? "\n" : "", me);
+			*sideband_type = SIDEBAND_PROTOCOL_ERROR;
+		} else {
+			/* covers flush, delim, etc */
+			*sideband_type = SIDEBAND_FLUSH;
+		}
+		goto cleanup;
+	}
+
 	band = buf[0] & 0xff;
 	buf[len] = '\0';
 	len--;
@@ -190,7 +205,7 @@
 		return 0;
 	case 1:
 		*sideband_type = SIDEBAND_PRIMARY;
-		break;
+		return 1;
 	default:
 		strbuf_addf(scratch, "%s%s: protocol error: bad band #%d",
 			    scratch->len ? "\n" : "", me, band);
diff --git a/sideband.h b/sideband.h
index 227740a..5a25331 100644
--- a/sideband.h
+++ b/sideband.h
@@ -18,8 +18,12 @@
  *
  * scratch must be a struct strbuf allocated by the caller. It is used to store
  * progress messages split across multiple packets.
+ *
+ * The "status" parameter is a pkt-line response as returned by
+ * packet_read_with_status() (e.g., PACKET_READ_NORMAL).
  */
-int demultiplex_sideband(const char *me, char *buf, int len,
+int demultiplex_sideband(const char *me, int status,
+			 char *buf, int len,
 			 int die_on_error,
 			 struct strbuf *scratch,
 			 enum sideband_type *sideband_type);
diff --git a/strmap.c b/strmap.c
new file mode 100644
index 0000000..4fb9f61
--- /dev/null
+++ b/strmap.c
@@ -0,0 +1,178 @@
+#include "git-compat-util.h"
+#include "strmap.h"
+#include "mem-pool.h"
+
+int cmp_strmap_entry(const void *hashmap_cmp_fn_data,
+		     const struct hashmap_entry *entry1,
+		     const struct hashmap_entry *entry2,
+		     const void *keydata)
+{
+	const struct strmap_entry *e1, *e2;
+
+	e1 = container_of(entry1, const struct strmap_entry, ent);
+	e2 = container_of(entry2, const struct strmap_entry, ent);
+	return strcmp(e1->key, e2->key);
+}
+
+static struct strmap_entry *find_strmap_entry(struct strmap *map,
+					      const char *str)
+{
+	struct strmap_entry entry;
+	hashmap_entry_init(&entry.ent, strhash(str));
+	entry.key = str;
+	return hashmap_get_entry(&map->map, &entry, ent, NULL);
+}
+
+void strmap_init(struct strmap *map)
+{
+	strmap_init_with_options(map, NULL, 1);
+}
+
+void strmap_init_with_options(struct strmap *map,
+			      struct mem_pool *pool,
+			      int strdup_strings)
+{
+	hashmap_init(&map->map, cmp_strmap_entry, NULL, 0);
+	map->pool = pool;
+	map->strdup_strings = strdup_strings;
+}
+
+static void strmap_free_entries_(struct strmap *map, int free_values)
+{
+	struct hashmap_iter iter;
+	struct strmap_entry *e;
+
+	if (!map)
+		return;
+
+	if (!free_values && map->pool)
+		/* Memory other than util is owned by and freed with the pool */
+		return;
+
+	/*
+	 * We need to iterate over the hashmap entries and free
+	 * e->key and e->value ourselves; hashmap has no API to
+	 * take care of that for us.  Since we're already iterating over
+	 * the hashmap, though, might as well free e too and avoid the need
+	 * to make some call into the hashmap API to do that.
+	 */
+	hashmap_for_each_entry(&map->map, &iter, e, ent) {
+		if (free_values)
+			free(e->value);
+		if (!map->pool)
+			free(e);
+	}
+}
+
+void strmap_clear(struct strmap *map, int free_values)
+{
+	strmap_free_entries_(map, free_values);
+	hashmap_clear(&map->map);
+}
+
+void strmap_partial_clear(struct strmap *map, int free_values)
+{
+	strmap_free_entries_(map, free_values);
+	hashmap_partial_clear(&map->map);
+}
+
+static struct strmap_entry *create_entry(struct strmap *map,
+					 const char *str,
+					 void *data)
+{
+	struct strmap_entry *entry;
+
+	if (map->strdup_strings) {
+		if (!map->pool) {
+			FLEXPTR_ALLOC_STR(entry, key, str);
+		} else {
+			size_t len = st_add(strlen(str), 1); /* include NUL */
+			entry = mem_pool_alloc(map->pool,
+					       st_add(sizeof(*entry), len));
+			memcpy(entry + 1, str, len);
+			entry->key = (void *)(entry + 1);
+		}
+	} else if (!map->pool) {
+		entry = xmalloc(sizeof(*entry));
+	} else {
+		entry = mem_pool_alloc(map->pool, sizeof(*entry));
+	}
+	hashmap_entry_init(&entry->ent, strhash(str));
+	if (!map->strdup_strings)
+		entry->key = str;
+	entry->value = data;
+	return entry;
+}
+
+void *strmap_put(struct strmap *map, const char *str, void *data)
+{
+	struct strmap_entry *entry = find_strmap_entry(map, str);
+
+	if (entry) {
+		void *old = entry->value;
+		entry->value = data;
+		return old;
+	}
+
+	entry = create_entry(map, str, data);
+	hashmap_add(&map->map, &entry->ent);
+	return NULL;
+}
+
+struct strmap_entry *strmap_get_entry(struct strmap *map, const char *str)
+{
+	return find_strmap_entry(map, str);
+}
+
+void *strmap_get(struct strmap *map, const char *str)
+{
+	struct strmap_entry *entry = find_strmap_entry(map, str);
+	return entry ? entry->value : NULL;
+}
+
+int strmap_contains(struct strmap *map, const char *str)
+{
+	return find_strmap_entry(map, str) != NULL;
+}
+
+void strmap_remove(struct strmap *map, const char *str, int free_value)
+{
+	struct strmap_entry entry, *ret;
+	hashmap_entry_init(&entry.ent, strhash(str));
+	entry.key = str;
+	ret = hashmap_remove_entry(&map->map, &entry, ent, NULL);
+	if (!ret)
+		return;
+	if (free_value)
+		free(ret->value);
+	if (!map->pool)
+		free(ret);
+}
+
+void strintmap_incr(struct strintmap *map, const char *str, intptr_t amt)
+{
+	struct strmap_entry *entry = find_strmap_entry(&map->map, str);
+	if (entry) {
+		intptr_t *whence = (intptr_t*)&entry->value;
+		*whence += amt;
+	}
+	else
+		strintmap_set(map, str, map->default_value + amt);
+}
+
+int strset_add(struct strset *set, const char *str)
+{
+	/*
+	 * Cannot use strmap_put() because it'll return NULL in both cases:
+	 *   - cannot find str: NULL means "not found"
+	 *   - does find str: NULL is the value associated with str
+	 */
+	struct strmap_entry *entry = find_strmap_entry(&set->map, str);
+
+	if (entry)
+		return 0;
+
+	entry = create_entry(&set->map, str, NULL);
+	hashmap_add(&set->map.map, &entry->ent);
+	return 1;
+}
diff --git a/strmap.h b/strmap.h
new file mode 100644
index 0000000..c4c1044
--- /dev/null
+++ b/strmap.h
@@ -0,0 +1,268 @@
+#ifndef STRMAP_H
+#define STRMAP_H
+
+#include "hashmap.h"
+
+struct mem_pool;
+struct strmap {
+	struct hashmap map;
+	struct mem_pool *pool;
+	unsigned int strdup_strings:1;
+};
+
+struct strmap_entry {
+	struct hashmap_entry ent;
+	const char *key;
+	void *value;
+	/* strmap_entry may be allocated extra space to store the key at end */
+};
+
+int cmp_strmap_entry(const void *hashmap_cmp_fn_data,
+		     const struct hashmap_entry *entry1,
+		     const struct hashmap_entry *entry2,
+		     const void *keydata);
+
+#define STRMAP_INIT { \
+			.map = HASHMAP_INIT(cmp_strmap_entry, NULL),  \
+			.strdup_strings = 1,                          \
+		    }
+#define STRINTMAP_INIT { \
+			.map = STRMAP_INIT,   \
+			.default_value = 0,   \
+		       }
+#define STRSET_INIT { .map = STRMAP_INIT }
+
+/*
+ * Initialize the members of the strmap.  Any keys added to the strmap will
+ * be strdup'ed with their memory managed by the strmap.
+ */
+void strmap_init(struct strmap *map);
+
+/*
+ * Same as strmap_init, but for those who want to control the memory management
+ * carefully instead of using the default of strdup_strings=1 and pool=NULL.
+ */
+void strmap_init_with_options(struct strmap *map,
+			      struct mem_pool *pool,
+			      int strdup_strings);
+
+/*
+ * Remove all entries from the map, releasing any allocated resources.
+ */
+void strmap_clear(struct strmap *map, int free_values);
+
+/*
+ * Similar to strmap_clear() but leaves map->map->table allocated and
+ * pre-sized so that subsequent uses won't need as many rehashings.
+ */
+void strmap_partial_clear(struct strmap *map, int free_values);
+
+/*
+ * Insert "str" into the map, pointing to "data".
+ *
+ * If an entry for "str" already exists, its data pointer is overwritten, and
+ * the original data pointer returned. Otherwise, returns NULL.
+ */
+void *strmap_put(struct strmap *map, const char *str, void *data);
+
+/*
+ * Return the strmap_entry mapped by "str", or NULL if there is not such
+ * an item in map.
+ */
+struct strmap_entry *strmap_get_entry(struct strmap *map, const char *str);
+
+/*
+ * Return the data pointer mapped by "str", or NULL if the entry does not
+ * exist.
+ */
+void *strmap_get(struct strmap *map, const char *str);
+
+/*
+ * Return non-zero iff "str" is present in the map. This differs from
+ * strmap_get() in that it can distinguish entries with a NULL data pointer.
+ */
+int strmap_contains(struct strmap *map, const char *str);
+
+/*
+ * Remove the given entry from the strmap.  If the string isn't in the
+ * strmap, the map is not altered.
+ */
+void strmap_remove(struct strmap *map, const char *str, int free_value);
+
+/*
+ * Return how many entries the strmap has.
+ */
+static inline unsigned int strmap_get_size(struct strmap *map)
+{
+	return hashmap_get_size(&map->map);
+}
+
+/*
+ * Return whether the strmap is empty.
+ */
+static inline int strmap_empty(struct strmap *map)
+{
+	return strmap_get_size(map) == 0;
+}
+
+/*
+ * iterate through @map using @iter, @var is a pointer to a type strmap_entry
+ */
+#define strmap_for_each_entry(mystrmap, iter, var)	\
+	hashmap_for_each_entry(&(mystrmap)->map, iter, var, ent)
+
+
+/*
+ * strintmap:
+ *    A map of string -> int, typecasting the void* of strmap to an int.
+ *
+ * Primary differences:
+ *    1) Since the void* value is just an int in disguise, there is no value
+ *       to free.  (Thus one fewer argument to strintmap_clear)
+ *    2) strintmap_get() returns an int, or returns the default_value if the
+ *       key is not found in the strintmap.
+ *    3) No strmap_put() equivalent; strintmap_set() and strintmap_incr()
+ *       instead.
+ */
+
+struct strintmap {
+	struct strmap map;
+	int default_value;
+};
+
+#define strintmap_for_each_entry(mystrmap, iter, var)	\
+	strmap_for_each_entry(&(mystrmap)->map, iter, var)
+
+static inline void strintmap_init(struct strintmap *map, int default_value)
+{
+	strmap_init(&map->map);
+	map->default_value = default_value;
+}
+
+static inline void strintmap_init_with_options(struct strintmap *map,
+					       int default_value,
+					       struct mem_pool *pool,
+					       int strdup_strings)
+{
+	strmap_init_with_options(&map->map, pool, strdup_strings);
+	map->default_value = default_value;
+}
+
+static inline void strintmap_clear(struct strintmap *map)
+{
+	strmap_clear(&map->map, 0);
+}
+
+static inline void strintmap_partial_clear(struct strintmap *map)
+{
+	strmap_partial_clear(&map->map, 0);
+}
+
+static inline int strintmap_contains(struct strintmap *map, const char *str)
+{
+	return strmap_contains(&map->map, str);
+}
+
+static inline void strintmap_remove(struct strintmap *map, const char *str)
+{
+	return strmap_remove(&map->map, str, 0);
+}
+
+static inline int strintmap_empty(struct strintmap *map)
+{
+	return strmap_empty(&map->map);
+}
+
+static inline unsigned int strintmap_get_size(struct strintmap *map)
+{
+	return strmap_get_size(&map->map);
+}
+
+/*
+ * Returns the value for str in the map.  If str isn't found in the map,
+ * the map's default_value is returned.
+ */
+static inline int strintmap_get(struct strintmap *map, const char *str)
+{
+	struct strmap_entry *result = strmap_get_entry(&map->map, str);
+	if (!result)
+		return map->default_value;
+	return (intptr_t)result->value;
+}
+
+static inline void strintmap_set(struct strintmap *map, const char *str,
+				 intptr_t v)
+{
+	strmap_put(&map->map, str, (void *)v);
+}
+
+/*
+ * Increment the value for str by amt.  If str isn't in the map, add it and
+ * set its value to default_value + amt.
+ */
+void strintmap_incr(struct strintmap *map, const char *str, intptr_t amt);
+
+/*
+ * strset:
+ *    A set of strings.
+ *
+ * Primary differences with strmap:
+ *    1) The value is always NULL, and ignored.  As there is no value to free,
+ *       there is one fewer argument to strset_clear
+ *    2) No strset_get() because there is no value.
+ *    3) No strset_put(); use strset_add() instead.
+ */
+
+struct strset {
+	struct strmap map;
+};
+
+#define strset_for_each_entry(mystrset, iter, var)	\
+	strmap_for_each_entry(&(mystrset)->map, iter, var)
+
+static inline void strset_init(struct strset *set)
+{
+	strmap_init(&set->map);
+}
+
+static inline void strset_init_with_options(struct strset *set,
+					    struct mem_pool *pool,
+					    int strdup_strings)
+{
+	strmap_init_with_options(&set->map, pool, strdup_strings);
+}
+
+static inline void strset_clear(struct strset *set)
+{
+	strmap_clear(&set->map, 0);
+}
+
+static inline void strset_partial_clear(struct strset *set)
+{
+	strmap_partial_clear(&set->map, 0);
+}
+
+static inline int strset_contains(struct strset *set, const char *str)
+{
+	return strmap_contains(&set->map, str);
+}
+
+static inline void strset_remove(struct strset *set, const char *str)
+{
+	return strmap_remove(&set->map, str, 0);
+}
+
+static inline int strset_empty(struct strset *set)
+{
+	return strmap_empty(&set->map);
+}
+
+static inline unsigned int strset_get_size(struct strset *set)
+{
+	return strmap_get_size(&set->map);
+}
+
+/* Returns 1 if str is added to the set; returns 0 if str was already in set */
+int strset_add(struct strset *set, const char *str);
+
+#endif /* STRMAP_H */
diff --git a/submodule-config.c b/submodule-config.c
index c569e22..f502505 100644
--- a/submodule-config.c
+++ b/submodule-config.c
@@ -103,8 +103,8 @@
 				ent /* member name */)
 		free_one_config(entry);
 
-	hashmap_free_entries(&cache->for_path, struct submodule_entry, ent);
-	hashmap_free_entries(&cache->for_name, struct submodule_entry, ent);
+	hashmap_clear_and_free(&cache->for_path, struct submodule_entry, ent);
+	hashmap_clear_and_free(&cache->for_name, struct submodule_entry, ent);
 	cache->initialized = 0;
 	cache->gitmodules_read = 0;
 }
diff --git a/submodule.c b/submodule.c
index b3bb59f..eef5204e 100644
--- a/submodule.c
+++ b/submodule.c
@@ -499,12 +499,6 @@
 		     DEFAULT_GIT_DIR_ENVIRONMENT);
 }
 
-static void prepare_submodule_repo_env_in_gitdir(struct strvec *out)
-{
-	prepare_submodule_repo_env_no_git_dir(out);
-	strvec_pushf(out, "%s=.", GIT_DIR_ENVIRONMENT);
-}
-
 /*
  * Initialize a repository struct for a submodule based on the provided 'path'.
  *
@@ -1455,8 +1449,8 @@
 		if (task->repo) {
 			struct strbuf submodule_prefix = STRBUF_INIT;
 			child_process_init(cp);
-			cp->dir = task->repo->gitdir;
-			prepare_submodule_repo_env_in_gitdir(&cp->env_array);
+			cp->dir = task->repo->worktree;
+			prepare_submodule_repo_env(&cp->env_array);
 			cp->git_cmd = 1;
 			if (!spf->quiet)
 				strbuf_addf(err, _("Fetching submodule %s%s\n"),
@@ -1505,9 +1499,9 @@
 			    spf->prefix, task->sub->path);
 
 		child_process_init(cp);
-		prepare_submodule_repo_env_in_gitdir(&cp->env_array);
+		prepare_submodule_repo_env(&cp->env_array);
 		cp->git_cmd = 1;
-		cp->dir = task->repo->gitdir;
+		cp->dir = task->repo->worktree;
 
 		strvec_init(&cp->args);
 		strvec_pushv(&cp->args, spf->args.v);
diff --git a/t/Makefile b/t/Makefile
index c83fd18..882d26e 100644
--- a/t/Makefile
+++ b/t/Makefile
@@ -34,6 +34,7 @@
 T = $(sort $(wildcard t[0-9][0-9][0-9][0-9]-*.sh))
 TGITWEB = $(sort $(wildcard t95[0-9][0-9]-*.sh))
 THELPERS = $(sort $(filter-out $(T),$(wildcard *.sh)))
+TPERF = $(sort $(wildcard perf/p[0-9][0-9][0-9][0-9]-*.sh))
 CHAINLINTTESTS = $(sort $(patsubst chainlint/%.test,%,$(wildcard chainlint/*.test)))
 CHAINLINT = sed -f chainlint.sed
 
@@ -81,17 +82,17 @@
 	test-lint-filenames
 
 test-lint-duplicates:
-	@dups=`echo $(T) | tr ' ' '\n' | sed 's/-.*//' | sort | uniq -d` && \
+	@dups=`echo $(T) $(TPERF) | tr ' ' '\n' | sed 's/-.*//' | sort | uniq -d` && \
 		test -z "$$dups" || { \
 		echo >&2 "duplicate test numbers:" $$dups; exit 1; }
 
 test-lint-executable:
-	@bad=`for i in $(T); do test -x "$$i" || echo $$i; done` && \
+	@bad=`for i in $(T) $(TPERF); do test -x "$$i" || echo $$i; done` && \
 		test -z "$$bad" || { \
 		echo >&2 "non-executable tests:" $$bad; exit 1; }
 
 test-lint-shell-syntax:
-	@'$(PERL_PATH_SQ)' check-non-portable-shell.pl $(T) $(THELPERS)
+	@'$(PERL_PATH_SQ)' check-non-portable-shell.pl $(T) $(THELPERS) $(TPERF)
 
 test-lint-filenames:
 	@# We do *not* pass a glob to ls-files but use grep instead, to catch
diff --git a/t/README b/t/README
index 2adaf7c..c730a70 100644
--- a/t/README
+++ b/t/README
@@ -258,16 +258,21 @@
 only some tests should be run or that some tests should be
 excluded from a run.
 
-The argument for --run is a list of individual test numbers or
-ranges with an optional negation prefix that define what tests in
-a test suite to include in the run.  A range is two numbers
-separated with a dash and matches a range of tests with both ends
-been included.  You may omit the first or the second number to
-mean "from the first test" or "up to the very last test"
-respectively.
+The argument for --run, <test-selector>, is a list of description
+substrings or globs or individual test numbers or ranges with an
+optional negation prefix (of '!') that define what tests in a test
+suite to include (or exclude, if negated) in the run.  A range is two
+numbers separated with a dash and matches a range of tests with both
+ends been included.  You may omit the first or the second number to
+mean "from the first test" or "up to the very last test" respectively.
 
-Optional prefix of '!' means that the test or a range of tests
-should be excluded from the run.
+The argument to --run is split on commas into separate strings,
+numbers, and ranges, and picks all tests that match any of the
+individual selection criteria.  If the substring of the description
+text that you want to match includes a comma, use the glob character
+'?' instead.  For example --run='rebase,merge?cherry-pick' would match
+on all tests that match either the glob *rebase* or the glob
+*merge?cherry-pick*.
 
 If --run starts with an unprefixed number or range the initial
 set of tests to run is empty. If the first item starts with '!'
@@ -275,9 +280,6 @@
 determined every test number or range is added or excluded from
 the set one by one, from left to right.
 
-Individual numbers or ranges could be separated either by a space
-or a comma.
-
 For example, to run only tests up to a specific test (21), one
 could do this:
 
@@ -290,7 +292,7 @@
 Common case is to run several setup tests (1, 2, 3) and then a
 specific test (21) that relies on that setup:
 
-    $ sh ./t9200-git-cvsexport-commit.sh --run='1 2 3 21'
+    $ sh ./t9200-git-cvsexport-commit.sh --run='1,2,3,21'
 
 or:
 
@@ -298,17 +300,17 @@
 
 or:
 
-    $ sh ./t9200-git-cvsexport-commit.sh --run='-3 21'
+    $ sh ./t9200-git-cvsexport-commit.sh --run='-3,21'
 
 As noted above, the test set is built by going through the items
 from left to right, so this:
 
-    $ sh ./t9200-git-cvsexport-commit.sh --run='1-4 !3'
+    $ sh ./t9200-git-cvsexport-commit.sh --run='1-4,!3'
 
 will run tests 1, 2, and 4.  Items that come later have higher
 precedence.  It means that this:
 
-    $ sh ./t9200-git-cvsexport-commit.sh --run='!3 1-4'
+    $ sh ./t9200-git-cvsexport-commit.sh --run='!3,1-4'
 
 would just run tests from 1 to 4, including 3.
 
@@ -317,6 +319,18 @@
 
     $ sh ./t9200-git-cvsexport-commit.sh --run='!7-11'
 
+Sometimes there may be multiple tests with e.g. "setup" in their name
+that are needed and rather than figuring out the number for all of them
+we can just use "setup" as a substring/glob to match against the test
+description:
+
+    $ sh ./t0050-filesystem.sh --run=setup,9-11
+
+or one could select both the setup tests and the rename ones (assuming all
+relevant tests had those words in their descriptions):
+
+    $ sh ./t0050-filesystem.sh --run=setup,rename
+
 Some tests in a test suite rely on the previous tests performing
 certain actions, specifically some tests are designated as
 "setup" test, so you cannot _arbitrarily_ disable one test and
diff --git a/t/annotate-tests.sh b/t/annotate-tests.sh
index d933af5..3aee61d 100644
--- a/t/annotate-tests.sh
+++ b/t/annotate-tests.sh
@@ -479,6 +479,24 @@
 	check_count -f hello.c -L$n -L^:ma.. F 4 G 1 H 1
 '
 
+test_expect_success 'setup -L :funcname with userdiff driver' '
+	echo "fortran-* diff=fortran" >.gitattributes &&
+	fortran_file=fortran-external-function &&
+	orig_file="$TEST_DIRECTORY/t4018/$fortran_file" &&
+	cp $orig_file . &&
+	git add $fortran_file &&
+	GIT_AUTHOR_NAME="A" GIT_AUTHOR_EMAIL="A@test.git" \
+	git commit -m "add fortran file" &&
+	sed -e "s/ChangeMe/IWasChanged/" <"$orig_file" >$fortran_file &&
+	git add $fortran_file &&
+	GIT_AUTHOR_NAME="B" GIT_AUTHOR_EMAIL="B@test.git" \
+	git commit -m "change fortran file"
+'
+
+test_expect_success 'blame -L :funcname with userdiff driver' '
+	check_count -f fortran-external-function -L:RIGHT A 7 B 1
+'
+
 test_expect_success 'setup incremental' '
 	(
 	GIT_AUTHOR_NAME=I &&
diff --git a/t/helper/test-crontab.c b/t/helper/test-crontab.c
new file mode 100644
index 0000000..e7c0137
--- /dev/null
+++ b/t/helper/test-crontab.c
@@ -0,0 +1,35 @@
+#include "test-tool.h"
+#include "cache.h"
+
+/*
+ * Usage: test-tool cron <file> [-l]
+ *
+ * If -l is specified, then write the contents of <file> to stdout.
+ * Otherwise, write from stdin into <file>.
+ */
+int cmd__crontab(int argc, const char **argv)
+{
+	int a;
+	FILE *from, *to;
+
+	if (argc == 3 && !strcmp(argv[2], "-l")) {
+		from = fopen(argv[1], "r");
+		if (!from)
+			return 0;
+		to = stdout;
+	} else if (argc == 2) {
+		from = stdin;
+		to = fopen(argv[1], "w");
+	} else
+		return error("unknown arguments");
+
+	while ((a = fgetc(from)) != EOF)
+		fputc(a, to);
+
+	if (argc == 3)
+		fclose(from);
+	else
+		fclose(to);
+
+	return 0;
+}
diff --git a/t/helper/test-fast-rebase.c b/t/helper/test-fast-rebase.c
new file mode 100644
index 0000000..3732122
--- /dev/null
+++ b/t/helper/test-fast-rebase.c
@@ -0,0 +1,211 @@
+/*
+ * "git fast-rebase" builtin command
+ *
+ * FAST: Forking Any Subprocesses (is) Taboo
+ *
+ * This is meant SOLELY as a demo of what is possible.  sequencer.c and
+ * rebase.c should be refactored to use the ideas here, rather than attempting
+ * to extend this file to replace those (unless Phillip or Dscho say that
+ * refactoring is too hard and we need a clean slate, but I'm guessing that
+ * refactoring is the better route).
+ */
+
+#define USE_THE_INDEX_COMPATIBILITY_MACROS
+#include "test-tool.h"
+
+#include "cache-tree.h"
+#include "commit.h"
+#include "lockfile.h"
+#include "merge-ort.h"
+#include "refs.h"
+#include "revision.h"
+#include "sequencer.h"
+#include "strvec.h"
+#include "tree.h"
+
+static const char *short_commit_name(struct commit *commit)
+{
+	return find_unique_abbrev(&commit->object.oid, DEFAULT_ABBREV);
+}
+
+static struct commit *peel_committish(const char *name)
+{
+	struct object *obj;
+	struct object_id oid;
+
+	if (get_oid(name, &oid))
+		return NULL;
+	obj = parse_object(the_repository, &oid);
+	return (struct commit *)peel_to_type(name, 0, obj, OBJ_COMMIT);
+}
+
+static char *get_author(const char *message)
+{
+	size_t len;
+	const char *a;
+
+	a = find_commit_header(message, "author", &len);
+	if (a)
+		return xmemdupz(a, len);
+
+	return NULL;
+}
+
+static struct commit *create_commit(struct tree *tree,
+				    struct commit *based_on,
+				    struct commit *parent)
+{
+	struct object_id ret;
+	struct object *obj;
+	struct commit_list *parents = NULL;
+	char *author;
+	char *sign_commit = NULL;
+	struct commit_extra_header *extra;
+	struct strbuf msg = STRBUF_INIT;
+	const char *out_enc = get_commit_output_encoding();
+	const char *message = logmsg_reencode(based_on, NULL, out_enc);
+	const char *orig_message = NULL;
+	const char *exclude_gpgsig[] = { "gpgsig", NULL };
+
+	commit_list_insert(parent, &parents);
+	extra = read_commit_extra_headers(based_on, exclude_gpgsig);
+	find_commit_subject(message, &orig_message);
+	strbuf_addstr(&msg, orig_message);
+	author = get_author(message);
+	reset_ident_date();
+	if (commit_tree_extended(msg.buf, msg.len, &tree->object.oid, parents,
+				 &ret, author, NULL, sign_commit, extra)) {
+		error(_("failed to write commit object"));
+		return NULL;
+	}
+	free(author);
+	strbuf_release(&msg);
+
+	obj = parse_object(the_repository, &ret);
+	return (struct commit *)obj;
+}
+
+int cmd__fast_rebase(int argc, const char **argv)
+{
+	struct commit *onto;
+	struct commit *last_commit = NULL, *last_picked_commit = NULL;
+	struct object_id head;
+	struct lock_file lock = LOCK_INIT;
+	int clean = 1;
+	struct strvec rev_walk_args = STRVEC_INIT;
+	struct rev_info revs;
+	struct commit *commit;
+	struct merge_options merge_opt;
+	struct tree *next_tree, *base_tree, *head_tree;
+	struct merge_result result;
+	struct strbuf reflog_msg = STRBUF_INIT;
+	struct strbuf branch_name = STRBUF_INIT;
+
+	/*
+	 * test-tool stuff doesn't set up the git directory by default; need to
+	 * do that manually.
+	 */
+	setup_git_directory();
+
+	if (argc == 2 && !strcmp(argv[1], "-h")) {
+		printf("Sorry, I am not a psychiatrist; I can not give you the help you need.  Oh, you meant usage...\n");
+		exit(129);
+	}
+
+	if (argc != 5 || strcmp(argv[1], "--onto"))
+		die("usage: read the code, figure out how to use it, then do so");
+
+	onto = peel_committish(argv[2]);
+	strbuf_addf(&branch_name, "refs/heads/%s", argv[4]);
+
+	/* Sanity check */
+	if (get_oid("HEAD", &head))
+		die(_("Cannot read HEAD"));
+	assert(oideq(&onto->object.oid, &head));
+
+	hold_locked_index(&lock, LOCK_DIE_ON_ERROR);
+	assert(repo_read_index(the_repository) >= 0);
+
+	repo_init_revisions(the_repository, &revs, NULL);
+	revs.verbose_header = 1;
+	revs.max_parents = 1;
+	revs.cherry_mark = 1;
+	revs.limited = 1;
+	revs.reverse = 1;
+	revs.right_only = 1;
+	revs.sort_order = REV_SORT_IN_GRAPH_ORDER;
+	revs.topo_order = 1;
+	strvec_pushl(&rev_walk_args, "", argv[4], "--not", argv[3], NULL);
+
+	if (setup_revisions(rev_walk_args.nr, rev_walk_args.v, &revs, NULL) > 1)
+		return error(_("unhandled options"));
+
+	strvec_clear(&rev_walk_args);
+
+	if (prepare_revision_walk(&revs) < 0)
+		return error(_("error preparing revisions"));
+
+	init_merge_options(&merge_opt, the_repository);
+	memset(&result, 0, sizeof(result));
+	merge_opt.show_rename_progress = 1;
+	merge_opt.branch1 = "HEAD";
+	head_tree = get_commit_tree(onto);
+	result.tree = head_tree;
+	last_commit = onto;
+	while ((commit = get_revision(&revs))) {
+		struct commit *base;
+
+		fprintf(stderr, "Rebasing %s...\r",
+			oid_to_hex(&commit->object.oid));
+		assert(commit->parents && !commit->parents->next);
+		base = commit->parents->item;
+
+		next_tree = get_commit_tree(commit);
+		base_tree = get_commit_tree(base);
+
+		merge_opt.branch2 = short_commit_name(commit);
+		merge_opt.ancestor = xstrfmt("parent of %s", merge_opt.branch2);
+
+		merge_incore_nonrecursive(&merge_opt,
+					  base_tree,
+					  result.tree,
+					  next_tree,
+					  &result);
+
+		free((char*)merge_opt.ancestor);
+		merge_opt.ancestor = NULL;
+		if (!result.clean)
+			die("Aborting: Hit a conflict and restarting is not implemented.");
+		last_picked_commit = commit;
+		last_commit = create_commit(result.tree, commit, last_commit);
+	}
+	fprintf(stderr, "\nDone.\n");
+	/* TODO: There should be some kind of rev_info_free(&revs) call... */
+	memset(&revs, 0, sizeof(revs));
+
+	merge_switch_to_result(&merge_opt, head_tree, &result, 1, !result.clean);
+
+	if (result.clean < 0)
+		exit(128);
+
+	strbuf_addf(&reflog_msg, "finish rebase %s onto %s",
+		    oid_to_hex(&last_picked_commit->object.oid),
+		    oid_to_hex(&last_commit->object.oid));
+	if (update_ref(reflog_msg.buf, branch_name.buf,
+		       &last_commit->object.oid,
+		       &last_picked_commit->object.oid,
+		       REF_NO_DEREF, UPDATE_REFS_MSG_ON_ERR)) {
+		error(_("could not update %s"), argv[4]);
+		die("Failed to update %s", argv[4]);
+	}
+	if (create_symref("HEAD", branch_name.buf, reflog_msg.buf) < 0)
+		die(_("unable to update HEAD"));
+	strbuf_release(&reflog_msg);
+	strbuf_release(&branch_name);
+
+	prime_cache_tree(the_repository, the_repository->index, result.tree);
+	if (write_locked_index(&the_index, &lock,
+			       COMMIT_LOCK | SKIP_IF_UNCHANGED))
+		die(_("unable to write %s"), get_index_file());
+	return (clean == 0);
+}
diff --git a/t/helper/test-hashmap.c b/t/helper/test-hashmap.c
index f387062..36ff07b 100644
--- a/t/helper/test-hashmap.c
+++ b/t/helper/test-hashmap.c
@@ -110,7 +110,7 @@
 				hashmap_add(&map, &entries[i]->ent);
 			}
 
-			hashmap_free(&map);
+			hashmap_clear(&map);
 		}
 	} else {
 		/* test map lookups */
@@ -130,7 +130,7 @@
 			}
 		}
 
-		hashmap_free(&map);
+		hashmap_clear(&map);
 	}
 }
 
@@ -151,12 +151,11 @@
 int cmd__hashmap(int argc, const char **argv)
 {
 	struct strbuf line = STRBUF_INIT;
-	struct hashmap map;
 	int icase;
+	struct hashmap map = HASHMAP_INIT(test_entry_cmp, &icase);
 
 	/* init hash map */
 	icase = argc > 1 && !strcmp("ignorecase", argv[1]);
-	hashmap_init(&map, test_entry_cmp, &icase, 0);
 
 	/* process commands from stdin */
 	while (strbuf_getline(&line, stdin) != EOF) {
@@ -262,6 +261,6 @@
 	}
 
 	strbuf_release(&line);
-	hashmap_free_entries(&map, struct test_entry, ent);
+	hashmap_clear_and_free(&map, struct test_entry, ent);
 	return 0;
 }
diff --git a/t/helper/test-pkt-line.c b/t/helper/test-pkt-line.c
index 6915295..5e638f0 100644
--- a/t/helper/test-pkt-line.c
+++ b/t/helper/test-pkt-line.c
@@ -84,6 +84,25 @@
 	}
 }
 
+static int send_split_sideband(void)
+{
+	const char *part1 = "Hello,";
+	const char *primary = "\001primary: regular output\n";
+	const char *part2 = " world!\n";
+
+	send_sideband(1, 2, part1, strlen(part1), LARGE_PACKET_MAX);
+	packet_write(1, primary, strlen(primary));
+	send_sideband(1, 2, part2, strlen(part2), LARGE_PACKET_MAX);
+	packet_response_end(1);
+
+	return 0;
+}
+
+static int receive_sideband(void)
+{
+	return recv_sideband("sideband", 0, 1);
+}
+
 int cmd__pkt_line(int argc, const char **argv)
 {
 	if (argc < 2)
@@ -95,6 +114,10 @@
 		unpack();
 	else if (!strcmp(argv[1], "unpack-sideband"))
 		unpack_sideband();
+	else if (!strcmp(argv[1], "send-split-sideband"))
+		send_split_sideband();
+	else if (!strcmp(argv[1], "receive-sideband"))
+		receive_sideband();
 	else
 		die("invalid argument '%s'", argv[1]);
 
diff --git a/t/helper/test-proc-receive.c b/t/helper/test-proc-receive.c
index 42164d9..cc08506 100644
--- a/t/helper/test-proc-receive.c
+++ b/t/helper/test-proc-receive.c
@@ -10,8 +10,11 @@
 	NULL
 };
 
-static int die_version;
-static int die_readline;
+static int die_read_version;
+static int die_write_version;
+static int die_read_commands;
+static int die_read_push_options;
+static int die_write_report;
 static int no_push_options;
 static int use_atomic;
 static int use_push_options;
@@ -33,14 +36,23 @@
 static void proc_receive_verison(struct packet_reader *reader) {
 	int server_version = 0;
 
+	if (die_read_version)
+		die("die with the --die-read-version option");
+
 	for (;;) {
 		int linelen;
 
 		if (packet_reader_read(reader) != PACKET_READ_NORMAL)
 			break;
 
+		/* Ignore version negotiation for version 0 */
+		if (version == 0)
+			continue;
+
 		if (reader->pktlen > 8 && starts_with(reader->line, "version=")) {
 			server_version = atoi(reader->line+8);
+			if (server_version != 1)
+				die("bad protocol version: %d", server_version);
 			linelen = strlen(reader->line);
 			if (linelen < reader->pktlen) {
 				const char *feature_list = reader->line + linelen + 1;
@@ -52,12 +64,13 @@
 		}
 	}
 
-	if (server_version != 1 || die_version)
-		die("bad protocol version: %d", server_version);
+	if (die_write_version)
+		die("die with the --die-write-version option");
 
-	packet_write_fmt(1, "version=%d%c%s\n",
-			 version, '\0',
-			 use_push_options && !no_push_options ? "push-options": "");
+	if (version != 0)
+		packet_write_fmt(1, "version=%d%c%s\n",
+				 version, '\0',
+				 use_push_options && !no_push_options ? "push-options": "");
 	packet_flush(1);
 }
 
@@ -75,11 +88,13 @@
 		if (packet_reader_read(reader) != PACKET_READ_NORMAL)
 			break;
 
+		if (die_read_commands)
+			die("die with the --die-read-commands option");
+
 		if (parse_oid_hex(reader->line, &old_oid, &p) ||
 		    *p++ != ' ' ||
 		    parse_oid_hex(p, &new_oid, &p) ||
-		    *p++ != ' ' ||
-		    die_readline)
+		    *p++ != ' ')
 			die("protocol error: expected 'old new ref', got '%s'",
 			    reader->line);
 		refname = p;
@@ -99,6 +114,9 @@
 	if (no_push_options || !use_push_options)
 	       return;
 
+	if (die_read_push_options)
+		die("die with the --die-read-push-options option");
+
 	while (1) {
 		if (packet_reader_read(reader) != PACKET_READ_NORMAL)
 			break;
@@ -117,10 +135,16 @@
 	struct option options[] = {
 		OPT_BOOL(0, "no-push-options", &no_push_options,
 			 "disable push options"),
-		OPT_BOOL(0, "die-version", &die_version,
-			 "die during version negotiation"),
-		OPT_BOOL(0, "die-readline", &die_readline,
-			 "die when readline"),
+		OPT_BOOL(0, "die-read-version", &die_read_version,
+			 "die when reading version"),
+		OPT_BOOL(0, "die-write-version", &die_write_version,
+			 "die when writing version"),
+		OPT_BOOL(0, "die-read-commands", &die_read_commands,
+			 "die when reading commands"),
+		OPT_BOOL(0, "die-read-push-options", &die_read_push_options,
+			 "die when reading push-options"),
+		OPT_BOOL(0, "die-write-report", &die_write_report,
+			 "die when writing report"),
 		OPT_STRING_LIST('r', "return", &returns, "old/new/ref/status/msg",
 				"return of results"),
 		OPT__VERBOSE(&verbose, "be verbose"),
@@ -136,7 +160,7 @@
 		usage_msg_opt("Too many arguments.", proc_receive_usage, options);
 	packet_reader_init(&reader, 0, NULL, 0,
 			   PACKET_READ_CHOMP_NEWLINE |
-			   PACKET_READ_DIE_ON_ERR_PACKET);
+			   PACKET_READ_GENTLE_ON_EOF);
 
 	sigchain_push(SIGPIPE, SIG_IGN);
 	proc_receive_verison(&reader);
@@ -166,6 +190,8 @@
 				fprintf(stderr, "proc-receive> %s\n", item->string);
 	}
 
+	if (die_write_report)
+		die("die with the --die-write-report option");
 	if (returns.nr)
 		for_each_string_list_item(item, &returns)
 			packet_write_fmt(1, "%s\n", item->string);
diff --git a/t/helper/test-tool.c b/t/helper/test-tool.c
index a0d3966..9d6d14d 100644
--- a/t/helper/test-tool.c
+++ b/t/helper/test-tool.c
@@ -18,6 +18,7 @@
 	{ "bloom", cmd__bloom },
 	{ "chmtime", cmd__chmtime },
 	{ "config", cmd__config },
+	{ "crontab", cmd__crontab },
 	{ "ctype", cmd__ctype },
 	{ "date", cmd__date },
 	{ "delta", cmd__delta },
@@ -28,6 +29,7 @@
 	{ "dump-split-index", cmd__dump_split_index },
 	{ "dump-untracked-cache", cmd__dump_untracked_cache },
 	{ "example-decorate", cmd__example_decorate },
+	{ "fast-rebase", cmd__fast_rebase },
 	{ "genrandom", cmd__genrandom },
 	{ "genzeros", cmd__genzeros },
 	{ "hashmap", cmd__hashmap },
diff --git a/t/helper/test-tool.h b/t/helper/test-tool.h
index 07034d3..a6470ff 100644
--- a/t/helper/test-tool.h
+++ b/t/helper/test-tool.h
@@ -8,6 +8,7 @@
 int cmd__bloom(int argc, const char **argv);
 int cmd__chmtime(int argc, const char **argv);
 int cmd__config(int argc, const char **argv);
+int cmd__crontab(int argc, const char **argv);
 int cmd__ctype(int argc, const char **argv);
 int cmd__date(int argc, const char **argv);
 int cmd__delta(int argc, const char **argv);
@@ -18,6 +19,7 @@
 int cmd__dump_split_index(int argc, const char **argv);
 int cmd__dump_untracked_cache(int argc, const char **argv);
 int cmd__example_decorate(int argc, const char **argv);
+int cmd__fast_rebase(int argc, const char **argv);
 int cmd__genrandom(int argc, const char **argv);
 int cmd__genzeros(int argc, const char **argv);
 int cmd__hashmap(int argc, const char **argv);
diff --git a/t/lib-merge.sh b/t/lib-merge.sh
new file mode 100644
index 0000000..8734ebf
--- /dev/null
+++ b/t/lib-merge.sh
@@ -0,0 +1,13 @@
+# Helper functions used by merge tests.
+
+test_expect_merge_algorithm () {
+	status_for_recursive=$1 status_for_ort=$2
+	shift 2
+
+	if test "$GIT_TEST_MERGE_ALGORITHM" = ort
+	then
+		test_expect_${status_for_ort} "$@"
+	else
+		test_expect_${status_for_recursive} "$@"
+	fi
+}
diff --git a/t/lib-submodule-update.sh b/t/lib-submodule-update.sh
index 87a7591..bd3fa3c 100644
--- a/t/lib-submodule-update.sh
+++ b/t/lib-submodule-update.sh
@@ -144,7 +144,7 @@
 		git checkout -b valid_sub1 &&
 		git revert HEAD &&
 
-		git checkout master
+		git checkout "${GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME-master}"
 	)
 }
 
diff --git a/t/perf/Makefile b/t/perf/Makefile
index 8c47155..fcb0e88 100644
--- a/t/perf/Makefile
+++ b/t/perf/Makefile
@@ -1,7 +1,7 @@
 -include ../../config.mak
 export GIT_TEST_OPTIONS
 
-all: perf
+all: test-lint perf
 
 perf: pre-clean
 	./run
@@ -12,4 +12,7 @@
 clean:
 	rm -rf build "trash directory".* test-results
 
+test-lint:
+	$(MAKE) -C .. test-lint
+
 .PHONY: all perf pre-clean clean
diff --git a/t/perf/README b/t/perf/README
index bd649af..fb9127a 100644
--- a/t/perf/README
+++ b/t/perf/README
@@ -28,6 +28,8 @@
     7810.3: grep --cached, cheap regex       3.07(3.02+0.25)
     7810.4: grep --cached, expensive regex   9.39(30.57+0.24)
 
+Output format is in seconds "Elapsed(User + System)"
+
 You can compare multiple repositories and even git revisions with the
 'run' script:
 
diff --git a/t/perf/p3400-rebase.sh b/t/perf/p3400-rebase.sh
index d202aae..7a0bb29 100755
--- a/t/perf/p3400-rebase.sh
+++ b/t/perf/p3400-rebase.sh
@@ -9,16 +9,16 @@
 	git checkout -f -B base &&
 	git checkout -B to-rebase &&
 	git checkout -B upstream &&
-	for i in $(seq 100)
+	for i in $(test_seq 100)
 	do
 		# simulate huge diffs
 		echo change$i >unrelated-file$i &&
-		seq 1000 >>unrelated-file$i &&
+		test_seq 1000 >>unrelated-file$i &&
 		git add unrelated-file$i &&
 		test_tick &&
 		git commit -m commit$i unrelated-file$i &&
 		echo change$i >unrelated-file$i &&
-		seq 1000 | tac >>unrelated-file$i &&
+		test_seq 1000 | tac >>unrelated-file$i &&
 		git add unrelated-file$i &&
 		test_tick &&
 		git commit -m commit$i-reverse unrelated-file$i ||
diff --git a/t/perf/p7519-fsmonitor.sh b/t/perf/p7519-fsmonitor.sh
index def7ecd..163a13b 100755
--- a/t/perf/p7519-fsmonitor.sh
+++ b/t/perf/p7519-fsmonitor.sh
@@ -22,7 +22,9 @@
 #
 # GIT_PERF_7519_UNTRACKED_CACHE: used to configure core.untrackedCache
 # GIT_PERF_7519_SPLIT_INDEX: used to configure core.splitIndex
-# GIT_PERF_7519_FSMONITOR: used to configure core.fsMonitor
+# GIT_PERF_7519_FSMONITOR: used to configure core.fsMonitor. May be an
+#   absolute path to an integration. May be a space delimited list of
+#   absolute paths to integrations.
 #
 # The big win for using fsmonitor is the elimination of the need to scan the
 # working directory looking for changed and untracked files. If the file
@@ -68,7 +70,7 @@
 	fi
 fi
 
-test_expect_success "setup for fsmonitor" '
+test_expect_success "one time repo setup" '
 	# set untrackedCache depending on the environment
 	if test -n "$GIT_PERF_7519_UNTRACKED_CACHE"
 	then
@@ -88,24 +90,36 @@
 		git config core.splitIndex "$GIT_PERF_7519_SPLIT_INDEX"
 	fi &&
 
+	mkdir 1_file 10_files 100_files 1000_files 10000_files &&
+	for i in $(test_seq 1 10); do touch 10_files/$i; done &&
+	for i in $(test_seq 1 100); do touch 100_files/$i; done &&
+	for i in $(test_seq 1 1000); do touch 1000_files/$i; done &&
+	for i in $(test_seq 1 10000); do touch 10000_files/$i; done &&
+	git add 1_file 10_files 100_files 1000_files 10000_files &&
+	git commit -qm "Add files" &&
+
+	# If Watchman exists, watch the work tree and attempt a query.
+	if test_have_prereq WATCHMAN; then
+		watchman watch "$GIT_WORK_TREE" &&
+		watchman watch-list | grep -q -F "$GIT_WORK_TREE"
+	fi
+'
+
+setup_for_fsmonitor() {
 	# set INTEGRATION_SCRIPT depending on the environment
-	if test -n "$GIT_PERF_7519_FSMONITOR"
+	if test -n "$INTEGRATION_PATH"
 	then
-		INTEGRATION_SCRIPT="$GIT_PERF_7519_FSMONITOR"
+		INTEGRATION_SCRIPT="$INTEGRATION_PATH"
 	else
 		#
 		# Choose integration script based on existence of Watchman.
-		# If Watchman exists, watch the work tree and attempt a query.
-		# If everything succeeds, use Watchman integration script,
-		# else fall back to an empty integration script.
+		# Fall back to an empty integration script.
 		#
 		mkdir .git/hooks &&
 		if test_have_prereq WATCHMAN
 		then
 			INTEGRATION_SCRIPT=".git/hooks/fsmonitor-watchman" &&
-			cp "$TEST_DIRECTORY/../templates/hooks--fsmonitor-watchman.sample" "$INTEGRATION_SCRIPT" &&
-			watchman watch "$GIT_WORK_TREE" &&
-			watchman watch-list | grep -q -F "$GIT_WORK_TREE"
+			cp "$TEST_DIRECTORY/../templates/hooks--fsmonitor-watchman.sample" "$INTEGRATION_SCRIPT"
 		else
 			INTEGRATION_SCRIPT=".git/hooks/fsmonitor-empty" &&
 			write_script "$INTEGRATION_SCRIPT"<<-\EOF
@@ -114,62 +128,94 @@
 	fi &&
 
 	git config core.fsmonitor "$INTEGRATION_SCRIPT" &&
-	git update-index --fsmonitor
-'
+	git update-index --fsmonitor 2>error &&
+	cat error &&
+	[ ! -s error ] # ensure no silent error
+}
 
-if test -n "$GIT_PERF_7519_DROP_CACHE"; then
-	test-tool drop-caches
+test_perf_w_drop_caches () {
+	if test -n "$GIT_PERF_7519_DROP_CACHE"; then
+		test-tool drop-caches
+	fi
+
+	test_perf "$@"
+}
+
+test_fsmonitor_suite() {
+	if test -n "$INTEGRATION_SCRIPT"; then
+		DESC="fsmonitor=$(basename $INTEGRATION_SCRIPT)"
+	else
+		DESC="fsmonitor=disabled"
+	fi
+
+	test_expect_success "test_initialization" '
+		git reset --hard &&
+		git status  # Warm caches
+	'
+
+	test_perf_w_drop_caches "status ($DESC)" '
+		git status
+	'
+
+	test_perf_w_drop_caches "status -uno ($DESC)" '
+		git status -uno
+	'
+
+	test_perf_w_drop_caches "status -uall ($DESC)" '
+		git status -uall
+	'
+
+	test_perf_w_drop_caches "status (dirty) ($DESC)" '
+		git ls-files | head -100000 | xargs -d "\n" touch -h &&
+		git status
+	'
+
+	test_perf_w_drop_caches "diff ($DESC)" '
+		git diff
+	'
+
+	test_perf_w_drop_caches "diff -- 0_files ($DESC)" '
+		git diff -- 1_file
+	'
+
+	test_perf_w_drop_caches "diff -- 10_files ($DESC)" '
+		git diff -- 10_files
+	'
+
+	test_perf_w_drop_caches "diff -- 100_files ($DESC)" '
+		git diff -- 100_files
+	'
+
+	test_perf_w_drop_caches "diff -- 1000_files ($DESC)" '
+		git diff -- 1000_files
+	'
+
+	test_perf_w_drop_caches "diff -- 10000_files ($DESC)" '
+		git diff -- 10000_files
+	'
+
+	test_perf_w_drop_caches "add ($DESC)" '
+		git add  --all
+	'
+}
+
+if test -n "$GIT_PERF_7519_FSMONITOR"; then
+	for INTEGRATION_PATH in $GIT_PERF_7519_FSMONITOR; do
+		test_expect_success "setup for fsmonitor $INTEGRATION_PATH" 'setup_for_fsmonitor'
+		test_fsmonitor_suite
+	done
+else
+	test_expect_success "setup for fsmonitor" 'setup_for_fsmonitor'
+	test_fsmonitor_suite
 fi
 
-test_perf "status (fsmonitor=$INTEGRATION_SCRIPT)" '
-	git status
-'
-
-if test -n "$GIT_PERF_7519_DROP_CACHE"; then
-	test-tool drop-caches
-fi
-
-test_perf "status -uno (fsmonitor=$INTEGRATION_SCRIPT)" '
-	git status -uno
-'
-
-if test -n "$GIT_PERF_7519_DROP_CACHE"; then
-	test-tool drop-caches
-fi
-
-test_perf "status -uall (fsmonitor=$INTEGRATION_SCRIPT)" '
-	git status -uall
-'
-
 test_expect_success "setup without fsmonitor" '
 	unset INTEGRATION_SCRIPT &&
 	git config --unset core.fsmonitor &&
 	git update-index --no-fsmonitor
 '
 
-if test -n "$GIT_PERF_7519_DROP_CACHE"; then
-	test-tool drop-caches
-fi
-
-test_perf "status (fsmonitor=$INTEGRATION_SCRIPT)" '
-	git status
-'
-
-if test -n "$GIT_PERF_7519_DROP_CACHE"; then
-	test-tool drop-caches
-fi
-
-test_perf "status -uno (fsmonitor=$INTEGRATION_SCRIPT)" '
-	git status -uno
-'
-
-if test -n "$GIT_PERF_7519_DROP_CACHE"; then
-	test-tool drop-caches
-fi
-
-test_perf "status -uall (fsmonitor=$INTEGRATION_SCRIPT)" '
-	git status -uall
-'
+test_fsmonitor_suite
 
 if test_have_prereq WATCHMAN
 then
diff --git a/t/t0000-basic.sh b/t/t0000-basic.sh
index 923281a..f4ba2e8 100755
--- a/t/t0000-basic.sh
+++ b/t/t0000-basic.sh
@@ -430,7 +430,7 @@
 
 test_expect_success '--run basic' "
 	run_sub_test_lib_test run-basic \
-		'--run basic' --run='1 3 5' <<-\\EOF &&
+		'--run basic' --run='1,3,5' <<-\\EOF &&
 	for i in 1 2 3 4 5 6
 	do
 		test_expect_success \"passing test #\$i\" 'true'
@@ -472,7 +472,7 @@
 
 test_expect_success '--run with two ranges' "
 	run_sub_test_lib_test run-two-ranges \
-		'--run with two ranges' --run='1-2 5-6' <<-\\EOF &&
+		'--run with two ranges' --run='1-2,5-6' <<-\\EOF &&
 	for i in 1 2 3 4 5 6
 	do
 		test_expect_success \"passing test #\$i\" 'true'
@@ -556,7 +556,7 @@
 
 test_expect_success '--run with two negations' "
 	run_sub_test_lib_test run-two-neg \
-		'--run with two negations' --run='"'!3 !6'"' <<-\\EOF &&
+		'--run with two negations' --run='"'!3,!6'"' <<-\\EOF &&
 	for i in 1 2 3 4 5 6
 	do
 		test_expect_success \"passing test #\$i\" 'true'
@@ -577,7 +577,7 @@
 
 test_expect_success '--run a range and negation' "
 	run_sub_test_lib_test run-range-and-neg \
-		'--run a range and negation' --run='"'-4 !2'"' <<-\\EOF &&
+		'--run a range and negation' --run='"'-4,!2'"' <<-\\EOF &&
 	for i in 1 2 3 4 5 6
 	do
 		test_expect_success \"passing test #\$i\" 'true'
@@ -620,7 +620,7 @@
 test_expect_success '--run include, exclude and include' "
 	run_sub_test_lib_test run-inc-neg-inc \
 		'--run include, exclude and include' \
-		--run='"'1-5 !1-3 2'"' <<-\\EOF &&
+		--run='"'1-5,!1-3,2'"' <<-\\EOF &&
 	for i in 1 2 3 4 5 6
 	do
 		test_expect_success \"passing test #\$i\" 'true'
@@ -664,7 +664,7 @@
 test_expect_success '--run exclude and include' "
 	run_sub_test_lib_test run-neg-inc \
 		'--run exclude and include' \
-		--run='"'!3- 5'"' <<-\\EOF &&
+		--run='"'!3-,5'"' <<-\\EOF &&
 	for i in 1 2 3 4 5 6
 	do
 		test_expect_success \"passing test #\$i\" 'true'
@@ -705,7 +705,31 @@
 	EOF
 "
 
-test_expect_success '--run invalid range start' "
+test_expect_success '--run substring selector' "
+	run_sub_test_lib_test run-substring-selector \
+		'--run empty selectors' \
+		--run='relevant' <<-\\EOF &&
+	test_expect_success \"relevant test\" 'true'
+	for i in 1 2 3 4 5 6
+	do
+		test_expect_success \"other test #\$i\" 'true'
+	done
+	test_done
+	EOF
+	check_sub_test_lib_test run-substring-selector <<-\\EOF
+	> ok 1 - relevant test
+	> ok 2 # skip other test #1 (--run)
+	> ok 3 # skip other test #2 (--run)
+	> ok 4 # skip other test #3 (--run)
+	> ok 5 # skip other test #4 (--run)
+	> ok 6 # skip other test #5 (--run)
+	> ok 7 # skip other test #6 (--run)
+	> # passed all 7 test(s)
+	> 1..7
+	EOF
+"
+
+test_expect_success '--run keyword selection' "
 	run_sub_test_lib_test_err run-inv-range-start \
 		'--run invalid range start' \
 		--run='a-5' <<-\\EOF &&
@@ -735,21 +759,6 @@
 	EOF_ERR
 "
 
-test_expect_success '--run invalid selector' "
-	run_sub_test_lib_test_err run-inv-selector \
-		'--run invalid selector' \
-		--run='1?' <<-\\EOF &&
-	test_expect_success \"passing test #1\" 'true'
-	test_done
-	EOF
-	check_sub_test_lib_test_err run-inv-selector \
-		<<-\\EOF_OUT 3<<-\\EOF_ERR
-	> FATAL: Unexpected exit with code 1
-	EOF_OUT
-	> error: --run: invalid non-numeric in test selector: '1?'
-	EOF_ERR
-"
-
 
 test_set_prereq HAVEIT
 haveit=no
@@ -831,6 +840,27 @@
 	exit 1
 fi
 
+test_lazy_prereq NESTED_INNER '
+	>inner &&
+	rm -f outer
+'
+test_lazy_prereq NESTED_PREREQ '
+	>outer &&
+	test_have_prereq NESTED_INNER &&
+	echo "can create new file in cwd" >file &&
+	test -f outer &&
+	test ! -f inner
+'
+test_expect_success NESTED_PREREQ 'evaluating nested lazy prereqs dont interfere with each other' '
+	nestedworks=yes
+'
+
+if test -z "$GIT_TEST_FAIL_PREREQS_INTERNAL" && test "$nestedworks" != yes
+then
+	say 'bug in test framework: nested lazy prerequisites do not work'
+	exit 1
+fi
+
 test_expect_success 'lazy prereqs do not turn off tracing' "
 	run_sub_test_lib_test lazy-prereq-and-tracing \
 		'lazy prereqs and -x' -v -x <<-\\EOF &&
@@ -1191,7 +1221,7 @@
 test_expect_success 'git read-tree followed by write-tree should be idempotent' '
 	rm -f .git/index &&
 	git read-tree $tree &&
-	test -f .git/index &&
+	test_path_is_file .git/index &&
 	newtree=$(git write-tree) &&
 	test "$newtree" = "$tree"
 '
diff --git a/t/t0001-init.sh b/t/t0001-init.sh
index 2f7c3dc..69a3204 100755
--- a/t/t0001-init.sh
+++ b/t/t0001-init.sh
@@ -553,14 +553,21 @@
 
 test_expect_success 'overridden default initial branch name (config)' '
 	test_config_global init.defaultBranch nmb &&
-	git init initial-branch-config &&
+	GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME= git init initial-branch-config &&
 	git -C initial-branch-config symbolic-ref HEAD >actual &&
 	grep nmb actual
 '
 
+test_expect_success 'overridden default main branch name (env)' '
+	test_config_global init.defaultBranch nmb &&
+	GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=env git init main-branch-env &&
+	git -C main-branch-env symbolic-ref HEAD >actual &&
+	grep env actual
+'
+
 test_expect_success 'invalid default branch name' '
-	test_config_global init.defaultBranch "with space" &&
-	test_must_fail git init initial-branch-invalid 2>err &&
+	test_must_fail env GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME="with space" \
+		git init initial-branch-invalid 2>err &&
 	test_i18ngrep "invalid branch name" err
 '
 
diff --git a/t/t0021-conversion.sh b/t/t0021-conversion.sh
index 4bfffa9..f6deaf4 100755
--- a/t/t0021-conversion.sh
+++ b/t/t0021-conversion.sh
@@ -23,10 +23,6 @@
 		perl -pe "s/./chr((ord($&) % 26) + ord('a'))/sge" >"$TEST_ROOT/$NAME"
 }
 
-file_size () {
-	test-tool path-utils file-size "$1"
-}
-
 filter_git () {
 	rm -f *.log &&
 	git "$@"
@@ -361,9 +357,9 @@
 		cp "$TEST_ROOT/test3 '\''sq'\'',\$x=.o" "testsubdir/test3 '\''sq'\'',\$x=.r" &&
 		>test4-empty.r &&
 
-		S=$(file_size test.r) &&
-		S2=$(file_size test2.r) &&
-		S3=$(file_size "testsubdir/test3 '\''sq'\'',\$x=.r") &&
+		S=$(test_file_size test.r) &&
+		S2=$(test_file_size test2.r) &&
+		S3=$(test_file_size "testsubdir/test3 '\''sq'\'',\$x=.r") &&
 		M=$(git hash-object test.r) &&
 		M2=$(git hash-object test2.r) &&
 		M3=$(git hash-object "testsubdir/test3 '\''sq'\'',\$x=.r") &&
@@ -432,9 +428,9 @@
 	(
 		cd repo &&
 
-		S=$(file_size test.r) &&
-		S2=$(file_size test2.r) &&
-		S3=$(file_size "testsubdir/test3 '\''sq'\'',\$x=.r") &&
+		S=$(test_file_size test.r) &&
+		S2=$(test_file_size test2.r) &&
+		S3=$(test_file_size "testsubdir/test3 '\''sq'\'',\$x=.r") &&
 		M=$(git hash-object test.r) &&
 		M2=$(git hash-object test2.r) &&
 		M3=$(git hash-object "testsubdir/test3 '\''sq'\'',\$x=.r") &&
@@ -549,7 +545,7 @@
 
 		echo "*.r filter=protocol" >.gitattributes &&
 		cp "$TEST_ROOT/test.o" test.r &&
-		S=$(file_size test.r) &&
+		S=$(test_file_size test.r) &&
 
 		# Check that the process filter is invoked here
 		filter_git add . &&
@@ -573,7 +569,7 @@
 
 		echo "*.r filter=protocol" >.gitattributes &&
 		cp "$TEST_ROOT/test.o" test.r &&
-		S=$(file_size test.r) &&
+		S=$(test_file_size test.r) &&
 
 		filter_git add . &&
 		cat >expected.log <<-EOF &&
@@ -697,9 +693,9 @@
 		echo "this is going to fail" >smudge-write-fail.o &&
 		cp smudge-write-fail.o smudge-write-fail.r &&
 
-		S=$(file_size test.r) &&
-		S2=$(file_size test2.r) &&
-		SF=$(file_size smudge-write-fail.r) &&
+		S=$(test_file_size test.r) &&
+		S2=$(test_file_size test2.r) &&
+		SF=$(test_file_size smudge-write-fail.r) &&
 		M=$(git hash-object test.r) &&
 		M2=$(git hash-object test2.r) &&
 		MF=$(git hash-object smudge-write-fail.r) &&
@@ -752,9 +748,9 @@
 		echo "this will cause an error" >error.o &&
 		cp error.o error.r &&
 
-		S=$(file_size test.r) &&
-		S2=$(file_size test2.r) &&
-		SE=$(file_size error.r) &&
+		S=$(test_file_size test.r) &&
+		S2=$(test_file_size test2.r) &&
+		SE=$(test_file_size error.r) &&
 		M=$(git hash-object test.r) &&
 		M2=$(git hash-object test2.r) &&
 		ME=$(git hash-object error.r) &&
@@ -797,7 +793,7 @@
 
 		M="blob=$(git hash-object abort.r)" &&
 		rm -f debug.log &&
-		SA=$(file_size abort.r) &&
+		SA=$(test_file_size abort.r) &&
 
 		git add . &&
 		rm -f *.r &&
@@ -859,7 +855,7 @@
 		git commit -m "test commit"
 	) &&
 
-	S=$(file_size "$TEST_ROOT/test.o") &&
+	S=$(test_file_size "$TEST_ROOT/test.o") &&
 	PM="ref=refs/heads/master treeish=$(git -C repo rev-parse --verify master) " &&
 	M="${PM}blob=$(git -C repo rev-parse --verify master:test.a)" &&
 	cat >a.exp <<-EOF &&
diff --git a/t/t0068-for-each-repo.sh b/t/t0068-for-each-repo.sh
new file mode 100755
index 0000000..136b4ec
--- /dev/null
+++ b/t/t0068-for-each-repo.sh
@@ -0,0 +1,30 @@
+#!/bin/sh
+
+test_description='git for-each-repo builtin'
+
+. ./test-lib.sh
+
+test_expect_success 'run based on configured value' '
+	git init one &&
+	git init two &&
+	git init three &&
+	git -C two commit --allow-empty -m "DID NOT RUN" &&
+	git config run.key "$TRASH_DIRECTORY/one" &&
+	git config --add run.key "$TRASH_DIRECTORY/three" &&
+	git for-each-repo --config=run.key commit --allow-empty -m "ran" &&
+	git -C one log -1 --pretty=format:%s >message &&
+	grep ran message &&
+	git -C two log -1 --pretty=format:%s >message &&
+	! grep ran message &&
+	git -C three log -1 --pretty=format:%s >message &&
+	grep ran message &&
+	git for-each-repo --config=run.key -- commit --allow-empty -m "ran again" &&
+	git -C one log -1 --pretty=format:%s >message &&
+	grep again message &&
+	git -C two log -1 --pretty=format:%s >message &&
+	! grep again message &&
+	git -C three log -1 --pretty=format:%s >message &&
+	grep again message
+'
+
+test_done
diff --git a/t/t0070-fundamental.sh b/t/t0070-fundamental.sh
index 7b111a5..8d59905 100755
--- a/t/t0070-fundamental.sh
+++ b/t/t0070-fundamental.sh
@@ -34,4 +34,22 @@
 	test-tool regex --bug
 '
 
+test_expect_success 'incomplete sideband messages are reassembled' '
+	test-tool pkt-line send-split-sideband >split-sideband &&
+	test-tool pkt-line receive-sideband <split-sideband 2>err &&
+	grep "Hello, world" err
+'
+
+test_expect_success 'eof on sideband message is reported' '
+	printf 1234 >input &&
+	test-tool pkt-line receive-sideband <input 2>err &&
+	test_i18ngrep "unexpected disconnect" err
+'
+
+test_expect_success 'missing sideband designator is reported' '
+	printf 0004 >input &&
+	test-tool pkt-line receive-sideband <input 2>err &&
+	test_i18ngrep "missing sideband" err
+'
+
 test_done
diff --git a/t/t0300-credentials.sh b/t/t0300-credentials.sh
index bc2d740..a18f8a4 100755
--- a/t/t0300-credentials.sh
+++ b/t/t0300-credentials.sh
@@ -265,6 +265,32 @@
 	EOF
 '
 
+test_expect_success 'git-credential respects core.askPass' '
+	write_script alternate-askpass <<-\EOF &&
+	echo >&2 "alternate askpass invoked"
+	echo alternate-value
+	EOF
+	test_config core.askpass "$PWD/alternate-askpass" &&
+	(
+		# unset GIT_ASKPASS set by lib-credential.sh which would
+		# override our config, but do so in a subshell so that we do
+		# not interfere with other tests
+		sane_unset GIT_ASKPASS &&
+		check fill <<-\EOF
+		protocol=http
+		host=example.com
+		--
+		protocol=http
+		host=example.com
+		username=alternate-value
+		password=alternate-value
+		--
+		alternate askpass invoked
+		alternate askpass invoked
+		EOF
+	)
+'
+
 HELPER="!f() {
 		cat >/dev/null
 		echo username=foo
diff --git a/t/t1004-read-tree-m-u-wf.sh b/t/t1004-read-tree-m-u-wf.sh
index c13578a..181956b 100755
--- a/t/t1004-read-tree-m-u-wf.sh
+++ b/t/t1004-read-tree-m-u-wf.sh
@@ -20,7 +20,7 @@
 	git branch side &&
 	git tag -f branch-point &&
 
-	echo file2 is not tracked on the master anymore &&
+	echo file2 is not tracked on the master branch anymore &&
 	rm -f file2 subdir/file2 &&
 	git update-index --remove file2 subdir/file2 &&
 	git commit -a -m "master removes file2 and subdir/file2"
diff --git a/t/t1050-large.sh b/t/t1050-large.sh
index 61e89a8..4bab6a5 100755
--- a/t/t1050-large.sh
+++ b/t/t1050-large.sh
@@ -5,12 +5,6 @@
 
 . ./test-lib.sh
 
-# This should be moved to test-lib.sh together with the
-# copy in t0021 after both topics have graduated to 'master'.
-file_size () {
-	test-tool path-utils file-size "$1"
-}
-
 test_expect_success setup '
 	# clone does not allow us to pass core.bigfilethreshold to
 	# new repos, so set core.bigfilethreshold globally
@@ -29,7 +23,7 @@
 	test_expect_success "add with $config" '
 		test_when_finished "rm -f .git/objects/pack/pack-*.* .git/index" &&
 		git $config add large1 &&
-		sz=$(file_size .git/objects/pack/pack-*.pack) &&
+		sz=$(test_file_size .git/objects/pack/pack-*.pack) &&
 		case "$expect" in
 		small) test "$sz" -le 100000 ;;
 		large) test "$sz" -ge 100000 ;;
diff --git a/t/t1309-early-config.sh b/t/t1309-early-config.sh
index ebb8e1a..b4a9158 100755
--- a/t/t1309-early-config.sh
+++ b/t/t1309-early-config.sh
@@ -91,11 +91,11 @@
 
 test_expect_success 'early config and onbranch' '
 	echo "[broken" >broken &&
-	test_with_config "[includeif \"onbranch:master\"]path=../broken"
+	test_with_config "[includeif \"onbranch:topic\"]path=../broken"
 '
 
 test_expect_success 'onbranch config outside of git repo' '
-	test_config_global includeIf.onbranch:master.path non-existent &&
+	test_config_global includeIf.onbranch:topic.path non-existent &&
 	nongit git help
 '
 
diff --git a/t/t1400-update-ref.sh b/t/t1400-update-ref.sh
index 770e7be..4c01e08 100755
--- a/t/t1400-update-ref.sh
+++ b/t/t1400-update-ref.sh
@@ -585,10 +585,10 @@
 	grep "fatal: badly quoted argument: \\\"master" err
 '
 
-test_expect_success 'stdin fails on invalid escape' '
-	echo "create $a \"ma\zter\"" >stdin &&
+test_expect_success PREPARE_FOR_MAIN_BRANCH 'stdin fails on invalid escape' '
+	echo "create $a \"ma\zn\"" >stdin &&
 	test_must_fail git update-ref --stdin <stdin 2>err &&
-	grep "fatal: badly quoted argument: \\\"ma\\\\zter\\\"" err
+	grep "fatal: badly quoted argument: \\\"ma\\\\zn\\\"" err
 '
 
 test_expect_success 'stdin fails on junk after quoted argument' '
@@ -704,9 +704,9 @@
 	test_cmp expect actual
 '
 
-test_expect_success 'stdin succeeds with escaped character' '
+test_expect_success PREPARE_FOR_MAIN_BRANCH 'stdin succeeds with escaped character' '
 	git update-ref -d $a &&
-	echo "create $a \"ma\\163ter\"" >stdin &&
+	echo "create $a \"ma\\151n\"" >stdin &&
 	git update-ref --stdin <stdin &&
 	git rev-parse $m >expect &&
 	git rev-parse $a >actual &&
diff --git a/t/t1503-rev-parse-verify.sh b/t/t1503-rev-parse-verify.sh
index 492edff..dc9fe3c 100755
--- a/t/t1503-rev-parse-verify.sh
+++ b/t/t1503-rev-parse-verify.sh
@@ -144,4 +144,17 @@
 	test_must_fail git rev-parse --verify broken
 '
 
+test_expect_success 'options can appear after --verify' '
+	git rev-parse --verify HEAD >expect &&
+	git rev-parse --verify -q HEAD >actual &&
+	test_cmp expect actual
+'
+
+test_expect_success 'verify respects --end-of-options' '
+	git update-ref refs/heads/-tricky HEAD &&
+	git rev-parse --verify HEAD >expect &&
+	git rev-parse --verify --end-of-options -tricky >actual &&
+	test_cmp expect actual
+'
+
 test_done
diff --git a/t/t1506-rev-parse-diagnosis.sh b/t/t1506-rev-parse-diagnosis.sh
index 3e657e6..e2ae15a 100755
--- a/t/t1506-rev-parse-diagnosis.sh
+++ b/t/t1506-rev-parse-diagnosis.sh
@@ -254,4 +254,29 @@
 	test_must_fail git rev-parse "foo\\*bar"
 '
 
+test_expect_success 'arg after dashdash not interpreted as option' '
+	cat >expect <<-\EOF &&
+	--
+	--local-env-vars
+	EOF
+	git rev-parse -- --local-env-vars >actual &&
+	test_cmp expect actual
+'
+
+test_expect_success 'arg after end-of-options not interpreted as option' '
+	test_must_fail git rev-parse --end-of-options --not-real -- 2>err &&
+	test_i18ngrep bad.revision.*--not-real err
+'
+
+test_expect_success 'end-of-options still allows --' '
+	cat >expect <<-EOF &&
+	--end-of-options
+	$(git rev-parse --verify HEAD)
+	--
+	path
+	EOF
+	git rev-parse --end-of-options HEAD -- path >actual &&
+	test_cmp expect actual
+'
+
 test_done
diff --git a/t/t2004-checkout-cache-temp.sh b/t/t2004-checkout-cache-temp.sh
index a12afe9..a9352b0 100755
--- a/t/t2004-checkout-cache-temp.sh
+++ b/t/t2004-checkout-cache-temp.sh
@@ -88,9 +88,17 @@
 	done
 '
 
+test_expect_success 'checkout all stages of unknown path' '
+	rm -f path* .merge_* actual &&
+	test_must_fail git checkout-index --stage=all --temp \
+		-- does-not-exist 2>stderr &&
+	test_i18ngrep not.in.the.cache stderr
+'
+
 test_expect_success 'checkout all stages/one file to nothing' '
 	rm -f path* .merge_* actual &&
-	git checkout-index --stage=all --temp -- path0 >actual &&
+	git checkout-index --stage=all --temp -- path0 >actual 2>stderr &&
+	test_must_be_empty stderr &&
 	test_line_count = 0 actual
 '
 
diff --git a/t/t2006-checkout-index-basic.sh b/t/t2006-checkout-index-basic.sh
index 57cbdfe..8e181db 100755
--- a/t/t2006-checkout-index-basic.sh
+++ b/t/t2006-checkout-index-basic.sh
@@ -21,4 +21,15 @@
 	test_i18ngrep "[Uu]sage" broken/usage
 '
 
+test_expect_success 'checkout-index reports errors (cmdline)' '
+	test_must_fail git checkout-index -- does-not-exist 2>stderr &&
+	test_i18ngrep not.in.the.cache stderr
+'
+
+test_expect_success 'checkout-index reports errors (stdin)' '
+	echo does-not-exist |
+	test_must_fail git checkout-index --stdin 2>stderr &&
+	test_i18ngrep not.in.the.cache stderr
+'
+
 test_done
diff --git a/t/t2016-checkout-patch.sh b/t/t2016-checkout-patch.sh
index 47aeb0b..d91a329 100755
--- a/t/t2016-checkout-patch.sh
+++ b/t/t2016-checkout-patch.sh
@@ -18,6 +18,10 @@
 
 # note: bar sorts before dir/foo, so the first 'n' is always to skip 'bar'
 
+# NEEDSWORK: Since the builtin add-p is used when $GIT_TEST_ADD_I_USE_BUILTIN
+# is given, we should replace the PERL prerequisite with an ADD_I prerequisite
+# which first checks if $GIT_TEST_ADD_I_USE_BUILTIN is defined before checking
+# PERL.
 test_expect_success PERL 'saying "n" does nothing' '
 	set_and_save_state dir/foo work head &&
 	test_write_lines n n | git checkout -p &&
@@ -59,6 +63,13 @@
 	verify_state dir/foo head head
 '
 
+test_expect_success PERL 'git checkout -p HEAD^...' '
+	# the third n is to get out in case it mistakenly does not apply
+	test_write_lines n y n | git checkout -p HEAD^... &&
+	verify_saved_state bar &&
+	verify_state dir/foo parent parent
+'
+
 test_expect_success PERL 'git checkout -p HEAD^' '
 	# the third n is to get out in case it mistakenly does not apply
 	test_write_lines n y n | git checkout -p HEAD^ &&
diff --git a/t/t2024-checkout-dwim.sh b/t/t2024-checkout-dwim.sh
index accfa9a..a4f8d3a 100755
--- a/t/t2024-checkout-dwim.sh
+++ b/t/t2024-checkout-dwim.sh
@@ -166,6 +166,17 @@
 	test_branch master
 '
 
+test_expect_success 'checkout.guess = false suppresses branch auto-vivification' '
+	git checkout -B master &&
+	status_uno_is_clean &&
+	test_might_fail git branch -D bar &&
+
+	test_config checkout.guess false &&
+	test_must_fail git checkout bar &&
+	test_must_fail git rev-parse --verify refs/heads/bar &&
+	test_branch master
+'
+
 test_expect_success 'setup more remotes with unconventional refspecs' '
 	git checkout -B master &&
 	status_uno_is_clean &&
diff --git a/t/t2060-switch.sh b/t/t2060-switch.sh
index 2c1b8c0..68c9101 100755
--- a/t/t2060-switch.sh
+++ b/t/t2060-switch.sh
@@ -85,9 +85,12 @@
 	test_cmp expected actual
 '
 
-test_expect_success 'guess and create branch ' '
+test_expect_success 'guess and create branch' '
 	test_when_finished git switch master &&
 	test_must_fail git switch --no-guess foo &&
+	test_config checkout.guess false &&
+	test_must_fail git switch foo &&
+	test_config checkout.guess true &&
 	git switch foo &&
 	echo refs/heads/foo >expected &&
 	git symbolic-ref HEAD >actual &&
diff --git a/t/t2071-restore-patch.sh b/t/t2071-restore-patch.sh
index 98b2476..b5c5c0f 100755
--- a/t/t2071-restore-patch.sh
+++ b/t/t2071-restore-patch.sh
@@ -60,6 +60,14 @@
 	verify_state dir/foo parent index
 '
 
+test_expect_success PERL 'git restore -p --source=HEAD^...' '
+	set_state dir/foo work index &&
+	# the third n is to get out in case it mistakenly does not apply
+	test_write_lines n y n | git restore -p --source=HEAD^... &&
+	verify_saved_state bar &&
+	verify_state dir/foo parent index
+'
+
 test_expect_success PERL 'git restore -p handles deletion' '
 	set_state dir/foo work index &&
 	rm dir/foo &&
diff --git a/t/t2106-update-index-assume-unchanged.sh b/t/t2106-update-index-assume-unchanged.sh
index 99d858c..2d450da 100755
--- a/t/t2106-update-index-assume-unchanged.sh
+++ b/t/t2106-update-index-assume-unchanged.sh
@@ -5,20 +5,23 @@
 
 . ./test-lib.sh
 
-test_expect_success 'setup' \
-	': >file &&
-	 git add file &&
-	 git commit -m initial &&
-	 git branch other &&
-	 echo upstream >file &&
-	 git add file &&
-	 git commit -m upstream'
+test_expect_success 'setup' '
+	: >file &&
+	git add file &&
+	git commit -m initial &&
+	git branch other &&
+	echo upstream >file &&
+	git add file &&
+	git commit -m upstream
+'
 
-test_expect_success 'do not switch branches with dirty file' \
-	'git reset --hard &&
-	 git checkout other &&
-	 echo dirt >file &&
-	 git update-index --assume-unchanged file &&
-	 test_must_fail git checkout master'
+test_expect_success 'do not switch branches with dirty file' '
+	git reset --hard &&
+	git checkout other &&
+	echo dirt >file &&
+	git update-index --assume-unchanged file &&
+	test_must_fail git checkout - 2>err &&
+	test_i18ngrep overwritten err
+'
 
 test_done
diff --git a/t/t2200-add-update.sh b/t/t2200-add-update.sh
index f764b7e..7cb7a70 100755
--- a/t/t2200-add-update.sh
+++ b/t/t2200-add-update.sh
@@ -179,7 +179,8 @@
 
 test_expect_success '"add -u non-existent" should fail' '
 	test_must_fail git add -u non-existent &&
-	! (git ls-files | grep "non-existent")
+	git ls-files >actual &&
+	! grep "non-existent" actual
 '
 
 test_done
diff --git a/t/t2402-worktree-list.sh b/t/t2402-worktree-list.sh
index 52585ec..795ddca 100755
--- a/t/t2402-worktree-list.sh
+++ b/t/t2402-worktree-list.sh
@@ -61,6 +61,16 @@
 	test_cmp expect actual
 '
 
+test_expect_success '"list" all worktrees with locked annotation' '
+	test_when_finished "rm -rf locked unlocked out && git worktree prune" &&
+	git worktree add --detach locked master &&
+	git worktree add --detach unlocked master &&
+	git worktree lock locked &&
+	git worktree list >out &&
+	grep "/locked  *[0-9a-f].* locked$" out &&
+	! grep "/unlocked  *[0-9a-f].* locked$" out
+'
+
 test_expect_success 'bare repo setup' '
 	git init --bare bare1 &&
 	echo "data" >file1 &&
diff --git a/t/t3040-subprojects-basic.sh b/t/t3040-subprojects-basic.sh
index b81eb5f..6abdcbb 100755
--- a/t/t3040-subprojects-basic.sh
+++ b/t/t3040-subprojects-basic.sh
@@ -79,7 +79,4 @@
 	git diff-index --exit-code --raw --cached save -- sub1
 '
 
-# just interesting what happened...
-# git diff --name-status -M save master
-
 test_done
diff --git a/t/t3200-branch.sh b/t/t3200-branch.sh
index 6efe7a4..a0b832d 100755
--- a/t/t3200-branch.sh
+++ b/t/t3200-branch.sh
@@ -321,11 +321,11 @@
 
 '
 
-test_expect_success 'git branch --column' '
+test_expect_success PREPARE_FOR_MAIN_BRANCH 'git branch --column' '
 	COLUMNS=81 git branch --column=column >actual &&
 	cat >expect <<\EOF &&
-  a/b/c    bam      foo      l      * master   n        o/p      r
-  abc      bar      j/k      m/m      mb       o/o      q        topic
+  a/b/c   bam     foo     l     * main    n       o/p     r
+  abc     bar     j/k     m/m     mb      o/o     q       topic
 EOF
 	test_cmp expect actual
 '
@@ -358,15 +358,15 @@
 	test_cmp expect actual
 '
 
-test_expect_success 'git branch with column.*' '
+test_expect_success PREPARE_FOR_MAIN_BRANCH 'git branch with column.*' '
 	git config column.ui column &&
 	git config column.branch "dense" &&
 	COLUMNS=80 git branch >actual &&
 	git config --unset column.branch &&
 	git config --unset column.ui &&
 	cat >expect <<\EOF &&
-  a/b/c   bam   foo   l   * master   n     o/p   r
-  abc     bar   j/k   m/m   mb       o/o   q     topic
+  a/b/c   bam   foo   l   * main   n     o/p   r
+  abc     bar   j/k   m/m   mb     o/o   q     topic
 EOF
 	test_cmp expect actual
 '
@@ -375,9 +375,9 @@
 	test_must_fail git branch --column -v
 '
 
-test_expect_success 'git branch -v with column.ui ignored' '
+test_expect_success PREPARE_FOR_MAIN_BRANCH 'git branch -v with column.ui ignored' '
 	git config column.ui column &&
-	COLUMNS=80 git branch -v | cut -c -9 | sed "s/ *$//" >actual &&
+	COLUMNS=80 git branch -v | cut -c -8 | sed "s/ *$//" >actual &&
 	git config --unset column.ui &&
 	cat >expect <<\EOF &&
   a/b/c
diff --git a/t/t3201-branch-contains.sh b/t/t3201-branch-contains.sh
index efea5c4..3733cd0 100755
--- a/t/t3201-branch-contains.sh
+++ b/t/t3201-branch-contains.sh
@@ -242,7 +242,7 @@
 # Here "topic" tracks "master" with one extra commit, and "zzz" points to the
 # same tip as master The name "zzz" must come alphabetically after "topic"
 # as we process them in that order.
-test_expect_success 'branch --merged with --verbose' '
+test_expect_success PREPARE_FOR_MAIN_BRANCH 'branch --merged with --verbose' '
 	git branch --track topic master &&
 	git branch zzz topic &&
 	git checkout topic &&
@@ -256,9 +256,9 @@
 	test_cmp expect actual &&
 	git branch --verbose --merged topic >actual &&
 	cat >expect <<-EOF &&
-	  master $(git rev-parse --short master) second on master
-	* topic  $(git rev-parse --short topic ) [ahead 1] foo
-	  zzz    $(git rev-parse --short zzz   ) second on master
+	  main  $(git rev-parse --short main) second on main
+	* topic $(git rev-parse --short topic ) [ahead 1] foo
+	  zzz   $(git rev-parse --short zzz   ) second on main
 	EOF
 	test_i18ncmp expect actual
 '
diff --git a/t/t3203-branch-output.sh b/t/t3203-branch-output.sh
index 71818b9..d655865 100755
--- a/t/t3203-branch-output.sh
+++ b/t/t3203-branch-output.sh
@@ -329,7 +329,7 @@
 	test_cmp expect.color actual
 '
 
-test_expect_success 'verbose output lists worktree path' '
+test_expect_success PREPARE_FOR_MAIN_BRANCH 'verbose output lists worktree path' '
 	one=$(git rev-parse --short HEAD) &&
 	two=$(git rev-parse --short master) &&
 	cat >expect <<-EOF &&
@@ -337,7 +337,7 @@
 	  ambiguous                    $one one
 	  branch-one                   $two two
 	+ branch-two                   $one ($(pwd)/worktree_dir) one
-	  master                       $two two
+	  main                         $two two
 	  ref-to-branch                $two two
 	  ref-to-remote                $two two
 	EOF
diff --git a/t/t3205-branch-color.sh b/t/t3205-branch-color.sh
index 4f1e16b..289625c 100755
--- a/t/t3205-branch-color.sh
+++ b/t/t3205-branch-color.sh
@@ -28,12 +28,12 @@
 	test_cmp expect actual
 '
 
-test_expect_success 'verbose output shows colors' '
+test_expect_success PREPARE_FOR_MAIN_BRANCH 'verbose output shows colors' '
 	oid=$(git rev-parse --short HEAD) &&
 	cat >expect <<-EOF &&
-	* <CYAN>master               <RESET> $oid foo
-	  <BLUE>other                <RESET> $oid foo
-	  <YELLOW>remotes/origin/master<RESET> $oid foo
+	* <CYAN>main               <RESET> $oid foo
+	  <BLUE>other              <RESET> $oid foo
+	  <YELLOW>remotes/origin/main<RESET> $oid foo
 	EOF
 	git branch --color -v -a >actual.raw &&
 	test_decode_color <actual.raw >actual &&
diff --git a/t/t3301-notes.sh b/t/t3301-notes.sh
index 8f43303..ca60faf 100755
--- a/t/t3301-notes.sh
+++ b/t/t3301-notes.sh
@@ -672,6 +672,11 @@
 	test_cmp expect-both-reversed actual
 '
 
+test_expect_success 'notes.displayRef with no value handled gracefully' '
+	test_must_fail git -c notes.displayRef log -0 --notes &&
+	test_must_fail git -c notes.displayRef diff-tree --notes HEAD
+'
+
 test_expect_success 'GIT_NOTES_DISPLAY_REF works' '
 	GIT_NOTES_DISPLAY_REF=refs/notes/commits:refs/notes/other \
 		git log -2 >actual &&
diff --git a/t/t3404-rebase-interactive.sh b/t/t3404-rebase-interactive.sh
index 07a1617..b06fc36 100755
--- a/t/t3404-rebase-interactive.sh
+++ b/t/t3404-rebase-interactive.sh
@@ -12,7 +12,7 @@
 
      one - two - three - four (conflict-branch)
    /
- A - B - C - D - E            (master)
+ A - B - C - D - E            (primary)
  | \
  |   F - G - H                (branch1)
  |     \
@@ -30,6 +30,7 @@
 . "$TEST_DIRECTORY"/lib-rebase.sh
 
 test_expect_success 'setup' '
+	git switch -C primary &&
 	test_commit A file1 &&
 	test_commit B file1 &&
 	test_commit C file2 &&
@@ -65,7 +66,7 @@
 export SHELL
 
 test_expect_success 'rebase --keep-empty' '
-	git checkout -b emptybranch master &&
+	git checkout -b emptybranch primary &&
 	git commit --allow-empty -m "empty" &&
 	git rebase --keep-empty -i HEAD~2 &&
 	git log --oneline >actual &&
@@ -86,7 +87,7 @@
 '
 
 test_expect_success 'rebase -i with the exec command' '
-	git checkout master &&
+	git checkout primary &&
 	(
 	set_fake_editor &&
 	FAKE_LINES="1 exec_>touch-one
@@ -103,12 +104,12 @@
 	test_path_is_file touch-three &&
 	test_path_is_file "touch-file  name with spaces" &&
 	test_path_is_file touch-after-semicolon &&
-	test_cmp_rev master HEAD &&
+	test_cmp_rev primary HEAD &&
 	rm -f touch-*
 '
 
 test_expect_success 'rebase -i with the exec command runs from tree root' '
-	git checkout master &&
+	git checkout primary &&
 	mkdir subdir && (cd subdir &&
 	set_fake_editor &&
 	FAKE_LINES="1 exec_>touch-subdir" \
@@ -121,7 +122,7 @@
 test_expect_success 'rebase -i with exec allows git commands in subdirs' '
 	test_when_finished "rm -rf subdir" &&
 	test_when_finished "git rebase --abort ||:" &&
-	git checkout master &&
+	git checkout primary &&
 	mkdir subdir && (cd subdir &&
 	set_fake_editor &&
 	FAKE_LINES="1 x_cd_subdir_&&_git_rev-parse_--is-inside-work-tree" \
@@ -139,13 +140,13 @@
 '
 
 test_expect_success 'rebase -i with the exec command checks tree cleanness' '
-	git checkout master &&
+	git checkout primary &&
 	(
 		set_fake_editor &&
 		test_must_fail env FAKE_LINES="exec_echo_foo_>file1 1" \
 			git rebase -i HEAD^
 	) &&
-	test_cmp_rev master^ HEAD &&
+	test_cmp_rev primary^ HEAD &&
 	git reset --hard &&
 	git rebase --continue
 '
@@ -168,7 +169,7 @@
 '
 
 test_expect_success 'rebase -i with exec of inexistent command' '
-	git checkout master &&
+	git checkout primary &&
 	test_when_finished "git rebase --abort" &&
 	(
 		set_fake_editor &&
@@ -259,8 +260,8 @@
 	>>>>>>> $commit (G)
 	EOF
 	git tag new-branch1 &&
-	test_must_fail git rebase -i master &&
-	test "$(git rev-parse HEAD~3)" = "$(git rev-parse master)" &&
+	test_must_fail git rebase -i primary &&
+	test "$(git rev-parse HEAD~3)" = "$(git rev-parse primary)" &&
 	test_cmp expect .git/rebase-merge/patch &&
 	test_cmp expect2 file1 &&
 	test "$(git diff --name-status |
@@ -287,7 +288,7 @@
 test_expect_success 'abort with error when new base cannot be checked out' '
 	git rm --cached file1 &&
 	git commit -m "remove file in base" &&
-	test_must_fail git rebase -i master > output 2>&1 &&
+	test_must_fail git rebase -i primary > output 2>&1 &&
 	test_i18ngrep "The following untracked working tree files would be overwritten by checkout:" \
 		output &&
 	test_i18ngrep "file1" output &&
@@ -301,7 +302,7 @@
 	test_tick &&
 	GIT_AUTHOR_NAME="Twerp Snog" git commit -m "different author" &&
 	git tag twerp &&
-	git rebase -i --onto master HEAD^ &&
+	git rebase -i --onto primary HEAD^ &&
 	git show HEAD | grep "^Author: Twerp Snog"
 '
 
@@ -336,10 +337,10 @@
 	(
 		set_fake_editor &&
 		FAKE_LINES="1 squash 2" EXPECT_HEADER_COUNT=2 \
-			git rebase -i --onto master HEAD~2
+			git rebase -i --onto primary HEAD~2
 	) &&
 	test B = $(cat file7) &&
-	test_cmp_rev HEAD^ master
+	test_cmp_rev HEAD^ primary
 '
 
 test_expect_success 'retain authorship when squashing' '
@@ -366,12 +367,12 @@
 '
 
 test_expect_success REBASE_P 'preserve merges with -p' '
-	git checkout -b to-be-preserved master^ &&
+	git checkout -b to-be-preserved primary^ &&
 	: > unrelated-file &&
 	git add unrelated-file &&
 	test_tick &&
 	git commit -m "unrelated" &&
-	git checkout -b another-branch master &&
+	git checkout -b another-branch primary &&
 	echo B > file1 &&
 	test_tick &&
 	git commit -m J file1 &&
@@ -394,7 +395,7 @@
 	git commit -m M file1 &&
 	git checkout -b to-be-rebased &&
 	test_tick &&
-	git rebase -i -p --onto branch1 master &&
+	git rebase -i -p --onto branch1 primary &&
 	git update-index --refresh &&
 	git diff-files --quiet &&
 	git diff-index --quiet --cached HEAD -- &&
@@ -437,7 +438,7 @@
 '
 
 test_expect_success 'verbose flag is heeded, even after --continue' '
-	git reset --hard master@{1} &&
+	git reset --hard primary@{1} &&
 	test_tick &&
 	test_must_fail git rebase -v -i --onto new-branch1 HEAD^ &&
 	echo resolved > file1 &&
@@ -802,7 +803,7 @@
 '
 
 test_expect_success 'avoid unnecessary reset' '
-	git checkout master &&
+	git checkout primary &&
 	git reset --hard &&
 	test-tool chmtime =123456789 file3 &&
 	git update-index --refresh &&
@@ -814,14 +815,14 @@
 '
 
 test_expect_success 'reword' '
-	git checkout -b reword-branch master &&
+	git checkout -b reword-branch primary &&
 	(
 		set_fake_editor &&
 		FAKE_LINES="1 2 3 reword 4" FAKE_COMMIT_MESSAGE="E changed" \
 			git rebase -i A &&
 		git show HEAD | grep "E changed" &&
-		test $(git rev-parse master) != $(git rev-parse HEAD) &&
-		test_cmp_rev master^ HEAD^ &&
+		test $(git rev-parse primary) != $(git rev-parse HEAD) &&
+		test_cmp_rev primary^ HEAD^ &&
 		FAKE_LINES="1 2 reword 3 4" FAKE_COMMIT_MESSAGE="D changed" \
 			git rebase -i A &&
 		git show HEAD^ | grep "D changed" &&
@@ -918,7 +919,7 @@
 '
 
 test_expect_success 'prepare for rebase -i --exec' '
-	git checkout master &&
+	git checkout primary &&
 	git checkout -b execute &&
 	test_commit one_exec main.txt one_exec &&
 	test_commit two_exec main.txt two_exec &&
@@ -1027,7 +1028,7 @@
 	git reset --hard execute &&
 	test_must_fail git rebase -i --exec 2>actual &&
 	test_i18ngrep "requires a value" actual &&
-	git checkout master
+	git checkout primary
 '
 
 test_expect_success 'rebase -i --root re-order and drop commits' '
@@ -1079,7 +1080,7 @@
 
 test_expect_success 'rebase -i --root reword original root commit' '
 	test_when_finished "test_might_fail git rebase --abort" &&
-	git checkout -b reword-original-root-branch master &&
+	git checkout -b reword-original-root-branch primary &&
 	(
 		set_fake_editor &&
 		FAKE_LINES="reword 1 2" FAKE_COMMIT_MESSAGE="A changed" \
@@ -1091,7 +1092,7 @@
 
 test_expect_success 'rebase -i --root reword new root commit' '
 	test_when_finished "test_might_fail git rebase --abort" &&
-	git checkout -b reword-now-root-branch master &&
+	git checkout -b reword-now-root-branch primary &&
 	(
 		set_fake_editor &&
 		FAKE_LINES="reword 3 1" FAKE_COMMIT_MESSAGE="C changed" \
@@ -1251,7 +1252,7 @@
 '
 
 test_expect_success 'short commit ID setup' '
-	test_when_finished "git checkout master" &&
+	test_when_finished "git checkout primary" &&
 	git checkout --orphan collide &&
 	git rm -rf . &&
 	(
@@ -1292,7 +1293,7 @@
 	t3404_collider	sha1:ac4f2ee
 	t3404_collider	sha256:16697
 	EOF
-	test_when_finished "reset_rebase && git checkout master" &&
+	test_when_finished "reset_rebase && git checkout primary" &&
 	git checkout collide &&
 	colliding_id=$(test_oid t3404_collision) &&
 	hexsz=$(test_oid hexsz) &&
@@ -1416,11 +1417,11 @@
 
 rebase_setup_and_clean () {
 	test_when_finished "
-		git checkout master &&
+		git checkout primary &&
 		test_might_fail git branch -D $1 &&
 		test_might_fail git rebase --abort
 	" &&
-	git checkout -b $1 ${2:-master}
+	git checkout -b $1 ${2:-primary}
 }
 
 test_expect_success 'drop' '
@@ -1451,7 +1452,7 @@
 	cat >expect <<-EOF &&
 	Warning: some commits may have been dropped accidentally.
 	Dropped commits (newer to older):
-	 - $(git rev-list --pretty=oneline --abbrev-commit -1 master)
+	 - $(git rev-list --pretty=oneline --abbrev-commit -1 primary)
 	To avoid this message, use "drop" to explicitly remove a commit.
 	EOF
 	test_config rebase.missingCommitsCheck warn &&
@@ -1469,8 +1470,8 @@
 	cat >expect <<-EOF &&
 	Warning: some commits may have been dropped accidentally.
 	Dropped commits (newer to older):
-	 - $(git rev-list --pretty=oneline --abbrev-commit -1 master)
-	 - $(git rev-list --pretty=oneline --abbrev-commit -1 master~2)
+	 - $(git rev-list --pretty=oneline --abbrev-commit -1 primary)
+	 - $(git rev-list --pretty=oneline --abbrev-commit -1 primary~2)
 	To avoid this message, use "drop" to explicitly remove a commit.
 
 	Use '\''git config rebase.missingCommitsCheck'\'' to change the level of warnings.
@@ -1512,11 +1513,11 @@
 
 test_expect_success 'rebase --edit-todo respects rebase.missingCommitsCheck = warn' '
 	cat >expect <<-EOF &&
-	error: invalid line 1: badcmd $(git rev-list --pretty=oneline --abbrev-commit -1 master~4)
+	error: invalid line 1: badcmd $(git rev-list --pretty=oneline --abbrev-commit -1 primary~4)
 	Warning: some commits may have been dropped accidentally.
 	Dropped commits (newer to older):
-	 - $(git rev-list --pretty=oneline --abbrev-commit -1 master)
-	 - $(git rev-list --pretty=oneline --abbrev-commit -1 master~4)
+	 - $(git rev-list --pretty=oneline --abbrev-commit -1 primary)
+	 - $(git rev-list --pretty=oneline --abbrev-commit -1 primary~4)
 	To avoid this message, use "drop" to explicitly remove a commit.
 	EOF
 	head -n4 expect >expect.2 &&
@@ -1546,11 +1547,11 @@
 
 test_expect_success 'rebase --edit-todo respects rebase.missingCommitsCheck = error' '
 	cat >expect <<-EOF &&
-	error: invalid line 1: badcmd $(git rev-list --pretty=oneline --abbrev-commit -1 master~4)
+	error: invalid line 1: badcmd $(git rev-list --pretty=oneline --abbrev-commit -1 primary~4)
 	Warning: some commits may have been dropped accidentally.
 	Dropped commits (newer to older):
-	 - $(git rev-list --pretty=oneline --abbrev-commit -1 master)
-	 - $(git rev-list --pretty=oneline --abbrev-commit -1 master~4)
+	 - $(git rev-list --pretty=oneline --abbrev-commit -1 primary)
+	 - $(git rev-list --pretty=oneline --abbrev-commit -1 primary~4)
 	To avoid this message, use "drop" to explicitly remove a commit.
 
 	Use '\''git config rebase.missingCommitsCheck'\'' to change the level of warnings.
@@ -1635,7 +1636,7 @@
 	(
 		set_cat_todo_editor &&
 		test_must_fail git rebase -i --exec "git show HEAD" \
-			--autosquash master >actual
+			--autosquash primary >actual
 	) &&
 	test_cmp expected actual
 '
@@ -1646,7 +1647,7 @@
 		set_fake_editor &&
 		test_must_fail env FAKE_LINES="1 2 3 bad 4 5" \
 		git rebase -i --root 2>actual &&
-		test_i18ngrep "badcmd $(git rev-list --oneline -1 master~1)" \
+		test_i18ngrep "badcmd $(git rev-list --oneline -1 primary~1)" \
 				actual &&
 		test_i18ngrep "You can fix this with .git rebase --edit-todo.." \
 				actual &&
@@ -1797,6 +1798,17 @@
 	test_i18ngrep "^# Rebase ..* onto $onto" actual
 '
 
+test_expect_success 'ORIG_HEAD is updated correctly' '
+	test_when_finished "git checkout primary && git branch -D test-orig-head" &&
+	git checkout -b test-orig-head A &&
+	git commit --allow-empty -m A1 &&
+	git commit --allow-empty -m A2 &&
+	git commit --allow-empty -m A3 &&
+	git commit --allow-empty -m A4 &&
+	git rebase primary &&
+	test_cmp_rev ORIG_HEAD test-orig-head@{1}
+'
+
 # This must be the last test in this file
 test_expect_success '$EDITOR and friends are unchanged' '
 	test_editor_unchanged
diff --git a/t/t3406-rebase-message.sh b/t/t3406-rebase-message.sh
index 927a4f4..4afc528 100755
--- a/t/t3406-rebase-message.sh
+++ b/t/t3406-rebase-message.sh
@@ -46,22 +46,22 @@
 
 test_expect_success 'rebase --stat' '
 	git reset --hard start &&
-        git rebase --stat master >diffstat.txt &&
-        grep "^ fileX |  *1 +$" diffstat.txt
+	git rebase --stat master >diffstat.txt &&
+	grep "^ fileX |  *1 +$" diffstat.txt
 '
 
 test_expect_success 'rebase w/config rebase.stat' '
 	git reset --hard start &&
-        git config rebase.stat true &&
-        git rebase master >diffstat.txt &&
-        grep "^ fileX |  *1 +$" diffstat.txt
+	git config rebase.stat true &&
+	git rebase master >diffstat.txt &&
+	grep "^ fileX |  *1 +$" diffstat.txt
 '
 
 test_expect_success 'rebase -n overrides config rebase.stat config' '
 	git reset --hard start &&
-        git config rebase.stat true &&
-        git rebase -n master >diffstat.txt &&
-        ! grep "^ fileX |  *1 +$" diffstat.txt
+	git config rebase.stat true &&
+	git rebase -n master >diffstat.txt &&
+	! grep "^ fileX |  *1 +$" diffstat.txt
 '
 
 # Output to stderr:
diff --git a/t/t3427-rebase-subtree.sh b/t/t3427-rebase-subtree.sh
index 2a7d958..5839719 100755
--- a/t/t3427-rebase-subtree.sh
+++ b/t/t3427-rebase-subtree.sh
@@ -19,7 +19,7 @@
 #                             \
 # README ---------------------- Add subproject master - topic_4 - files_subtree/topic_5
 #
-# Where the merge moves the files master[123].t into the subdirectory
+# Where the merge moves the files topic_[123].t into the subdirectory
 # files_subtree/ and topic_4 as well as files_subtree/topic_5 add files to that
 # directory directly.
 #
diff --git a/t/t3435-rebase-gpg-sign.sh b/t/t3435-rebase-gpg-sign.sh
index b47c59c..54120b0 100755
--- a/t/t3435-rebase-gpg-sign.sh
+++ b/t/t3435-rebase-gpg-sign.sh
@@ -68,4 +68,60 @@
 	test_must_fail git verify-commit HEAD
 '
 
+test_expect_success 'rebase -r, merge strategy, --gpg-sign will sign commit' '
+	git reset --hard merged &&
+	test_unconfig commit.gpgsign &&
+	git rebase -fr --gpg-sign -s resolve --root &&
+	git verify-commit HEAD
+'
+
+test_expect_success 'rebase -r, merge strategy, commit.gpgsign=true will sign commit' '
+	git reset --hard merged &&
+	git config commit.gpgsign true &&
+	git rebase -fr -s resolve --root &&
+	git verify-commit HEAD
+'
+
+test_expect_success 'rebase -r, merge strategy, commit.gpgsign=false --gpg-sign will sign commit' '
+	git reset --hard merged &&
+	git config commit.gpgsign false &&
+	git rebase -fr --gpg-sign -s resolve --root &&
+	git verify-commit HEAD
+'
+
+test_expect_success "rebase -r, merge strategy, commit.gpgsign=true --no-gpg-sign won't sign commit" '
+	git reset --hard merged &&
+	git config commit.gpgsign true &&
+	git rebase -fr --no-gpg-sign -s resolve --root &&
+	test_must_fail git verify-commit HEAD
+'
+
+test_expect_success 'rebase -r --gpg-sign will sign commit' '
+	git reset --hard merged &&
+	test_unconfig commit.gpgsign &&
+	git rebase -fr --gpg-sign --root &&
+	git verify-commit HEAD
+'
+
+test_expect_success 'rebase -r with commit.gpgsign=true will sign commit' '
+	git reset --hard merged &&
+	git config commit.gpgsign true &&
+	git rebase -fr --root &&
+	git verify-commit HEAD
+'
+
+test_expect_success 'rebase -r --gpg-sign with commit.gpgsign=false will sign commit' '
+	git reset --hard merged &&
+	git config commit.gpgsign false &&
+	git rebase -fr --gpg-sign --root &&
+	git verify-commit HEAD
+'
+
+test_expect_success "rebase -r --no-gpg-sign with commit.gpgsign=true won't sign commit" '
+	git reset --hard merged &&
+	git config commit.gpgsign true &&
+	git rebase -fr --no-gpg-sign --root &&
+	test_must_fail git verify-commit HEAD
+'
+
 test_done
diff --git a/t/t3920-crlf-messages.sh b/t/t3920-crlf-messages.sh
new file mode 100755
index 0000000..70ddce3
--- /dev/null
+++ b/t/t3920-crlf-messages.sh
@@ -0,0 +1,126 @@
+#!/bin/sh
+
+test_description='Test ref-filter and pretty APIs for commit and tag messages using CRLF'
+. ./test-lib.sh
+
+LIB_CRLF_BRANCHES=""
+
+create_crlf_ref () {
+	branch="$1" &&
+	cat >.crlf-orig-$branch.txt &&
+	cat .crlf-orig-$branch.txt | append_cr >.crlf-message-$branch.txt &&
+	grep 'Subject' .crlf-orig-$branch.txt | tr '\n' ' ' | sed 's/[ ]*$//' | tr -d '\n' >.crlf-subject-$branch.txt &&
+	grep 'Body' .crlf-message-$branch.txt >.crlf-body-$branch.txt || true &&
+	LIB_CRLF_BRANCHES="${LIB_CRLF_BRANCHES} ${branch}" &&
+	test_tick &&
+	hash=$(git commit-tree HEAD^{tree} -p HEAD -F .crlf-message-${branch}.txt) &&
+	git branch ${branch} ${hash} &&
+	git tag tag-${branch} ${branch} -F .crlf-message-${branch}.txt --cleanup=verbatim
+}
+
+create_crlf_refs () {
+	create_crlf_ref crlf <<-\EOF &&
+	Subject first line
+
+	Body first line
+	Body second line
+	EOF
+	create_crlf_ref crlf-empty-lines-after-subject <<-\EOF &&
+	Subject first line
+
+
+	Body first line
+	Body second line
+	EOF
+	create_crlf_ref crlf-two-line-subject <<-\EOF &&
+	Subject first line
+	Subject second line
+
+	Body first line
+	Body second line
+	EOF
+	create_crlf_ref crlf-two-line-subject-no-body <<-\EOF &&
+	Subject first line
+	Subject second line
+	EOF
+	create_crlf_ref crlf-two-line-subject-no-body-trailing-newline <<-\EOF
+	Subject first line
+	Subject second line
+
+	EOF
+}
+
+test_crlf_subject_body_and_contents() {
+	command_and_args="$@" &&
+	command=$1 &&
+	if test ${command} = "branch" || test ${command} = "for-each-ref" || test ${command} = "tag"
+	then
+		atoms="(contents:subject) (contents:body) (contents)"
+	elif test ${command} = "log" || test ${command} = "show"
+	then
+		atoms="s b B"
+	fi &&
+	files="subject body message" &&
+	while test -n "${atoms}"
+	do
+		set ${atoms} && atom=$1 && shift && atoms="$*" &&
+		set ${files} &&	file=$1 && shift && files="$*" &&
+		test_expect_success "${command}: --format='%${atom}' works with messages using CRLF" "
+			rm -f expect &&
+			for ref in ${LIB_CRLF_BRANCHES}
+			do
+				cat .crlf-${file}-\"\${ref}\".txt >>expect &&
+				printf \"\n\" >>expect
+			done &&
+			git $command_and_args --format=\"%${atom}\" >actual &&
+			test_cmp expect actual
+		"
+	done
+}
+
+
+test_expect_success 'Setup refs with commit and tag messages using CRLF' '
+	test_commit inital &&
+	create_crlf_refs
+'
+
+test_expect_success 'branch: --verbose works with messages using CRLF' '
+	rm -f expect &&
+	for branch in $LIB_CRLF_BRANCHES
+	do
+		printf "  " >>expect &&
+		cat .crlf-subject-${branch}.txt >>expect &&
+		printf "\n" >>expect
+	done &&
+	git branch -v >tmp &&
+	# Remove first two columns, and the line for the currently checked out branch
+	current=$(git branch --show-current) &&
+	grep -v $current <tmp | awk "{\$1=\$2=\"\"}1"  >actual &&
+	test_cmp expect actual
+'
+
+test_crlf_subject_body_and_contents branch --list crlf*
+
+test_crlf_subject_body_and_contents tag --list tag-crlf*
+
+test_crlf_subject_body_and_contents for-each-ref refs/heads/crlf*
+
+test_expect_success 'log: --oneline works with messages using CRLF' '
+	for branch in $LIB_CRLF_BRANCHES
+	do
+		cat .crlf-subject-${branch}.txt >expect &&
+		printf "\n" >>expect &&
+		git log --oneline -1 ${branch} >tmp-branch &&
+		git log --oneline -1 tag-${branch} >tmp-tag &&
+		cut -d" " -f2- <tmp-branch >actual-branch &&
+		cut -d" " -f2- <tmp-tag >actual-tag &&
+		test_cmp expect actual-branch &&
+		test_cmp expect actual-tag || return 1
+	done
+'
+
+test_crlf_subject_body_and_contents log --all --reverse --grep Subject
+
+test_crlf_subject_body_and_contents show $LIB_CRLF_BRANCHES
+
+test_done
diff --git a/t/t4013-diff-various.sh b/t/t4013-diff-various.sh
index 5c7b012..f72d456 100755
--- a/t/t4013-diff-various.sh
+++ b/t/t4013-diff-various.sh
@@ -6,6 +6,7 @@
 test_description='Various diff formatting options'
 
 . ./test-lib.sh
+. "$TEST_DIRECTORY"/diff-lib.sh
 
 test_expect_success setup '
 
@@ -333,6 +334,7 @@
 log -GF master
 log -GF -p master
 log -GF -p --pickaxe-all master
+log -IA -IB -I1 -I2 -p master
 log --decorate --all
 log --decorate=full --all
 
@@ -473,4 +475,43 @@
 	test_cmp expect actual
 '
 
+test_expect_success 'diff -I<regex>: setup' '
+	git checkout master &&
+	test_seq 50 >file0 &&
+	git commit -m "Set up -I<regex> test file" file0 &&
+	test_seq 50 | sed -e "s/13/ten and three/" -e "/7\$/d" >file0 &&
+	echo >>file0
+'
+test_expect_success 'diff -I<regex>' '
+	git diff --ignore-blank-lines -I"ten.*e" -I"^[124-9]" >actual &&
+	cat >expect <<-\EOF &&
+	diff --git a/file0 b/file0
+	--- a/file0
+	+++ b/file0
+	@@ -34,7 +31,6 @@
+	 34
+	 35
+	 36
+	-37
+	 38
+	 39
+	 40
+	EOF
+	compare_diff_patch expect actual
+'
+
+test_expect_success 'diff -I<regex> --stat' '
+	git diff --stat --ignore-blank-lines -I"ten.*e" -I"^[124-9]" >actual &&
+	cat >expect <<-\EOF &&
+	 file0 | 1 -
+	 1 file changed, 1 deletion(-)
+	EOF
+	test_cmp expect actual
+'
+
+test_expect_success 'diff -I<regex>: detect malformed regex' '
+	test_expect_code 129 git diff --ignore-matching-lines="^[124-9" 2>error &&
+	test_i18ngrep "invalid regex given to -I: " error
+'
+
 test_done
diff --git a/t/t4013/diff.log_-IA_-IB_-I1_-I2_-p_master b/t/t4013/diff.log_-IA_-IB_-I1_-I2_-p_master
new file mode 100644
index 0000000..929f35a
--- /dev/null
+++ b/t/t4013/diff.log_-IA_-IB_-I1_-I2_-p_master
@@ -0,0 +1,99 @@
+$ git log -IA -IB -I1 -I2 -p master
+commit 59d314ad6f356dd08601a4cd5e530381da3e3c64
+Merge: 9a6d494 c7a2ab9
+Author: A U Thor <author@example.com>
+Date:   Mon Jun 26 00:04:00 2006 +0000
+
+    Merge branch 'side'
+
+commit c7a2ab9e8eac7b117442a607d5a9b3950ae34d5a
+Author: A U Thor <author@example.com>
+Date:   Mon Jun 26 00:03:00 2006 +0000
+
+    Side
+
+diff --git a/file0 b/file0
+index 01e79c3..f4615da 100644
+--- a/file0
++++ b/file0
+@@ -1,3 +1,6 @@
+ 1
+ 2
+ 3
++A
++B
++C
+diff --git a/file3 b/file3
+new file mode 100644
+index 0000000..7289e35
+
+commit 9a6d4949b6b76956d9d5e26f2791ec2ceff5fdc0
+Author: A U Thor <author@example.com>
+Date:   Mon Jun 26 00:02:00 2006 +0000
+
+    Third
+
+diff --git a/dir/sub b/dir/sub
+index 8422d40..cead32e 100644
+--- a/dir/sub
++++ b/dir/sub
+@@ -2,3 +2,5 @@ A
+ B
+ C
+ D
++E
++F
+diff --git a/file1 b/file1
+new file mode 100644
+index 0000000..b1e6722
+--- /dev/null
++++ b/file1
+@@ -0,0 +1,3 @@
++A
++B
++C
+
+commit 1bde4ae5f36c8d9abe3a0fce0c6aab3c4a12fe44
+Author: A U Thor <author@example.com>
+Date:   Mon Jun 26 00:01:00 2006 +0000
+
+    Second
+    
+    This is the second commit.
+
+diff --git a/dir/sub b/dir/sub
+index 35d242b..8422d40 100644
+--- a/dir/sub
++++ b/dir/sub
+@@ -1,2 +1,4 @@
+ A
+ B
++C
++D
+diff --git a/file0 b/file0
+index 01e79c3..b414108 100644
+--- a/file0
++++ b/file0
+@@ -1,3 +1,6 @@
+ 1
+ 2
+ 3
++4
++5
++6
+diff --git a/file2 b/file2
+deleted file mode 100644
+index 01e79c3..0000000
+--- a/file2
++++ /dev/null
+@@ -1,3 +0,0 @@
+-1
+-2
+-3
+
+commit 444ac553ac7612cc88969031b02b3767fb8a353a
+Author: A U Thor <author@example.com>
+Date:   Mon Jun 26 00:00:00 2006 +0000
+
+    Initial
+$
diff --git a/t/t4014-format-patch.sh b/t/t4014-format-patch.sh
index 294e76c..c5e5e0d 100755
--- a/t/t4014-format-patch.sh
+++ b/t/t4014-format-patch.sh
@@ -313,6 +313,60 @@
 	ls patches/0001-Side-changes-1.patch patches/0002-Side-changes-2.patch patches/0003-Side-changes-3-with-n-backslash-n-in-it.patch
 '
 
+test_expect_success 'filename length limit' '
+	test_when_finished "rm -f 000*" &&
+	rm -rf 000[1-9]-*.patch &&
+	for len in 15 25 35
+	do
+		git format-patch --filename-max-length=$len -3 side &&
+		max=$(
+			for patch in 000[1-9]-*.patch
+			do
+				echo "$patch" | wc -c
+			done |
+			sort -nr |
+			head -n 1
+		) &&
+		test $max -le $len || return 1
+	done
+'
+
+test_expect_success 'filename length limit from config' '
+	test_when_finished "rm -f 000*" &&
+	rm -rf 000[1-9]-*.patch &&
+	for len in 15 25 35
+	do
+		git -c format.filenameMaxLength=$len format-patch -3 side &&
+		max=$(
+			for patch in 000[1-9]-*.patch
+			do
+				echo "$patch" | wc -c
+			done |
+			sort -nr |
+			head -n 1
+		) &&
+		test $max -le $len || return 1
+	done
+'
+
+test_expect_success 'filename limit applies only to basename' '
+	test_when_finished "rm -rf patches/" &&
+	rm -rf patches/ &&
+	for len in 15 25 35
+	do
+		git format-patch -o patches --filename-max-length=$len -3 side &&
+		max=$(
+			for patch in patches/000[1-9]-*.patch
+			do
+				echo "${patch#patches/}" | wc -c
+			done |
+			sort -nr |
+			head -n 1
+		) &&
+		test $max -le $len || return 1
+	done
+'
+
 test_expect_success 'reroll count' '
 	rm -fr patches &&
 	git format-patch -o patches --cover-letter --reroll-count 4 master..side >list &&
@@ -1919,6 +1973,39 @@
 	test_path_is_dir patchset
 '
 
+test_expect_success 'format-patch forbids multiple outputs' '
+	rm -fr outfile outdir &&
+	test_must_fail \
+		git format-patch --stdout --output-directory=outdir &&
+	test_must_fail \
+		git format-patch --stdout --output=outfile &&
+	test_must_fail \
+		git format-patch --output=outfile --output-directory=outdir
+'
+
+test_expect_success 'configured outdir does not conflict with output options' '
+	rm -fr outfile outdir &&
+	test_config format.outputDirectory outdir &&
+	git format-patch --stdout &&
+	test_path_is_missing outdir &&
+	git format-patch --output=outfile &&
+	test_path_is_missing outdir
+'
+
+test_expect_success 'format-patch --output' '
+	rm -fr outfile &&
+	git format-patch -3 --stdout HEAD >expect &&
+	git format-patch -3 --output=outfile HEAD &&
+	test_cmp expect outfile
+'
+
+test_expect_success 'format-patch --cover-letter --output' '
+	rm -fr outfile &&
+	git format-patch --cover-letter -3 --stdout HEAD >expect &&
+	git format-patch --cover-letter -3 --output=outfile HEAD &&
+	test_cmp expect outfile
+'
+
 test_expect_success 'format-patch --base' '
 	git checkout patchid &&
 
diff --git a/t/t4015-diff-whitespace.sh b/t/t4015-diff-whitespace.sh
index 8bdaa0a..47f0e28 100755
--- a/t/t4015-diff-whitespace.sh
+++ b/t/t4015-diff-whitespace.sh
@@ -877,13 +877,13 @@
 test_expect_success 'combined diff with autocrlf conversion' '
 
 	git reset --hard &&
-	echo >x hello &&
-	git commit -m "one side" x &&
+	test_commit "one side" x hello one-side &&
 	git checkout HEAD^ &&
 	echo >x goodbye &&
 	git commit -m "the other side" x &&
 	git config core.autocrlf true &&
-	test_must_fail git merge master &&
+	test_must_fail git merge one-side >actual &&
+	test_i18ngrep "Automatic merge failed" actual &&
 
 	git diff >actual.raw &&
 	sed -e "1,/^@@@/d" actual.raw >actual &&
diff --git a/t/t4018-diff-funcname.sh b/t/t4018-diff-funcname.sh
index 9d07797..9675bc1 100755
--- a/t/t4018-diff-funcname.sh
+++ b/t/t4018-diff-funcname.sh
@@ -27,6 +27,7 @@
 
 diffpatterns="
 	ada
+	bash
 	bibtex
 	cpp
 	csharp
diff --git a/t/t4018/bash-arithmetic-function b/t/t4018/bash-arithmetic-function
new file mode 100644
index 0000000..c0b276c
--- /dev/null
+++ b/t/t4018/bash-arithmetic-function
@@ -0,0 +1,4 @@
+RIGHT() ((
+
+    ChangeMe = "$x" + "$y"
+))
diff --git a/t/t4018/bash-bashism-style-compact b/t/t4018/bash-bashism-style-compact
new file mode 100644
index 0000000..1ca3126
--- /dev/null
+++ b/t/t4018/bash-bashism-style-compact
@@ -0,0 +1,6 @@
+function RIGHT {
+    function InvalidSyntax{
+        :
+        echo 'ChangeMe'
+    }
+}
diff --git a/t/t4018/bash-bashism-style-function b/t/t4018/bash-bashism-style-function
new file mode 100644
index 0000000..f1de4fa
--- /dev/null
+++ b/t/t4018/bash-bashism-style-function
@@ -0,0 +1,4 @@
+function RIGHT {
+    :
+    echo 'ChangeMe'
+}
diff --git a/t/t4018/bash-bashism-style-whitespace b/t/t4018/bash-bashism-style-whitespace
new file mode 100644
index 0000000..ade85dd
--- /dev/null
+++ b/t/t4018/bash-bashism-style-whitespace
@@ -0,0 +1,4 @@
+	 function 	RIGHT 	( 	) 	{
+
+	    ChangeMe
+	 }
diff --git a/t/t4018/bash-conditional-function b/t/t4018/bash-conditional-function
new file mode 100644
index 0000000..c5949e8
--- /dev/null
+++ b/t/t4018/bash-conditional-function
@@ -0,0 +1,4 @@
+RIGHT() [[ \
+
+    "$a" > "$ChangeMe"
+]]
diff --git a/t/t4018/bash-missing-parentheses b/t/t4018/bash-missing-parentheses
new file mode 100644
index 0000000..8c8a05d
--- /dev/null
+++ b/t/t4018/bash-missing-parentheses
@@ -0,0 +1,6 @@
+function RIGHT {
+    functionInvalidSyntax {
+        :
+        echo 'ChangeMe'
+    }
+}
diff --git a/t/t4018/bash-mixed-style-compact b/t/t4018/bash-mixed-style-compact
new file mode 100644
index 0000000..d9364cb
--- /dev/null
+++ b/t/t4018/bash-mixed-style-compact
@@ -0,0 +1,4 @@
+function RIGHT(){
+    :
+    echo 'ChangeMe'
+}
diff --git a/t/t4018/bash-mixed-style-function b/t/t4018/bash-mixed-style-function
new file mode 100644
index 0000000..555f9b2
--- /dev/null
+++ b/t/t4018/bash-mixed-style-function
@@ -0,0 +1,4 @@
+function RIGHT() {
+
+    ChangeMe
+}
diff --git a/t/t4018/bash-nested-functions b/t/t4018/bash-nested-functions
new file mode 100644
index 0000000..2c9237e
--- /dev/null
+++ b/t/t4018/bash-nested-functions
@@ -0,0 +1,6 @@
+outer() {
+    RIGHT() {
+        :
+        echo 'ChangeMe'
+    }
+}
diff --git a/t/t4018/bash-other-characters b/t/t4018/bash-other-characters
new file mode 100644
index 0000000..a3f390d
--- /dev/null
+++ b/t/t4018/bash-other-characters
@@ -0,0 +1,4 @@
+_RIGHT_0n() {
+
+    ChangeMe
+}
diff --git a/t/t4018/bash-posix-style-compact b/t/t4018/bash-posix-style-compact
new file mode 100644
index 0000000..045bd20
--- /dev/null
+++ b/t/t4018/bash-posix-style-compact
@@ -0,0 +1,4 @@
+RIGHT(){
+
+    ChangeMe
+}
diff --git a/t/t4018/bash-posix-style-function b/t/t4018/bash-posix-style-function
new file mode 100644
index 0000000..a4d1448
--- /dev/null
+++ b/t/t4018/bash-posix-style-function
@@ -0,0 +1,4 @@
+RIGHT() {
+
+    ChangeMe
+}
diff --git a/t/t4018/bash-posix-style-whitespace b/t/t4018/bash-posix-style-whitespace
new file mode 100644
index 0000000..4d984f0
--- /dev/null
+++ b/t/t4018/bash-posix-style-whitespace
@@ -0,0 +1,4 @@
+	 RIGHT 	( 	) 	{
+
+	    ChangeMe
+	 }
diff --git a/t/t4018/bash-subshell-function b/t/t4018/bash-subshell-function
new file mode 100644
index 0000000..80baa09
--- /dev/null
+++ b/t/t4018/bash-subshell-function
@@ -0,0 +1,4 @@
+RIGHT() (
+
+    ChangeMe=2
+)
diff --git a/t/t4018/bash-trailing-comment b/t/t4018/bash-trailing-comment
new file mode 100644
index 0000000..f1edbed
--- /dev/null
+++ b/t/t4018/bash-trailing-comment
@@ -0,0 +1,4 @@
+RIGHT() { # Comment
+
+    ChangeMe
+}
diff --git a/t/t4018/css-attribute-value-selector b/t/t4018/css-attribute-value-selector
new file mode 100644
index 0000000..918256b
--- /dev/null
+++ b/t/t4018/css-attribute-value-selector
@@ -0,0 +1,4 @@
+[class*="RIGHT"] {
+    background : #000;
+    border : 10px ChangeMe #C6C6C6;
+}
diff --git a/t/t4018/css-block-level-@-statements b/t/t4018/css-block-level-@-statements
new file mode 100644
index 0000000..d6755f2
--- /dev/null
+++ b/t/t4018/css-block-level-@-statements
@@ -0,0 +1,10 @@
+@keyframes RIGHT {
+    from {
+        background : #000;
+        border : 10px ChangeMe #C6C6C6;
+    }
+    to {
+        background : #fff;
+        border : 10px solid #C6C6C6;
+    }
+}
diff --git a/t/t4018/css-class-selector b/t/t4018/css-class-selector
new file mode 100644
index 0000000..f790a00
--- /dev/null
+++ b/t/t4018/css-class-selector
@@ -0,0 +1,4 @@
+.RIGHT {
+    background : #000;
+    border : 10px ChangeMe #C6C6C6;
+}
diff --git a/t/t4018/css-id-selector b/t/t4018/css-id-selector
new file mode 100644
index 0000000..17c5111
--- /dev/null
+++ b/t/t4018/css-id-selector
@@ -0,0 +1,4 @@
+#RIGHT {
+    background : #000;
+    border : 10px ChangeMe #C6C6C6;
+}
diff --git a/t/t4018/css-root-selector b/t/t4018/css-root-selector
new file mode 100644
index 0000000..22b958e
--- /dev/null
+++ b/t/t4018/css-root-selector
@@ -0,0 +1,4 @@
+:RIGHT {
+    background : #000;
+    border : 10px ChangeMe #C6C6C6;
+}
diff --git a/t/t4018/php-abstract-method b/t/t4018/php-abstract-method
new file mode 100644
index 0000000..ce215df7
--- /dev/null
+++ b/t/t4018/php-abstract-method
@@ -0,0 +1,7 @@
+abstract class Klass
+{
+    abstract public function RIGHT(): ?string
+    {
+        return 'ChangeMe';
+    }
+}
diff --git a/t/t4018/php-final-method b/t/t4018/php-final-method
new file mode 100644
index 0000000..537fb8a
--- /dev/null
+++ b/t/t4018/php-final-method
@@ -0,0 +1,7 @@
+class Klass
+{
+    final public function RIGHT(): string
+    {
+        return 'ChangeMe';
+    }
+}
diff --git a/t/t4018/rust-macro-rules b/t/t4018/rust-macro-rules
new file mode 100644
index 0000000..ec610c5
--- /dev/null
+++ b/t/t4018/rust-macro-rules
@@ -0,0 +1,6 @@
+macro_rules! RIGHT {
+    () => {
+        // a comment
+        let x = ChangeMe;
+    };
+}
diff --git a/t/t4068-diff-symmetric-merge-base.sh b/t/t4068-diff-symmetric-merge-base.sh
new file mode 100755
index 0000000..03487cc
--- /dev/null
+++ b/t/t4068-diff-symmetric-merge-base.sh
@@ -0,0 +1,193 @@
+#!/bin/sh
+
+test_description='behavior of diff with symmetric-diff setups and --merge-base'
+
+. ./test-lib.sh
+
+# build these situations:
+#  - normal merge with one merge base (br1...b2r);
+#  - criss-cross merge ie 2 merge bases (br1...master);
+#  - disjoint subgraph (orphan branch, br3...master).
+#
+#     B---E   <-- master
+#    / \ /
+#   A   X
+#    \ / \
+#     C---D--G   <-- br1
+#      \    /
+#       ---F   <-- br2
+#
+#  H  <-- br3
+#
+# We put files into a few commits so that we can verify the
+# output as well.
+
+test_expect_success setup '
+	git commit --allow-empty -m A &&
+	echo b >b &&
+	git add b &&
+	git commit -m B &&
+	git checkout -b br1 HEAD^ &&
+	echo c >c &&
+	git add c &&
+	git commit -m C &&
+	git tag commit-C &&
+	git merge -m D master &&
+	git tag commit-D &&
+	git checkout master &&
+	git merge -m E commit-C &&
+	git checkout -b br2 commit-C &&
+	echo f >f &&
+	git add f &&
+	git commit -m F &&
+	git checkout br1 &&
+	git merge -m G br2 &&
+	git checkout --orphan br3 &&
+	git commit -m H
+'
+
+test_expect_success 'diff with one merge base' '
+	git diff commit-D...br1 >tmp &&
+	tail -n 1 tmp >actual &&
+	echo +f >expect &&
+	test_cmp expect actual
+'
+
+# The output (in tmp) can have +b or +c depending
+# on which merge base (commit B or C) is picked.
+# It should have one of those two, which comes out
+# to seven lines.
+test_expect_success 'diff with two merge bases' '
+	git diff br1...master >tmp 2>err &&
+	test_line_count = 7 tmp &&
+	test_line_count = 1 err
+'
+
+test_expect_success 'diff with no merge bases' '
+	test_must_fail git diff br2...br3 2>err &&
+	test_i18ngrep "fatal: br2...br3: no merge base" err
+'
+
+test_expect_success 'diff with too many symmetric differences' '
+	test_must_fail git diff br1...master br2...br3 2>err &&
+	test_i18ngrep "usage" err
+'
+
+test_expect_success 'diff with symmetric difference and extraneous arg' '
+	test_must_fail git diff master br1...master 2>err &&
+	test_i18ngrep "usage" err
+'
+
+test_expect_success 'diff with two ranges' '
+	test_must_fail git diff master br1..master br2..br3 2>err &&
+	test_i18ngrep "usage" err
+'
+
+test_expect_success 'diff with ranges and extra arg' '
+	test_must_fail git diff master br1..master commit-D 2>err &&
+	test_i18ngrep "usage" err
+'
+
+test_expect_success 'diff --merge-base with no commits' '
+	test_must_fail git diff --merge-base
+'
+
+test_expect_success 'diff --merge-base with three commits' '
+	test_must_fail git diff --merge-base br1 br2 master 2>err &&
+	test_i18ngrep "usage" err
+'
+
+for cmd in diff-index diff
+do
+	test_expect_success "$cmd --merge-base with one commit" '
+		git checkout master &&
+		git $cmd commit-C >expect &&
+		git $cmd --merge-base br2 >actual &&
+		test_cmp expect actual
+	'
+
+	test_expect_success "$cmd --merge-base with one commit and unstaged changes" '
+		git checkout master &&
+		test_when_finished git reset --hard &&
+		echo unstaged >>c &&
+		git $cmd commit-C >expect &&
+		git $cmd --merge-base br2 >actual &&
+		test_cmp expect actual
+	'
+
+	test_expect_success "$cmd --merge-base with one commit and staged and unstaged changes" '
+		git checkout master &&
+		test_when_finished git reset --hard &&
+		echo staged >>c &&
+		git add c &&
+		echo unstaged >>c &&
+		git $cmd commit-C >expect &&
+		git $cmd --merge-base br2 >actual &&
+		test_cmp expect actual
+	'
+
+	test_expect_success "$cmd --merge-base --cached with one commit and staged and unstaged changes" '
+		git checkout master &&
+		test_when_finished git reset --hard &&
+		echo staged >>c &&
+		git add c &&
+		echo unstaged >>c &&
+		git $cmd --cached commit-C >expect &&
+		git $cmd --cached --merge-base br2 >actual &&
+		test_cmp expect actual
+	'
+
+	test_expect_success "$cmd --merge-base with non-commit" '
+		git checkout master &&
+		test_must_fail git $cmd --merge-base master^{tree} 2>err &&
+		test_i18ngrep "fatal: --merge-base only works with commits" err
+	'
+
+	test_expect_success "$cmd --merge-base with no merge bases and one commit" '
+		git checkout master &&
+		test_must_fail git $cmd --merge-base br3 2>err &&
+		test_i18ngrep "fatal: no merge base found" err
+	'
+
+	test_expect_success "$cmd --merge-base with multiple merge bases and one commit" '
+		git checkout master &&
+		test_must_fail git $cmd --merge-base br1 2>err &&
+		test_i18ngrep "fatal: multiple merge bases found" err
+	'
+done
+
+for cmd in diff-tree diff
+do
+	test_expect_success "$cmd --merge-base with two commits" '
+		git $cmd commit-C master >expect &&
+		git $cmd --merge-base br2 master >actual &&
+		test_cmp expect actual
+	'
+
+	test_expect_success "$cmd --merge-base commit and non-commit" '
+		test_must_fail git $cmd --merge-base br2 master^{tree} 2>err &&
+		test_i18ngrep "fatal: --merge-base only works with commits" err
+	'
+
+	test_expect_success "$cmd --merge-base with no merge bases and two commits" '
+		test_must_fail git $cmd --merge-base br2 br3 2>err &&
+		test_i18ngrep "fatal: no merge base found" err
+	'
+
+	test_expect_success "$cmd --merge-base with multiple merge bases and two commits" '
+		test_must_fail git $cmd --merge-base master br1 2>err &&
+		test_i18ngrep "fatal: multiple merge bases found" err
+	'
+done
+
+test_expect_success 'diff-tree --merge-base with one commit' '
+	test_must_fail git diff-tree --merge-base master 2>err &&
+	test_i18ngrep "fatal: --merge-base only works with two commits" err
+'
+
+test_expect_success 'diff --merge-base with range' '
+	test_must_fail git diff --merge-base br2..br3 2>err &&
+	test_i18ngrep "fatal: --merge-base does not work with ranges" err
+'
+
+test_done
diff --git a/t/t4068-diff-symmetric.sh b/t/t4068-diff-symmetric.sh
deleted file mode 100755
index 31d17a5..0000000
--- a/t/t4068-diff-symmetric.sh
+++ /dev/null
@@ -1,91 +0,0 @@
-#!/bin/sh
-
-test_description='behavior of diff with symmetric-diff setups'
-
-. ./test-lib.sh
-
-# build these situations:
-#  - normal merge with one merge base (br1...b2r);
-#  - criss-cross merge ie 2 merge bases (br1...master);
-#  - disjoint subgraph (orphan branch, br3...master).
-#
-#     B---E   <-- master
-#    / \ /
-#   A   X
-#    \ / \
-#     C---D--G   <-- br1
-#      \    /
-#       ---F   <-- br2
-#
-#  H  <-- br3
-#
-# We put files into a few commits so that we can verify the
-# output as well.
-
-test_expect_success setup '
-	git commit --allow-empty -m A &&
-	echo b >b &&
-	git add b &&
-	git commit -m B &&
-	git checkout -b br1 HEAD^ &&
-	echo c >c &&
-	git add c &&
-	git commit -m C &&
-	git tag commit-C &&
-	git merge -m D master &&
-	git tag commit-D &&
-	git checkout master &&
-	git merge -m E commit-C &&
-	git checkout -b br2 commit-C &&
-	echo f >f &&
-	git add f &&
-	git commit -m F &&
-	git checkout br1 &&
-	git merge -m G br2 &&
-	git checkout --orphan br3 &&
-	git commit -m H
-'
-
-test_expect_success 'diff with one merge base' '
-	git diff commit-D...br1 >tmp &&
-	tail -n 1 tmp >actual &&
-	echo +f >expect &&
-	test_cmp expect actual
-'
-
-# The output (in tmp) can have +b or +c depending
-# on which merge base (commit B or C) is picked.
-# It should have one of those two, which comes out
-# to seven lines.
-test_expect_success 'diff with two merge bases' '
-	git diff br1...master >tmp 2>err &&
-	test_line_count = 7 tmp &&
-	test_line_count = 1 err
-'
-
-test_expect_success 'diff with no merge bases' '
-	test_must_fail git diff br2...br3 >tmp 2>err &&
-	test_i18ngrep "fatal: br2...br3: no merge base" err
-'
-
-test_expect_success 'diff with too many symmetric differences' '
-	test_must_fail git diff br1...master br2...br3 >tmp 2>err &&
-	test_i18ngrep "usage" err
-'
-
-test_expect_success 'diff with symmetric difference and extraneous arg' '
-	test_must_fail git diff master br1...master >tmp 2>err &&
-	test_i18ngrep "usage" err
-'
-
-test_expect_success 'diff with two ranges' '
-	test_must_fail git diff master br1..master br2..br3 >tmp 2>err &&
-	test_i18ngrep "usage" err
-'
-
-test_expect_success 'diff with ranges and extra arg' '
-	test_must_fail git diff master br1..master commit-D >tmp 2>err &&
-	test_i18ngrep "usage" err
-'
-
-test_done
diff --git a/t/t4114-apply-typechange.sh b/t/t4114-apply-typechange.sh
index ebadbc3..da3e64f 100755
--- a/t/t4114-apply-typechange.sh
+++ b/t/t4114-apply-typechange.sh
@@ -88,6 +88,13 @@
 	'
 test_debug 'cat patch'
 
+test_expect_success 'symlink becomes file, in reverse' '
+	git checkout -f foo-symlinked-to-bar &&
+	git diff-tree -p HEAD foo-back-to-file > patch &&
+	git checkout foo-back-to-file &&
+	git apply -R --index < patch
+	'
+
 test_expect_success 'binary file becomes symlink' '
 	git checkout -f foo-becomes-binary &&
 	git diff-tree -p --binary HEAD foo-symlinked-to-bar > patch &&
diff --git a/t/t4127-apply-same-fn.sh b/t/t4127-apply-same-fn.sh
index 972946c..305b7e6 100755
--- a/t/t4127-apply-same-fn.sh
+++ b/t/t4127-apply-same-fn.sh
@@ -32,6 +32,10 @@
 
 test_expect_success 'apply same filename with overlapping changes' '
 	git reset --hard &&
+
+	# Store same_fn so that we can check apply -R in next test
+	cp same_fn same_fn1 &&
+
 	modify "s/^d/z/" same_fn &&
 	git diff > patch0 &&
 	git add same_fn &&
@@ -43,6 +47,11 @@
 	test_cmp same_fn same_fn2
 '
 
+test_expect_success 'apply same filename with overlapping changes, in reverse' '
+	git apply -R patch0 &&
+	test_cmp same_fn same_fn1
+'
+
 test_expect_success 'apply same new filename after rename' '
 	git reset --hard &&
 	git mv same_fn new_fn &&
diff --git a/t/t4211-line-log.sh b/t/t4211-line-log.sh
index 2d1d7b5..85d1514 100755
--- a/t/t4211-line-log.sh
+++ b/t/t4211-line-log.sh
@@ -8,6 +8,28 @@
 	git reset --hard
 '
 
+test_expect_success 'basic command line parsing' '
+	# This may fail due to "no such path a.c in commit", or
+	# "-L is incompatible with pathspec", depending on the
+	# order the error is checked.  Either is acceptable.
+	test_must_fail git log -L1,1:a.c -- a.c &&
+
+	# -L requires there is no pathspec
+	test_must_fail git log -L1,1:b.c -- b.c 2>error &&
+	test_i18ngrep "cannot be used with pathspec" error &&
+
+	# This would fail because --follow wants a single path, but
+	# we may fail due to incompatibility between -L/--follow in
+	# the future.  Either is acceptable.
+	test_must_fail git log -L1,1:b.c --follow &&
+	test_must_fail git log --follow -L1,1:b.c &&
+
+	# This would fail because -L wants no pathspec, but
+	# we may fail due to incompatibility between -L/--follow in
+	# the future.  Either is acceptable.
+	test_must_fail git log --follow -L1,1:b.c -- b.c
+'
+
 canned_test_1 () {
 	test_expect_$1 "$2" "
 		git log $2 >actual &&
diff --git a/t/t5310-pack-bitmaps.sh b/t/t5310-pack-bitmaps.sh
index 8318781..1d40fca 100755
--- a/t/t5310-pack-bitmaps.sh
+++ b/t/t5310-pack-bitmaps.sh
@@ -277,7 +277,7 @@
 	git pack-objects --stdout --revs <revs >/dev/null
 '
 
-test_expect_success JGIT 'we can read jgit bitmaps' '
+test_expect_success JGIT,SHA1 'we can read jgit bitmaps' '
 	git clone --bare . compat-jgit.git &&
 	(
 		cd compat-jgit.git &&
@@ -287,7 +287,7 @@
 	)
 '
 
-test_expect_success JGIT 'jgit can read our bitmaps' '
+test_expect_success JGIT,SHA1 'jgit can read our bitmaps' '
 	git clone --bare . compat-us.git &&
 	(
 		cd compat-us.git &&
diff --git a/t/t5315-pack-objects-compression.sh b/t/t5315-pack-objects-compression.sh
index df970d7..8bacd96 100755
--- a/t/t5315-pack-objects-compression.sh
+++ b/t/t5315-pack-objects-compression.sh
@@ -4,12 +4,6 @@
 
 . ./test-lib.sh
 
-# This should be moved to test-lib.sh together with the
-# copy in t0021 after both topics have graduated to 'master'.
-file_size () {
-	test-tool path-utils file-size "$1"
-}
-
 test_expect_success setup '
 	printf "%2000000s" X |
 	git hash-object -w --stdin >object-name &&
@@ -24,7 +18,7 @@
 	test_expect_success "pack-objects with $config" '
 		test_when_finished "rm -f pack-*.*" &&
 		git $config pack-objects pack <object-name &&
-		sz=$(file_size pack-*.pack) &&
+		sz=$(test_file_size pack-*.pack) &&
 		case "$expect" in
 		small) test "$sz" -le 100000 ;;
 		large) test "$sz" -ge 100000 ;;
diff --git a/t/t5319-multi-pack-index.sh b/t/t5319-multi-pack-index.sh
index f340b37..ace469c 100755
--- a/t/t5319-multi-pack-index.sh
+++ b/t/t5319-multi-pack-index.sh
@@ -3,6 +3,7 @@
 test_description='multi-pack-indexes'
 . ./test-lib.sh
 
+GIT_TEST_MULTI_PACK_INDEX=0
 objdir=.git/objects
 
 HASH_LEN=$(test_oid rawsz)
@@ -173,12 +174,12 @@
 '
 
 test_expect_success 'write force progress on for stderr' '
-	git multi-pack-index --object-dir=$objdir --progress write 2>err &&
+	GIT_PROGRESS_DELAY=0 git multi-pack-index --object-dir=$objdir --progress write 2>err &&
 	test_file_not_empty err
 '
 
 test_expect_success 'write with the --no-progress option' '
-	git multi-pack-index --object-dir=$objdir --no-progress write 2>err &&
+	GIT_PROGRESS_DELAY=0 git multi-pack-index --object-dir=$objdir --no-progress write 2>err &&
 	test_line_count = 0 err
 '
 
@@ -368,17 +369,17 @@
 '
 
 test_expect_success 'repack progress off for redirected stderr' '
-	git multi-pack-index --object-dir=$objdir repack 2>err &&
+	GIT_PROGRESS_DELAY=0 git multi-pack-index --object-dir=$objdir repack 2>err &&
 	test_line_count = 0 err
 '
 
 test_expect_success 'repack force progress on for stderr' '
-	git multi-pack-index --object-dir=$objdir --progress repack 2>err &&
+	GIT_PROGRESS_DELAY=0 git multi-pack-index --object-dir=$objdir --progress repack 2>err &&
 	test_file_not_empty err
 '
 
 test_expect_success 'repack with the --no-progress option' '
-	git multi-pack-index --object-dir=$objdir --no-progress repack 2>err &&
+	GIT_PROGRESS_DELAY=0 git multi-pack-index --object-dir=$objdir --no-progress repack 2>err &&
 	test_line_count = 0 err
 '
 
@@ -562,7 +563,7 @@
 test_expect_success 'expire force progress on for stderr' '
 	(
 		cd dup &&
-		git multi-pack-index --progress expire 2>err &&
+		GIT_PROGRESS_DELAY=0 git multi-pack-index --progress expire 2>err &&
 		test_file_not_empty err
 	)
 '
@@ -570,7 +571,7 @@
 test_expect_success 'expire with the --no-progress option' '
 	(
 		cd dup &&
-		git multi-pack-index --no-progress expire 2>err &&
+		GIT_PROGRESS_DELAY=0 git multi-pack-index --no-progress expire 2>err &&
 		test_line_count = 0 err
 	)
 '
diff --git a/t/t5324-split-commit-graph.sh b/t/t5324-split-commit-graph.sh
index c334ee9..4d3842b 100755
--- a/t/t5324-split-commit-graph.sh
+++ b/t/t5324-split-commit-graph.sh
@@ -440,4 +440,17 @@
 	verify_chain_files_exist $graphdir
 '
 
+test_expect_success 'prevent regression for duplicate commits across layers' '
+	git init dup &&
+	git -C dup commit --allow-empty -m one &&
+	git -C dup -c core.commitGraph=false commit-graph write --split=no-merge --reachable 2>err &&
+	test_i18ngrep "attempting to write a commit-graph" err &&
+	git -C dup commit-graph write --split=no-merge --reachable &&
+	git -C dup commit --allow-empty -m two &&
+	git -C dup commit-graph write --split=no-merge --reachable &&
+	git -C dup commit --allow-empty -m three &&
+	git -C dup commit-graph write --split --reachable &&
+	git -C dup commit-graph verify
+'
+
 test_done
diff --git a/t/t5400-send-pack.sh b/t/t5400-send-pack.sh
index b84618c..cc86ef2 100755
--- a/t/t5400-send-pack.sh
+++ b/t/t5400-send-pack.sh
@@ -21,14 +21,15 @@
 	i=0 &&
 	while test $i -le $cnt
 	do
-	    i=$(($i+1)) &&
-	    test_tick &&
-	    echo "Commit #$i" >mozart/is/pink &&
-	    git update-index --add mozart/is/pink &&
-	    tree=$(git write-tree) &&
-	    commit=$(echo "Commit #$i" | git commit-tree $tree -p $parent) &&
-	    git update-ref refs/tags/commit$i $commit &&
-	    parent=$commit || return 1
+		i=$(($i+1)) &&
+		test_tick &&
+		echo "Commit #$i" >mozart/is/pink &&
+		git update-index --add mozart/is/pink &&
+		tree=$(git write-tree) &&
+		commit=$(echo "Commit #$i" |
+			 git commit-tree $tree -p $parent) &&
+		git update-ref refs/tags/commit$i $commit &&
+		parent=$commit || return 1
 	done &&
 	git update-ref HEAD "$commit" &&
 	git clone ./. victim &&
@@ -38,14 +39,14 @@
 	i=0 &&
 	while test $i -le $cnt
 	do
-	    i=$(($i+1)) &&
-	    test_tick &&
-	    echo "Rebase #$i" >mozart/is/pink &&
-	    git update-index --add mozart/is/pink &&
-	    tree=$(git write-tree) &&
-	    commit=$(echo "Rebase #$i" | git commit-tree $tree -p $parent) &&
-	    git update-ref refs/tags/rebase$i $commit &&
-	    parent=$commit || return 1
+		i=$(($i+1)) &&
+		test_tick &&
+		echo "Rebase #$i" >mozart/is/pink &&
+		git update-index --add mozart/is/pink &&
+		tree=$(git write-tree) &&
+		commit=$(echo "Rebase #$i" | git commit-tree $tree -p $parent) &&
+		git update-ref refs/tags/rebase$i $commit &&
+		parent=$commit || return 1
 	done &&
 	git update-ref HEAD "$commit" &&
 	echo Rebase &&
@@ -57,11 +58,11 @@
 '
 
 test_expect_success 'pack the destination repository' '
-    (
-	cd victim &&
-	git repack -a -d &&
-	git prune
-    )
+	(
+		cd victim &&
+		git repack -a -d &&
+		git prune
+	)
 '
 
 test_expect_success 'refuse pushing rewound head without --force' '
@@ -85,10 +86,10 @@
 
 test_expect_success 'refuse deleting push with denyDeletes' '
 	(
-	    cd victim &&
-	    test_might_fail git branch -D extra &&
-	    git config receive.denyDeletes true &&
-	    git branch extra master
+		cd victim &&
+		test_might_fail git branch -D extra &&
+		git config receive.denyDeletes true &&
+		git branch extra master
 	) &&
 	test_must_fail git send-pack ./victim :extra master
 '
@@ -118,9 +119,9 @@
 
 test_expect_success 'denyNonFastforwards trumps --force' '
 	(
-	    cd victim &&
-	    test_might_fail git branch -D extra &&
-	    git config receive.denyNonFastforwards true
+		cd victim &&
+		test_might_fail git branch -D extra &&
+		git config receive.denyNonFastforwards true
 	) &&
 	victim_orig=$(cd victim && git rev-parse --verify master) &&
 	test_must_fail git send-pack --force ./victim master^:master &&
@@ -143,16 +144,16 @@
 test_expect_success 'push --all excludes remote-tracking hierarchy' '
 	mkdir parent &&
 	(
-	    cd parent &&
-	    git init && : >file && git add file && git commit -m add
+		cd parent &&
+		git init && : >file && git add file && git commit -m add
 	) &&
 	git clone parent child &&
 	(
-	    cd child && git push --all
+		cd child && git push --all
 	) &&
 	(
-	    cd parent &&
-	    test -z "$(git for-each-ref refs/remotes/origin)"
+		cd parent &&
+		test -z "$(git for-each-ref refs/remotes/origin)"
 	)
 '
 
@@ -160,33 +161,33 @@
 	rm -rf parent child &&
 	git init parent &&
 	(
-	    # Setup a repo with 2 packs
-	    cd parent &&
-	    echo "Some text" >file.txt &&
-	    git add . &&
-	    git commit -m "Initial commit" &&
-	    git repack -adl &&
-	    echo "Some more text" >>file.txt &&
-	    git commit -a -m "Second commit" &&
-	    git repack
+		# Setup a repo with 2 packs
+		cd parent &&
+		echo "Some text" >file.txt &&
+		git add . &&
+		git commit -m "Initial commit" &&
+		git repack -adl &&
+		echo "Some more text" >>file.txt &&
+		git commit -a -m "Second commit" &&
+		git repack
 	) &&
 	cp -R parent child &&
 	(
-	    # Set the child to auto-pack if more than one pack exists
-	    cd child &&
-	    git config gc.autopacklimit 1 &&
-	    git config gc.autodetach false &&
-	    git branch test_auto_gc &&
-	    # And create a file that follows the temporary object naming
-	    # convention for the auto-gc to remove
-	    : >.git/objects/tmp_test_object &&
-	    test-tool chmtime =-1209601 .git/objects/tmp_test_object
+		# Set the child to auto-pack if more than one pack exists
+		cd child &&
+		git config gc.autopacklimit 1 &&
+		git config gc.autodetach false &&
+		git branch test_auto_gc &&
+		# And create a file that follows the temporary object naming
+		# convention for the auto-gc to remove
+		: >.git/objects/tmp_test_object &&
+		test-tool chmtime =-1209601 .git/objects/tmp_test_object
 	) &&
 	(
-	    cd parent &&
-	    echo "Even more text" >>file.txt &&
-	    git commit -a -m "Third commit" &&
-	    git send-pack ../child HEAD:refs/heads/test_auto_gc
+		cd parent &&
+		echo "Even more text" >>file.txt &&
+		git commit -a -m "Third commit" &&
+		git send-pack ../child HEAD:refs/heads/test_auto_gc
 	) &&
 	test ! -e child/.git/objects/tmp_test_object
 '
@@ -195,15 +196,15 @@
 	rm -rf parent child &&
 	mkdir parent &&
 	(
-	    cd parent &&
-	    git init &&
-	    echo one >file && git add file && git commit -m one &&
-	    git config receive.denyCurrentBranch warn &&
-	    echo two >file && git commit -a -m two
+		cd parent &&
+		git init &&
+		echo one >file && git add file && git commit -m one &&
+		git config receive.denyCurrentBranch warn &&
+		echo two >file && git commit -a -m two
 	) &&
 	git clone parent child &&
 	(
-	    cd child && git reset --hard HEAD^
+		cd child && git reset --hard HEAD^
 	)
 }
 
@@ -211,16 +212,16 @@
 	rewound_push_setup &&
 	parent_orig=$(cd parent && git rev-parse --verify master) &&
 	(
-	    cd child &&
-	    test_must_fail git send-pack ../parent \
-		refs/heads/master:refs/heads/master
+		cd child &&
+		test_must_fail git send-pack ../parent \
+			refs/heads/master:refs/heads/master
 	) &&
 	parent_head=$(cd parent && git rev-parse --verify master) &&
 	test "$parent_orig" = "$parent_head" &&
 	(
-	    cd child &&
-	    git send-pack ../parent \
-	        +refs/heads/master:refs/heads/master
+		cd child &&
+		git send-pack ../parent \
+			+refs/heads/master:refs/heads/master
 	) &&
 	parent_head=$(cd parent && git rev-parse --verify master) &&
 	child_head=$(cd child && git rev-parse --verify master) &&
@@ -231,16 +232,16 @@
 	rewound_push_setup &&
 	parent_orig=$(cd parent && git rev-parse --verify master) &&
 	(
-	    cd child &&
-	    test_must_fail git send-pack ../parent \
-	        "refs/heads/*:refs/heads/*"
+		cd child &&
+		test_must_fail git send-pack ../parent \
+			"refs/heads/*:refs/heads/*"
 	) &&
 	parent_head=$(cd parent && git rev-parse --verify master) &&
 	test "$parent_orig" = "$parent_head" &&
 	(
-	    cd child &&
-	    git send-pack ../parent \
-	        "+refs/heads/*:refs/heads/*"
+		cd child &&
+		git send-pack ../parent \
+			"+refs/heads/*:refs/heads/*"
 	) &&
 	parent_head=$(cd parent && git rev-parse --verify master) &&
 	child_head=$(cd child && git rev-parse --verify master) &&
@@ -250,8 +251,8 @@
 test_expect_success 'deny pushing to delete current branch' '
 	rewound_push_setup &&
 	(
-	    cd child &&
-	    test_must_fail git send-pack ../parent :refs/heads/master 2>errs
+		cd child &&
+		test_must_fail git send-pack ../parent :refs/heads/master 2>errs
 	)
 '
 
@@ -289,7 +290,7 @@
 	EOF
 
 	GIT_TRACE_PACKET=$(pwd)/trace GIT_TEST_PROTOCOL_VERSION=0 \
-	    git push \
+	git push \
 		--receive-pack="unset GIT_TRACE_PACKET; git-receive-pack" \
 		fork HEAD:foo &&
 	extract_ref_advertisement <trace >refs &&
diff --git a/t/t5402-post-merge-hook.sh b/t/t5402-post-merge-hook.sh
index 6eb2ffd..4aeea8f 100755
--- a/t/t5402-post-merge-hook.sh
+++ b/t/t5402-post-merge-hook.sh
@@ -15,7 +15,7 @@
 	git update-index a &&
 	tree1=$(git write-tree) &&
 	commit1=$(echo modify | git commit-tree $tree1 -p $commit0) &&
-        git update-ref refs/heads/master $commit0 &&
+	git update-ref refs/heads/master $commit0 &&
 	git clone ./. clone1 &&
 	GIT_DIR=clone1/.git git update-index --add a &&
 	git clone ./. clone2 &&
@@ -23,34 +23,34 @@
 '
 
 for clone in 1 2; do
-    cat >clone${clone}/.git/hooks/post-merge <<'EOF'
+	cat >clone${clone}/.git/hooks/post-merge <<'EOF'
 #!/bin/sh
 echo $@ >> $GIT_DIR/post-merge.args
 EOF
-    chmod u+x clone${clone}/.git/hooks/post-merge
+	chmod u+x clone${clone}/.git/hooks/post-merge
 done
 
 test_expect_success 'post-merge does not run for up-to-date ' '
-        GIT_DIR=clone1/.git git merge $commit0 &&
+	GIT_DIR=clone1/.git git merge $commit0 &&
 	! test -f clone1/.git/post-merge.args
 '
 
 test_expect_success 'post-merge runs as expected ' '
-        GIT_DIR=clone1/.git git merge $commit1 &&
+	GIT_DIR=clone1/.git git merge $commit1 &&
 	test -e clone1/.git/post-merge.args
 '
 
 test_expect_success 'post-merge from normal merge receives the right argument ' '
-        grep 0 clone1/.git/post-merge.args
+	grep 0 clone1/.git/post-merge.args
 '
 
 test_expect_success 'post-merge from squash merge runs as expected ' '
-        GIT_DIR=clone2/.git git merge --squash $commit1 &&
+	GIT_DIR=clone2/.git git merge --squash $commit1 &&
 	test -e clone2/.git/post-merge.args
 '
 
 test_expect_success 'post-merge from squash merge receives the right argument ' '
-        grep 1 clone2/.git/post-merge.args
+	grep 1 clone2/.git/post-merge.args
 '
 
 test_done
diff --git a/t/t5411-proc-receive-hook.sh b/t/t5411-proc-receive-hook.sh
index 7464872..98b0e81 100755
--- a/t/t5411-proc-receive-hook.sh
+++ b/t/t5411-proc-receive-hook.sh
@@ -5,13 +5,16 @@
 
 test_description='Test proc-receive hook'
 
+GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
+export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+
 . ./test-lib.sh
 
 . "$TEST_DIRECTORY"/t5411/common-functions.sh
 
 setup_upstream_and_workbench () {
-	# Refs of upstream : master(A)
-	# Refs of workbench: master(A)  tags/v123
+	# Refs of upstream : main(A)
+	# Refs of workbench: main(A)  tags/v123
 	test_expect_success "setup upstream and workbench" '
 		rm -rf upstream.git &&
 		rm -rf workbench &&
@@ -25,10 +28,10 @@
 			git config core.abbrev 7 &&
 			git tag -m "v123" v123 $A &&
 			git remote add origin ../upstream.git &&
-			git push origin master &&
-			git update-ref refs/heads/master $A $B &&
+			git push origin main &&
+			git update-ref refs/heads/main $A $B &&
 			git -C ../upstream.git update-ref \
-				refs/heads/master $A $B
+				refs/heads/main $A $B
 		) &&
 		TAG=$(git -C workbench rev-parse v123) &&
 
@@ -99,8 +102,8 @@
 # Re-initialize the upstream repository and local workbench.
 setup_upstream_and_workbench
 
-# Refs of upstream : master(A)
-# Refs of workbench: master(A)  tags/v123
+# Refs of upstream : main(A)
+# Refs of workbench: main(A)  tags/v123
 test_expect_success "setup for HTTP protocol" '
 	git -C upstream.git config http.receivepack true &&
 	upstream="$HTTPD_DOCUMENT_ROOT_PATH/upstream.git" &&
diff --git a/t/t5411/common-functions.sh b/t/t5411/common-functions.sh
index 6580beb..344d13f 100644
--- a/t/t5411/common-functions.sh
+++ b/t/t5411/common-functions.sh
@@ -28,7 +28,7 @@
 		shift ||
 		return 1
 	done &&
-	git -C "$repo" update-ref refs/heads/master $oid
+	git -C "$repo" update-ref refs/heads/main $oid
 }
 
 # Format the output of git-push, git-show-ref and other commands to make a
@@ -42,7 +42,7 @@
 make_user_friendly_and_stable_output () {
 	sed \
 		-e "s/  *\$//" \
-		-e "s/   */ /g" \
+		-e "s/  */ /g" \
 		-e "s/'/\"/g" \
 		-e "s/	/    /g" \
 		-e "s/$A/<COMMIT-A>/g" \
@@ -54,3 +54,8 @@
 		-e "s#To $URL_PREFIX/upstream.git#To <URL/of/upstream.git>#" \
 		-e "/^error: / d"
 }
+
+filter_out_user_friendly_and_stable_output () {
+	make_user_friendly_and_stable_output |
+		sed -n ${1+"$@"}
+}
diff --git a/t/t5411/once-0010-report-status-v1.sh b/t/t5411/once-0010-report-status-v1.sh
index dc2cf4a..cb431a9 100644
--- a/t/t5411/once-0010-report-status-v1.sh
+++ b/t/t5411/once-0010-report-status-v1.sh
@@ -6,12 +6,12 @@
 	write_script "$upstream/hooks/proc-receive" <<-EOF
 	printf >&2 "# proc-receive hook\n"
 	test-tool proc-receive -v \
-		-r "ok refs/for/master/topic1" \
+		-r "ok refs/for/main/topic1" \
 		-r "option fall-through" \
-		-r "ok refs/for/master/topic2" \
+		-r "ok refs/for/main/topic2" \
 		-r "option refname refs/for/changes/23/123/1" \
 		-r "option new-oid $A" \
-		-r "ok refs/for/master/topic2" \
+		-r "ok refs/for/main/topic2" \
 		-r "option refname refs/for/changes/24/124/2" \
 		-r "option old-oid $B" \
 		-r "option new-oid $A" \
@@ -20,26 +20,26 @@
 	EOF
 '
 
-# Refs of upstream : master(A)
-# Refs of workbench: master(A)  tags/v123
-# git push         : (B)                   refs/for/master/topic1(A)  foo(A)  refs/for/next/topic(A)  refs/for/master/topic2(A)
+# Refs of upstream : main(A)
+# Refs of workbench: main(A)  tags/v123
+# git push         : (B)                   refs/for/main/topic1(A)  foo(A)  refs/for/next/topic(A)  refs/for/main/topic2(A)
 test_expect_success "proc-receive: report status v1" '
 	{
 		if test -z "$GIT_DEFAULT_HASH" || test "$GIT_DEFAULT_HASH" = "sha1"
 		then
-			printf "%s %s refs/heads/master\0report-status\n" \
+			printf "%s %s refs/heads/main\0report-status\n" \
 				$A $B | packetize
 		else
-			printf "%s %s refs/heads/master\0report-status object-format=$GIT_DEFAULT_HASH\n" \
+			printf "%s %s refs/heads/main\0report-status object-format=$GIT_DEFAULT_HASH\n" \
 				$A $B | packetize
 		fi &&
-		printf "%s %s refs/for/master/topic1\n" \
+		printf "%s %s refs/for/main/topic1\n" \
 			$ZERO_OID $A | packetize &&
 		printf "%s %s refs/heads/foo\n" \
 			$ZERO_OID $A | packetize &&
 		printf "%s %s refs/for/next/topic\n" \
 			$ZERO_OID $A | packetize &&
-		printf "%s %s refs/for/master/topic2\n" \
+		printf "%s %s refs/for/main/topic2\n" \
 			$ZERO_OID $A | packetize &&
 		printf 0000 &&
 		printf "" | git -C "$upstream" pack-objects --stdout
@@ -48,35 +48,35 @@
 	make_user_friendly_and_stable_output <out >actual &&
 	cat >expect <<-EOF &&
 	# pre-receive hook
-	pre-receive< <COMMIT-A> <COMMIT-B> refs/heads/master
-	pre-receive< <ZERO-OID> <COMMIT-A> refs/for/master/topic1
+	pre-receive< <COMMIT-A> <COMMIT-B> refs/heads/main
+	pre-receive< <ZERO-OID> <COMMIT-A> refs/for/main/topic1
 	pre-receive< <ZERO-OID> <COMMIT-A> refs/heads/foo
 	pre-receive< <ZERO-OID> <COMMIT-A> refs/for/next/topic
-	pre-receive< <ZERO-OID> <COMMIT-A> refs/for/master/topic2
+	pre-receive< <ZERO-OID> <COMMIT-A> refs/for/main/topic2
 	# proc-receive hook
-	proc-receive< <ZERO-OID> <COMMIT-A> refs/for/master/topic1
+	proc-receive< <ZERO-OID> <COMMIT-A> refs/for/main/topic1
 	proc-receive< <ZERO-OID> <COMMIT-A> refs/for/next/topic
-	proc-receive< <ZERO-OID> <COMMIT-A> refs/for/master/topic2
-	proc-receive> ok refs/for/master/topic1
+	proc-receive< <ZERO-OID> <COMMIT-A> refs/for/main/topic2
+	proc-receive> ok refs/for/main/topic1
 	proc-receive> option fall-through
-	proc-receive> ok refs/for/master/topic2
+	proc-receive> ok refs/for/main/topic2
 	proc-receive> option refname refs/for/changes/23/123/1
 	proc-receive> option new-oid <COMMIT-A>
-	proc-receive> ok refs/for/master/topic2
+	proc-receive> ok refs/for/main/topic2
 	proc-receive> option refname refs/for/changes/24/124/2
 	proc-receive> option old-oid <COMMIT-B>
 	proc-receive> option new-oid <COMMIT-A>
 	proc-receive> option forced-update
 	proc-receive> ng refs/for/next/topic target branch not exist
 	000eunpack ok
-	0019ok refs/heads/master
-	001eok refs/for/master/topic1
+	0017ok refs/heads/main
+	001cok refs/for/main/topic1
 	0016ok refs/heads/foo
 	0033ng refs/for/next/topic target branch not exist
-	001eok refs/for/master/topic2
+	001cok refs/for/main/topic2
 	0000# post-receive hook
-	post-receive< <COMMIT-A> <COMMIT-B> refs/heads/master
-	post-receive< <ZERO-OID> <COMMIT-A> refs/for/master/topic1
+	post-receive< <COMMIT-A> <COMMIT-B> refs/heads/main
+	post-receive< <ZERO-OID> <COMMIT-A> refs/for/main/topic1
 	post-receive< <ZERO-OID> <COMMIT-A> refs/heads/foo
 	post-receive< <ZERO-OID> <COMMIT-A> refs/for/changes/23/123/1
 	post-receive< <COMMIT-B> <COMMIT-A> refs/for/changes/24/124/2
@@ -86,9 +86,9 @@
 	git -C "$upstream" show-ref >out &&
 	make_user_friendly_and_stable_output <out >actual &&
 	cat >expect <<-EOF &&
-	<COMMIT-A> refs/for/master/topic1
+	<COMMIT-A> refs/for/main/topic1
 	<COMMIT-A> refs/heads/foo
-	<COMMIT-B> refs/heads/master
+	<COMMIT-B> refs/heads/main
 	EOF
 	test_cmp expect actual
 '
diff --git a/t/t5411/test-0000-standard-git-push.sh b/t/t5411/test-0000-standard-git-push.sh
index e206587..47b058a 100644
--- a/t/t5411/test-0000-standard-git-push.sh
+++ b/t/t5411/test-0000-standard-git-push.sh
@@ -1,70 +1,69 @@
-# Refs of upstream : master(A)  
-# Refs of workbench: master(A)  tags/v123
-# git-push         : master(B)             next(A)
+# Refs of upstream : main(A)  
+# Refs of workbench: main(A)  tags/v123
+# git-push         : main(B)             next(A)
 test_expect_success "git-push ($PROTOCOL)" '
 	git -C workbench push origin \
-		$B:refs/heads/master \
+		$B:refs/heads/main \
 		HEAD:refs/heads/next \
 		>out 2>&1 &&
 	make_user_friendly_and_stable_output <out >actual &&
 	cat >expect <<-EOF &&
 	remote: # pre-receive hook
-	remote: pre-receive< <COMMIT-A> <COMMIT-B> refs/heads/master
+	remote: pre-receive< <COMMIT-A> <COMMIT-B> refs/heads/main
 	remote: pre-receive< <ZERO-OID> <COMMIT-A> refs/heads/next
 	remote: # post-receive hook
-	remote: post-receive< <COMMIT-A> <COMMIT-B> refs/heads/master
+	remote: post-receive< <COMMIT-A> <COMMIT-B> refs/heads/main
 	remote: post-receive< <ZERO-OID> <COMMIT-A> refs/heads/next
 	To <URL/of/upstream.git>
-	 <OID-A>..<OID-B> <COMMIT-B> -> master
+	 <OID-A>..<OID-B> <COMMIT-B> -> main
 	 * [new branch] HEAD -> next
 	EOF
 	test_cmp expect actual &&
 	git -C "$upstream" show-ref >out &&
 	make_user_friendly_and_stable_output <out >actual &&
 	cat >expect <<-EOF &&
-	<COMMIT-B> refs/heads/master
+	<COMMIT-B> refs/heads/main
 	<COMMIT-A> refs/heads/next
 	EOF
 	test_cmp expect actual
 '
 
-# Refs of upstream : master(B)  next(A)
-# Refs of workbench: master(A)           tags/v123
-# git-push --atomic: master(A)  next(B)
+# Refs of upstream : main(B)  next(A)
+# Refs of workbench: main(A)           tags/v123
+# git-push --atomic: main(A)  next(B)
 test_expect_success "git-push --atomic ($PROTOCOL)" '
 	test_must_fail git -C workbench push --atomic origin \
-		master \
+		main \
 		$B:refs/heads/next \
 		>out 2>&1 &&
-	make_user_friendly_and_stable_output <out |
-		sed -n \
-			-e "/^To / { s/   */ /g; p; }" \
-			-e "/^ ! / { s/   */ /g; p; }" \
-			>actual &&
+	filter_out_user_friendly_and_stable_output \
+		-e "/^To / { p; }" \
+		-e "/^ ! / { p; }" \
+		<out >actual &&
 	cat >expect <<-EOF &&
 	To <URL/of/upstream.git>
-	 ! [rejected] master -> master (non-fast-forward)
+	 ! [rejected] main -> main (non-fast-forward)
 	 ! [rejected] <COMMIT-B> -> next (atomic push failed)
 	EOF
 	test_cmp expect actual &&
 	git -C "$upstream" show-ref >out &&
 	make_user_friendly_and_stable_output <out >actual &&
 	cat >expect <<-EOF &&
-	<COMMIT-B> refs/heads/master
+	<COMMIT-B> refs/heads/main
 	<COMMIT-A> refs/heads/next
 	EOF
 	test_cmp expect actual
 '
 
-# Refs of upstream : master(B)  next(A)
-# Refs of workbench: master(A)           tags/v123
-# git-push         : master(A)  next(B)
+# Refs of upstream : main(B)  next(A)
+# Refs of workbench: main(A)           tags/v123
+# git-push         : main(A)  next(B)
 test_expect_success "non-fast-forward git-push ($PROTOCOL)" '
 	test_must_fail git \
 		-C workbench \
 		-c advice.pushUpdateRejected=false \
 		push origin \
-		master \
+		main \
 		$B:refs/heads/next \
 		>out 2>&1 &&
 	make_user_friendly_and_stable_output <out >actual &&
@@ -75,48 +74,48 @@
 	remote: post-receive< <COMMIT-A> <COMMIT-B> refs/heads/next
 	To <URL/of/upstream.git>
 	 <OID-A>..<OID-B> <COMMIT-B> -> next
-	 ! [rejected] master -> master (non-fast-forward)
+	 ! [rejected] main -> main (non-fast-forward)
 	EOF
 	test_cmp expect actual &&
 	git -C "$upstream" show-ref >out &&
 	make_user_friendly_and_stable_output <out >actual &&
 	cat >expect <<-EOF &&
-	<COMMIT-B> refs/heads/master
+	<COMMIT-B> refs/heads/main
 	<COMMIT-B> refs/heads/next
 	EOF
 	test_cmp expect actual
 '
 
-# Refs of upstream : master(B)  next(B)
-# Refs of workbench: master(A)           tags/v123
-# git-push -f      : master(A)  NULL     tags/v123  refs/review/master/topic(A)  a/b/c(A)
+# Refs of upstream : main(B)  next(B)
+# Refs of workbench: main(A)           tags/v123
+# git-push -f      : main(A)  NULL     tags/v123  refs/review/main/topic(A)  a/b/c(A)
 test_expect_success "git-push -f ($PROTOCOL)" '
 	git -C workbench push -f origin \
 		refs/tags/v123 \
 		:refs/heads/next \
-		master \
-		master:refs/review/master/topic \
+		main \
+		main:refs/review/main/topic \
 		HEAD:refs/heads/a/b/c \
 		>out 2>&1 &&
 	make_user_friendly_and_stable_output <out >actual &&
 	cat >expect <<-EOF &&
 	remote: # pre-receive hook
-	remote: pre-receive< <COMMIT-B> <COMMIT-A> refs/heads/master
+	remote: pre-receive< <COMMIT-B> <COMMIT-A> refs/heads/main
 	remote: pre-receive< <COMMIT-B> <ZERO-OID> refs/heads/next
 	remote: pre-receive< <ZERO-OID> <TAG-v123> refs/tags/v123
-	remote: pre-receive< <ZERO-OID> <COMMIT-A> refs/review/master/topic
+	remote: pre-receive< <ZERO-OID> <COMMIT-A> refs/review/main/topic
 	remote: pre-receive< <ZERO-OID> <COMMIT-A> refs/heads/a/b/c
 	remote: # post-receive hook
-	remote: post-receive< <COMMIT-B> <COMMIT-A> refs/heads/master
+	remote: post-receive< <COMMIT-B> <COMMIT-A> refs/heads/main
 	remote: post-receive< <COMMIT-B> <ZERO-OID> refs/heads/next
 	remote: post-receive< <ZERO-OID> <TAG-v123> refs/tags/v123
-	remote: post-receive< <ZERO-OID> <COMMIT-A> refs/review/master/topic
+	remote: post-receive< <ZERO-OID> <COMMIT-A> refs/review/main/topic
 	remote: post-receive< <ZERO-OID> <COMMIT-A> refs/heads/a/b/c
 	To <URL/of/upstream.git>
-	 + <OID-B>...<OID-A> master -> master (forced update)
+	 + <OID-B>...<OID-A> main -> main (forced update)
 	 - [deleted] next
 	 * [new tag] v123 -> v123
-	 * [new reference] master -> refs/review/master/topic
+	 * [new reference] main -> refs/review/main/topic
 	 * [new branch] HEAD -> a/b/c
 	EOF
 	test_cmp expect actual &&
@@ -124,19 +123,19 @@
 	make_user_friendly_and_stable_output <out >actual &&
 	cat >expect <<-EOF &&
 	<COMMIT-A> refs/heads/a/b/c
-	<COMMIT-A> refs/heads/master
-	<COMMIT-A> refs/review/master/topic
+	<COMMIT-A> refs/heads/main
+	<COMMIT-A> refs/review/main/topic
 	<TAG-v123> refs/tags/v123
 	EOF
 	test_cmp expect actual
 '
 
-# Refs of upstream : master(A)  tags/v123  refs/review/master/topic(A)  a/b/c(A)
-# Refs of workbench: master(A)  tags/v123
+# Refs of upstream : main(A)  tags/v123  refs/review/main/topic(A)  a/b/c(A)
+# Refs of workbench: main(A)  tags/v123
 test_expect_success "cleanup ($PROTOCOL)" '
 	(
 		cd "$upstream" &&
-		git update-ref -d refs/review/master/topic &&
+		git update-ref -d refs/review/main/topic &&
 		git update-ref -d refs/tags/v123 &&
 		git update-ref -d refs/heads/a/b/c
 	)
diff --git a/t/t5411/test-0001-standard-git-push--porcelain.sh b/t/t5411/test-0001-standard-git-push--porcelain.sh
index 48f6fcc..bbead12 100644
--- a/t/t5411/test-0001-standard-git-push--porcelain.sh
+++ b/t/t5411/test-0001-standard-git-push--porcelain.sh
@@ -1,21 +1,21 @@
-# Refs of upstream : master(A)  
-# Refs of workbench: master(A)  tags/v123
-# git-push         : master(B)             next(A)
+# Refs of upstream : main(A)  
+# Refs of workbench: main(A)  tags/v123
+# git-push         : main(B)             next(A)
 test_expect_success "git-push ($PROTOCOL/porcelain)" '
 	git -C workbench push --porcelain origin \
-		$B:refs/heads/master \
+		$B:refs/heads/main \
 		HEAD:refs/heads/next \
 		>out 2>&1 &&
 	make_user_friendly_and_stable_output <out >actual &&
 	cat >expect <<-EOF &&
 	remote: # pre-receive hook
-	remote: pre-receive< <COMMIT-A> <COMMIT-B> refs/heads/master
+	remote: pre-receive< <COMMIT-A> <COMMIT-B> refs/heads/main
 	remote: pre-receive< <ZERO-OID> <COMMIT-A> refs/heads/next
 	remote: # post-receive hook
-	remote: post-receive< <COMMIT-A> <COMMIT-B> refs/heads/master
+	remote: post-receive< <COMMIT-A> <COMMIT-B> refs/heads/main
 	remote: post-receive< <ZERO-OID> <COMMIT-A> refs/heads/next
 	To <URL/of/upstream.git>
-	     <COMMIT-B>:refs/heads/master    <OID-A>..<OID-B>
+	     <COMMIT-B>:refs/heads/main    <OID-A>..<OID-B>
 	*    HEAD:refs/heads/next    [new branch]
 	Done
 	EOF
@@ -23,50 +23,49 @@
 	git -C "$upstream" show-ref >out &&
 	make_user_friendly_and_stable_output <out >actual &&
 	cat >expect <<-EOF &&
-	<COMMIT-B> refs/heads/master
+	<COMMIT-B> refs/heads/main
 	<COMMIT-A> refs/heads/next
 	EOF
 	test_cmp expect actual
 '
 
-# Refs of upstream : master(B)  next(A)
-# Refs of workbench: master(A)           tags/v123
-# git-push --atomic: master(A)  next(B)
+# Refs of upstream : main(B)  next(A)
+# Refs of workbench: main(A)           tags/v123
+# git-push --atomic: main(A)  next(B)
 test_expect_success "git-push --atomic ($PROTOCOL/porcelain)" '
 	test_must_fail git -C workbench push --atomic --porcelain origin \
-		master \
+		main \
 		$B:refs/heads/next \
 		>out 2>&1 &&
-	make_user_friendly_and_stable_output <out |
-		sed -n \
-			-e "s/^# GETTEXT POISON #//" \
-			-e "/^To / { s/   */ /g; p; }" \
-			-e "/^! / { s/   */ /g; p; }" \
-			>actual &&
+	filter_out_user_friendly_and_stable_output \
+		-e "s/^# GETTEXT POISON #//" \
+		-e "/^To / { p; }" \
+		-e "/^! / { p; }" \
+		<out >actual &&
 	cat >expect <<-EOF &&
 	To <URL/of/upstream.git>
-	! refs/heads/master:refs/heads/master [rejected] (non-fast-forward)
-	! <COMMIT-B>:refs/heads/next [rejected] (atomic push failed)
+	!    refs/heads/main:refs/heads/main    [rejected] (non-fast-forward)
+	!    <COMMIT-B>:refs/heads/next    [rejected] (atomic push failed)
 	EOF
 	test_cmp expect actual &&
 	git -C "$upstream" show-ref >out &&
 	make_user_friendly_and_stable_output <out >actual &&
 	cat >expect <<-EOF &&
-	<COMMIT-B> refs/heads/master
+	<COMMIT-B> refs/heads/main
 	<COMMIT-A> refs/heads/next
 	EOF
 	test_cmp expect actual
 '
 
-# Refs of upstream : master(B)  next(A)
-# Refs of workbench: master(A)           tags/v123
-# git-push         : master(A)  next(B)
+# Refs of upstream : main(B)  next(A)
+# Refs of workbench: main(A)           tags/v123
+# git-push         : main(A)  next(B)
 test_expect_success "non-fast-forward git-push ($PROTOCOL/porcelain)" '
 	test_must_fail git \
 		-C workbench \
 		-c advice.pushUpdateRejected=false \
 		push --porcelain origin \
-		master \
+		main \
 		$B:refs/heads/next \
 		>out 2>&1 &&
 	make_user_friendly_and_stable_output <out >actual &&
@@ -77,49 +76,49 @@
 	remote: post-receive< <COMMIT-A> <COMMIT-B> refs/heads/next
 	To <URL/of/upstream.git>
 	     <COMMIT-B>:refs/heads/next    <OID-A>..<OID-B>
-	!    refs/heads/master:refs/heads/master    [rejected] (non-fast-forward)
+	!    refs/heads/main:refs/heads/main    [rejected] (non-fast-forward)
 	Done
 	EOF
 	test_cmp expect actual &&
 	git -C "$upstream" show-ref >out &&
 	make_user_friendly_and_stable_output <out >actual &&
 	cat >expect <<-EOF &&
-	<COMMIT-B> refs/heads/master
+	<COMMIT-B> refs/heads/main
 	<COMMIT-B> refs/heads/next
 	EOF
 	test_cmp expect actual
 '
 
-# Refs of upstream : master(B)  next(B)
-# Refs of workbench: master(A)           tags/v123
-# git-push -f      : master(A)  NULL     tags/v123  refs/review/master/topic(A)  a/b/c(A)
+# Refs of upstream : main(B)  next(B)
+# Refs of workbench: main(A)           tags/v123
+# git-push -f      : main(A)  NULL     tags/v123  refs/review/main/topic(A)  a/b/c(A)
 test_expect_success "git-push -f ($PROTOCOL/porcelain)" '
 	git -C workbench push --porcelain -f origin \
 		refs/tags/v123 \
 		:refs/heads/next \
-		master \
-		master:refs/review/master/topic \
+		main \
+		main:refs/review/main/topic \
 		HEAD:refs/heads/a/b/c \
 		>out 2>&1 &&
 	make_user_friendly_and_stable_output <out >actual &&
 	cat >expect <<-EOF &&
 	remote: # pre-receive hook
-	remote: pre-receive< <COMMIT-B> <COMMIT-A> refs/heads/master
+	remote: pre-receive< <COMMIT-B> <COMMIT-A> refs/heads/main
 	remote: pre-receive< <COMMIT-B> <ZERO-OID> refs/heads/next
 	remote: pre-receive< <ZERO-OID> <TAG-v123> refs/tags/v123
-	remote: pre-receive< <ZERO-OID> <COMMIT-A> refs/review/master/topic
+	remote: pre-receive< <ZERO-OID> <COMMIT-A> refs/review/main/topic
 	remote: pre-receive< <ZERO-OID> <COMMIT-A> refs/heads/a/b/c
 	remote: # post-receive hook
-	remote: post-receive< <COMMIT-B> <COMMIT-A> refs/heads/master
+	remote: post-receive< <COMMIT-B> <COMMIT-A> refs/heads/main
 	remote: post-receive< <COMMIT-B> <ZERO-OID> refs/heads/next
 	remote: post-receive< <ZERO-OID> <TAG-v123> refs/tags/v123
-	remote: post-receive< <ZERO-OID> <COMMIT-A> refs/review/master/topic
+	remote: post-receive< <ZERO-OID> <COMMIT-A> refs/review/main/topic
 	remote: post-receive< <ZERO-OID> <COMMIT-A> refs/heads/a/b/c
 	To <URL/of/upstream.git>
-	+    refs/heads/master:refs/heads/master    <OID-B>...<OID-A> (forced update)
+	+    refs/heads/main:refs/heads/main    <OID-B>...<OID-A> (forced update)
 	-    :refs/heads/next    [deleted]
 	*    refs/tags/v123:refs/tags/v123    [new tag]
-	*    refs/heads/master:refs/review/master/topic    [new reference]
+	*    refs/heads/main:refs/review/main/topic    [new reference]
 	*    HEAD:refs/heads/a/b/c    [new branch]
 	Done
 	EOF
@@ -128,19 +127,19 @@
 	make_user_friendly_and_stable_output <out >actual &&
 	cat >expect <<-EOF &&
 	<COMMIT-A> refs/heads/a/b/c
-	<COMMIT-A> refs/heads/master
-	<COMMIT-A> refs/review/master/topic
+	<COMMIT-A> refs/heads/main
+	<COMMIT-A> refs/review/main/topic
 	<TAG-v123> refs/tags/v123
 	EOF
 	test_cmp expect actual
 '
 
-# Refs of upstream : master(A)  tags/v123  refs/review/master/topic(A)  a/b/c(A)
-# Refs of workbench: master(A)  tags/v123
+# Refs of upstream : main(A)  tags/v123  refs/review/main/topic(A)  a/b/c(A)
+# Refs of workbench: main(A)  tags/v123
 test_expect_success "cleanup ($PROTOCOL/porcelain)" '
 	(
 		cd "$upstream" &&
-		git update-ref -d refs/review/master/topic &&
+		git update-ref -d refs/review/main/topic &&
 		git update-ref -d refs/tags/v123 &&
 		git update-ref -d refs/heads/a/b/c
 	)
diff --git a/t/t5411/test-0002-pre-receive-declined.sh b/t/t5411/test-0002-pre-receive-declined.sh
index c246f7e..e7d113a 100644
--- a/t/t5411/test-0002-pre-receive-declined.sh
+++ b/t/t5411/test-0002-pre-receive-declined.sh
@@ -5,25 +5,25 @@
 	EOF
 '
 
-# Refs of upstream : master(A)
-# Refs of workbench: master(A)  tags/v123
-# git-push         : master(B)             next(A)
+# Refs of upstream : main(A)
+# Refs of workbench: main(A)  tags/v123
+# git-push         : main(B)             next(A)
 test_expect_success "git-push is declined ($PROTOCOL)" '
 	test_must_fail git -C workbench push origin \
-		$B:refs/heads/master \
+		$B:refs/heads/main \
 		HEAD:refs/heads/next \
 		>out 2>&1 &&
 	make_user_friendly_and_stable_output <out >actual &&
 	cat >expect <<-EOF &&
 	To <URL/of/upstream.git>
-	 ! [remote rejected] <COMMIT-B> -> master (pre-receive hook declined)
+	 ! [remote rejected] <COMMIT-B> -> main (pre-receive hook declined)
 	 ! [remote rejected] HEAD -> next (pre-receive hook declined)
 	EOF
 	test_cmp expect actual &&
 	git -C "$upstream" show-ref >out &&
 	make_user_friendly_and_stable_output <out >actual &&
 	cat >expect <<-EOF &&
-	<COMMIT-A> refs/heads/master
+	<COMMIT-A> refs/heads/main
 	EOF
 	test_cmp expect actual
 '
diff --git a/t/t5411/test-0003-pre-receive-declined--porcelain.sh b/t/t5411/test-0003-pre-receive-declined--porcelain.sh
index b14894d..cc0cca6 100644
--- a/t/t5411/test-0003-pre-receive-declined--porcelain.sh
+++ b/t/t5411/test-0003-pre-receive-declined--porcelain.sh
@@ -5,18 +5,18 @@
 	EOF
 '
 
-# Refs of upstream : master(A)
-# Refs of workbench: master(A)  tags/v123
-# git-push         : master(B)             next(A)
+# Refs of upstream : main(A)
+# Refs of workbench: main(A)  tags/v123
+# git-push         : main(B)             next(A)
 test_expect_success "git-push is declined ($PROTOCOL/porcelain)" '
 	test_must_fail git -C workbench push --porcelain origin \
-		$B:refs/heads/master \
+		$B:refs/heads/main \
 		HEAD:refs/heads/next \
 		>out 2>&1 &&
 	make_user_friendly_and_stable_output <out >actual &&
 	cat >expect <<-EOF &&
 	To <URL/of/upstream.git>
-	!    <COMMIT-B>:refs/heads/master    [remote rejected] (pre-receive hook declined)
+	!    <COMMIT-B>:refs/heads/main    [remote rejected] (pre-receive hook declined)
 	!    HEAD:refs/heads/next    [remote rejected] (pre-receive hook declined)
 	Done
 	EOF
@@ -24,7 +24,7 @@
 	git -C "$upstream" show-ref >out &&
 	make_user_friendly_and_stable_output <out >actual &&
 	cat >expect <<-EOF &&
-	<COMMIT-A> refs/heads/master
+	<COMMIT-A> refs/heads/main
 	EOF
 	test_cmp expect actual
 '
diff --git a/t/t5411/test-0011-no-hook-error.sh b/t/t5411/test-0011-no-hook-error.sh
index bb6ec92..c508309 100644
--- a/t/t5411/test-0011-no-hook-error.sh
+++ b/t/t5411/test-0011-no-hook-error.sh
@@ -1,64 +1,64 @@
-# Refs of upstream : master(A)
-# Refs of workbench: master(A)  tags/v123
-# git push         :                       next(A)  refs/for/master/topic(A)
+# Refs of upstream : main(A)
+# Refs of workbench: main(A)  tags/v123
+# git push         :                       next(A)  refs/for/main/topic(A)
 test_expect_success "proc-receive: no hook, fail to push special ref ($PROTOCOL)" '
 	test_must_fail git -C workbench push origin \
 		HEAD:next \
-		HEAD:refs/for/master/topic \
+		HEAD:refs/for/main/topic \
 		>out 2>&1 &&
 	make_user_friendly_and_stable_output <out >actual &&
 	cat >expect <<-EOF &&
 	remote: # pre-receive hook
 	remote: pre-receive< <ZERO-OID> <COMMIT-A> refs/heads/next
-	remote: pre-receive< <ZERO-OID> <COMMIT-A> refs/for/master/topic
+	remote: pre-receive< <ZERO-OID> <COMMIT-A> refs/for/main/topic
 	remote: error: cannot find hook "proc-receive"
 	remote: # post-receive hook
 	remote: post-receive< <ZERO-OID> <COMMIT-A> refs/heads/next
 	To <URL/of/upstream.git>
 	 * [new branch] HEAD -> next
-	 ! [remote rejected] HEAD -> refs/for/master/topic (fail to run proc-receive hook)
+	 ! [remote rejected] HEAD -> refs/for/main/topic (fail to run proc-receive hook)
 	EOF
 	test_cmp expect actual &&
 	git -C "$upstream" show-ref >out &&
 	make_user_friendly_and_stable_output <out >actual &&
 	cat >expect <<-EOF &&
-	<COMMIT-A> refs/heads/master
+	<COMMIT-A> refs/heads/main
 	<COMMIT-A> refs/heads/next
 	EOF
 	test_cmp expect actual
 '
 
-# Refs of upstream : master(A)             next(A)
-# Refs of workbench: master(A)  tags/v123
+# Refs of upstream : main(A)             next(A)
+# Refs of workbench: main(A)  tags/v123
 test_expect_success "cleanup ($PROTOCOL)" '
 	git -C "$upstream" update-ref -d refs/heads/next
 '
 
-# Refs of upstream : master(A)
-# Refs of workbench: master(A)  tags/v123
-# git push --atomic: (B)                   next(A)  refs/for/master/topic(A)
+# Refs of upstream : main(A)
+# Refs of workbench: main(A)  tags/v123
+# git push --atomic: (B)                   next(A)  refs/for/main/topic(A)
 test_expect_success "proc-receive: no hook, all failed for atomic push ($PROTOCOL)" '
 	test_must_fail git -C workbench push --atomic origin \
-		$B:master \
+		$B:main \
 		HEAD:next \
-		HEAD:refs/for/master/topic >out 2>&1 &&
+		HEAD:refs/for/main/topic >out 2>&1 &&
 	make_user_friendly_and_stable_output <out >actual &&
 	cat >expect <<-EOF &&
 	remote: # pre-receive hook
-	remote: pre-receive< <COMMIT-A> <COMMIT-B> refs/heads/master
+	remote: pre-receive< <COMMIT-A> <COMMIT-B> refs/heads/main
 	remote: pre-receive< <ZERO-OID> <COMMIT-A> refs/heads/next
-	remote: pre-receive< <ZERO-OID> <COMMIT-A> refs/for/master/topic
+	remote: pre-receive< <ZERO-OID> <COMMIT-A> refs/for/main/topic
 	remote: error: cannot find hook "proc-receive"
 	To <URL/of/upstream.git>
-	 ! [remote rejected] <COMMIT-B> -> master (fail to run proc-receive hook)
+	 ! [remote rejected] <COMMIT-B> -> main (fail to run proc-receive hook)
 	 ! [remote rejected] HEAD -> next (fail to run proc-receive hook)
-	 ! [remote rejected] HEAD -> refs/for/master/topic (fail to run proc-receive hook)
+	 ! [remote rejected] HEAD -> refs/for/main/topic (fail to run proc-receive hook)
 	EOF
 	test_cmp expect actual &&
 	git -C "$upstream" show-ref >out &&
 	make_user_friendly_and_stable_output <out >actual &&
 	cat >expect <<-EOF &&
-	<COMMIT-A> refs/heads/master
+	<COMMIT-A> refs/heads/main
 	EOF
 	test_cmp expect actual
 '
diff --git a/t/t5411/test-0012-no-hook-error--porcelain.sh b/t/t5411/test-0012-no-hook-error--porcelain.sh
index 4814f74..14ea433 100644
--- a/t/t5411/test-0012-no-hook-error--porcelain.sh
+++ b/t/t5411/test-0012-no-hook-error--porcelain.sh
@@ -1,66 +1,66 @@
-# Refs of upstream : master(A)
-# Refs of workbench: master(A)  tags/v123
-# git push         :                       next(A)  refs/for/master/topic(A)
+# Refs of upstream : main(A)
+# Refs of workbench: main(A)  tags/v123
+# git push         :                       next(A)  refs/for/main/topic(A)
 test_expect_success "proc-receive: no hook, fail to push special ref ($PROTOCOL/porcelain)" '
 	test_must_fail git -C workbench push --porcelain origin \
 		HEAD:next \
-		HEAD:refs/for/master/topic \
+		HEAD:refs/for/main/topic \
 		>out 2>&1 &&
 	make_user_friendly_and_stable_output <out >actual &&
 	cat >expect <<-EOF &&
 	remote: # pre-receive hook
 	remote: pre-receive< <ZERO-OID> <COMMIT-A> refs/heads/next
-	remote: pre-receive< <ZERO-OID> <COMMIT-A> refs/for/master/topic
+	remote: pre-receive< <ZERO-OID> <COMMIT-A> refs/for/main/topic
 	remote: error: cannot find hook "proc-receive"
 	remote: # post-receive hook
 	remote: post-receive< <ZERO-OID> <COMMIT-A> refs/heads/next
 	To <URL/of/upstream.git>
 	*    HEAD:refs/heads/next    [new branch]
-	!    HEAD:refs/for/master/topic    [remote rejected] (fail to run proc-receive hook)
+	!    HEAD:refs/for/main/topic    [remote rejected] (fail to run proc-receive hook)
 	Done
 	EOF
 	test_cmp expect actual &&
 	git -C "$upstream" show-ref >out &&
 	make_user_friendly_and_stable_output <out >actual &&
 	cat >expect <<-EOF &&
-	<COMMIT-A> refs/heads/master
+	<COMMIT-A> refs/heads/main
 	<COMMIT-A> refs/heads/next
 	EOF
 	test_cmp expect actual
 '
 
-# Refs of upstream : master(A)             next(A)
-# Refs of workbench: master(A)  tags/v123
+# Refs of upstream : main(A)             next(A)
+# Refs of workbench: main(A)  tags/v123
 test_expect_success "cleanup ($PROTOCOL/porcelain)" '
 	git -C "$upstream" update-ref -d refs/heads/next
 '
 
-# Refs of upstream : master(A)
-# Refs of workbench: master(A)  tags/v123
-# git push --atomic: (B)                   next(A)  refs/for/master/topic(A)
+# Refs of upstream : main(A)
+# Refs of workbench: main(A)  tags/v123
+# git push --atomic: (B)                   next(A)  refs/for/main/topic(A)
 test_expect_success "proc-receive: no hook, all failed for atomic push ($PROTOCOL/porcelain)" '
 	test_must_fail git -C workbench push --porcelain --atomic origin \
-		$B:master \
+		$B:main \
 		HEAD:next \
-		HEAD:refs/for/master/topic >out 2>&1 &&
+		HEAD:refs/for/main/topic >out 2>&1 &&
 	make_user_friendly_and_stable_output <out >actual &&
 	cat >expect <<-EOF &&
 	remote: # pre-receive hook
-	remote: pre-receive< <COMMIT-A> <COMMIT-B> refs/heads/master
+	remote: pre-receive< <COMMIT-A> <COMMIT-B> refs/heads/main
 	remote: pre-receive< <ZERO-OID> <COMMIT-A> refs/heads/next
-	remote: pre-receive< <ZERO-OID> <COMMIT-A> refs/for/master/topic
+	remote: pre-receive< <ZERO-OID> <COMMIT-A> refs/for/main/topic
 	remote: error: cannot find hook "proc-receive"
 	To <URL/of/upstream.git>
-	!    <COMMIT-B>:refs/heads/master    [remote rejected] (fail to run proc-receive hook)
+	!    <COMMIT-B>:refs/heads/main    [remote rejected] (fail to run proc-receive hook)
 	!    HEAD:refs/heads/next    [remote rejected] (fail to run proc-receive hook)
-	!    HEAD:refs/for/master/topic    [remote rejected] (fail to run proc-receive hook)
+	!    HEAD:refs/for/main/topic    [remote rejected] (fail to run proc-receive hook)
 	Done
 	EOF
 	test_cmp expect actual &&
 	git -C "$upstream" show-ref >out &&
 	make_user_friendly_and_stable_output <out >actual &&
 	cat >expect <<-EOF &&
-	<COMMIT-A> refs/heads/master
+	<COMMIT-A> refs/heads/main
 	EOF
 	test_cmp expect actual
 '
diff --git a/t/t5411/test-0013-bad-protocol.sh b/t/t5411/test-0013-bad-protocol.sh
index c5fe4cb..b9be12b 100644
--- a/t/t5411/test-0013-bad-protocol.sh
+++ b/t/t5411/test-0013-bad-protocol.sh
@@ -5,22 +5,23 @@
 	EOF
 '
 
-# Refs of upstream : master(A)
-# Refs of workbench: master(A)  tags/v123
-# git push         :                       refs/for/master/topic(A)
+# Refs of upstream : main(A)
+# Refs of workbench: main(A)  tags/v123
+# git push         :                       refs/for/main/topic(A)
 test_expect_success "proc-receive: bad protocol (unknown version, $PROTOCOL)" '
 	test_must_fail git -C workbench push origin \
-		HEAD:refs/for/master/topic \
+		HEAD:refs/for/main/topic \
 		>out 2>&1 &&
 	make_user_friendly_and_stable_output <out >actual &&
 
 	# Check status report for git-push
 	sed -n \
-		-e "/^To / { p; n; p; }" \
+		-e "/^To / { p; }" \
+		-e "/^ ! / { p; }" \
 		<actual >actual-report &&
 	cat >expect <<-EOF &&
 	To <URL/of/upstream.git>
-	 ! [remote rejected] HEAD -> refs/for/master/topic (fail to run proc-receive hook)
+	 ! [remote rejected] HEAD -> refs/for/main/topic (fail to run proc-receive hook)
 	EOF
 	test_cmp expect actual-report &&
 
@@ -36,68 +37,176 @@
 	git -C "$upstream" show-ref >out &&
 	make_user_friendly_and_stable_output <out >actual &&
 	cat >expect <<-EOF &&
-	<COMMIT-A> refs/heads/master
+	<COMMIT-A> refs/heads/main
 	EOF
 	test_cmp expect actual
 '
 
-test_expect_success "setup proc-receive hook (hook --die-version, $PROTOCOL)" '
+test_expect_success "setup proc-receive hook (hook --die-read-version, $PROTOCOL)" '
 	write_script "$upstream/hooks/proc-receive" <<-EOF
 	printf >&2 "# proc-receive hook\n"
-	test-tool proc-receive -v --die-version
+	test-tool proc-receive -v --die-read-version
 	EOF
 '
 
-# Refs of upstream : master(A)
-# Refs of workbench: master(A)  tags/v123
-# git push         :                       refs/for/master/topic(A)
-test_expect_success "proc-receive: bad protocol (hook --die-version, $PROTOCOL)" '
+# Refs of upstream : main(A)
+# Refs of workbench: main(A)  tags/v123
+# git push         :                       refs/for/main/topic(A)
+test_expect_success "proc-receive: bad protocol (hook --die-read-version, $PROTOCOL)" '
 	test_must_fail git -C workbench push origin \
-		HEAD:refs/for/master/topic \
+		HEAD:refs/for/main/topic \
 		>out 2>&1 &&
-	make_user_friendly_and_stable_output <out >actual &&
-
+	filter_out_user_friendly_and_stable_output \
+		-e "/^To / { p; }" \
+		-e "/^ ! / { p; }" \
+		<out >actual &&
 	cat >expect <<-EOF &&
-	remote: # pre-receive hook
-	remote: pre-receive< <ZERO-OID> <COMMIT-A> refs/for/master/topic
-	remote: # proc-receive hook
-	remote: fatal: bad protocol version: 1
-	remote: error: proc-receive version "0" is not supported
 	To <URL/of/upstream.git>
-	 ! [remote rejected] HEAD -> refs/for/master/topic (fail to run proc-receive hook)
+	 ! [remote rejected] HEAD -> refs/for/main/topic (fail to run proc-receive hook)
 	EOF
 	test_cmp expect actual &&
+	grep "remote: fatal: die with the --die-read-version option" out &&
+	grep "remote: error: fail to negotiate version with proc-receive hook" out &&
 
 	git -C "$upstream" show-ref >out &&
 	make_user_friendly_and_stable_output <out >actual &&
 	cat >expect <<-EOF &&
-	<COMMIT-A> refs/heads/master
+	<COMMIT-A> refs/heads/main
 	EOF
 	test_cmp expect actual
 '
 
-test_expect_success "setup proc-receive hook (hook --die-readline, $PROTOCOL)" '
+test_expect_success "setup proc-receive hook (hook --die-write-version, $PROTOCOL)" '
 	write_script "$upstream/hooks/proc-receive" <<-EOF
 	printf >&2 "# proc-receive hook\n"
-	test-tool proc-receive -v --die-readline
+	test-tool proc-receive -v --die-write-version
 	EOF
 '
 
-# Refs of upstream : master(A)
-# Refs of workbench: master(A)  tags/v123
-# git push         :                       refs/for/master/topic(A)
-test_expect_success "proc-receive: bad protocol (hook --die-readline, $PROTOCOL)" '
+# Refs of upstream : main(A)
+# Refs of workbench: main(A)  tags/v123
+# git push         :                       refs/for/main/topic(A)
+test_expect_success "proc-receive: bad protocol (hook --die-write-version, $PROTOCOL)" '
 	test_must_fail git -C workbench push origin \
-		HEAD:refs/for/master/topic \
+		HEAD:refs/for/main/topic \
 		>out 2>&1 &&
-	make_user_friendly_and_stable_output <out >actual &&
-
-	grep "remote: fatal: protocol error: expected \"old new ref\", got \"<ZERO-OID> <COMMIT-A> refs/for/master/topic\"" actual &&
+	filter_out_user_friendly_and_stable_output \
+		-e "/^To / { p; }" \
+		-e "/^ ! / { p; }" \
+		<out >actual &&
+	cat >expect <<-EOF &&
+	To <URL/of/upstream.git>
+	 ! [remote rejected] HEAD -> refs/for/main/topic (fail to run proc-receive hook)
+	EOF
+	test_cmp expect actual &&
+	grep "remote: fatal: die with the --die-write-version option" out &&
+	grep "remote: error: fail to negotiate version with proc-receive hook" out &&
 
 	git -C "$upstream" show-ref >out &&
 	make_user_friendly_and_stable_output <out >actual &&
 	cat >expect <<-EOF &&
-	<COMMIT-A> refs/heads/master
+	<COMMIT-A> refs/heads/main
+	EOF
+	test_cmp expect actual
+'
+
+test_expect_success "setup proc-receive hook (hook --die-read-commands, $PROTOCOL)" '
+	write_script "$upstream/hooks/proc-receive" <<-EOF
+	printf >&2 "# proc-receive hook\n"
+	test-tool proc-receive -v --die-read-commands
+	EOF
+'
+
+# Refs of upstream : main(A)
+# Refs of workbench: main(A)  tags/v123
+# git push         :                       refs/for/main/topic(A)
+test_expect_success "proc-receive: bad protocol (hook --die-read-commands, $PROTOCOL)" '
+	test_must_fail git -C workbench push origin \
+		HEAD:refs/for/main/topic \
+		>out 2>&1 &&
+	filter_out_user_friendly_and_stable_output \
+		-e "/^To / { p; }" \
+		-e "/^ ! / { p; }" \
+		<out >actual &&
+	cat >expect <<-EOF &&
+	To <URL/of/upstream.git>
+	 ! [remote rejected] HEAD -> refs/for/main/topic (fail to run proc-receive hook)
+	EOF
+	test_cmp expect actual &&
+	grep "remote: fatal: die with the --die-read-commands option" out &&
+
+	git -C "$upstream" show-ref >out &&
+	make_user_friendly_and_stable_output <out >actual &&
+	cat >expect <<-EOF &&
+	<COMMIT-A> refs/heads/main
+	EOF
+	test_cmp expect actual
+'
+
+test_expect_success "setup proc-receive hook (hook --die-read-push-options, $PROTOCOL)" '
+	write_script "$upstream/hooks/proc-receive" <<-EOF
+	printf >&2 "# proc-receive hook\n"
+	test-tool proc-receive -v --die-read-push-options
+	EOF
+'
+
+# Refs of upstream : main(A)
+# Refs of workbench: main(A)  tags/v123
+# git push         :                       refs/for/main/topic(A)
+test_expect_success "proc-receive: bad protocol (hook --die-read-push-options, $PROTOCOL)" '
+	git -C "$upstream" config receive.advertisePushOptions true &&
+	test_must_fail git -C workbench push origin \
+		-o reviewers=user1,user2 \
+		HEAD:refs/for/main/topic \
+		>out 2>&1 &&
+	filter_out_user_friendly_and_stable_output \
+		-e "/^To / { p; }" \
+		-e "/^ ! / { p; }" \
+		<out >actual &&
+	cat >expect <<-EOF &&
+	To <URL/of/upstream.git>
+	 ! [remote rejected] HEAD -> refs/for/main/topic (fail to run proc-receive hook)
+	EOF
+	test_cmp expect actual &&
+	grep "remote: fatal: die with the --die-read-push-options option" out &&
+
+	git -C "$upstream" show-ref >out &&
+	make_user_friendly_and_stable_output <out >actual &&
+	cat >expect <<-EOF &&
+	<COMMIT-A> refs/heads/main
+	EOF
+	test_cmp expect actual
+'
+
+test_expect_success "setup proc-receive hook (hook --die-write-report, $PROTOCOL)" '
+	write_script "$upstream/hooks/proc-receive" <<-EOF
+	printf >&2 "# proc-receive hook\n"
+	test-tool proc-receive -v --die-write-report
+	EOF
+'
+
+# Refs of upstream : main(A)
+# Refs of workbench: main(A)  tags/v123
+# git push         :                       refs/for/main/topic(A)
+test_expect_success "proc-receive: bad protocol (hook --die-write-report, $PROTOCOL)" '
+	test_must_fail git -C workbench push origin \
+		HEAD:refs/for/main/topic \
+		>out 2>&1 &&
+	filter_out_user_friendly_and_stable_output \
+		-e "/^To / { p; }" \
+		-e "/^ ! / { p; }" \
+		<out >actual &&
+	cat >expect <<-EOF &&
+	To <URL/of/upstream.git>
+	 ! [remote rejected] HEAD -> refs/for/main/topic (fail to run proc-receive hook)
+	EOF
+	test_cmp expect actual &&
+	grep "remote: fatal: die with the --die-write-report option" out &&
+
+	git -C "$upstream" show-ref >out &&
+	make_user_friendly_and_stable_output <out >actual &&
+	cat >expect <<-EOF &&
+	<COMMIT-A> refs/heads/main
 	EOF
 	test_cmp expect actual
 '
@@ -109,38 +218,39 @@
 	EOF
 '
 
-# Refs of upstream : master(A)
-# Refs of workbench: master(A)  tags/v123
-# git push         :                       next(A)  refs/for/master/topic(A)
+# Refs of upstream : main(A)
+# Refs of workbench: main(A)  tags/v123
+# git push         :                       next(A)  refs/for/main/topic(A)
 test_expect_success "proc-receive: bad protocol (no report, $PROTOCOL)" '
 	test_must_fail git -C workbench push origin \
 		HEAD:refs/heads/next \
-		HEAD:refs/for/master/topic >out 2>&1 &&
+		HEAD:refs/for/main/topic >out 2>&1 &&
 	make_user_friendly_and_stable_output <out >actual &&
 	cat >expect <<-EOF &&
 	remote: # pre-receive hook
 	remote: pre-receive< <ZERO-OID> <COMMIT-A> refs/heads/next
-	remote: pre-receive< <ZERO-OID> <COMMIT-A> refs/for/master/topic
+	remote: pre-receive< <ZERO-OID> <COMMIT-A> refs/for/main/topic
 	remote: # proc-receive hook
-	remote: proc-receive< <ZERO-OID> <COMMIT-A> refs/for/master/topic
+	remote: proc-receive< <ZERO-OID> <COMMIT-A> refs/for/main/topic
 	remote: # post-receive hook
 	remote: post-receive< <ZERO-OID> <COMMIT-A> refs/heads/next
 	To <URL/of/upstream.git>
 	 * [new branch] HEAD -> next
-	 ! [remote rejected] HEAD -> refs/for/master/topic (proc-receive failed to report status)
+	 ! [remote rejected] HEAD -> refs/for/main/topic (proc-receive failed to report status)
 	EOF
 	test_cmp expect actual &&
+
 	git -C "$upstream" show-ref >out &&
 	make_user_friendly_and_stable_output <out >actual &&
 	cat >expect <<-EOF &&
-	<COMMIT-A> refs/heads/master
+	<COMMIT-A> refs/heads/main
 	<COMMIT-A> refs/heads/next
 	EOF
 	test_cmp expect actual
 '
 
-# Refs of upstream : master(A)             next(A)
-# Refs of workbench: master(A)  tags/v123
+# Refs of upstream : main(A)             next(A)
+# Refs of workbench: main(A)  tags/v123
 test_expect_success "cleanup ($PROTOCOL)" '
 	git -C "$upstream" update-ref -d refs/heads/next
 
@@ -154,29 +264,30 @@
 	EOF
 '
 
-# Refs of upstream : master(A)
-# Refs of workbench: master(A)  tags/v123
-# git push         :                       refs/for/master/topic
+# Refs of upstream : main(A)
+# Refs of workbench: main(A)  tags/v123
+# git push         :                       refs/for/main/topic
 test_expect_success "proc-receive: bad protocol (no ref, $PROTOCOL)" '
 	test_must_fail git -C workbench push origin \
-		HEAD:refs/for/master/topic\
+		HEAD:refs/for/main/topic\
 		>out 2>&1 &&
 	make_user_friendly_and_stable_output <out >actual &&
 	cat >expect <<-EOF &&
 	remote: # pre-receive hook
-	remote: pre-receive< <ZERO-OID> <COMMIT-A> refs/for/master/topic
+	remote: pre-receive< <ZERO-OID> <COMMIT-A> refs/for/main/topic
 	remote: # proc-receive hook
-	remote: proc-receive< <ZERO-OID> <COMMIT-A> refs/for/master/topic
+	remote: proc-receive< <ZERO-OID> <COMMIT-A> refs/for/main/topic
 	remote: proc-receive> ok
 	remote: error: proc-receive reported incomplete status line: "ok"
 	To <URL/of/upstream.git>
-	 ! [remote rejected] HEAD -> refs/for/master/topic (proc-receive failed to report status)
+	 ! [remote rejected] HEAD -> refs/for/main/topic (proc-receive failed to report status)
 	EOF
 	test_cmp expect actual &&
+
 	git -C "$upstream" show-ref >out &&
 	make_user_friendly_and_stable_output <out >actual &&
 	cat >expect <<-EOF &&
-	<COMMIT-A> refs/heads/master
+	<COMMIT-A> refs/heads/main
 	EOF
 	test_cmp expect actual
 '
@@ -185,33 +296,34 @@
 	write_script "$upstream/hooks/proc-receive" <<-EOF
 	printf >&2 "# proc-receive hook\n"
 	test-tool proc-receive -v \
-		-r "xx refs/for/master/topic"
+		-r "xx refs/for/main/topic"
 	EOF
 '
 
-# Refs of upstream : master(A)
-# Refs of workbench: master(A)  tags/v123
-# git push         :                       refs/for/master/topic
+# Refs of upstream : main(A)
+# Refs of workbench: main(A)  tags/v123
+# git push         :                       refs/for/main/topic
 test_expect_success "proc-receive: bad protocol (unknown status, $PROTOCOL)" '
 	test_must_fail git -C workbench push origin \
-			HEAD:refs/for/master/topic \
+			HEAD:refs/for/main/topic \
 			>out 2>&1 &&
 	make_user_friendly_and_stable_output <out >actual &&
 	cat >expect <<-EOF &&
 	remote: # pre-receive hook
-	remote: pre-receive< <ZERO-OID> <COMMIT-A> refs/for/master/topic
+	remote: pre-receive< <ZERO-OID> <COMMIT-A> refs/for/main/topic
 	remote: # proc-receive hook
-	remote: proc-receive< <ZERO-OID> <COMMIT-A> refs/for/master/topic
-	remote: proc-receive> xx refs/for/master/topic
-	remote: error: proc-receive reported bad status "xx" on ref "refs/for/master/topic"
+	remote: proc-receive< <ZERO-OID> <COMMIT-A> refs/for/main/topic
+	remote: proc-receive> xx refs/for/main/topic
+	remote: error: proc-receive reported bad status "xx" on ref "refs/for/main/topic"
 	To <URL/of/upstream.git>
-	 ! [remote rejected] HEAD -> refs/for/master/topic (proc-receive failed to report status)
+	 ! [remote rejected] HEAD -> refs/for/main/topic (proc-receive failed to report status)
 	EOF
 	test_cmp expect actual &&
+
 	git -C "$upstream" show-ref >out &&
 	make_user_friendly_and_stable_output <out >actual &&
 	cat >expect <<-EOF &&
-	<COMMIT-A> refs/heads/master
+	<COMMIT-A> refs/heads/main
 	EOF
 	test_cmp expect actual
 '
diff --git a/t/t5411/test-0014-bad-protocol--porcelain.sh b/t/t5411/test-0014-bad-protocol--porcelain.sh
index 53b47b0..fdb4569 100644
--- a/t/t5411/test-0014-bad-protocol--porcelain.sh
+++ b/t/t5411/test-0014-bad-protocol--porcelain.sh
@@ -5,12 +5,12 @@
 	EOF
 '
 
-# Refs of upstream : master(A)
-# Refs of workbench: master(A)  tags/v123
-# git push         :                       refs/for/master/topic(A)
+# Refs of upstream : main(A)
+# Refs of workbench: main(A)  tags/v123
+# git push         :                       refs/for/main/topic(A)
 test_expect_success "proc-receive: bad protocol (unknown version, $PROTOCOL/porcelain)" '
 	test_must_fail git -C workbench push --porcelain origin \
-		HEAD:refs/for/master/topic \
+		HEAD:refs/for/main/topic \
 		>out 2>&1 &&
 	make_user_friendly_and_stable_output <out >actual &&
 
@@ -20,7 +20,7 @@
 		<actual >actual-report &&
 	cat >expect <<-EOF &&
 	To <URL/of/upstream.git>
-	!    HEAD:refs/for/master/topic    [remote rejected] (fail to run proc-receive hook)
+	!    HEAD:refs/for/main/topic    [remote rejected] (fail to run proc-receive hook)
 	Done
 	EOF
 	test_cmp expect actual-report &&
@@ -37,7 +37,176 @@
 	git -C "$upstream" show-ref >out &&
 	make_user_friendly_and_stable_output <out >actual &&
 	cat >expect <<-EOF &&
-	<COMMIT-A> refs/heads/master
+	<COMMIT-A> refs/heads/main
+	EOF
+	test_cmp expect actual
+'
+
+test_expect_success "setup proc-receive hook (hook --die-read-version, $PROTOCOL/porcelain)" '
+	write_script "$upstream/hooks/proc-receive" <<-EOF
+	printf >&2 "# proc-receive hook\n"
+	test-tool proc-receive -v --die-read-version
+	EOF
+'
+
+# Refs of upstream : main(A)
+# Refs of workbench: main(A)  tags/v123
+# git push         :                       refs/for/main/topic(A)
+test_expect_success "proc-receive: bad protocol (hook --die-read-version, $PROTOCOL/porcelain)" '
+	test_must_fail git -C workbench push --porcelain origin \
+		HEAD:refs/for/main/topic \
+		>out 2>&1 &&
+	filter_out_user_friendly_and_stable_output \
+		-e "/^To / { p; n; p; n; p; }" \
+		<out >actual &&
+	cat >expect <<-EOF &&
+	To <URL/of/upstream.git>
+	!    HEAD:refs/for/main/topic    [remote rejected] (fail to run proc-receive hook)
+	Done
+	EOF
+	test_cmp expect actual &&
+	grep "remote: fatal: die with the --die-read-version option" out &&
+	grep "remote: error: fail to negotiate version with proc-receive hook" out &&
+
+	git -C "$upstream" show-ref >out &&
+	make_user_friendly_and_stable_output <out >actual &&
+	cat >expect <<-EOF &&
+	<COMMIT-A> refs/heads/main
+	EOF
+	test_cmp expect actual
+'
+
+test_expect_success "setup proc-receive hook (hook --die-write-version, $PROTOCOL/porcelain)" '
+	write_script "$upstream/hooks/proc-receive" <<-EOF
+	printf >&2 "# proc-receive hook\n"
+	test-tool proc-receive -v --die-write-version
+	EOF
+'
+
+# Refs of upstream : main(A)
+# Refs of workbench: main(A)  tags/v123
+# git push         :                       refs/for/main/topic(A)
+test_expect_success "proc-receive: bad protocol (hook --die-write-version, $PROTOCOL/porcelain)" '
+	test_must_fail git -C workbench push --porcelain origin \
+		HEAD:refs/for/main/topic \
+		>out 2>&1 &&
+	filter_out_user_friendly_and_stable_output \
+		-e "/^To / { p; n; p; n; p; }" \
+		<out >actual &&
+	cat >expect <<-EOF &&
+	To <URL/of/upstream.git>
+	!    HEAD:refs/for/main/topic    [remote rejected] (fail to run proc-receive hook)
+	Done
+	EOF
+	test_cmp expect actual &&
+	grep "remote: fatal: die with the --die-write-version option" out &&
+	grep "remote: error: fail to negotiate version with proc-receive hook" out &&
+
+	git -C "$upstream" show-ref >out &&
+	make_user_friendly_and_stable_output <out >actual &&
+	cat >expect <<-EOF &&
+	<COMMIT-A> refs/heads/main
+	EOF
+	test_cmp expect actual
+'
+
+test_expect_success "setup proc-receive hook (hook --die-read-commands, $PROTOCOL/porcelain)" '
+	write_script "$upstream/hooks/proc-receive" <<-EOF
+	printf >&2 "# proc-receive hook\n"
+	test-tool proc-receive -v --die-read-commands
+	EOF
+'
+
+# Refs of upstream : main(A)
+# Refs of workbench: main(A)  tags/v123
+# git push         :                       refs/for/main/topic(A)
+test_expect_success "proc-receive: bad protocol (hook --die-read-commands, $PROTOCOL/porcelain)" '
+	test_must_fail git -C workbench push --porcelain origin \
+		HEAD:refs/for/main/topic \
+		>out 2>&1 &&
+	filter_out_user_friendly_and_stable_output \
+		-e "/^To / { p; n; p; n; p; }" \
+		<out >actual &&
+	cat >expect <<-EOF &&
+	To <URL/of/upstream.git>
+	!    HEAD:refs/for/main/topic    [remote rejected] (fail to run proc-receive hook)
+	Done
+	EOF
+	test_cmp expect actual &&
+	grep "remote: fatal: die with the --die-read-commands option" out &&
+
+	git -C "$upstream" show-ref >out &&
+	make_user_friendly_and_stable_output <out >actual &&
+	cat >expect <<-EOF &&
+	<COMMIT-A> refs/heads/main
+	EOF
+	test_cmp expect actual
+'
+
+test_expect_success "setup proc-receive hook (hook --die-read-push-options, $PROTOCOL/porcelain)" '
+	write_script "$upstream/hooks/proc-receive" <<-EOF
+	printf >&2 "# proc-receive hook\n"
+	test-tool proc-receive -v --die-read-push-options
+	EOF
+'
+
+# Refs of upstream : main(A)
+# Refs of workbench: main(A)  tags/v123
+# git push         :                       refs/for/main/topic(A)
+test_expect_success "proc-receive: bad protocol (hook --die-read-push-options, $PROTOCOL/porcelain)" '
+	git -C "$upstream" config receive.advertisePushOptions true &&
+	test_must_fail git -C workbench push --porcelain origin \
+		-o reviewers=user1,user2 \
+		HEAD:refs/for/main/topic \
+		>out 2>&1 &&
+	filter_out_user_friendly_and_stable_output \
+		-e "/^To / { p; n; p; n; p; }" \
+		<out >actual &&
+	cat >expect <<-EOF &&
+	To <URL/of/upstream.git>
+	!    HEAD:refs/for/main/topic    [remote rejected] (fail to run proc-receive hook)
+	Done
+	EOF
+	test_cmp expect actual &&
+	grep "remote: fatal: die with the --die-read-push-options option" out &&
+
+	git -C "$upstream" show-ref >out &&
+	make_user_friendly_and_stable_output <out >actual &&
+	cat >expect <<-EOF &&
+	<COMMIT-A> refs/heads/main
+	EOF
+	test_cmp expect actual
+'
+
+test_expect_success "setup proc-receive hook (hook --die-write-report, $PROTOCOL/porcelain)" '
+	write_script "$upstream/hooks/proc-receive" <<-EOF
+	printf >&2 "# proc-receive hook\n"
+	test-tool proc-receive -v --die-write-report
+	EOF
+'
+
+# Refs of upstream : main(A)
+# Refs of workbench: main(A)  tags/v123
+# git push         :                       refs/for/main/topic(A)
+test_expect_success "proc-receive: bad protocol (hook --die-write-report, $PROTOCOL/porcelain)" '
+	test_must_fail git -C workbench push --porcelain origin \
+		HEAD:refs/for/main/topic \
+		>out 2>&1 &&
+	filter_out_user_friendly_and_stable_output \
+		-e "/^To / { p; n; p; n; p; }" \
+		<out >actual &&
+	cat >expect <<-EOF &&
+	To <URL/of/upstream.git>
+	!    HEAD:refs/for/main/topic    [remote rejected] (fail to run proc-receive hook)
+	Done
+	EOF
+	test_cmp expect actual &&
+	grep "remote: fatal: die with the --die-write-report option" out &&
+
+	git -C "$upstream" show-ref >out &&
+	make_user_friendly_and_stable_output <out >actual &&
+	cat >expect <<-EOF &&
+	<COMMIT-A> refs/heads/main
 	EOF
 	test_cmp expect actual
 '
@@ -49,42 +218,42 @@
 	EOF
 '
 
-# Refs of upstream : master(A)
-# Refs of workbench: master(A)  tags/v123
-# git push         :                       next(A)  refs/for/master/topic(A)
+# Refs of upstream : main(A)
+# Refs of workbench: main(A)  tags/v123
+# git push         :                       next(A)  refs/for/main/topic(A)
 test_expect_success "proc-receive: bad protocol (no report, $PROTOCOL/porcelain)" '
 	test_must_fail git -C workbench push --porcelain origin \
 		HEAD:refs/heads/next \
-		HEAD:refs/for/master/topic >out 2>&1 &&
+		HEAD:refs/for/main/topic >out 2>&1 &&
 	make_user_friendly_and_stable_output <out >actual &&
 	cat >expect <<-EOF &&
 	remote: # pre-receive hook
 	remote: pre-receive< <ZERO-OID> <COMMIT-A> refs/heads/next
-	remote: pre-receive< <ZERO-OID> <COMMIT-A> refs/for/master/topic
+	remote: pre-receive< <ZERO-OID> <COMMIT-A> refs/for/main/topic
 	remote: # proc-receive hook
-	remote: proc-receive< <ZERO-OID> <COMMIT-A> refs/for/master/topic
+	remote: proc-receive< <ZERO-OID> <COMMIT-A> refs/for/main/topic
 	remote: # post-receive hook
 	remote: post-receive< <ZERO-OID> <COMMIT-A> refs/heads/next
 	To <URL/of/upstream.git>
 	*    HEAD:refs/heads/next    [new branch]
-	!    HEAD:refs/for/master/topic    [remote rejected] (proc-receive failed to report status)
+	!    HEAD:refs/for/main/topic    [remote rejected] (proc-receive failed to report status)
 	Done
 	EOF
 	test_cmp expect actual &&
+
 	git -C "$upstream" show-ref >out &&
 	make_user_friendly_and_stable_output <out >actual &&
 	cat >expect <<-EOF &&
-	<COMMIT-A> refs/heads/master
+	<COMMIT-A> refs/heads/main
 	<COMMIT-A> refs/heads/next
 	EOF
 	test_cmp expect actual
 '
 
-# Refs of upstream : master(A)             next(A)
-# Refs of workbench: master(A)  tags/v123
+# Refs of upstream : main(A)             next(A)
+# Refs of workbench: main(A)  tags/v123
 test_expect_success "cleanup ($PROTOCOL/porcelain)" '
 	git -C "$upstream" update-ref -d refs/heads/next
-
 '
 
 test_expect_success "setup proc-receive hook (no ref, $PROTOCOL/porcelain)" '
@@ -95,30 +264,31 @@
 	EOF
 '
 
-# Refs of upstream : master(A)
-# Refs of workbench: master(A)  tags/v123
-# git push         :                       refs/for/master/topic
+# Refs of upstream : main(A)
+# Refs of workbench: main(A)  tags/v123
+# git push         :                       refs/for/main/topic
 test_expect_success "proc-receive: bad protocol (no ref, $PROTOCOL/porcelain)" '
 	test_must_fail git -C workbench push --porcelain origin \
-		HEAD:refs/for/master/topic\
+		HEAD:refs/for/main/topic\
 		>out 2>&1 &&
 	make_user_friendly_and_stable_output <out >actual &&
 	cat >expect <<-EOF &&
 	remote: # pre-receive hook
-	remote: pre-receive< <ZERO-OID> <COMMIT-A> refs/for/master/topic
+	remote: pre-receive< <ZERO-OID> <COMMIT-A> refs/for/main/topic
 	remote: # proc-receive hook
-	remote: proc-receive< <ZERO-OID> <COMMIT-A> refs/for/master/topic
+	remote: proc-receive< <ZERO-OID> <COMMIT-A> refs/for/main/topic
 	remote: proc-receive> ok
 	remote: error: proc-receive reported incomplete status line: "ok"
 	To <URL/of/upstream.git>
-	!    HEAD:refs/for/master/topic    [remote rejected] (proc-receive failed to report status)
+	!    HEAD:refs/for/main/topic    [remote rejected] (proc-receive failed to report status)
 	Done
 	EOF
 	test_cmp expect actual &&
+
 	git -C "$upstream" show-ref >out &&
 	make_user_friendly_and_stable_output <out >actual &&
 	cat >expect <<-EOF &&
-	<COMMIT-A> refs/heads/master
+	<COMMIT-A> refs/heads/main
 	EOF
 	test_cmp expect actual
 '
@@ -127,34 +297,35 @@
 	write_script "$upstream/hooks/proc-receive" <<-EOF
 	printf >&2 "# proc-receive hook\n"
 	test-tool proc-receive -v \
-		-r "xx refs/for/master/topic"
+		-r "xx refs/for/main/topic"
 	EOF
 '
 
-# Refs of upstream : master(A)
-# Refs of workbench: master(A)  tags/v123
-# git push         :                       refs/for/master/topic
+# Refs of upstream : main(A)
+# Refs of workbench: main(A)  tags/v123
+# git push         :                       refs/for/main/topic
 test_expect_success "proc-receive: bad protocol (unknown status, $PROTOCOL/porcelain)" '
 	test_must_fail git -C workbench push --porcelain origin \
-			HEAD:refs/for/master/topic \
+			HEAD:refs/for/main/topic \
 			>out 2>&1 &&
 	make_user_friendly_and_stable_output <out >actual &&
 	cat >expect <<-EOF &&
 	remote: # pre-receive hook
-	remote: pre-receive< <ZERO-OID> <COMMIT-A> refs/for/master/topic
+	remote: pre-receive< <ZERO-OID> <COMMIT-A> refs/for/main/topic
 	remote: # proc-receive hook
-	remote: proc-receive< <ZERO-OID> <COMMIT-A> refs/for/master/topic
-	remote: proc-receive> xx refs/for/master/topic
-	remote: error: proc-receive reported bad status "xx" on ref "refs/for/master/topic"
+	remote: proc-receive< <ZERO-OID> <COMMIT-A> refs/for/main/topic
+	remote: proc-receive> xx refs/for/main/topic
+	remote: error: proc-receive reported bad status "xx" on ref "refs/for/main/topic"
 	To <URL/of/upstream.git>
-	!    HEAD:refs/for/master/topic    [remote rejected] (proc-receive failed to report status)
+	!    HEAD:refs/for/main/topic    [remote rejected] (proc-receive failed to report status)
 	Done
 	EOF
 	test_cmp expect actual &&
+
 	git -C "$upstream" show-ref >out &&
 	make_user_friendly_and_stable_output <out >actual &&
 	cat >expect <<-EOF &&
-	<COMMIT-A> refs/heads/master
+	<COMMIT-A> refs/heads/main
 	EOF
 	test_cmp expect actual
 '
diff --git a/t/t5411/test-0020-report-ng.sh b/t/t5411/test-0020-report-ng.sh
index f726b7c..5a9e0da 100644
--- a/t/t5411/test-0020-report-ng.sh
+++ b/t/t5411/test-0020-report-ng.sh
@@ -2,32 +2,32 @@
 	write_script "$upstream/hooks/proc-receive" <<-EOF
 	printf >&2 "# proc-receive hook\n"
 	test-tool proc-receive -v \
-		-r "ng refs/for/master/topic"
+		-r "ng refs/for/main/topic"
 	EOF
 '
 
-# Refs of upstream : master(A)
-# Refs of workbench: master(A)  tags/v123
-# git push         :                       refs/for/master/topic
+# Refs of upstream : main(A)
+# Refs of workbench: main(A)  tags/v123
+# git push         :                       refs/for/main/topic
 test_expect_success "proc-receive: fail to update (ng, no message, $PROTOCOL)" '
 	test_must_fail git -C workbench push origin \
-		HEAD:refs/for/master/topic \
+		HEAD:refs/for/main/topic \
 		>out 2>&1 &&
 	make_user_friendly_and_stable_output <out >actual &&
 	cat >expect <<-EOF &&
 	remote: # pre-receive hook
-	remote: pre-receive< <ZERO-OID> <COMMIT-A> refs/for/master/topic
+	remote: pre-receive< <ZERO-OID> <COMMIT-A> refs/for/main/topic
 	remote: # proc-receive hook
-	remote: proc-receive< <ZERO-OID> <COMMIT-A> refs/for/master/topic
-	remote: proc-receive> ng refs/for/master/topic
+	remote: proc-receive< <ZERO-OID> <COMMIT-A> refs/for/main/topic
+	remote: proc-receive> ng refs/for/main/topic
 	To <URL/of/upstream.git>
-	 ! [remote rejected] HEAD -> refs/for/master/topic (failed)
+	 ! [remote rejected] HEAD -> refs/for/main/topic (failed)
 	EOF
 	test_cmp expect actual &&
 	git -C "$upstream" show-ref >out &&
 	make_user_friendly_and_stable_output <out >actual &&
 	cat >expect <<-EOF &&
-	<COMMIT-A> refs/heads/master
+	<COMMIT-A> refs/heads/main
 	EOF
 	test_cmp expect actual
 '
@@ -36,32 +36,32 @@
 	write_script "$upstream/hooks/proc-receive" <<-EOF
 	printf >&2 "# proc-receive hook\n"
 	test-tool proc-receive -v \
-		-r "ng refs/for/master/topic error msg"
+		-r "ng refs/for/main/topic error msg"
 	EOF
 '
 
-# Refs of upstream : master(A)
-# Refs of workbench: master(A)  tags/v123
-# git push         :                       refs/for/master/topic
+# Refs of upstream : main(A)
+# Refs of workbench: main(A)  tags/v123
+# git push         :                       refs/for/main/topic
 test_expect_success "proc-receive: fail to update (ng, with message, $PROTOCOL)" '
 	test_must_fail git -C workbench push origin \
-		HEAD:refs/for/master/topic \
+		HEAD:refs/for/main/topic \
 		>out 2>&1 &&
 	make_user_friendly_and_stable_output <out >actual &&
 	cat >expect <<-EOF &&
 	remote: # pre-receive hook
-	remote: pre-receive< <ZERO-OID> <COMMIT-A> refs/for/master/topic
+	remote: pre-receive< <ZERO-OID> <COMMIT-A> refs/for/main/topic
 	remote: # proc-receive hook
-	remote: proc-receive< <ZERO-OID> <COMMIT-A> refs/for/master/topic
-	remote: proc-receive> ng refs/for/master/topic error msg
+	remote: proc-receive< <ZERO-OID> <COMMIT-A> refs/for/main/topic
+	remote: proc-receive> ng refs/for/main/topic error msg
 	To <URL/of/upstream.git>
-	 ! [remote rejected] HEAD -> refs/for/master/topic (error msg)
+	 ! [remote rejected] HEAD -> refs/for/main/topic (error msg)
 	EOF
 	test_cmp expect actual &&
 	git -C "$upstream" show-ref >out &&
 	make_user_friendly_and_stable_output <out >actual &&
 	cat >expect <<-EOF &&
-	<COMMIT-A> refs/heads/master
+	<COMMIT-A> refs/heads/main
 	EOF
 	test_cmp expect actual
 '
diff --git a/t/t5411/test-0021-report-ng--porcelain.sh b/t/t5411/test-0021-report-ng--porcelain.sh
index fbf5569..93475a8 100644
--- a/t/t5411/test-0021-report-ng--porcelain.sh
+++ b/t/t5411/test-0021-report-ng--porcelain.sh
@@ -2,33 +2,33 @@
 	write_script "$upstream/hooks/proc-receive" <<-EOF
 	printf >&2 "# proc-receive hook\n"
 	test-tool proc-receive -v \
-		-r "ng refs/for/master/topic"
+		-r "ng refs/for/main/topic"
 	EOF
 '
 
-# Refs of upstream : master(A)
-# Refs of workbench: master(A)  tags/v123
-# git push         :                       refs/for/master/topic
+# Refs of upstream : main(A)
+# Refs of workbench: main(A)  tags/v123
+# git push         :                       refs/for/main/topic
 test_expect_success "proc-receive: fail to update (ng, no message, $PROTOCOL/porcelain)" '
 	test_must_fail git -C workbench push --porcelain origin \
-		HEAD:refs/for/master/topic \
+		HEAD:refs/for/main/topic \
 		>out 2>&1 &&
 	make_user_friendly_and_stable_output <out >actual &&
 	cat >expect <<-EOF &&
 	remote: # pre-receive hook
-	remote: pre-receive< <ZERO-OID> <COMMIT-A> refs/for/master/topic
+	remote: pre-receive< <ZERO-OID> <COMMIT-A> refs/for/main/topic
 	remote: # proc-receive hook
-	remote: proc-receive< <ZERO-OID> <COMMIT-A> refs/for/master/topic
-	remote: proc-receive> ng refs/for/master/topic
+	remote: proc-receive< <ZERO-OID> <COMMIT-A> refs/for/main/topic
+	remote: proc-receive> ng refs/for/main/topic
 	To <URL/of/upstream.git>
-	!    HEAD:refs/for/master/topic    [remote rejected] (failed)
+	!    HEAD:refs/for/main/topic    [remote rejected] (failed)
 	Done
 	EOF
 	test_cmp expect actual &&
 	git -C "$upstream" show-ref >out &&
 	make_user_friendly_and_stable_output <out >actual &&
 	cat >expect <<-EOF &&
-	<COMMIT-A> refs/heads/master
+	<COMMIT-A> refs/heads/main
 	EOF
 	test_cmp expect actual
 '
@@ -37,33 +37,33 @@
 	write_script "$upstream/hooks/proc-receive" <<-EOF
 	printf >&2 "# proc-receive hook\n"
 	test-tool proc-receive -v \
-		-r "ng refs/for/master/topic error msg"
+		-r "ng refs/for/main/topic error msg"
 	EOF
 '
 
-# Refs of upstream : master(A)
-# Refs of workbench: master(A)  tags/v123
-# git push         :                       refs/for/master/topic
+# Refs of upstream : main(A)
+# Refs of workbench: main(A)  tags/v123
+# git push         :                       refs/for/main/topic
 test_expect_success "proc-receive: fail to update (ng, with message, $PROTOCOL/porcelain)" '
 	test_must_fail git -C workbench push --porcelain origin \
-		HEAD:refs/for/master/topic \
+		HEAD:refs/for/main/topic \
 		>out 2>&1 &&
 	make_user_friendly_and_stable_output <out >actual &&
 	cat >expect <<-EOF &&
 	remote: # pre-receive hook
-	remote: pre-receive< <ZERO-OID> <COMMIT-A> refs/for/master/topic
+	remote: pre-receive< <ZERO-OID> <COMMIT-A> refs/for/main/topic
 	remote: # proc-receive hook
-	remote: proc-receive< <ZERO-OID> <COMMIT-A> refs/for/master/topic
-	remote: proc-receive> ng refs/for/master/topic error msg
+	remote: proc-receive< <ZERO-OID> <COMMIT-A> refs/for/main/topic
+	remote: proc-receive> ng refs/for/main/topic error msg
 	To <URL/of/upstream.git>
-	!    HEAD:refs/for/master/topic    [remote rejected] (error msg)
+	!    HEAD:refs/for/main/topic    [remote rejected] (error msg)
 	Done
 	EOF
 	test_cmp expect actual &&
 	git -C "$upstream" show-ref >out &&
 	make_user_friendly_and_stable_output <out >actual &&
 	cat >expect <<-EOF &&
-	<COMMIT-A> refs/heads/master
+	<COMMIT-A> refs/heads/main
 	EOF
 	test_cmp expect actual
 '
diff --git a/t/t5411/test-0022-report-unexpect-ref.sh b/t/t5411/test-0022-report-unexpect-ref.sh
index 92a415b..f8be8a0 100644
--- a/t/t5411/test-0022-report-unexpect-ref.sh
+++ b/t/t5411/test-0022-report-unexpect-ref.sh
@@ -2,44 +2,44 @@
 	write_script "$upstream/hooks/proc-receive" <<-EOF
 	printf >&2 "# proc-receive hook\n"
 	test-tool proc-receive -v \
-		-r "ok refs/heads/master"
+		-r "ok refs/heads/main"
 	EOF
 '
 
-# Refs of upstream : master(A)
-# Refs of workbench: master(A)  tags/v123
-# git push         : (B)                   refs/for/master/topic
+# Refs of upstream : main(A)
+# Refs of workbench: main(A)  tags/v123
+# git push         : (B)                   refs/for/main/topic
 test_expect_success "proc-receive: report unexpected ref ($PROTOCOL)" '
 	test_must_fail git -C workbench push origin \
-		$B:refs/heads/master \
-		HEAD:refs/for/master/topic \
+		$B:refs/heads/main \
+		HEAD:refs/for/main/topic \
 		>out 2>&1 &&
 	make_user_friendly_and_stable_output <out >actual &&
 	cat >expect <<-EOF &&
 	remote: # pre-receive hook
-	remote: pre-receive< <COMMIT-A> <COMMIT-B> refs/heads/master
-	remote: pre-receive< <ZERO-OID> <COMMIT-A> refs/for/master/topic
+	remote: pre-receive< <COMMIT-A> <COMMIT-B> refs/heads/main
+	remote: pre-receive< <ZERO-OID> <COMMIT-A> refs/for/main/topic
 	remote: # proc-receive hook
-	remote: proc-receive< <ZERO-OID> <COMMIT-A> refs/for/master/topic
-	remote: proc-receive> ok refs/heads/master
-	remote: error: proc-receive reported status on unexpected ref: refs/heads/master
+	remote: proc-receive< <ZERO-OID> <COMMIT-A> refs/for/main/topic
+	remote: proc-receive> ok refs/heads/main
+	remote: error: proc-receive reported status on unexpected ref: refs/heads/main
 	remote: # post-receive hook
-	remote: post-receive< <COMMIT-A> <COMMIT-B> refs/heads/master
+	remote: post-receive< <COMMIT-A> <COMMIT-B> refs/heads/main
 	To <URL/of/upstream.git>
-	 <OID-A>..<OID-B> <COMMIT-B> -> master
-	 ! [remote rejected] HEAD -> refs/for/master/topic (proc-receive failed to report status)
+	 <OID-A>..<OID-B> <COMMIT-B> -> main
+	 ! [remote rejected] HEAD -> refs/for/main/topic (proc-receive failed to report status)
 	EOF
 	test_cmp expect actual &&
 	git -C "$upstream" show-ref >out &&
 	make_user_friendly_and_stable_output <out >actual &&
 	cat >expect <<-EOF &&
-	<COMMIT-B> refs/heads/master
+	<COMMIT-B> refs/heads/main
 	EOF
 	test_cmp expect actual
 '
 
-# Refs of upstream : master(B)
-# Refs of workbench: master(A)  tags/v123
+# Refs of upstream : main(B)
+# Refs of workbench: main(A)  tags/v123
 test_expect_success "cleanup ($PROTOCOL)" '
-	git -C "$upstream" update-ref refs/heads/master $A
+	git -C "$upstream" update-ref refs/heads/main $A
 '
diff --git a/t/t5411/test-0023-report-unexpect-ref--porcelain.sh b/t/t5411/test-0023-report-unexpect-ref--porcelain.sh
index acbf93e..778150f 100644
--- a/t/t5411/test-0023-report-unexpect-ref--porcelain.sh
+++ b/t/t5411/test-0023-report-unexpect-ref--porcelain.sh
@@ -2,45 +2,45 @@
 	write_script "$upstream/hooks/proc-receive" <<-EOF
 	printf >&2 "# proc-receive hook\n"
 	test-tool proc-receive -v \
-		-r "ok refs/heads/master"
+		-r "ok refs/heads/main"
 	EOF
 '
 
-# Refs of upstream : master(A)
-# Refs of workbench: master(A)  tags/v123
-# git push         : (B)                   refs/for/master/topic
+# Refs of upstream : main(A)
+# Refs of workbench: main(A)  tags/v123
+# git push         : (B)                   refs/for/main/topic
 test_expect_success "proc-receive: report unexpected ref ($PROTOCOL/porcelain)" '
 	test_must_fail git -C workbench push --porcelain origin \
-		$B:refs/heads/master \
-		HEAD:refs/for/master/topic \
+		$B:refs/heads/main \
+		HEAD:refs/for/main/topic \
 		>out 2>&1 &&
 	make_user_friendly_and_stable_output <out >actual &&
 	cat >expect <<-EOF &&
 	remote: # pre-receive hook
-	remote: pre-receive< <COMMIT-A> <COMMIT-B> refs/heads/master
-	remote: pre-receive< <ZERO-OID> <COMMIT-A> refs/for/master/topic
+	remote: pre-receive< <COMMIT-A> <COMMIT-B> refs/heads/main
+	remote: pre-receive< <ZERO-OID> <COMMIT-A> refs/for/main/topic
 	remote: # proc-receive hook
-	remote: proc-receive< <ZERO-OID> <COMMIT-A> refs/for/master/topic
-	remote: proc-receive> ok refs/heads/master
-	remote: error: proc-receive reported status on unexpected ref: refs/heads/master
+	remote: proc-receive< <ZERO-OID> <COMMIT-A> refs/for/main/topic
+	remote: proc-receive> ok refs/heads/main
+	remote: error: proc-receive reported status on unexpected ref: refs/heads/main
 	remote: # post-receive hook
-	remote: post-receive< <COMMIT-A> <COMMIT-B> refs/heads/master
+	remote: post-receive< <COMMIT-A> <COMMIT-B> refs/heads/main
 	To <URL/of/upstream.git>
-	     <COMMIT-B>:refs/heads/master    <OID-A>..<OID-B>
-	!    HEAD:refs/for/master/topic    [remote rejected] (proc-receive failed to report status)
+	     <COMMIT-B>:refs/heads/main    <OID-A>..<OID-B>
+	!    HEAD:refs/for/main/topic    [remote rejected] (proc-receive failed to report status)
 	Done
 	EOF
 	test_cmp expect actual &&
 	git -C "$upstream" show-ref >out &&
 	make_user_friendly_and_stable_output <out >actual &&
 	cat >expect <<-EOF &&
-	<COMMIT-B> refs/heads/master
+	<COMMIT-B> refs/heads/main
 	EOF
 	test_cmp expect actual
 '
 
-# Refs of upstream : master(B)
-# Refs of workbench: master(A)  tags/v123
+# Refs of upstream : main(B)
+# Refs of workbench: main(A)  tags/v123
 test_expect_success "cleanup ($PROTOCOL/porcelain)" '
-	git -C "$upstream" update-ref refs/heads/master $A
+	git -C "$upstream" update-ref refs/heads/main $A
 '
diff --git a/t/t5411/test-0024-report-unknown-ref.sh b/t/t5411/test-0024-report-unknown-ref.sh
index c3946f3..d4e74e4 100644
--- a/t/t5411/test-0024-report-unknown-ref.sh
+++ b/t/t5411/test-0024-report-unknown-ref.sh
@@ -2,12 +2,12 @@
 	write_script "$upstream/hooks/proc-receive" <<-EOF
 	printf >&2 "# proc-receive hook\n"
 	test-tool proc-receive -v \
-		-r "ok refs/for/master/topic"
+		-r "ok refs/for/main/topic"
 	EOF
 '
 
-# Refs of upstream : master(A)
-# Refs of workbench: master(A)  tags/v123
+# Refs of upstream : main(A)
+# Refs of workbench: main(A)  tags/v123
 # git push         :                       refs/for/a/b/c/my/topic
 test_expect_success "proc-receive: report unknown reference ($PROTOCOL)" '
 	test_must_fail git -C workbench push origin \
@@ -19,8 +19,8 @@
 	remote: pre-receive< <ZERO-OID> <COMMIT-A> refs/for/a/b/c/my/topic
 	remote: # proc-receive hook
 	remote: proc-receive< <ZERO-OID> <COMMIT-A> refs/for/a/b/c/my/topic
-	remote: proc-receive> ok refs/for/master/topic
-	remote: error: proc-receive reported status on unknown ref: refs/for/master/topic
+	remote: proc-receive> ok refs/for/main/topic
+	remote: error: proc-receive reported status on unknown ref: refs/for/main/topic
 	To <URL/of/upstream.git>
 	 ! [remote rejected] HEAD -> refs/for/a/b/c/my/topic (proc-receive failed to report status)
 	EOF
@@ -28,7 +28,7 @@
 	git -C "$upstream" show-ref >out &&
 	make_user_friendly_and_stable_output <out >actual &&
 	cat >expect <<-EOF &&
-	<COMMIT-A> refs/heads/master
+	<COMMIT-A> refs/heads/main
 	EOF
 	test_cmp expect actual
 '
diff --git a/t/t5411/test-0025-report-unknown-ref--porcelain.sh b/t/t5411/test-0025-report-unknown-ref--porcelain.sh
index d093b1a..039e8b6 100644
--- a/t/t5411/test-0025-report-unknown-ref--porcelain.sh
+++ b/t/t5411/test-0025-report-unknown-ref--porcelain.sh
@@ -2,12 +2,12 @@
 	write_script "$upstream/hooks/proc-receive" <<-EOF
 	printf >&2 "# proc-receive hook\n"
 	test-tool proc-receive -v \
-		-r "ok refs/for/master/topic"
+		-r "ok refs/for/main/topic"
 	EOF
 '
 
-# Refs of upstream : master(A)
-# Refs of workbench: master(A)  tags/v123
+# Refs of upstream : main(A)
+# Refs of workbench: main(A)  tags/v123
 # git push         :                       refs/for/a/b/c/my/topic
 test_expect_success "proc-receive: report unknown reference ($PROTOCOL/porcelain)" '
 	test_must_fail git -C workbench push --porcelain origin \
@@ -19,8 +19,8 @@
 	remote: pre-receive< <ZERO-OID> <COMMIT-A> refs/for/a/b/c/my/topic
 	remote: # proc-receive hook
 	remote: proc-receive< <ZERO-OID> <COMMIT-A> refs/for/a/b/c/my/topic
-	remote: proc-receive> ok refs/for/master/topic
-	remote: error: proc-receive reported status on unknown ref: refs/for/master/topic
+	remote: proc-receive> ok refs/for/main/topic
+	remote: error: proc-receive reported status on unknown ref: refs/for/main/topic
 	To <URL/of/upstream.git>
 	!    HEAD:refs/for/a/b/c/my/topic    [remote rejected] (proc-receive failed to report status)
 	Done
@@ -29,7 +29,7 @@
 	git -C "$upstream" show-ref >out &&
 	make_user_friendly_and_stable_output <out >actual &&
 	cat >expect <<-EOF &&
-	<COMMIT-A> refs/heads/master
+	<COMMIT-A> refs/heads/main
 	EOF
 	test_cmp expect actual
 '
diff --git a/t/t5411/test-0026-push-options.sh b/t/t5411/test-0026-push-options.sh
index d0c4da8..e88edb1 100644
--- a/t/t5411/test-0026-push-options.sh
+++ b/t/t5411/test-0026-push-options.sh
@@ -3,19 +3,19 @@
 	write_script "$upstream/hooks/proc-receive" <<-EOF
 	printf >&2 "# proc-receive hook\n"
 	test-tool proc-receive -v \
-		-r "ok refs/for/master/topic"
+		-r "ok refs/for/main/topic"
 	EOF
 '
 
-# Refs of upstream : master(A)
-# Refs of workbench: master(A)  tags/v123
-# git push -o ...  :                       refs/for/master/topic
+# Refs of upstream : main(A)
+# Refs of workbench: main(A)  tags/v123
+# git push -o ...  :                       refs/for/main/topic
 test_expect_success "proc-receive: not support push options ($PROTOCOL)" '
 	test_must_fail git -C workbench push \
 		-o issue=123 \
 		-o reviewer=user1 \
 		origin \
-		HEAD:refs/for/master/topic \
+		HEAD:refs/for/main/topic \
 		>out 2>&1 &&
 	make_user_friendly_and_stable_output <out >actual &&
 	test_i18ngrep "fatal: the receiving end does not support push options" \
@@ -23,7 +23,7 @@
 	git -C "$upstream" show-ref >out &&
 	make_user_friendly_and_stable_output <out >actual &&
 	cat >expect <<-EOF &&
-	<COMMIT-A> refs/heads/master
+	<COMMIT-A> refs/heads/main
 	EOF
 	test_cmp expect actual
 '
@@ -32,9 +32,69 @@
 	git -C "$upstream" config receive.advertisePushOptions true
 '
 
-# Refs of upstream : master(A)
-# Refs of workbench: master(A)  tags/v123
-# git push -o ...  :                       next(A)  refs/for/master/topic
+test_expect_success "setup version=0 for proc-receive hook ($PROTOCOL)" '
+	write_script "$upstream/hooks/proc-receive" <<-EOF
+	printf >&2 "# proc-receive hook\n"
+	test-tool proc-receive -v \
+		--version 0 \
+		-r "ok refs/for/main/topic"
+	EOF
+'
+
+# Refs of upstream : main(A)
+# Refs of workbench: main(A)  tags/v123
+# git push -o ...  :                       next(A)  refs/for/main/topic
+test_expect_success "proc-receive: ignore push-options for version 0 ($PROTOCOL)" '
+	git -C workbench push \
+		--atomic \
+		-o issue=123 \
+		-o reviewer=user1 \
+		origin \
+		HEAD:refs/heads/next \
+		HEAD:refs/for/main/topic \
+		>out 2>&1 &&
+	make_user_friendly_and_stable_output <out >actual &&
+	cat >expect <<-EOF &&
+	remote: # pre-receive hook
+	remote: pre-receive< <ZERO-OID> <COMMIT-A> refs/heads/next
+	remote: pre-receive< <ZERO-OID> <COMMIT-A> refs/for/main/topic
+	remote: # proc-receive hook
+	remote: proc-receive< <ZERO-OID> <COMMIT-A> refs/for/main/topic
+	remote: proc-receive> ok refs/for/main/topic
+	remote: # post-receive hook
+	remote: post-receive< <ZERO-OID> <COMMIT-A> refs/heads/next
+	remote: post-receive< <ZERO-OID> <COMMIT-A> refs/for/main/topic
+	To <URL/of/upstream.git>
+	 * [new branch] HEAD -> next
+	 * [new reference] HEAD -> refs/for/main/topic
+	EOF
+	test_cmp expect actual &&
+	git -C "$upstream" show-ref >out &&
+	make_user_friendly_and_stable_output <out >actual &&
+	cat >expect <<-EOF &&
+	<COMMIT-A> refs/heads/main
+	<COMMIT-A> refs/heads/next
+	EOF
+	test_cmp expect actual
+'
+
+test_expect_success "restore proc-receive hook ($PROTOCOL)" '
+	write_script "$upstream/hooks/proc-receive" <<-EOF
+	printf >&2 "# proc-receive hook\n"
+	test-tool proc-receive -v \
+		-r "ok refs/for/main/topic"
+	EOF
+'
+
+# Refs of upstream : main(A)             next(A)
+# Refs of workbench: main(A)  tags/v123
+test_expect_success "cleanup ($PROTOCOL)" '
+	git -C "$upstream" update-ref -d refs/heads/next
+'
+
+# Refs of upstream : main(A)
+# Refs of workbench: main(A)  tags/v123
+# git push -o ...  :                       next(A)  refs/for/main/topic
 test_expect_success "proc-receive: push with options ($PROTOCOL)" '
 	git -C workbench push \
 		--atomic \
@@ -42,38 +102,38 @@
 		-o reviewer=user1 \
 		origin \
 		HEAD:refs/heads/next \
-		HEAD:refs/for/master/topic \
+		HEAD:refs/for/main/topic \
 		>out 2>&1 &&
 	make_user_friendly_and_stable_output <out >actual &&
 	cat >expect <<-EOF &&
 	remote: # pre-receive hook
 	remote: pre-receive< <ZERO-OID> <COMMIT-A> refs/heads/next
-	remote: pre-receive< <ZERO-OID> <COMMIT-A> refs/for/master/topic
+	remote: pre-receive< <ZERO-OID> <COMMIT-A> refs/for/main/topic
 	remote: # proc-receive hook
 	remote: proc-receive: atomic push_options
-	remote: proc-receive< <ZERO-OID> <COMMIT-A> refs/for/master/topic
+	remote: proc-receive< <ZERO-OID> <COMMIT-A> refs/for/main/topic
 	remote: proc-receive< issue=123
 	remote: proc-receive< reviewer=user1
-	remote: proc-receive> ok refs/for/master/topic
+	remote: proc-receive> ok refs/for/main/topic
 	remote: # post-receive hook
 	remote: post-receive< <ZERO-OID> <COMMIT-A> refs/heads/next
-	remote: post-receive< <ZERO-OID> <COMMIT-A> refs/for/master/topic
+	remote: post-receive< <ZERO-OID> <COMMIT-A> refs/for/main/topic
 	To <URL/of/upstream.git>
 	 * [new branch] HEAD -> next
-	 * [new reference] HEAD -> refs/for/master/topic
+	 * [new reference] HEAD -> refs/for/main/topic
 	EOF
 	test_cmp expect actual &&
 	git -C "$upstream" show-ref >out &&
 	make_user_friendly_and_stable_output <out >actual &&
 	cat >expect <<-EOF &&
-	<COMMIT-A> refs/heads/master
+	<COMMIT-A> refs/heads/main
 	<COMMIT-A> refs/heads/next
 	EOF
 	test_cmp expect actual
 '
 
-# Refs of upstream : master(A)             next(A)
-# Refs of workbench: master(A)  tags/v123
+# Refs of upstream : main(A)             next(A)
+# Refs of workbench: main(A)  tags/v123
 test_expect_success "cleanup ($PROTOCOL)" '
 	git -C "$upstream" update-ref -d refs/heads/next
 '
diff --git a/t/t5411/test-0027-push-options--porcelain.sh b/t/t5411/test-0027-push-options--porcelain.sh
index c89a1e7..3a6561b 100644
--- a/t/t5411/test-0027-push-options--porcelain.sh
+++ b/t/t5411/test-0027-push-options--porcelain.sh
@@ -3,20 +3,20 @@
 	write_script "$upstream/hooks/proc-receive" <<-EOF
 	printf >&2 "# proc-receive hook\n"
 	test-tool proc-receive -v \
-		-r "ok refs/for/master/topic"
+		-r "ok refs/for/main/topic"
 	EOF
 '
 
-# Refs of upstream : master(A)
-# Refs of workbench: master(A)  tags/v123
-# git push -o ...  :                       refs/for/master/topic
+# Refs of upstream : main(A)
+# Refs of workbench: main(A)  tags/v123
+# git push -o ...  :                       refs/for/main/topic
 test_expect_success "proc-receive: not support push options ($PROTOCOL/porcelain)" '
 	test_must_fail git -C workbench push \
 		--porcelain \
 		-o issue=123 \
 		-o reviewer=user1 \
 		origin \
-		HEAD:refs/for/master/topic \
+		HEAD:refs/for/main/topic \
 		>out 2>&1 &&
 	make_user_friendly_and_stable_output <out >actual &&
 	test_i18ngrep "fatal: the receiving end does not support push options" \
@@ -24,7 +24,7 @@
 	git -C "$upstream" show-ref >out &&
 	make_user_friendly_and_stable_output <out >actual &&
 	cat >expect <<-EOF &&
-	<COMMIT-A> refs/heads/master
+	<COMMIT-A> refs/heads/main
 	EOF
 	test_cmp expect actual
 '
@@ -33,9 +33,71 @@
 	git -C "$upstream" config receive.advertisePushOptions true
 '
 
-# Refs of upstream : master(A)
-# Refs of workbench: master(A)  tags/v123
-# git push -o ...  :                       next(A)  refs/for/master/topic
+test_expect_success "setup version=0 for proc-receive hook ($PROTOCOL/porcelain)" '
+	write_script "$upstream/hooks/proc-receive" <<-EOF
+	printf >&2 "# proc-receive hook\n"
+	test-tool proc-receive -v \
+		--version 0 \
+		-r "ok refs/for/main/topic"
+	EOF
+'
+
+# Refs of upstream : main(A)
+# Refs of workbench: main(A)  tags/v123
+# git push -o ...  :                       next(A)  refs/for/main/topic
+test_expect_success "proc-receive: ignore push-options for version 0 ($PROTOCOL/porcelain)" '
+	git -C workbench push \
+		--porcelain \
+		--atomic \
+		-o issue=123 \
+		-o reviewer=user1 \
+		origin \
+		HEAD:refs/heads/next \
+		HEAD:refs/for/main/topic \
+		>out 2>&1 &&
+	make_user_friendly_and_stable_output <out >actual &&
+	cat >expect <<-EOF &&
+	remote: # pre-receive hook
+	remote: pre-receive< <ZERO-OID> <COMMIT-A> refs/heads/next
+	remote: pre-receive< <ZERO-OID> <COMMIT-A> refs/for/main/topic
+	remote: # proc-receive hook
+	remote: proc-receive< <ZERO-OID> <COMMIT-A> refs/for/main/topic
+	remote: proc-receive> ok refs/for/main/topic
+	remote: # post-receive hook
+	remote: post-receive< <ZERO-OID> <COMMIT-A> refs/heads/next
+	remote: post-receive< <ZERO-OID> <COMMIT-A> refs/for/main/topic
+	To <URL/of/upstream.git>
+	*    HEAD:refs/heads/next    [new branch]
+	*    HEAD:refs/for/main/topic    [new reference]
+	Done
+	EOF
+	test_cmp expect actual &&
+	git -C "$upstream" show-ref >out &&
+	make_user_friendly_and_stable_output <out >actual &&
+	cat >expect <<-EOF &&
+	<COMMIT-A> refs/heads/main
+	<COMMIT-A> refs/heads/next
+	EOF
+	test_cmp expect actual
+'
+
+test_expect_success "restore proc-receive hook ($PROTOCOL/porcelain)" '
+	write_script "$upstream/hooks/proc-receive" <<-EOF
+	printf >&2 "# proc-receive hook\n"
+	test-tool proc-receive -v \
+		-r "ok refs/for/main/topic"
+	EOF
+'
+
+# Refs of upstream : main(A)             next(A)
+# Refs of workbench: main(A)  tags/v123
+test_expect_success "cleanup ($PROTOCOL/porcelain)" '
+	git -C "$upstream" update-ref -d refs/heads/next
+'
+
+# Refs of upstream : main(A)
+# Refs of workbench: main(A)  tags/v123
+# git push -o ...  :                       next(A)  refs/for/main/topic
 test_expect_success "proc-receive: push with options ($PROTOCOL/porcelain)" '
 	git -C workbench push \
 		--porcelain \
@@ -44,39 +106,39 @@
 		-o reviewer=user1 \
 		origin \
 		HEAD:refs/heads/next \
-		HEAD:refs/for/master/topic \
+		HEAD:refs/for/main/topic \
 		>out 2>&1 &&
 	make_user_friendly_and_stable_output <out >actual &&
 	cat >expect <<-EOF &&
 	remote: # pre-receive hook
 	remote: pre-receive< <ZERO-OID> <COMMIT-A> refs/heads/next
-	remote: pre-receive< <ZERO-OID> <COMMIT-A> refs/for/master/topic
+	remote: pre-receive< <ZERO-OID> <COMMIT-A> refs/for/main/topic
 	remote: # proc-receive hook
 	remote: proc-receive: atomic push_options
-	remote: proc-receive< <ZERO-OID> <COMMIT-A> refs/for/master/topic
+	remote: proc-receive< <ZERO-OID> <COMMIT-A> refs/for/main/topic
 	remote: proc-receive< issue=123
 	remote: proc-receive< reviewer=user1
-	remote: proc-receive> ok refs/for/master/topic
+	remote: proc-receive> ok refs/for/main/topic
 	remote: # post-receive hook
 	remote: post-receive< <ZERO-OID> <COMMIT-A> refs/heads/next
-	remote: post-receive< <ZERO-OID> <COMMIT-A> refs/for/master/topic
+	remote: post-receive< <ZERO-OID> <COMMIT-A> refs/for/main/topic
 	To <URL/of/upstream.git>
 	*    HEAD:refs/heads/next    [new branch]
-	*    HEAD:refs/for/master/topic    [new reference]
+	*    HEAD:refs/for/main/topic    [new reference]
 	Done
 	EOF
 	test_cmp expect actual &&
 	git -C "$upstream" show-ref >out &&
 	make_user_friendly_and_stable_output <out >actual &&
 	cat >expect <<-EOF &&
-	<COMMIT-A> refs/heads/master
+	<COMMIT-A> refs/heads/main
 	<COMMIT-A> refs/heads/next
 	EOF
 	test_cmp expect actual
 '
 
-# Refs of upstream : master(A)             next(A)
-# Refs of workbench: master(A)  tags/v123
+# Refs of upstream : main(A)             next(A)
+# Refs of workbench: main(A)  tags/v123
 test_expect_success "cleanup ($PROTOCOL/porcelain)" '
 	git -C "$upstream" update-ref -d refs/heads/next
 '
diff --git a/t/t5411/test-0030-report-ok.sh b/t/t5411/test-0030-report-ok.sh
index 44c99d3..5d6feef 100644
--- a/t/t5411/test-0030-report-ok.sh
+++ b/t/t5411/test-0030-report-ok.sh
@@ -2,34 +2,34 @@
 	write_script "$upstream/hooks/proc-receive" <<-EOF
 	printf >&2 "# proc-receive hook\n"
 	test-tool proc-receive -v \
-		-r "ok refs/for/master/topic"
+		-r "ok refs/for/main/topic"
 	EOF
 '
 
-# Refs of upstream : master(A)
-# Refs of workbench: master(A)  tags/v123
-# git push         :                       refs/for/master/topic
+# Refs of upstream : main(A)
+# Refs of workbench: main(A)  tags/v123
+# git push         :                       refs/for/main/topic
 test_expect_success "proc-receive: ok ($PROTOCOL)" '
 	git -C workbench push origin \
-		HEAD:refs/for/master/topic \
+		HEAD:refs/for/main/topic \
 		>out 2>&1 &&
 	make_user_friendly_and_stable_output <out >actual &&
 	cat >expect <<-EOF &&
 	remote: # pre-receive hook
-	remote: pre-receive< <ZERO-OID> <COMMIT-A> refs/for/master/topic
+	remote: pre-receive< <ZERO-OID> <COMMIT-A> refs/for/main/topic
 	remote: # proc-receive hook
-	remote: proc-receive< <ZERO-OID> <COMMIT-A> refs/for/master/topic
-	remote: proc-receive> ok refs/for/master/topic
+	remote: proc-receive< <ZERO-OID> <COMMIT-A> refs/for/main/topic
+	remote: proc-receive> ok refs/for/main/topic
 	remote: # post-receive hook
-	remote: post-receive< <ZERO-OID> <COMMIT-A> refs/for/master/topic
+	remote: post-receive< <ZERO-OID> <COMMIT-A> refs/for/main/topic
 	To <URL/of/upstream.git>
-	 * [new reference] HEAD -> refs/for/master/topic
+	 * [new reference] HEAD -> refs/for/main/topic
 	EOF
 	test_cmp expect actual &&
 	git -C "$upstream" show-ref >out &&
 	make_user_friendly_and_stable_output <out >actual &&
 	cat >expect <<-EOF &&
-	<COMMIT-A> refs/heads/master
+	<COMMIT-A> refs/heads/main
 	EOF
 	test_cmp expect actual
 '
diff --git a/t/t5411/test-0031-report-ok--porcelain.sh b/t/t5411/test-0031-report-ok--porcelain.sh
index 3223b26..91666d3 100644
--- a/t/t5411/test-0031-report-ok--porcelain.sh
+++ b/t/t5411/test-0031-report-ok--porcelain.sh
@@ -2,35 +2,35 @@
 	write_script "$upstream/hooks/proc-receive" <<-EOF
 	printf >&2 "# proc-receive hook\n"
 	test-tool proc-receive -v \
-		-r "ok refs/for/master/topic"
+		-r "ok refs/for/main/topic"
 	EOF
 '
 
-# Refs of upstream : master(A)
-# Refs of workbench: master(A)  tags/v123
-# git push         :                       refs/for/master/topic
+# Refs of upstream : main(A)
+# Refs of workbench: main(A)  tags/v123
+# git push         :                       refs/for/main/topic
 test_expect_success "proc-receive: ok ($PROTOCOL/porcelain)" '
 	git -C workbench push --porcelain origin \
-		HEAD:refs/for/master/topic \
+		HEAD:refs/for/main/topic \
 		>out 2>&1 &&
 	make_user_friendly_and_stable_output <out >actual &&
 	cat >expect <<-EOF &&
 	remote: # pre-receive hook
-	remote: pre-receive< <ZERO-OID> <COMMIT-A> refs/for/master/topic
+	remote: pre-receive< <ZERO-OID> <COMMIT-A> refs/for/main/topic
 	remote: # proc-receive hook
-	remote: proc-receive< <ZERO-OID> <COMMIT-A> refs/for/master/topic
-	remote: proc-receive> ok refs/for/master/topic
+	remote: proc-receive< <ZERO-OID> <COMMIT-A> refs/for/main/topic
+	remote: proc-receive> ok refs/for/main/topic
 	remote: # post-receive hook
-	remote: post-receive< <ZERO-OID> <COMMIT-A> refs/for/master/topic
+	remote: post-receive< <ZERO-OID> <COMMIT-A> refs/for/main/topic
 	To <URL/of/upstream.git>
-	*    HEAD:refs/for/master/topic    [new reference]
+	*    HEAD:refs/for/main/topic    [new reference]
 	Done
 	EOF
 	test_cmp expect actual &&
 	git -C "$upstream" show-ref >out &&
 	make_user_friendly_and_stable_output <out >actual &&
 	cat >expect <<-EOF &&
-	<COMMIT-A> refs/heads/master
+	<COMMIT-A> refs/heads/main
 	EOF
 	test_cmp expect actual
 '
diff --git a/t/t5411/test-0032-report-with-options.sh b/t/t5411/test-0032-report-with-options.sh
index b77b78c..a0faf5c 100644
--- a/t/t5411/test-0032-report-with-options.sh
+++ b/t/t5411/test-0032-report-with-options.sh
@@ -7,24 +7,24 @@
 	EOF
 '
 
-# Refs of upstream : master(A)
-# Refs of workbench: master(A)  tags/v123
-# git push         :                       refs/for/next/topic(A)  refs/for/a/b/c/topic(A)  refs/for/master/topic(A)
+# Refs of upstream : main(A)
+# Refs of workbench: main(A)  tags/v123
+# git push         :                       refs/for/next/topic(A)  refs/for/a/b/c/topic(A)  refs/for/main/topic(A)
 test_expect_success "proc-receive: report option without matching ok ($PROTOCOL)" '
 	test_must_fail git -C workbench push origin \
-		HEAD:refs/for/master/topic \
+		HEAD:refs/for/main/topic \
 		>out 2>&1 &&
 	make_user_friendly_and_stable_output <out >actual &&
 	cat >expect <<-EOF &&
 	remote: # pre-receive hook
-	remote: pre-receive< <ZERO-OID> <COMMIT-A> refs/for/master/topic
+	remote: pre-receive< <ZERO-OID> <COMMIT-A> refs/for/main/topic
 	remote: # proc-receive hook
-	remote: proc-receive< <ZERO-OID> <COMMIT-A> refs/for/master/topic
+	remote: proc-receive< <ZERO-OID> <COMMIT-A> refs/for/main/topic
 	remote: proc-receive> option refname refs/pull/123/head
 	remote: proc-receive> option old-oid <COMMIT-B>
 	remote: error: proc-receive reported "option" without a matching "ok/ng" directive
 	To <URL/of/upstream.git>
-	 ! [remote rejected] HEAD -> refs/for/master/topic (proc-receive failed to report status)
+	 ! [remote rejected] HEAD -> refs/for/main/topic (proc-receive failed to report status)
 	EOF
 	test_cmp expect actual
 '
@@ -33,25 +33,25 @@
 	write_script "$upstream/hooks/proc-receive" <<-EOF
 	printf >&2 "# proc-receive hook\n"
 	test-tool proc-receive -v \
-		-r "ok refs/for/master/topic" \
+		-r "ok refs/for/main/topic" \
 		-r "option refname refs/pull/123/head"
 	EOF
 '
 
-# Refs of upstream : master(A)
-# Refs of workbench: master(A)  tags/v123
-# git push         :                       refs/for/next/topic(A)  refs/for/a/b/c/topic(A)  refs/for/master/topic(A)
+# Refs of upstream : main(A)
+# Refs of workbench: main(A)  tags/v123
+# git push         :                       refs/for/next/topic(A)  refs/for/a/b/c/topic(A)  refs/for/main/topic(A)
 test_expect_success "proc-receive: report option refname ($PROTOCOL)" '
 	git -C workbench push origin \
-		HEAD:refs/for/master/topic \
+		HEAD:refs/for/main/topic \
 		>out 2>&1 &&
 	make_user_friendly_and_stable_output <out >actual &&
 	cat >expect <<-EOF &&
 	remote: # pre-receive hook
-	remote: pre-receive< <ZERO-OID> <COMMIT-A> refs/for/master/topic
+	remote: pre-receive< <ZERO-OID> <COMMIT-A> refs/for/main/topic
 	remote: # proc-receive hook
-	remote: proc-receive< <ZERO-OID> <COMMIT-A> refs/for/master/topic
-	remote: proc-receive> ok refs/for/master/topic
+	remote: proc-receive< <ZERO-OID> <COMMIT-A> refs/for/main/topic
+	remote: proc-receive> ok refs/for/main/topic
 	remote: proc-receive> option refname refs/pull/123/head
 	remote: # post-receive hook
 	remote: post-receive< <ZERO-OID> <COMMIT-A> refs/pull/123/head
@@ -65,25 +65,25 @@
 	write_script "$upstream/hooks/proc-receive" <<-EOF
 	printf >&2 "# proc-receive hook\n"
 	test-tool proc-receive -v \
-		-r "ok refs/for/master/topic" \
+		-r "ok refs/for/main/topic" \
 		-r "option refname refs/pull/123/head" \
 		-r "option forced-update"
 	EOF
 '
-# Refs of upstream : master(A)
-# Refs of workbench: master(A)  tags/v123
-# git push         :                       refs/for/next/topic(A)  refs/for/a/b/c/topic(A)  refs/for/master/topic(A)
+# Refs of upstream : main(A)
+# Refs of workbench: main(A)  tags/v123
+# git push         :                       refs/for/next/topic(A)  refs/for/a/b/c/topic(A)  refs/for/main/topic(A)
 test_expect_success "proc-receive: report option refname and forced-update ($PROTOCOL)" '
 	git -C workbench push origin \
-		HEAD:refs/for/master/topic \
+		HEAD:refs/for/main/topic \
 		>out 2>&1 &&
 	make_user_friendly_and_stable_output <out >actual &&
 	cat >expect <<-EOF &&
 	remote: # pre-receive hook
-	remote: pre-receive< <ZERO-OID> <COMMIT-A> refs/for/master/topic
+	remote: pre-receive< <ZERO-OID> <COMMIT-A> refs/for/main/topic
 	remote: # proc-receive hook
-	remote: proc-receive< <ZERO-OID> <COMMIT-A> refs/for/master/topic
-	remote: proc-receive> ok refs/for/master/topic
+	remote: proc-receive< <ZERO-OID> <COMMIT-A> refs/for/main/topic
+	remote: proc-receive> ok refs/for/main/topic
 	remote: proc-receive> option refname refs/pull/123/head
 	remote: proc-receive> option forced-update
 	remote: # post-receive hook
@@ -98,26 +98,26 @@
 	write_script "$upstream/hooks/proc-receive" <<-EOF
 	printf >&2 "# proc-receive hook\n"
 	test-tool proc-receive -v \
-		-r "ok refs/for/master/topic" \
+		-r "ok refs/for/main/topic" \
 		-r "option refname refs/pull/123/head" \
 		-r "option old-oid $B"
 	EOF
 '
 
-# Refs of upstream : master(A)
-# Refs of workbench: master(A)  tags/v123
-# git push         :                       refs/for/next/topic(A)  refs/for/a/b/c/topic(A)  refs/for/master/topic(A)
+# Refs of upstream : main(A)
+# Refs of workbench: main(A)  tags/v123
+# git push         :                       refs/for/next/topic(A)  refs/for/a/b/c/topic(A)  refs/for/main/topic(A)
 test_expect_success "proc-receive: report option refname and old-oid ($PROTOCOL)" '
 	git -C workbench push origin \
-		HEAD:refs/for/master/topic \
+		HEAD:refs/for/main/topic \
 		>out 2>&1 &&
 	make_user_friendly_and_stable_output <out >actual &&
 	cat >expect <<-EOF &&
 	remote: # pre-receive hook
-	remote: pre-receive< <ZERO-OID> <COMMIT-A> refs/for/master/topic
+	remote: pre-receive< <ZERO-OID> <COMMIT-A> refs/for/main/topic
 	remote: # proc-receive hook
-	remote: proc-receive< <ZERO-OID> <COMMIT-A> refs/for/master/topic
-	remote: proc-receive> ok refs/for/master/topic
+	remote: proc-receive< <ZERO-OID> <COMMIT-A> refs/for/main/topic
+	remote: proc-receive> ok refs/for/main/topic
 	remote: proc-receive> option refname refs/pull/123/head
 	remote: proc-receive> option old-oid <COMMIT-B>
 	remote: # post-receive hook
@@ -132,30 +132,30 @@
 	write_script "$upstream/hooks/proc-receive" <<-EOF
 	printf >&2 "# proc-receive hook\n"
 	test-tool proc-receive -v \
-		-r "ok refs/for/master/topic" \
+		-r "ok refs/for/main/topic" \
 		-r "option old-oid $B"
 	EOF
 '
 
-# Refs of upstream : master(A)
-# Refs of workbench: master(A)  tags/v123
-# git push         :                       refs/for/next/topic(A)  refs/for/a/b/c/topic(A)  refs/for/master/topic(A)
+# Refs of upstream : main(A)
+# Refs of workbench: main(A)  tags/v123
+# git push         :                       refs/for/next/topic(A)  refs/for/a/b/c/topic(A)  refs/for/main/topic(A)
 test_expect_success "proc-receive: report option old-oid ($PROTOCOL)" '
 	git -C workbench push origin \
-		HEAD:refs/for/master/topic \
+		HEAD:refs/for/main/topic \
 		>out 2>&1 &&
 	make_user_friendly_and_stable_output <out >actual &&
 	cat >expect <<-EOF &&
 	remote: # pre-receive hook
-	remote: pre-receive< <ZERO-OID> <COMMIT-A> refs/for/master/topic
+	remote: pre-receive< <ZERO-OID> <COMMIT-A> refs/for/main/topic
 	remote: # proc-receive hook
-	remote: proc-receive< <ZERO-OID> <COMMIT-A> refs/for/master/topic
-	remote: proc-receive> ok refs/for/master/topic
+	remote: proc-receive< <ZERO-OID> <COMMIT-A> refs/for/main/topic
+	remote: proc-receive> ok refs/for/main/topic
 	remote: proc-receive> option old-oid <COMMIT-B>
 	remote: # post-receive hook
-	remote: post-receive< <COMMIT-B> <COMMIT-A> refs/for/master/topic
+	remote: post-receive< <COMMIT-B> <COMMIT-A> refs/for/main/topic
 	To <URL/of/upstream.git>
-	 <OID-B>..<OID-A> HEAD -> refs/for/master/topic
+	 <OID-B>..<OID-A> HEAD -> refs/for/main/topic
 	EOF
 	test_cmp expect actual
 '
@@ -164,32 +164,32 @@
 	write_script "$upstream/hooks/proc-receive" <<-EOF
 	printf >&2 "# proc-receive hook\n"
 	test-tool proc-receive -v \
-		-r "ok refs/for/master/topic" \
+		-r "ok refs/for/main/topic" \
 		-r "option old-oid $A" \
 		-r "option new-oid $B"
 	EOF
 '
 
-# Refs of upstream : master(A)
-# Refs of workbench: master(A)  tags/v123
-# git push         :                       refs/for/next/topic(A)  refs/for/a/b/c/topic(A)  refs/for/master/topic(A)
+# Refs of upstream : main(A)
+# Refs of workbench: main(A)  tags/v123
+# git push         :                       refs/for/next/topic(A)  refs/for/a/b/c/topic(A)  refs/for/main/topic(A)
 test_expect_success "proc-receive: report option old-oid and new-oid ($PROTOCOL)" '
 	git -C workbench push origin \
-		HEAD:refs/for/master/topic \
+		HEAD:refs/for/main/topic \
 		>out 2>&1 &&
 	make_user_friendly_and_stable_output <out >actual &&
 	cat >expect <<-EOF &&
 	remote: # pre-receive hook
-	remote: pre-receive< <ZERO-OID> <COMMIT-A> refs/for/master/topic
+	remote: pre-receive< <ZERO-OID> <COMMIT-A> refs/for/main/topic
 	remote: # proc-receive hook
-	remote: proc-receive< <ZERO-OID> <COMMIT-A> refs/for/master/topic
-	remote: proc-receive> ok refs/for/master/topic
+	remote: proc-receive< <ZERO-OID> <COMMIT-A> refs/for/main/topic
+	remote: proc-receive> ok refs/for/main/topic
 	remote: proc-receive> option old-oid <COMMIT-A>
 	remote: proc-receive> option new-oid <COMMIT-B>
 	remote: # post-receive hook
-	remote: post-receive< <COMMIT-A> <COMMIT-B> refs/for/master/topic
+	remote: post-receive< <COMMIT-A> <COMMIT-B> refs/for/main/topic
 	To <URL/of/upstream.git>
-	 <OID-A>..<OID-B> HEAD -> refs/for/master/topic
+	 <OID-A>..<OID-B> HEAD -> refs/for/main/topic
 	EOF
 	test_cmp expect actual
 '
@@ -201,7 +201,7 @@
 		-r "ok refs/for/a/b/c/topic" \
 		-r "ok refs/for/next/topic" \
 		-r "option refname refs/pull/123/head" \
-		-r "ok refs/for/master/topic" \
+		-r "ok refs/for/main/topic" \
 		-r "option refname refs/pull/124/head" \
 		-r "option old-oid $B" \
 		-r "option forced-update" \
@@ -209,29 +209,29 @@
 	EOF
 '
 
-# Refs of upstream : master(A)
-# Refs of workbench: master(A)  tags/v123
-# git push         :                       refs/for/next/topic(A)  refs/for/a/b/c/topic(A)  refs/for/master/topic(A)
+# Refs of upstream : main(A)
+# Refs of workbench: main(A)  tags/v123
+# git push         :                       refs/for/next/topic(A)  refs/for/a/b/c/topic(A)  refs/for/main/topic(A)
 test_expect_success "proc-receive: report with multiple rewrites ($PROTOCOL)" '
 	git -C workbench push origin \
 		HEAD:refs/for/next/topic \
 		HEAD:refs/for/a/b/c/topic \
-		HEAD:refs/for/master/topic \
+		HEAD:refs/for/main/topic \
 		>out 2>&1 &&
 	make_user_friendly_and_stable_output <out >actual &&
 	cat >expect <<-EOF &&
 	remote: # pre-receive hook
 	remote: pre-receive< <ZERO-OID> <COMMIT-A> refs/for/next/topic
 	remote: pre-receive< <ZERO-OID> <COMMIT-A> refs/for/a/b/c/topic
-	remote: pre-receive< <ZERO-OID> <COMMIT-A> refs/for/master/topic
+	remote: pre-receive< <ZERO-OID> <COMMIT-A> refs/for/main/topic
 	remote: # proc-receive hook
 	remote: proc-receive< <ZERO-OID> <COMMIT-A> refs/for/next/topic
 	remote: proc-receive< <ZERO-OID> <COMMIT-A> refs/for/a/b/c/topic
-	remote: proc-receive< <ZERO-OID> <COMMIT-A> refs/for/master/topic
+	remote: proc-receive< <ZERO-OID> <COMMIT-A> refs/for/main/topic
 	remote: proc-receive> ok refs/for/a/b/c/topic
 	remote: proc-receive> ok refs/for/next/topic
 	remote: proc-receive> option refname refs/pull/123/head
-	remote: proc-receive> ok refs/for/master/topic
+	remote: proc-receive> ok refs/for/main/topic
 	remote: proc-receive> option refname refs/pull/124/head
 	remote: proc-receive> option old-oid <COMMIT-B>
 	remote: proc-receive> option forced-update
@@ -250,7 +250,7 @@
 	git -C "$upstream" show-ref >out &&
 	make_user_friendly_and_stable_output <out >actual &&
 	cat >expect <<-EOF &&
-	<COMMIT-A> refs/heads/master
+	<COMMIT-A> refs/heads/main
 	EOF
 	test_cmp expect actual
 '
diff --git a/t/t5411/test-0033-report-with-options--porcelain.sh b/t/t5411/test-0033-report-with-options--porcelain.sh
index 1fe352b..32ae26b 100644
--- a/t/t5411/test-0033-report-with-options--porcelain.sh
+++ b/t/t5411/test-0033-report-with-options--porcelain.sh
@@ -7,24 +7,24 @@
 	EOF
 '
 
-# Refs of upstream : master(A)
-# Refs of workbench: master(A)  tags/v123
-# git push         :                       refs/for/next/topic(A)  refs/for/a/b/c/topic(A)  refs/for/master/topic(A)
+# Refs of upstream : main(A)
+# Refs of workbench: main(A)  tags/v123
+# git push         :                       refs/for/next/topic(A)  refs/for/a/b/c/topic(A)  refs/for/main/topic(A)
 test_expect_success "proc-receive: report option without matching ok ($PROTOCOL/porcelain)" '
 	test_must_fail git -C workbench push --porcelain origin \
-		HEAD:refs/for/master/topic \
+		HEAD:refs/for/main/topic \
 		>out 2>&1 &&
 	make_user_friendly_and_stable_output <out >actual &&
 	cat >expect <<-EOF &&
 	remote: # pre-receive hook
-	remote: pre-receive< <ZERO-OID> <COMMIT-A> refs/for/master/topic
+	remote: pre-receive< <ZERO-OID> <COMMIT-A> refs/for/main/topic
 	remote: # proc-receive hook
-	remote: proc-receive< <ZERO-OID> <COMMIT-A> refs/for/master/topic
+	remote: proc-receive< <ZERO-OID> <COMMIT-A> refs/for/main/topic
 	remote: proc-receive> option refname refs/pull/123/head
 	remote: proc-receive> option old-oid <COMMIT-B>
 	remote: error: proc-receive reported "option" without a matching "ok/ng" directive
 	To <URL/of/upstream.git>
-	!    HEAD:refs/for/master/topic    [remote rejected] (proc-receive failed to report status)
+	!    HEAD:refs/for/main/topic    [remote rejected] (proc-receive failed to report status)
 	Done
 	EOF
 	test_cmp expect actual
@@ -34,25 +34,25 @@
 	write_script "$upstream/hooks/proc-receive" <<-EOF
 	printf >&2 "# proc-receive hook\n"
 	test-tool proc-receive -v \
-		-r "ok refs/for/master/topic" \
+		-r "ok refs/for/main/topic" \
 		-r "option refname refs/pull/123/head"
 	EOF
 '
 
-# Refs of upstream : master(A)
-# Refs of workbench: master(A)  tags/v123
-# git push         :                       refs/for/next/topic(A)  refs/for/a/b/c/topic(A)  refs/for/master/topic(A)
+# Refs of upstream : main(A)
+# Refs of workbench: main(A)  tags/v123
+# git push         :                       refs/for/next/topic(A)  refs/for/a/b/c/topic(A)  refs/for/main/topic(A)
 test_expect_success "proc-receive: report option refname ($PROTOCOL/porcelain)" '
 	git -C workbench push --porcelain origin \
-		HEAD:refs/for/master/topic \
+		HEAD:refs/for/main/topic \
 		>out 2>&1 &&
 	make_user_friendly_and_stable_output <out >actual &&
 	cat >expect <<-EOF &&
 	remote: # pre-receive hook
-	remote: pre-receive< <ZERO-OID> <COMMIT-A> refs/for/master/topic
+	remote: pre-receive< <ZERO-OID> <COMMIT-A> refs/for/main/topic
 	remote: # proc-receive hook
-	remote: proc-receive< <ZERO-OID> <COMMIT-A> refs/for/master/topic
-	remote: proc-receive> ok refs/for/master/topic
+	remote: proc-receive< <ZERO-OID> <COMMIT-A> refs/for/main/topic
+	remote: proc-receive> ok refs/for/main/topic
 	remote: proc-receive> option refname refs/pull/123/head
 	remote: # post-receive hook
 	remote: post-receive< <ZERO-OID> <COMMIT-A> refs/pull/123/head
@@ -67,26 +67,26 @@
 	write_script "$upstream/hooks/proc-receive" <<-EOF
 	printf >&2 "# proc-receive hook\n"
 	test-tool proc-receive -v \
-		-r "ok refs/for/master/topic" \
+		-r "ok refs/for/main/topic" \
 		-r "option refname refs/pull/123/head" \
 		-r "option forced-update"
 	EOF
 '
 
-# Refs of upstream : master(A)
-# Refs of workbench: master(A)  tags/v123
-# git push         :                       refs/for/next/topic(A)  refs/for/a/b/c/topic(A)  refs/for/master/topic(A)
+# Refs of upstream : main(A)
+# Refs of workbench: main(A)  tags/v123
+# git push         :                       refs/for/next/topic(A)  refs/for/a/b/c/topic(A)  refs/for/main/topic(A)
 test_expect_success "proc-receive: report option refname and forced-update ($PROTOCOL/porcelain)" '
 	git -C workbench push --porcelain origin \
-		HEAD:refs/for/master/topic \
+		HEAD:refs/for/main/topic \
 		>out 2>&1 &&
 	make_user_friendly_and_stable_output <out >actual &&
 	cat >expect <<-EOF &&
 	remote: # pre-receive hook
-	remote: pre-receive< <ZERO-OID> <COMMIT-A> refs/for/master/topic
+	remote: pre-receive< <ZERO-OID> <COMMIT-A> refs/for/main/topic
 	remote: # proc-receive hook
-	remote: proc-receive< <ZERO-OID> <COMMIT-A> refs/for/master/topic
-	remote: proc-receive> ok refs/for/master/topic
+	remote: proc-receive< <ZERO-OID> <COMMIT-A> refs/for/main/topic
+	remote: proc-receive> ok refs/for/main/topic
 	remote: proc-receive> option refname refs/pull/123/head
 	remote: proc-receive> option forced-update
 	remote: # post-receive hook
@@ -102,26 +102,26 @@
 	write_script "$upstream/hooks/proc-receive" <<-EOF
 	printf >&2 "# proc-receive hook\n"
 	test-tool proc-receive -v \
-		-r "ok refs/for/master/topic" \
+		-r "ok refs/for/main/topic" \
 		-r "option refname refs/pull/123/head" \
 		-r "option old-oid $B"
 	EOF
 '
 
-# Refs of upstream : master(A)
-# Refs of workbench: master(A)  tags/v123
-# git push         :                       refs/for/next/topic(A)  refs/for/a/b/c/topic(A)  refs/for/master/topic(A)
+# Refs of upstream : main(A)
+# Refs of workbench: main(A)  tags/v123
+# git push         :                       refs/for/next/topic(A)  refs/for/a/b/c/topic(A)  refs/for/main/topic(A)
 test_expect_success "proc-receive: report option refname and old-oid ($PROTOCOL/porcelain)" '
 	git -C workbench push --porcelain origin \
-		HEAD:refs/for/master/topic \
+		HEAD:refs/for/main/topic \
 		>out 2>&1 &&
 	make_user_friendly_and_stable_output <out >actual &&
 	cat >expect <<-EOF &&
 	remote: # pre-receive hook
-	remote: pre-receive< <ZERO-OID> <COMMIT-A> refs/for/master/topic
+	remote: pre-receive< <ZERO-OID> <COMMIT-A> refs/for/main/topic
 	remote: # proc-receive hook
-	remote: proc-receive< <ZERO-OID> <COMMIT-A> refs/for/master/topic
-	remote: proc-receive> ok refs/for/master/topic
+	remote: proc-receive< <ZERO-OID> <COMMIT-A> refs/for/main/topic
+	remote: proc-receive> ok refs/for/main/topic
 	remote: proc-receive> option refname refs/pull/123/head
 	remote: proc-receive> option old-oid <COMMIT-B>
 	remote: # post-receive hook
@@ -137,30 +137,30 @@
 	write_script "$upstream/hooks/proc-receive" <<-EOF
 	printf >&2 "# proc-receive hook\n"
 	test-tool proc-receive -v \
-		-r "ok refs/for/master/topic" \
+		-r "ok refs/for/main/topic" \
 		-r "option old-oid $B"
 	EOF
 '
 
-# Refs of upstream : master(A)
-# Refs of workbench: master(A)  tags/v123
-# git push         :                       refs/for/next/topic(A)  refs/for/a/b/c/topic(A)  refs/for/master/topic(A)
+# Refs of upstream : main(A)
+# Refs of workbench: main(A)  tags/v123
+# git push         :                       refs/for/next/topic(A)  refs/for/a/b/c/topic(A)  refs/for/main/topic(A)
 test_expect_success "proc-receive: report option old-oid ($PROTOCOL/porcelain)" '
 	git -C workbench push --porcelain origin \
-		HEAD:refs/for/master/topic \
+		HEAD:refs/for/main/topic \
 		>out 2>&1 &&
 	make_user_friendly_and_stable_output <out >actual &&
 	cat >expect <<-EOF &&
 	remote: # pre-receive hook
-	remote: pre-receive< <ZERO-OID> <COMMIT-A> refs/for/master/topic
+	remote: pre-receive< <ZERO-OID> <COMMIT-A> refs/for/main/topic
 	remote: # proc-receive hook
-	remote: proc-receive< <ZERO-OID> <COMMIT-A> refs/for/master/topic
-	remote: proc-receive> ok refs/for/master/topic
+	remote: proc-receive< <ZERO-OID> <COMMIT-A> refs/for/main/topic
+	remote: proc-receive> ok refs/for/main/topic
 	remote: proc-receive> option old-oid <COMMIT-B>
 	remote: # post-receive hook
-	remote: post-receive< <COMMIT-B> <COMMIT-A> refs/for/master/topic
+	remote: post-receive< <COMMIT-B> <COMMIT-A> refs/for/main/topic
 	To <URL/of/upstream.git>
-	     HEAD:refs/for/master/topic    <OID-B>..<OID-A>
+	     HEAD:refs/for/main/topic    <OID-B>..<OID-A>
 	Done
 	EOF
 	test_cmp expect actual
@@ -170,32 +170,32 @@
 	write_script "$upstream/hooks/proc-receive" <<-EOF
 	printf >&2 "# proc-receive hook\n"
 	test-tool proc-receive -v \
-		-r "ok refs/for/master/topic" \
+		-r "ok refs/for/main/topic" \
 		-r "option old-oid $A" \
 		-r "option new-oid $B"
 	EOF
 '
 
-# Refs of upstream : master(A)
-# Refs of workbench: master(A)  tags/v123
-# git push         :                       refs/for/next/topic(A)  refs/for/a/b/c/topic(A)  refs/for/master/topic(A)
+# Refs of upstream : main(A)
+# Refs of workbench: main(A)  tags/v123
+# git push         :                       refs/for/next/topic(A)  refs/for/a/b/c/topic(A)  refs/for/main/topic(A)
 test_expect_success "proc-receive: report option old-oid and new-oid ($PROTOCOL/porcelain)" '
 	git -C workbench push --porcelain origin \
-		HEAD:refs/for/master/topic \
+		HEAD:refs/for/main/topic \
 		>out 2>&1 &&
 	make_user_friendly_and_stable_output <out >actual &&
 	cat >expect <<-EOF &&
 	remote: # pre-receive hook
-	remote: pre-receive< <ZERO-OID> <COMMIT-A> refs/for/master/topic
+	remote: pre-receive< <ZERO-OID> <COMMIT-A> refs/for/main/topic
 	remote: # proc-receive hook
-	remote: proc-receive< <ZERO-OID> <COMMIT-A> refs/for/master/topic
-	remote: proc-receive> ok refs/for/master/topic
+	remote: proc-receive< <ZERO-OID> <COMMIT-A> refs/for/main/topic
+	remote: proc-receive> ok refs/for/main/topic
 	remote: proc-receive> option old-oid <COMMIT-A>
 	remote: proc-receive> option new-oid <COMMIT-B>
 	remote: # post-receive hook
-	remote: post-receive< <COMMIT-A> <COMMIT-B> refs/for/master/topic
+	remote: post-receive< <COMMIT-A> <COMMIT-B> refs/for/main/topic
 	To <URL/of/upstream.git>
-	     HEAD:refs/for/master/topic    <OID-A>..<OID-B>
+	     HEAD:refs/for/main/topic    <OID-A>..<OID-B>
 	Done
 	EOF
 	test_cmp expect actual
@@ -208,7 +208,7 @@
 		-r "ok refs/for/a/b/c/topic" \
 		-r "ok refs/for/next/topic" \
 		-r "option refname refs/pull/123/head" \
-		-r "ok refs/for/master/topic" \
+		-r "ok refs/for/main/topic" \
 		-r "option refname refs/pull/124/head" \
 		-r "option old-oid $B" \
 		-r "option forced-update" \
@@ -217,29 +217,29 @@
 	EOF
 '
 
-# Refs of upstream : master(A)
-# Refs of workbench: master(A)  tags/v123
-# git push         :                       refs/for/next/topic(A)  refs/for/a/b/c/topic(A)  refs/for/master/topic(A)
+# Refs of upstream : main(A)
+# Refs of workbench: main(A)  tags/v123
+# git push         :                       refs/for/next/topic(A)  refs/for/a/b/c/topic(A)  refs/for/main/topic(A)
 test_expect_success "proc-receive: report with multiple rewrites ($PROTOCOL/porcelain)" '
 	git -C workbench push --porcelain origin \
 		HEAD:refs/for/next/topic \
 		HEAD:refs/for/a/b/c/topic \
-		HEAD:refs/for/master/topic \
+		HEAD:refs/for/main/topic \
 		>out 2>&1 &&
 	make_user_friendly_and_stable_output <out >actual &&
 	cat >expect <<-EOF &&
 	remote: # pre-receive hook
 	remote: pre-receive< <ZERO-OID> <COMMIT-A> refs/for/next/topic
 	remote: pre-receive< <ZERO-OID> <COMMIT-A> refs/for/a/b/c/topic
-	remote: pre-receive< <ZERO-OID> <COMMIT-A> refs/for/master/topic
+	remote: pre-receive< <ZERO-OID> <COMMIT-A> refs/for/main/topic
 	remote: # proc-receive hook
 	remote: proc-receive< <ZERO-OID> <COMMIT-A> refs/for/next/topic
 	remote: proc-receive< <ZERO-OID> <COMMIT-A> refs/for/a/b/c/topic
-	remote: proc-receive< <ZERO-OID> <COMMIT-A> refs/for/master/topic
+	remote: proc-receive< <ZERO-OID> <COMMIT-A> refs/for/main/topic
 	remote: proc-receive> ok refs/for/a/b/c/topic
 	remote: proc-receive> ok refs/for/next/topic
 	remote: proc-receive> option refname refs/pull/123/head
-	remote: proc-receive> ok refs/for/master/topic
+	remote: proc-receive> ok refs/for/main/topic
 	remote: proc-receive> option refname refs/pull/124/head
 	remote: proc-receive> option old-oid <COMMIT-B>
 	remote: proc-receive> option forced-update
@@ -259,7 +259,7 @@
 	git -C "$upstream" show-ref >out &&
 	make_user_friendly_and_stable_output <out >actual &&
 	cat >expect <<-EOF &&
-	<COMMIT-A> refs/heads/master
+	<COMMIT-A> refs/heads/main
 	EOF
 	test_cmp expect actual
 '
diff --git a/t/t5411/test-0034-report-ft.sh b/t/t5411/test-0034-report-ft.sh
index aca2b06..c355c29 100644
--- a/t/t5411/test-0034-report-ft.sh
+++ b/t/t5411/test-0034-report-ft.sh
@@ -2,43 +2,43 @@
 	write_script "$upstream/hooks/proc-receive" <<-EOF
 	printf >&2 "# proc-receive hook\n"
 	test-tool proc-receive -v \
-		-r "ok refs/for/master/topic" \
+		-r "ok refs/for/main/topic" \
 		-r "option fall-through"
 	EOF
 '
 
-# Refs of upstream : master(A)
-# Refs of workbench: master(A)  tags/v123
-# git push         :                       refs/for/master/topic(B)
+# Refs of upstream : main(A)
+# Refs of workbench: main(A)  tags/v123
+# git push         :                       refs/for/main/topic(B)
 test_expect_success "proc-receive: fall throught, let receive-pack to execute ($PROTOCOL)" '
 	git -C workbench push origin \
-		$B:refs/for/master/topic \
+		$B:refs/for/main/topic \
 		>out 2>&1 &&
 	make_user_friendly_and_stable_output <out >actual &&
 	cat >expect <<-EOF &&
 	remote: # pre-receive hook
-	remote: pre-receive< <ZERO-OID> <COMMIT-B> refs/for/master/topic
+	remote: pre-receive< <ZERO-OID> <COMMIT-B> refs/for/main/topic
 	remote: # proc-receive hook
-	remote: proc-receive< <ZERO-OID> <COMMIT-B> refs/for/master/topic
-	remote: proc-receive> ok refs/for/master/topic
+	remote: proc-receive< <ZERO-OID> <COMMIT-B> refs/for/main/topic
+	remote: proc-receive> ok refs/for/main/topic
 	remote: proc-receive> option fall-through
 	remote: # post-receive hook
-	remote: post-receive< <ZERO-OID> <COMMIT-B> refs/for/master/topic
+	remote: post-receive< <ZERO-OID> <COMMIT-B> refs/for/main/topic
 	To <URL/of/upstream.git>
-	 * [new reference] <COMMIT-B> -> refs/for/master/topic
+	 * [new reference] <COMMIT-B> -> refs/for/main/topic
 	EOF
 	test_cmp expect actual &&
 	git -C "$upstream" show-ref >out &&
 	make_user_friendly_and_stable_output <out >actual &&
 	cat >expect <<-EOF &&
-	<COMMIT-B> refs/for/master/topic
-	<COMMIT-A> refs/heads/master
+	<COMMIT-B> refs/for/main/topic
+	<COMMIT-A> refs/heads/main
 	EOF
 	test_cmp expect actual
 '
 
-# Refs of upstream : master(A)             refs/for/master/topic(A)
-# Refs of workbench: master(A)  tags/v123
+# Refs of upstream : main(A)             refs/for/main/topic(A)
+# Refs of workbench: main(A)  tags/v123
 test_expect_success "cleanup ($PROTOCOL)" '
-	git -C "$upstream" update-ref -d refs/for/master/topic
+	git -C "$upstream" update-ref -d refs/for/main/topic
 '
diff --git a/t/t5411/test-0035-report-ft--porcelain.sh b/t/t5411/test-0035-report-ft--porcelain.sh
index 30ffffb..8ce4e58 100644
--- a/t/t5411/test-0035-report-ft--porcelain.sh
+++ b/t/t5411/test-0035-report-ft--porcelain.sh
@@ -2,44 +2,44 @@
 	write_script "$upstream/hooks/proc-receive" <<-EOF
 	printf >&2 "# proc-receive hook\n"
 	test-tool proc-receive -v \
-		-r "ok refs/for/master/topic" \
+		-r "ok refs/for/main/topic" \
 		-r "option fall-through"
 	EOF
 '
 
-# Refs of upstream : master(A)
-# Refs of workbench: master(A)  tags/v123
-# git push         :                       refs/for/master/topic(B)
+# Refs of upstream : main(A)
+# Refs of workbench: main(A)  tags/v123
+# git push         :                       refs/for/main/topic(B)
 test_expect_success "proc-receive: fall throught, let receive-pack to execute ($PROTOCOL/porcelain)" '
 	git -C workbench push --porcelain origin \
-		$B:refs/for/master/topic \
+		$B:refs/for/main/topic \
 		>out 2>&1 &&
 	make_user_friendly_and_stable_output <out >actual &&
 	cat >expect <<-EOF &&
 	remote: # pre-receive hook
-	remote: pre-receive< <ZERO-OID> <COMMIT-B> refs/for/master/topic
+	remote: pre-receive< <ZERO-OID> <COMMIT-B> refs/for/main/topic
 	remote: # proc-receive hook
-	remote: proc-receive< <ZERO-OID> <COMMIT-B> refs/for/master/topic
-	remote: proc-receive> ok refs/for/master/topic
+	remote: proc-receive< <ZERO-OID> <COMMIT-B> refs/for/main/topic
+	remote: proc-receive> ok refs/for/main/topic
 	remote: proc-receive> option fall-through
 	remote: # post-receive hook
-	remote: post-receive< <ZERO-OID> <COMMIT-B> refs/for/master/topic
+	remote: post-receive< <ZERO-OID> <COMMIT-B> refs/for/main/topic
 	To <URL/of/upstream.git>
-	*    <COMMIT-B>:refs/for/master/topic    [new reference]
+	*    <COMMIT-B>:refs/for/main/topic    [new reference]
 	Done
 	EOF
 	test_cmp expect actual &&
 	git -C "$upstream" show-ref >out &&
 	make_user_friendly_and_stable_output <out >actual &&
 	cat >expect <<-EOF &&
-	<COMMIT-B> refs/for/master/topic
-	<COMMIT-A> refs/heads/master
+	<COMMIT-B> refs/for/main/topic
+	<COMMIT-A> refs/heads/main
 	EOF
 	test_cmp expect actual
 '
 
-# Refs of upstream : master(A)             refs/for/master/topic(A)
-# Refs of workbench: master(A)  tags/v123
+# Refs of upstream : main(A)             refs/for/main/topic(A)
+# Refs of workbench: main(A)  tags/v123
 test_expect_success "cleanup ($PROTOCOL/porcelain)" '
-	git -C "$upstream" update-ref -d refs/for/master/topic
+	git -C "$upstream" update-ref -d refs/for/main/topic
 '
diff --git a/t/t5411/test-0036-report-multi-rewrite-for-one-ref.sh b/t/t5411/test-0036-report-multi-rewrite-for-one-ref.sh
index 73283d8..fad8eea 100644
--- a/t/t5411/test-0036-report-multi-rewrite-for-one-ref.sh
+++ b/t/t5411/test-0036-report-multi-rewrite-for-one-ref.sh
@@ -17,50 +17,50 @@
 	write_script "$upstream/hooks/proc-receive" <<-EOF
 	printf >&2 "# proc-receive hook\n"
 	test-tool proc-receive -v \
-		-r "ok refs/for/master/topic" \
+		-r "ok refs/for/main/topic" \
 		-r "option old-oid $A" \
 		-r "option new-oid $B" \
-		-r "ok refs/for/master/topic" \
+		-r "ok refs/for/main/topic" \
 		-r "option refname refs/changes/24/124/1" \
 		-r "option old-oid $ZERO_OID" \
 		-r "option new-oid $A" \
-		-r "ok refs/for/master/topic" \
+		-r "ok refs/for/main/topic" \
 		-r "option refname refs/changes/25/125/1" \
 		-r "option old-oid $A" \
 		-r "option new-oid $B"
 	EOF
 '
 
-# Refs of upstream : master(A)
-# Refs of workbench: master(A)  tags/v123
-# git push         :                       refs/for/master/topic(A)
+# Refs of upstream : main(A)
+# Refs of workbench: main(A)  tags/v123
+# git push         :                       refs/for/main/topic(A)
 test_expect_success "proc-receive: multiple rewrite for one ref, no refname for the 1st rewrite ($PROTOCOL)" '
 	git -C workbench push origin \
-		HEAD:refs/for/master/topic \
+		HEAD:refs/for/main/topic \
 		>out 2>&1 &&
 	make_user_friendly_and_stable_output <out >actual &&
 	cat >expect <<-EOF &&
 	remote: # pre-receive hook
-	remote: pre-receive< <ZERO-OID> <COMMIT-A> refs/for/master/topic
+	remote: pre-receive< <ZERO-OID> <COMMIT-A> refs/for/main/topic
 	remote: # proc-receive hook
-	remote: proc-receive< <ZERO-OID> <COMMIT-A> refs/for/master/topic
-	remote: proc-receive> ok refs/for/master/topic
+	remote: proc-receive< <ZERO-OID> <COMMIT-A> refs/for/main/topic
+	remote: proc-receive> ok refs/for/main/topic
 	remote: proc-receive> option old-oid <COMMIT-A>
 	remote: proc-receive> option new-oid <COMMIT-B>
-	remote: proc-receive> ok refs/for/master/topic
+	remote: proc-receive> ok refs/for/main/topic
 	remote: proc-receive> option refname refs/changes/24/124/1
 	remote: proc-receive> option old-oid <ZERO-OID>
 	remote: proc-receive> option new-oid <COMMIT-A>
-	remote: proc-receive> ok refs/for/master/topic
+	remote: proc-receive> ok refs/for/main/topic
 	remote: proc-receive> option refname refs/changes/25/125/1
 	remote: proc-receive> option old-oid <COMMIT-A>
 	remote: proc-receive> option new-oid <COMMIT-B>
 	remote: # post-receive hook
-	remote: post-receive< <COMMIT-A> <COMMIT-B> refs/for/master/topic
+	remote: post-receive< <COMMIT-A> <COMMIT-B> refs/for/main/topic
 	remote: post-receive< <ZERO-OID> <COMMIT-A> refs/changes/24/124/1
 	remote: post-receive< <COMMIT-A> <COMMIT-B> refs/changes/25/125/1
 	To <URL/of/upstream.git>
-	 <OID-A>..<OID-B> HEAD -> refs/for/master/topic
+	 <OID-A>..<OID-B> HEAD -> refs/for/main/topic
 	 * [new reference] HEAD -> refs/changes/24/124/1
 	 <OID-A>..<OID-B> HEAD -> refs/changes/25/125/1
 	EOF
@@ -68,7 +68,7 @@
 	git -C "$upstream" show-ref >out &&
 	make_user_friendly_and_stable_output <out >actual &&
 	cat >expect <<-EOF &&
-	<COMMIT-A> refs/heads/master
+	<COMMIT-A> refs/heads/main
 	EOF
 	test_cmp expect actual
 '
@@ -80,10 +80,10 @@
 	cat >expect <<-EOF &&
 	<COMMIT-A> refs/t/changes/24/124/1
 	<COMMIT-B> refs/t/changes/25/125/1
-	<COMMIT-B> refs/t/for/master/topic
+	<COMMIT-B> refs/t/for/main/topic
 	EOF
 	test_cmp expect actual &&
-	git -C workbench update-ref -d refs/t/for/master/topic &&
+	git -C workbench update-ref -d refs/t/for/main/topic &&
 	git -C workbench update-ref -d refs/t/changes/24/124/1 &&
 	git -C workbench update-ref -d refs/t/changes/25/125/1
 '
@@ -92,14 +92,14 @@
 	write_script "$upstream/hooks/proc-receive" <<-EOF
 	printf >&2 "# proc-receive hook\n"
 	test-tool proc-receive -v \
-		-r "ok refs/for/master/topic" \
+		-r "ok refs/for/main/topic" \
 		-r "option refname refs/changes/24/124/1" \
 		-r "option old-oid $ZERO_OID" \
 		-r "option new-oid $A" \
-		-r "ok refs/for/master/topic" \
+		-r "ok refs/for/main/topic" \
 		-r "option old-oid $A" \
 		-r "option new-oid $B" \
-		-r "ok refs/for/master/topic" \
+		-r "ok refs/for/main/topic" \
 		-r "option refname refs/changes/25/125/1" \
 		-r "option old-oid $B" \
 		-r "option new-oid $A" \
@@ -107,45 +107,45 @@
 	EOF
 '
 
-# Refs of upstream : master(A)
-# Refs of workbench: master(A)  tags/v123
-# git push         :                       refs/for/master/topic(A)
+# Refs of upstream : main(A)
+# Refs of workbench: main(A)  tags/v123
+# git push         :                       refs/for/main/topic(A)
 test_expect_success "proc-receive: multiple rewrites for one ref, no refname for the 2nd rewrite ($PROTOCOL)" '
 	git -C workbench push origin \
-		HEAD:refs/for/master/topic \
+		HEAD:refs/for/main/topic \
 		>out 2>&1 &&
 	make_user_friendly_and_stable_output <out >actual &&
 	cat >expect <<-EOF &&
 	remote: # pre-receive hook
-	remote: pre-receive< <ZERO-OID> <COMMIT-A> refs/for/master/topic
+	remote: pre-receive< <ZERO-OID> <COMMIT-A> refs/for/main/topic
 	remote: # proc-receive hook
-	remote: proc-receive< <ZERO-OID> <COMMIT-A> refs/for/master/topic
-	remote: proc-receive> ok refs/for/master/topic
+	remote: proc-receive< <ZERO-OID> <COMMIT-A> refs/for/main/topic
+	remote: proc-receive> ok refs/for/main/topic
 	remote: proc-receive> option refname refs/changes/24/124/1
 	remote: proc-receive> option old-oid <ZERO-OID>
 	remote: proc-receive> option new-oid <COMMIT-A>
-	remote: proc-receive> ok refs/for/master/topic
+	remote: proc-receive> ok refs/for/main/topic
 	remote: proc-receive> option old-oid <COMMIT-A>
 	remote: proc-receive> option new-oid <COMMIT-B>
-	remote: proc-receive> ok refs/for/master/topic
+	remote: proc-receive> ok refs/for/main/topic
 	remote: proc-receive> option refname refs/changes/25/125/1
 	remote: proc-receive> option old-oid <COMMIT-B>
 	remote: proc-receive> option new-oid <COMMIT-A>
 	remote: proc-receive> option forced-update
 	remote: # post-receive hook
 	remote: post-receive< <ZERO-OID> <COMMIT-A> refs/changes/24/124/1
-	remote: post-receive< <COMMIT-A> <COMMIT-B> refs/for/master/topic
+	remote: post-receive< <COMMIT-A> <COMMIT-B> refs/for/main/topic
 	remote: post-receive< <COMMIT-B> <COMMIT-A> refs/changes/25/125/1
 	To <URL/of/upstream.git>
 	 * [new reference] HEAD -> refs/changes/24/124/1
-	 <OID-A>..<OID-B> HEAD -> refs/for/master/topic
+	 <OID-A>..<OID-B> HEAD -> refs/for/main/topic
 	 + <OID-B>...<OID-A> HEAD -> refs/changes/25/125/1 (forced update)
 	EOF
 	test_cmp expect actual &&
 	git -C "$upstream" show-ref >out &&
 	make_user_friendly_and_stable_output <out >actual &&
 	cat >expect <<-EOF &&
-	<COMMIT-A> refs/heads/master
+	<COMMIT-A> refs/heads/main
 	EOF
 	test_cmp expect actual
 '
@@ -157,10 +157,10 @@
 	cat >expect <<-EOF &&
 	<COMMIT-A> refs/t/changes/24/124/1
 	<COMMIT-A> refs/t/changes/25/125/1
-	<COMMIT-B> refs/t/for/master/topic
+	<COMMIT-B> refs/t/for/main/topic
 	EOF
 	test_cmp expect actual &&
-	git -C workbench update-ref -d refs/t/for/master/topic &&
+	git -C workbench update-ref -d refs/t/for/main/topic &&
 	git -C workbench update-ref -d refs/t/changes/24/124/1 &&
 	git -C workbench update-ref -d refs/t/changes/25/125/1
 '
@@ -169,31 +169,31 @@
 	write_script "$upstream/hooks/proc-receive" <<-EOF
 	printf >&2 "# proc-receive hook\n"
 	test-tool proc-receive -v \
-		-r "ok refs/for/master/topic" \
+		-r "ok refs/for/main/topic" \
 		-r "option refname refs/changes/23/123/1" \
-		-r "ok refs/for/master/topic" \
+		-r "ok refs/for/main/topic" \
 		-r "option refname refs/changes/24/124/2" \
 		-r "option old-oid $A" \
 		-r "option new-oid $B"
 	EOF
 '
 
-# Refs of upstream : master(A)
-# Refs of workbench: master(A)  tags/v123
-# git push         :                       refs/for/master/topic(A)
+# Refs of upstream : main(A)
+# Refs of workbench: main(A)  tags/v123
+# git push         :                       refs/for/main/topic(A)
 test_expect_success "proc-receive: multiple rewrites for one ref ($PROTOCOL)" '
 	git -C workbench push origin \
-		HEAD:refs/for/master/topic \
+		HEAD:refs/for/main/topic \
 		>out 2>&1 &&
 	make_user_friendly_and_stable_output <out >actual &&
 	cat >expect <<-EOF &&
 	remote: # pre-receive hook
-	remote: pre-receive< <ZERO-OID> <COMMIT-A> refs/for/master/topic
+	remote: pre-receive< <ZERO-OID> <COMMIT-A> refs/for/main/topic
 	remote: # proc-receive hook
-	remote: proc-receive< <ZERO-OID> <COMMIT-A> refs/for/master/topic
-	remote: proc-receive> ok refs/for/master/topic
+	remote: proc-receive< <ZERO-OID> <COMMIT-A> refs/for/main/topic
+	remote: proc-receive> ok refs/for/main/topic
 	remote: proc-receive> option refname refs/changes/23/123/1
-	remote: proc-receive> ok refs/for/master/topic
+	remote: proc-receive> ok refs/for/main/topic
 	remote: proc-receive> option refname refs/changes/24/124/2
 	remote: proc-receive> option old-oid <COMMIT-A>
 	remote: proc-receive> option new-oid <COMMIT-B>
@@ -208,7 +208,7 @@
 	git -C "$upstream" show-ref >out &&
 	make_user_friendly_and_stable_output <out >actual &&
 	cat >expect <<-EOF &&
-	<COMMIT-A> refs/heads/master
+	<COMMIT-A> refs/heads/main
 	EOF
 	test_cmp expect actual
 '
diff --git a/t/t5411/test-0037-report-multi-rewrite-for-one-ref--porcelain.sh b/t/t5411/test-0037-report-multi-rewrite-for-one-ref--porcelain.sh
index 77b5b22..dc254d5 100644
--- a/t/t5411/test-0037-report-multi-rewrite-for-one-ref--porcelain.sh
+++ b/t/t5411/test-0037-report-multi-rewrite-for-one-ref--porcelain.sh
@@ -2,50 +2,50 @@
 	write_script "$upstream/hooks/proc-receive" <<-EOF
 	printf >&2 "# proc-receive hook\n"
 	test-tool proc-receive -v \
-		-r "ok refs/for/master/topic" \
+		-r "ok refs/for/main/topic" \
 		-r "option old-oid $A" \
 		-r "option new-oid $B" \
-		-r "ok refs/for/master/topic" \
+		-r "ok refs/for/main/topic" \
 		-r "option refname refs/changes/24/124/1" \
 		-r "option old-oid $ZERO_OID" \
 		-r "option new-oid $A" \
-		-r "ok refs/for/master/topic" \
+		-r "ok refs/for/main/topic" \
 		-r "option refname refs/changes/25/125/1" \
 		-r "option old-oid $A" \
 		-r "option new-oid $B"
 	EOF
 '
 
-# Refs of upstream : master(A)
-# Refs of workbench: master(A)  tags/v123
-# git push         :                       refs/for/master/topic(A)
+# Refs of upstream : main(A)
+# Refs of workbench: main(A)  tags/v123
+# git push         :                       refs/for/main/topic(A)
 test_expect_success "proc-receive: multiple rewrite for one ref, no refname for the 1st rewrite ($PROTOCOL/porcelain)" '
 	git -C workbench push --porcelain origin \
-		HEAD:refs/for/master/topic \
+		HEAD:refs/for/main/topic \
 		>out 2>&1 &&
 	make_user_friendly_and_stable_output <out >actual &&
 	cat >expect <<-EOF &&
 	remote: # pre-receive hook
-	remote: pre-receive< <ZERO-OID> <COMMIT-A> refs/for/master/topic
+	remote: pre-receive< <ZERO-OID> <COMMIT-A> refs/for/main/topic
 	remote: # proc-receive hook
-	remote: proc-receive< <ZERO-OID> <COMMIT-A> refs/for/master/topic
-	remote: proc-receive> ok refs/for/master/topic
+	remote: proc-receive< <ZERO-OID> <COMMIT-A> refs/for/main/topic
+	remote: proc-receive> ok refs/for/main/topic
 	remote: proc-receive> option old-oid <COMMIT-A>
 	remote: proc-receive> option new-oid <COMMIT-B>
-	remote: proc-receive> ok refs/for/master/topic
+	remote: proc-receive> ok refs/for/main/topic
 	remote: proc-receive> option refname refs/changes/24/124/1
 	remote: proc-receive> option old-oid <ZERO-OID>
 	remote: proc-receive> option new-oid <COMMIT-A>
-	remote: proc-receive> ok refs/for/master/topic
+	remote: proc-receive> ok refs/for/main/topic
 	remote: proc-receive> option refname refs/changes/25/125/1
 	remote: proc-receive> option old-oid <COMMIT-A>
 	remote: proc-receive> option new-oid <COMMIT-B>
 	remote: # post-receive hook
-	remote: post-receive< <COMMIT-A> <COMMIT-B> refs/for/master/topic
+	remote: post-receive< <COMMIT-A> <COMMIT-B> refs/for/main/topic
 	remote: post-receive< <ZERO-OID> <COMMIT-A> refs/changes/24/124/1
 	remote: post-receive< <COMMIT-A> <COMMIT-B> refs/changes/25/125/1
 	To <URL/of/upstream.git>
-	     HEAD:refs/for/master/topic    <OID-A>..<OID-B>
+	     HEAD:refs/for/main/topic    <OID-A>..<OID-B>
 	*    HEAD:refs/changes/24/124/1    [new reference]
 	     HEAD:refs/changes/25/125/1    <OID-A>..<OID-B>
 	Done
@@ -54,7 +54,7 @@
 	git -C "$upstream" show-ref >out &&
 	make_user_friendly_and_stable_output <out >actual &&
 	cat >expect <<-EOF &&
-	<COMMIT-A> refs/heads/master
+	<COMMIT-A> refs/heads/main
 	EOF
 	test_cmp expect actual
 '
@@ -63,14 +63,14 @@
 	write_script "$upstream/hooks/proc-receive" <<-EOF
 	printf >&2 "# proc-receive hook\n"
 	test-tool proc-receive -v \
-		-r "ok refs/for/master/topic" \
+		-r "ok refs/for/main/topic" \
 		-r "option refname refs/changes/24/124/1" \
 		-r "option old-oid $ZERO_OID" \
 		-r "option new-oid $A" \
-		-r "ok refs/for/master/topic" \
+		-r "ok refs/for/main/topic" \
 		-r "option old-oid $A" \
 		-r "option new-oid $B" \
-		-r "ok refs/for/master/topic" \
+		-r "ok refs/for/main/topic" \
 		-r "option refname refs/changes/25/125/1" \
 		-r "option old-oid $B" \
 		-r "option new-oid $A" \
@@ -78,38 +78,38 @@
 	EOF
 '
 
-# Refs of upstream : master(A)
-# Refs of workbench: master(A)  tags/v123
-# git push         :                       refs/for/master/topic(A)
+# Refs of upstream : main(A)
+# Refs of workbench: main(A)  tags/v123
+# git push         :                       refs/for/main/topic(A)
 test_expect_success "proc-receive: multiple rewrites for one ref, no refname for the 2nd rewrite ($PROTOCOL/porcelain)" '
 	git -C workbench push --porcelain origin \
-		HEAD:refs/for/master/topic \
+		HEAD:refs/for/main/topic \
 		>out 2>&1 &&
 	make_user_friendly_and_stable_output <out >actual &&
 	cat >expect <<-EOF &&
 	remote: # pre-receive hook
-	remote: pre-receive< <ZERO-OID> <COMMIT-A> refs/for/master/topic
+	remote: pre-receive< <ZERO-OID> <COMMIT-A> refs/for/main/topic
 	remote: # proc-receive hook
-	remote: proc-receive< <ZERO-OID> <COMMIT-A> refs/for/master/topic
-	remote: proc-receive> ok refs/for/master/topic
+	remote: proc-receive< <ZERO-OID> <COMMIT-A> refs/for/main/topic
+	remote: proc-receive> ok refs/for/main/topic
 	remote: proc-receive> option refname refs/changes/24/124/1
 	remote: proc-receive> option old-oid <ZERO-OID>
 	remote: proc-receive> option new-oid <COMMIT-A>
-	remote: proc-receive> ok refs/for/master/topic
+	remote: proc-receive> ok refs/for/main/topic
 	remote: proc-receive> option old-oid <COMMIT-A>
 	remote: proc-receive> option new-oid <COMMIT-B>
-	remote: proc-receive> ok refs/for/master/topic
+	remote: proc-receive> ok refs/for/main/topic
 	remote: proc-receive> option refname refs/changes/25/125/1
 	remote: proc-receive> option old-oid <COMMIT-B>
 	remote: proc-receive> option new-oid <COMMIT-A>
 	remote: proc-receive> option forced-update
 	remote: # post-receive hook
 	remote: post-receive< <ZERO-OID> <COMMIT-A> refs/changes/24/124/1
-	remote: post-receive< <COMMIT-A> <COMMIT-B> refs/for/master/topic
+	remote: post-receive< <COMMIT-A> <COMMIT-B> refs/for/main/topic
 	remote: post-receive< <COMMIT-B> <COMMIT-A> refs/changes/25/125/1
 	To <URL/of/upstream.git>
 	*    HEAD:refs/changes/24/124/1    [new reference]
-	     HEAD:refs/for/master/topic    <OID-A>..<OID-B>
+	     HEAD:refs/for/main/topic    <OID-A>..<OID-B>
 	+    HEAD:refs/changes/25/125/1    <OID-B>...<OID-A> (forced update)
 	Done
 	EOF
@@ -117,7 +117,7 @@
 	git -C "$upstream" show-ref >out &&
 	make_user_friendly_and_stable_output <out >actual &&
 	cat >expect <<-EOF &&
-	<COMMIT-A> refs/heads/master
+	<COMMIT-A> refs/heads/main
 	EOF
 	test_cmp expect actual
 '
@@ -126,31 +126,31 @@
 	write_script "$upstream/hooks/proc-receive" <<-EOF
 	printf >&2 "# proc-receive hook\n"
 	test-tool proc-receive -v \
-		-r "ok refs/for/master/topic" \
+		-r "ok refs/for/main/topic" \
 		-r "option refname refs/changes/23/123/1" \
-		-r "ok refs/for/master/topic" \
+		-r "ok refs/for/main/topic" \
 		-r "option refname refs/changes/24/124/2" \
 		-r "option old-oid $A" \
 		-r "option new-oid $B"
 	EOF
 '
 
-# Refs of upstream : master(A)
-# Refs of workbench: master(A)  tags/v123
-# git push         :                       refs/for/master/topic(A)
+# Refs of upstream : main(A)
+# Refs of workbench: main(A)  tags/v123
+# git push         :                       refs/for/main/topic(A)
 test_expect_success "proc-receive: multiple rewrites for one ref ($PROTOCOL/porcelain)" '
 	git -C workbench push --porcelain origin \
-		HEAD:refs/for/master/topic \
+		HEAD:refs/for/main/topic \
 		>out 2>&1 &&
 	make_user_friendly_and_stable_output <out >actual &&
 	cat >expect <<-EOF &&
 	remote: # pre-receive hook
-	remote: pre-receive< <ZERO-OID> <COMMIT-A> refs/for/master/topic
+	remote: pre-receive< <ZERO-OID> <COMMIT-A> refs/for/main/topic
 	remote: # proc-receive hook
-	remote: proc-receive< <ZERO-OID> <COMMIT-A> refs/for/master/topic
-	remote: proc-receive> ok refs/for/master/topic
+	remote: proc-receive< <ZERO-OID> <COMMIT-A> refs/for/main/topic
+	remote: proc-receive> ok refs/for/main/topic
 	remote: proc-receive> option refname refs/changes/23/123/1
-	remote: proc-receive> ok refs/for/master/topic
+	remote: proc-receive> ok refs/for/main/topic
 	remote: proc-receive> option refname refs/changes/24/124/2
 	remote: proc-receive> option old-oid <COMMIT-A>
 	remote: proc-receive> option new-oid <COMMIT-B>
@@ -166,7 +166,7 @@
 	git -C "$upstream" show-ref >out &&
 	make_user_friendly_and_stable_output <out >actual &&
 	cat >expect <<-EOF &&
-	<COMMIT-A> refs/heads/master
+	<COMMIT-A> refs/heads/main
 	EOF
 	test_cmp expect actual
 '
diff --git a/t/t5411/test-0038-report-mixed-refs.sh b/t/t5411/test-0038-report-mixed-refs.sh
index a74a2cb..0d071eb 100644
--- a/t/t5411/test-0038-report-mixed-refs.sh
+++ b/t/t5411/test-0038-report-mixed-refs.sh
@@ -4,63 +4,63 @@
 	test-tool proc-receive -v \
 		-r "ok refs/for/next/topic2" \
 		-r "ng refs/for/next/topic1 fail to call Web API" \
-		-r "ok refs/for/master/topic" \
-		-r "option refname refs/for/master/topic" \
+		-r "ok refs/for/main/topic" \
+		-r "option refname refs/for/main/topic" \
 		-r "option old-oid $A" \
 		-r "option new-oid $B"
 	EOF
 '
 
-# Refs of upstream : master(A)
-# Refs of workbench: master(A)  tags/v123
-# git push         : (B)                   bar(A)  baz(A)  refs/for/next/topic(A)  foo(A)  refs/for/master/topic(A)
+# Refs of upstream : main(A)
+# Refs of workbench: main(A)  tags/v123
+# git push         : (B)                   bar(A)  baz(A)  refs/for/next/topic(A)  foo(A)  refs/for/main/topic(A)
 test_expect_success "proc-receive: report update of mixed refs ($PROTOCOL)" '
 	test_must_fail git -C workbench push origin \
-		$B:refs/heads/master \
+		$B:refs/heads/main \
 		HEAD:refs/heads/bar \
 		HEAD:refs/heads/baz \
 		HEAD:refs/for/next/topic2 \
 		HEAD:refs/for/next/topic1 \
 		HEAD:refs/heads/foo \
-		HEAD:refs/for/master/topic \
+		HEAD:refs/for/main/topic \
 		HEAD:refs/for/next/topic3 \
 		>out 2>&1 &&
 	make_user_friendly_and_stable_output <out >actual &&
 	cat >expect <<-EOF &&
 	remote: # pre-receive hook
-	remote: pre-receive< <COMMIT-A> <COMMIT-B> refs/heads/master
+	remote: pre-receive< <COMMIT-A> <COMMIT-B> refs/heads/main
 	remote: pre-receive< <ZERO-OID> <COMMIT-A> refs/heads/bar
 	remote: pre-receive< <ZERO-OID> <COMMIT-A> refs/heads/baz
 	remote: pre-receive< <ZERO-OID> <COMMIT-A> refs/for/next/topic2
 	remote: pre-receive< <ZERO-OID> <COMMIT-A> refs/for/next/topic1
 	remote: pre-receive< <ZERO-OID> <COMMIT-A> refs/heads/foo
-	remote: pre-receive< <ZERO-OID> <COMMIT-A> refs/for/master/topic
+	remote: pre-receive< <ZERO-OID> <COMMIT-A> refs/for/main/topic
 	remote: pre-receive< <ZERO-OID> <COMMIT-A> refs/for/next/topic3
 	remote: # proc-receive hook
 	remote: proc-receive< <ZERO-OID> <COMMIT-A> refs/for/next/topic2
 	remote: proc-receive< <ZERO-OID> <COMMIT-A> refs/for/next/topic1
-	remote: proc-receive< <ZERO-OID> <COMMIT-A> refs/for/master/topic
+	remote: proc-receive< <ZERO-OID> <COMMIT-A> refs/for/main/topic
 	remote: proc-receive< <ZERO-OID> <COMMIT-A> refs/for/next/topic3
 	remote: proc-receive> ok refs/for/next/topic2
 	remote: proc-receive> ng refs/for/next/topic1 fail to call Web API
-	remote: proc-receive> ok refs/for/master/topic
-	remote: proc-receive> option refname refs/for/master/topic
+	remote: proc-receive> ok refs/for/main/topic
+	remote: proc-receive> option refname refs/for/main/topic
 	remote: proc-receive> option old-oid <COMMIT-A>
 	remote: proc-receive> option new-oid <COMMIT-B>
 	remote: # post-receive hook
-	remote: post-receive< <COMMIT-A> <COMMIT-B> refs/heads/master
+	remote: post-receive< <COMMIT-A> <COMMIT-B> refs/heads/main
 	remote: post-receive< <ZERO-OID> <COMMIT-A> refs/heads/bar
 	remote: post-receive< <ZERO-OID> <COMMIT-A> refs/heads/baz
 	remote: post-receive< <ZERO-OID> <COMMIT-A> refs/for/next/topic2
 	remote: post-receive< <ZERO-OID> <COMMIT-A> refs/heads/foo
-	remote: post-receive< <COMMIT-A> <COMMIT-B> refs/for/master/topic
+	remote: post-receive< <COMMIT-A> <COMMIT-B> refs/for/main/topic
 	To <URL/of/upstream.git>
-	 <OID-A>..<OID-B> <COMMIT-B> -> master
+	 <OID-A>..<OID-B> <COMMIT-B> -> main
 	 * [new branch] HEAD -> bar
 	 * [new branch] HEAD -> baz
 	 * [new reference] HEAD -> refs/for/next/topic2
 	 * [new branch] HEAD -> foo
-	 <OID-A>..<OID-B> HEAD -> refs/for/master/topic
+	 <OID-A>..<OID-B> HEAD -> refs/for/main/topic
 	 ! [remote rejected] HEAD -> refs/for/next/topic1 (fail to call Web API)
 	 ! [remote rejected] HEAD -> refs/for/next/topic3 (proc-receive failed to report status)
 	EOF
@@ -71,17 +71,17 @@
 	<COMMIT-A> refs/heads/bar
 	<COMMIT-A> refs/heads/baz
 	<COMMIT-A> refs/heads/foo
-	<COMMIT-B> refs/heads/master
+	<COMMIT-B> refs/heads/main
 	EOF
 	test_cmp expect actual
 '
 
-# Refs of upstream : master(B)             foo(A)  bar(A))  baz(A)
-# Refs of workbench: master(A)  tags/v123
+# Refs of upstream : main(B)             foo(A)  bar(A))  baz(A)
+# Refs of workbench: main(A)  tags/v123
 test_expect_success "cleanup ($PROTOCOL)" '
 	(
 		cd "$upstream" &&
-		git update-ref refs/heads/master $A &&
+		git update-ref refs/heads/main $A &&
 		git update-ref -d refs/heads/foo &&
 		git update-ref -d refs/heads/bar &&
 		git update-ref -d refs/heads/baz
diff --git a/t/t5411/test-0039-report-mixed-refs--porcelain.sh b/t/t5411/test-0039-report-mixed-refs--porcelain.sh
index e4baa13..d840991 100644
--- a/t/t5411/test-0039-report-mixed-refs--porcelain.sh
+++ b/t/t5411/test-0039-report-mixed-refs--porcelain.sh
@@ -4,63 +4,63 @@
 	test-tool proc-receive -v \
 		-r "ok refs/for/next/topic2" \
 		-r "ng refs/for/next/topic1 fail to call Web API" \
-		-r "ok refs/for/master/topic" \
-		-r "option refname refs/for/master/topic" \
+		-r "ok refs/for/main/topic" \
+		-r "option refname refs/for/main/topic" \
 		-r "option old-oid $A" \
 		-r "option new-oid $B"
 	EOF
 '
 
-# Refs of upstream : master(A)
-# Refs of workbench: master(A)  tags/v123
-# git push         : (B)                   bar(A)  baz(A)  refs/for/next/topic(A)  foo(A)  refs/for/master/topic(A)
+# Refs of upstream : main(A)
+# Refs of workbench: main(A)  tags/v123
+# git push         : (B)                   bar(A)  baz(A)  refs/for/next/topic(A)  foo(A)  refs/for/main/topic(A)
 test_expect_success "proc-receive: report update of mixed refs ($PROTOCOL/porcelain)" '
 	test_must_fail git -C workbench push --porcelain origin \
-		$B:refs/heads/master \
+		$B:refs/heads/main \
 		HEAD:refs/heads/bar \
 		HEAD:refs/heads/baz \
 		HEAD:refs/for/next/topic2 \
 		HEAD:refs/for/next/topic1 \
 		HEAD:refs/heads/foo \
-		HEAD:refs/for/master/topic \
+		HEAD:refs/for/main/topic \
 		HEAD:refs/for/next/topic3 \
 		>out 2>&1 &&
 	make_user_friendly_and_stable_output <out >actual &&
 	cat >expect <<-EOF &&
 	remote: # pre-receive hook
-	remote: pre-receive< <COMMIT-A> <COMMIT-B> refs/heads/master
+	remote: pre-receive< <COMMIT-A> <COMMIT-B> refs/heads/main
 	remote: pre-receive< <ZERO-OID> <COMMIT-A> refs/heads/bar
 	remote: pre-receive< <ZERO-OID> <COMMIT-A> refs/heads/baz
 	remote: pre-receive< <ZERO-OID> <COMMIT-A> refs/for/next/topic2
 	remote: pre-receive< <ZERO-OID> <COMMIT-A> refs/for/next/topic1
 	remote: pre-receive< <ZERO-OID> <COMMIT-A> refs/heads/foo
-	remote: pre-receive< <ZERO-OID> <COMMIT-A> refs/for/master/topic
+	remote: pre-receive< <ZERO-OID> <COMMIT-A> refs/for/main/topic
 	remote: pre-receive< <ZERO-OID> <COMMIT-A> refs/for/next/topic3
 	remote: # proc-receive hook
 	remote: proc-receive< <ZERO-OID> <COMMIT-A> refs/for/next/topic2
 	remote: proc-receive< <ZERO-OID> <COMMIT-A> refs/for/next/topic1
-	remote: proc-receive< <ZERO-OID> <COMMIT-A> refs/for/master/topic
+	remote: proc-receive< <ZERO-OID> <COMMIT-A> refs/for/main/topic
 	remote: proc-receive< <ZERO-OID> <COMMIT-A> refs/for/next/topic3
 	remote: proc-receive> ok refs/for/next/topic2
 	remote: proc-receive> ng refs/for/next/topic1 fail to call Web API
-	remote: proc-receive> ok refs/for/master/topic
-	remote: proc-receive> option refname refs/for/master/topic
+	remote: proc-receive> ok refs/for/main/topic
+	remote: proc-receive> option refname refs/for/main/topic
 	remote: proc-receive> option old-oid <COMMIT-A>
 	remote: proc-receive> option new-oid <COMMIT-B>
 	remote: # post-receive hook
-	remote: post-receive< <COMMIT-A> <COMMIT-B> refs/heads/master
+	remote: post-receive< <COMMIT-A> <COMMIT-B> refs/heads/main
 	remote: post-receive< <ZERO-OID> <COMMIT-A> refs/heads/bar
 	remote: post-receive< <ZERO-OID> <COMMIT-A> refs/heads/baz
 	remote: post-receive< <ZERO-OID> <COMMIT-A> refs/for/next/topic2
 	remote: post-receive< <ZERO-OID> <COMMIT-A> refs/heads/foo
-	remote: post-receive< <COMMIT-A> <COMMIT-B> refs/for/master/topic
+	remote: post-receive< <COMMIT-A> <COMMIT-B> refs/for/main/topic
 	To <URL/of/upstream.git>
-	     <COMMIT-B>:refs/heads/master    <OID-A>..<OID-B>
+	     <COMMIT-B>:refs/heads/main    <OID-A>..<OID-B>
 	*    HEAD:refs/heads/bar    [new branch]
 	*    HEAD:refs/heads/baz    [new branch]
 	*    HEAD:refs/for/next/topic2    [new reference]
 	*    HEAD:refs/heads/foo    [new branch]
-	     HEAD:refs/for/master/topic    <OID-A>..<OID-B>
+	     HEAD:refs/for/main/topic    <OID-A>..<OID-B>
 	!    HEAD:refs/for/next/topic1    [remote rejected] (fail to call Web API)
 	!    HEAD:refs/for/next/topic3    [remote rejected] (proc-receive failed to report status)
 	Done
@@ -72,17 +72,17 @@
 	<COMMIT-A> refs/heads/bar
 	<COMMIT-A> refs/heads/baz
 	<COMMIT-A> refs/heads/foo
-	<COMMIT-B> refs/heads/master
+	<COMMIT-B> refs/heads/main
 	EOF
 	test_cmp expect actual
 '
 
-# Refs of upstream : master(B)             foo(A)  bar(A))  baz(A)
-# Refs of workbench: master(A)  tags/v123
+# Refs of upstream : main(B)             foo(A)  bar(A))  baz(A)
+# Refs of workbench: main(A)  tags/v123
 test_expect_success "cleanup ($PROTOCOL/porcelain)" '
 	(
 		cd "$upstream" &&
-		git update-ref refs/heads/master $A &&
+		git update-ref refs/heads/main $A &&
 		git update-ref -d refs/heads/foo &&
 		git update-ref -d refs/heads/bar &&
 		git update-ref -d refs/heads/baz
diff --git a/t/t5411/test-0040-process-all-refs.sh b/t/t5411/test-0040-process-all-refs.sh
index b07c999..2565302 100644
--- a/t/t5411/test-0040-process-all-refs.sh
+++ b/t/t5411/test-0040-process-all-refs.sh
@@ -3,12 +3,12 @@
 	git -C "$upstream" config --add receive.procReceiveRefs refs
 '
 
-# Refs of upstream : master(A)
-# Refs of workbench: master(A)  tags/v123
+# Refs of upstream : main(A)
+# Refs of workbench: main(A)  tags/v123
 test_expect_success "setup upstream branches ($PROTOCOL)" '
 	(
 		cd "$upstream" &&
-		git update-ref refs/heads/master $B &&
+		git update-ref refs/heads/main $B &&
 		git update-ref refs/heads/foo $A &&
 		git update-ref refs/heads/bar $A &&
 		git update-ref refs/heads/baz $A
@@ -20,13 +20,13 @@
 	write_script "$upstream/hooks/proc-receive" <<-EOF
 	printf >&2 "# proc-receive hook\n"
 	test-tool proc-receive -v \
-		-r "ok refs/heads/master" \
+		-r "ok refs/heads/main" \
 		-r "option fall-through" \
 		-r "ok refs/heads/foo" \
 		-r "option fall-through" \
 		-r "ok refs/heads/bar" \
 		-r "option fall-through" \
-		-r "ok refs/for/master/topic" \
+		-r "ok refs/for/main/topic" \
 		-r "option refname refs/pull/123/head" \
 		-r "option old-oid $A" \
 		-r "option new-oid $B" \
@@ -38,15 +38,15 @@
 	EOF
 '
 
-# Refs of upstream : master(B)             foo(A)  bar(A))  baz(A)
-# Refs of workbench: master(A)  tags/v123
-# git push -f      : master(A)             (NULL)  (B)              refs/for/master/topic(A)  refs/for/next/topic(A)
+# Refs of upstream : main(B)             foo(A)  bar(A))  baz(A)
+# Refs of workbench: main(A)  tags/v123
+# git push -f      : main(A)             (NULL)  (B)              refs/for/main/topic(A)  refs/for/next/topic(A)
 test_expect_success "proc-receive: process all refs ($PROTOCOL)" '
 	git -C workbench push -f origin \
-		HEAD:refs/heads/master \
+		HEAD:refs/heads/main \
 		:refs/heads/foo \
 		$B:refs/heads/bar \
-		HEAD:refs/for/master/topic \
+		HEAD:refs/for/main/topic \
 		HEAD:refs/for/next/topic \
 		>out 2>&1 &&
 	make_user_friendly_and_stable_output <out >actual &&
@@ -54,22 +54,22 @@
 	remote: # pre-receive hook
 	remote: pre-receive< <COMMIT-A> <COMMIT-B> refs/heads/bar
 	remote: pre-receive< <COMMIT-A> <ZERO-OID> refs/heads/foo
-	remote: pre-receive< <COMMIT-B> <COMMIT-A> refs/heads/master
-	remote: pre-receive< <ZERO-OID> <COMMIT-A> refs/for/master/topic
+	remote: pre-receive< <COMMIT-B> <COMMIT-A> refs/heads/main
+	remote: pre-receive< <ZERO-OID> <COMMIT-A> refs/for/main/topic
 	remote: pre-receive< <ZERO-OID> <COMMIT-A> refs/for/next/topic
 	remote: # proc-receive hook
 	remote: proc-receive< <COMMIT-A> <COMMIT-B> refs/heads/bar
 	remote: proc-receive< <COMMIT-A> <ZERO-OID> refs/heads/foo
-	remote: proc-receive< <COMMIT-B> <COMMIT-A> refs/heads/master
-	remote: proc-receive< <ZERO-OID> <COMMIT-A> refs/for/master/topic
+	remote: proc-receive< <COMMIT-B> <COMMIT-A> refs/heads/main
+	remote: proc-receive< <ZERO-OID> <COMMIT-A> refs/for/main/topic
 	remote: proc-receive< <ZERO-OID> <COMMIT-A> refs/for/next/topic
-	remote: proc-receive> ok refs/heads/master
+	remote: proc-receive> ok refs/heads/main
 	remote: proc-receive> option fall-through
 	remote: proc-receive> ok refs/heads/foo
 	remote: proc-receive> option fall-through
 	remote: proc-receive> ok refs/heads/bar
 	remote: proc-receive> option fall-through
-	remote: proc-receive> ok refs/for/master/topic
+	remote: proc-receive> ok refs/for/main/topic
 	remote: proc-receive> option refname refs/pull/123/head
 	remote: proc-receive> option old-oid <COMMIT-A>
 	remote: proc-receive> option new-oid <COMMIT-B>
@@ -81,13 +81,13 @@
 	remote: # post-receive hook
 	remote: post-receive< <COMMIT-A> <COMMIT-B> refs/heads/bar
 	remote: post-receive< <COMMIT-A> <ZERO-OID> refs/heads/foo
-	remote: post-receive< <COMMIT-B> <COMMIT-A> refs/heads/master
+	remote: post-receive< <COMMIT-B> <COMMIT-A> refs/heads/main
 	remote: post-receive< <COMMIT-A> <COMMIT-B> refs/pull/123/head
 	remote: post-receive< <COMMIT-B> <COMMIT-A> refs/pull/124/head
 	To <URL/of/upstream.git>
 	 <OID-A>..<OID-B> <COMMIT-B> -> bar
 	 - [deleted] foo
-	 + <OID-B>...<OID-A> HEAD -> master (forced update)
+	 + <OID-B>...<OID-A> HEAD -> main (forced update)
 	 <OID-A>..<OID-B> HEAD -> refs/pull/123/head
 	 + <OID-B>...<OID-A> HEAD -> refs/pull/124/head (forced update)
 	EOF
@@ -97,13 +97,13 @@
 	cat >expect <<-EOF &&
 	<COMMIT-B> refs/heads/bar
 	<COMMIT-A> refs/heads/baz
-	<COMMIT-A> refs/heads/master
+	<COMMIT-A> refs/heads/main
 	EOF
 	test_cmp expect actual
 '
 
-# Refs of upstream : master(A)             bar(A)  baz(B)
-# Refs of workbench: master(A)  tags/v123
+# Refs of upstream : main(A)             bar(A)  baz(B)
+# Refs of workbench: main(A)  tags/v123
 test_expect_success "cleanup ($PROTOCOL)" '
 	(
 		cd "$upstream" &&
diff --git a/t/t5411/test-0041-process-all-refs--porcelain.sh b/t/t5411/test-0041-process-all-refs--porcelain.sh
index 0dd9824..e21420b 100644
--- a/t/t5411/test-0041-process-all-refs--porcelain.sh
+++ b/t/t5411/test-0041-process-all-refs--porcelain.sh
@@ -3,12 +3,12 @@
 	git -C "$upstream" config --add receive.procReceiveRefs refs
 '
 
-# Refs of upstream : master(A)
-# Refs of workbench: master(A)  tags/v123
+# Refs of upstream : main(A)
+# Refs of workbench: main(A)  tags/v123
 test_expect_success "setup upstream branches ($PROTOCOL/porcelain)" '
 	(
 		cd "$upstream" &&
-		git update-ref refs/heads/master $B &&
+		git update-ref refs/heads/main $B &&
 		git update-ref refs/heads/foo $A &&
 		git update-ref refs/heads/bar $A &&
 		git update-ref refs/heads/baz $A
@@ -20,13 +20,13 @@
 	write_script "$upstream/hooks/proc-receive" <<-EOF
 	printf >&2 "# proc-receive hook\n"
 	test-tool proc-receive -v \
-		-r "ok refs/heads/master" \
+		-r "ok refs/heads/main" \
 		-r "option fall-through" \
 		-r "ok refs/heads/foo" \
 		-r "option fall-through" \
 		-r "ok refs/heads/bar" \
 		-r "option fall-through" \
-		-r "ok refs/for/master/topic" \
+		-r "ok refs/for/main/topic" \
 		-r "option refname refs/pull/123/head" \
 		-r "option old-oid $A" \
 		-r "option new-oid $B" \
@@ -38,15 +38,15 @@
 	EOF
 '
 
-# Refs of upstream : master(B)             foo(A)  bar(A))  baz(A)
-# Refs of workbench: master(A)  tags/v123
-# git push -f      : master(A)             (NULL)  (B)              refs/for/master/topic(A)  refs/for/next/topic(A)
+# Refs of upstream : main(B)             foo(A)  bar(A))  baz(A)
+# Refs of workbench: main(A)  tags/v123
+# git push -f      : main(A)             (NULL)  (B)              refs/for/main/topic(A)  refs/for/next/topic(A)
 test_expect_success "proc-receive: process all refs ($PROTOCOL/porcelain)" '
 	git -C workbench push --porcelain -f origin \
-		HEAD:refs/heads/master \
+		HEAD:refs/heads/main \
 		:refs/heads/foo \
 		$B:refs/heads/bar \
-		HEAD:refs/for/master/topic \
+		HEAD:refs/for/main/topic \
 		HEAD:refs/for/next/topic \
 		>out 2>&1 &&
 	make_user_friendly_and_stable_output <out >actual &&
@@ -54,22 +54,22 @@
 	remote: # pre-receive hook
 	remote: pre-receive< <COMMIT-A> <COMMIT-B> refs/heads/bar
 	remote: pre-receive< <COMMIT-A> <ZERO-OID> refs/heads/foo
-	remote: pre-receive< <COMMIT-B> <COMMIT-A> refs/heads/master
-	remote: pre-receive< <ZERO-OID> <COMMIT-A> refs/for/master/topic
+	remote: pre-receive< <COMMIT-B> <COMMIT-A> refs/heads/main
+	remote: pre-receive< <ZERO-OID> <COMMIT-A> refs/for/main/topic
 	remote: pre-receive< <ZERO-OID> <COMMIT-A> refs/for/next/topic
 	remote: # proc-receive hook
 	remote: proc-receive< <COMMIT-A> <COMMIT-B> refs/heads/bar
 	remote: proc-receive< <COMMIT-A> <ZERO-OID> refs/heads/foo
-	remote: proc-receive< <COMMIT-B> <COMMIT-A> refs/heads/master
-	remote: proc-receive< <ZERO-OID> <COMMIT-A> refs/for/master/topic
+	remote: proc-receive< <COMMIT-B> <COMMIT-A> refs/heads/main
+	remote: proc-receive< <ZERO-OID> <COMMIT-A> refs/for/main/topic
 	remote: proc-receive< <ZERO-OID> <COMMIT-A> refs/for/next/topic
-	remote: proc-receive> ok refs/heads/master
+	remote: proc-receive> ok refs/heads/main
 	remote: proc-receive> option fall-through
 	remote: proc-receive> ok refs/heads/foo
 	remote: proc-receive> option fall-through
 	remote: proc-receive> ok refs/heads/bar
 	remote: proc-receive> option fall-through
-	remote: proc-receive> ok refs/for/master/topic
+	remote: proc-receive> ok refs/for/main/topic
 	remote: proc-receive> option refname refs/pull/123/head
 	remote: proc-receive> option old-oid <COMMIT-A>
 	remote: proc-receive> option new-oid <COMMIT-B>
@@ -81,13 +81,13 @@
 	remote: # post-receive hook
 	remote: post-receive< <COMMIT-A> <COMMIT-B> refs/heads/bar
 	remote: post-receive< <COMMIT-A> <ZERO-OID> refs/heads/foo
-	remote: post-receive< <COMMIT-B> <COMMIT-A> refs/heads/master
+	remote: post-receive< <COMMIT-B> <COMMIT-A> refs/heads/main
 	remote: post-receive< <COMMIT-A> <COMMIT-B> refs/pull/123/head
 	remote: post-receive< <COMMIT-B> <COMMIT-A> refs/pull/124/head
 	To <URL/of/upstream.git>
 	     <COMMIT-B>:refs/heads/bar    <OID-A>..<OID-B>
 	-    :refs/heads/foo    [deleted]
-	+    HEAD:refs/heads/master    <OID-B>...<OID-A> (forced update)
+	+    HEAD:refs/heads/main    <OID-B>...<OID-A> (forced update)
 	     HEAD:refs/pull/123/head    <OID-A>..<OID-B>
 	+    HEAD:refs/pull/124/head    <OID-B>...<OID-A> (forced update)
 	Done
@@ -98,13 +98,13 @@
 	cat >expect <<-EOF &&
 	<COMMIT-B> refs/heads/bar
 	<COMMIT-A> refs/heads/baz
-	<COMMIT-A> refs/heads/master
+	<COMMIT-A> refs/heads/main
 	EOF
 	test_cmp expect actual
 '
 
-# Refs of upstream : master(A)             bar(A)  baz(B)
-# Refs of workbench: master(A)  tags/v123
+# Refs of upstream : main(A)             bar(A)  baz(B)
+# Refs of workbench: main(A)  tags/v123
 test_expect_success "cleanup ($PROTOCOL/porcelain)" '
 	(
 		cd "$upstream" &&
diff --git a/t/t5411/test-0050-proc-receive-refs-with-modifiers.sh b/t/t5411/test-0050-proc-receive-refs-with-modifiers.sh
index c22849c..2e29518 100644
--- a/t/t5411/test-0050-proc-receive-refs-with-modifiers.sh
+++ b/t/t5411/test-0050-proc-receive-refs-with-modifiers.sh
@@ -2,7 +2,7 @@
 	(
 		cd "$upstream" &&
 		git config --unset-all receive.procReceiveRefs &&
-		git config --add receive.procReceiveRefs m:refs/heads/master &&
+		git config --add receive.procReceiveRefs m:refs/heads/main &&
 		git config --add receive.procReceiveRefs ad:refs/heads &&
 		git config --add receive.procReceiveRefs "a!:refs/heads"
 	)
@@ -12,7 +12,7 @@
 	write_script "$upstream/hooks/proc-receive" <<-EOF
 	printf >&2 "# proc-receive hook\n"
 	test-tool proc-receive -v \
-		-r "ok refs/heads/master" \
+		-r "ok refs/heads/main" \
 		-r "option refname refs/pull/123/head" \
 		-r "option old-oid $A" \
 		-r "option new-oid $B" \
@@ -21,22 +21,22 @@
 	EOF
 '
 
-# Refs of upstream : master(A)
-# Refs of workbench: master(A)  tags/v123
-# git push         : master(B)  tags/v123
+# Refs of upstream : main(A)
+# Refs of workbench: main(A)  tags/v123
+# git push         : main(B)  tags/v123
 test_expect_success "proc-receive: update branch and new tag ($PROTOCOL)" '
 	git -C workbench push origin \
-		$B:refs/heads/master \
+		$B:refs/heads/main \
 		v123 >out 2>&1 &&
 	make_user_friendly_and_stable_output <out >actual &&
 	cat >expect <<-EOF &&
 	remote: # pre-receive hook
-	remote: pre-receive< <COMMIT-A> <COMMIT-B> refs/heads/master
+	remote: pre-receive< <COMMIT-A> <COMMIT-B> refs/heads/main
 	remote: pre-receive< <ZERO-OID> <TAG-v123> refs/tags/v123
 	remote: # proc-receive hook
-	remote: proc-receive< <COMMIT-A> <COMMIT-B> refs/heads/master
+	remote: proc-receive< <COMMIT-A> <COMMIT-B> refs/heads/main
 	remote: proc-receive< <ZERO-OID> <TAG-v123> refs/tags/v123
-	remote: proc-receive> ok refs/heads/master
+	remote: proc-receive> ok refs/heads/main
 	remote: proc-receive> option refname refs/pull/123/head
 	remote: proc-receive> option old-oid <COMMIT-A>
 	remote: proc-receive> option new-oid <COMMIT-B>
@@ -53,20 +53,20 @@
 	git -C "$upstream" show-ref >out &&
 	make_user_friendly_and_stable_output <out >actual &&
 	cat >expect <<-EOF &&
-	<COMMIT-A> refs/heads/master
+	<COMMIT-A> refs/heads/main
 	EOF
 	test_cmp expect actual
 '
 
-# Refs of upstream : master(A)
-# Refs of workbench: master(A)  tags/v123
+# Refs of upstream : main(A)
+# Refs of workbench: main(A)  tags/v123
 test_expect_success "setup upstream: create tags/v123 ($PROTOCOL)" '
 	git -C "$upstream" update-ref refs/heads/topic $A &&
 	git -C "$upstream" update-ref refs/tags/v123 $TAG &&
 	git -C "$upstream" show-ref >out &&
 	make_user_friendly_and_stable_output <out >actual &&
 	cat >expect <<-EOF &&
-	<COMMIT-A> refs/heads/master
+	<COMMIT-A> refs/heads/main
 	<COMMIT-A> refs/heads/topic
 	<TAG-v123> refs/tags/v123
 	EOF
@@ -77,7 +77,7 @@
 	write_script "$upstream/hooks/proc-receive" <<-EOF
 	printf >&2 "# proc-receive hook\n"
 	test-tool proc-receive -v \
-		-r "ok refs/heads/master" \
+		-r "ok refs/heads/main" \
 		-r "option refname refs/pull/123/head" \
 		-r "option old-oid $A" \
 		-r "option new-oid $ZERO_OID" \
@@ -87,26 +87,26 @@
 	EOF
 '
 
-# Refs of upstream : master(A)  topic(A)  tags/v123
-# Refs of workbench: master(A)            tags/v123
+# Refs of upstream : main(A)  topic(A)  tags/v123
+# Refs of workbench: main(A)            tags/v123
 # git push         : NULL       topic(B)  NULL       next(A)
 test_expect_success "proc-receive: create/delete branch, and delete tag ($PROTOCOL)" '
 	git -C workbench push origin \
-		:refs/heads/master \
+		:refs/heads/main \
 		$B:refs/heads/topic \
 		$A:refs/heads/next \
 		:refs/tags/v123 >out 2>&1 &&
 	make_user_friendly_and_stable_output <out >actual &&
 	cat >expect <<-EOF &&
 	remote: # pre-receive hook
-	remote: pre-receive< <COMMIT-A> <ZERO-OID> refs/heads/master
+	remote: pre-receive< <COMMIT-A> <ZERO-OID> refs/heads/main
 	remote: pre-receive< <COMMIT-A> <COMMIT-B> refs/heads/topic
 	remote: pre-receive< <TAG-v123> <ZERO-OID> refs/tags/v123
 	remote: pre-receive< <ZERO-OID> <COMMIT-A> refs/heads/next
 	remote: # proc-receive hook
-	remote: proc-receive< <COMMIT-A> <ZERO-OID> refs/heads/master
+	remote: proc-receive< <COMMIT-A> <ZERO-OID> refs/heads/main
 	remote: proc-receive< <ZERO-OID> <COMMIT-A> refs/heads/next
-	remote: proc-receive> ok refs/heads/master
+	remote: proc-receive> ok refs/heads/main
 	remote: proc-receive> option refname refs/pull/123/head
 	remote: proc-receive> option old-oid <COMMIT-A>
 	remote: proc-receive> option new-oid <ZERO-OID>
@@ -128,7 +128,7 @@
 	git -C "$upstream" show-ref >out &&
 	make_user_friendly_and_stable_output <out >actual &&
 	cat >expect <<-EOF &&
-	<COMMIT-A> refs/heads/master
+	<COMMIT-A> refs/heads/main
 	<COMMIT-B> refs/heads/topic
 	EOF
 	test_cmp expect actual
diff --git a/t/t5505-remote.sh b/t/t5505-remote.sh
index 8d62edd..eaa6e90 100755
--- a/t/t5505-remote.sh
+++ b/t/t5505-remote.sh
@@ -145,8 +145,8 @@
 test_expect_success 'remove errors out early when deleting non-existent branch' '
 	(
 		cd test &&
-		echo "fatal: No such remote: '\''foo'\''" >expect &&
-		test_must_fail git remote rm foo 2>actual &&
+		echo "error: No such remote: '\''foo'\''" >expect &&
+		test_expect_code 2 git remote rm foo 2>actual &&
 		test_i18ncmp expect actual
 	)
 '
@@ -173,24 +173,37 @@
 test_expect_success 'rename errors out early when deleting non-existent branch' '
 	(
 		cd test &&
-		echo "fatal: No such remote: '\''foo'\''" >expect &&
-		test_must_fail git remote rename foo bar 2>actual &&
+		echo "error: No such remote: '\''foo'\''" >expect &&
+		test_expect_code 2 git remote rename foo bar 2>actual &&
 		test_i18ncmp expect actual
 	)
 '
 
+test_expect_success 'rename errors out early when when new name is invalid' '
+	test_config remote.foo.vcs bar &&
+	echo "fatal: '\''invalid...name'\'' is not a valid remote name" >expect &&
+	test_must_fail git remote rename foo invalid...name 2>actual &&
+	test_i18ncmp expect actual
+'
+
 test_expect_success 'add existing foreign_vcs remote' '
 	test_config remote.foo.vcs bar &&
-	echo "fatal: remote foo already exists." >expect &&
-	test_must_fail git remote add foo bar 2>actual &&
+	echo "error: remote foo already exists." >expect &&
+	test_expect_code 3 git remote add foo bar 2>actual &&
 	test_i18ncmp expect actual
 '
 
 test_expect_success 'add existing foreign_vcs remote' '
 	test_config remote.foo.vcs bar &&
 	test_config remote.bar.vcs bar &&
-	echo "fatal: remote bar already exists." >expect &&
-	test_must_fail git remote rename foo bar 2>actual &&
+	echo "error: remote bar already exists." >expect &&
+	test_expect_code 3 git remote rename foo bar 2>actual &&
+	test_i18ncmp expect actual
+'
+
+test_expect_success 'add invalid foreign_vcs remote' '
+	echo "fatal: '\''invalid...name'\'' is not a valid remote name" >expect &&
+	test_must_fail git remote add invalid...name bar 2>actual &&
 	test_i18ncmp expect actual
 '
 
@@ -200,28 +213,28 @@
   Push  URL: $(pwd)/one
   HEAD branch: master
   Remote branches:
-    master new (next fetch will store in remotes/origin)
-    side   tracked
+    main new (next fetch will store in remotes/origin)
+    side tracked
   Local branches configured for 'git pull':
-    ahead    merges with remote master
-    master   merges with remote master
+    ahead    merges with remote main
+    main     merges with remote main
     octopus  merges with remote topic-a
                 and with remote topic-b
                 and with remote topic-c
     rebase  rebases onto remote master
   Local refs configured for 'git push':
-    master pushes to master   (local out of date)
-    master pushes to upstream (create)
+    main pushes to main     (local out of date)
+    main pushes to upstream (create)
 * remote two
   Fetch URL: ../two
   Push  URL: ../three
   HEAD branch: master
   Local refs configured for 'git push':
-    ahead  forces to master  (fast-forwardable)
-    master pushes to another (up to date)
+    ahead forces to main    (fast-forwardable)
+    main  pushes to another (up to date)
 EOF
 
-test_expect_success 'show' '
+test_expect_success PREPARE_FOR_MAIN_BRANCH 'show' '
 	(
 		cd test &&
 		git config --add remote.origin.fetch refs/heads/master:refs/heads/upstream &&
@@ -264,15 +277,15 @@
     master
     side
   Local branches configured for 'git pull':
-    ahead  merges with remote master
-    master merges with remote master
+    ahead merges with remote main
+    main  merges with remote main
   Local refs configured for 'git push' (status not queried):
     (matching)           pushes to (matching)
-    refs/heads/master    pushes to refs/heads/upstream
+    refs/heads/main      pushes to refs/heads/upstream
     refs/tags/lastbackup forces to refs/tags/lastbackup
 EOF
 
-test_expect_success 'show -n' '
+test_expect_success PREPARE_FOR_MAIN_BRANCH 'show -n' '
 	mv one one.unreachable &&
 	(
 		cd test &&
@@ -315,7 +328,7 @@
 	)
 '
 
-test_expect_success 'set-head --auto has no problem w/multiple HEADs' '
+test_expect_success PREPARE_FOR_MAIN_BRANCH 'set-head --auto has no problem w/multiple HEADs' '
 	(
 		cd test &&
 		git fetch two "refs/heads/*:refs/remotes/two/*" &&
@@ -1335,7 +1348,7 @@
 	)
 '
 
-test_expect_success 'refs/remotes/* <src> refspec and unqualified <dst> DWIM and advice' '
+test_expect_success PREPARE_FOR_MAIN_BRANCH 'refs/remotes/* <src> refspec and unqualified <dst> DWIM and advice' '
 	(
 		cd two &&
 		git tag -a -m "Some tag" my-tag master &&
diff --git a/t/t5510-fetch.sh b/t/t5510-fetch.sh
index dbc724e..5d67335 100755
--- a/t/t5510-fetch.sh
+++ b/t/t5510-fetch.sh
@@ -942,7 +942,7 @@
 	)
 '
 
-test_expect_success C_LOCALE_OUTPUT 'fetch aligned output' '
+test_expect_success PREPARE_FOR_MAIN_BRANCH,C_LOCALE_OUTPUT 'fetch aligned output' '
 	git clone . full-output &&
 	test_commit looooooooooooong-tag &&
 	(
@@ -951,13 +951,13 @@
 		grep -e "->" actual | cut -c 22- >../actual
 	) &&
 	cat >expect <<-\EOF &&
-	master               -> origin/master
+	main                 -> origin/main
 	looooooooooooong-tag -> looooooooooooong-tag
 	EOF
 	test_cmp expect actual
 '
 
-test_expect_success C_LOCALE_OUTPUT 'fetch compact output' '
+test_expect_success PREPARE_FOR_MAIN_BRANCH,C_LOCALE_OUTPUT 'fetch compact output' '
 	git clone . compact &&
 	test_commit extraaa &&
 	(
@@ -966,7 +966,7 @@
 		grep -e "->" actual | cut -c 22- >../actual
 	) &&
 	cat >expect <<-\EOF &&
-	master     -> origin/*
+	main       -> origin/*
 	extraaa    -> *
 	EOF
 	test_cmp expect actual
diff --git a/t/t5515-fetch-merge-logic.sh b/t/t5515-fetch-merge-logic.sh
index 70a9d2d..50f1410 100755
--- a/t/t5515-fetch-merge-logic.sh
+++ b/t/t5515-fetch-merge-logic.sh
@@ -11,11 +11,14 @@
 GIT_TEST_PROTOCOL_VERSION=0
 export GIT_TEST_PROTOCOL_VERSION
 
+GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
+export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
+
 . ./test-lib.sh
 
 build_script () {
 	script="$1" &&
-	for i in one three_file master topic_2 one_tree three two two2 three2
+	for i in one three_file main topic_2 one_tree three two two2 three2
 	do
 		echo "s/$(test_oid --hash=sha1 "$i")/$(test_oid "$i")/g" >>"$script"
 	done
@@ -40,8 +43,8 @@
 	three_file sha1:0e3b14047d3ee365f4f2a1b673db059c3972589c
 	three_file sha256:bc4447d50c07497a8bfe6eef817f2364ecca9d471452e43b52756cc1a908bd32
 
-	master sha1:6c9dec2b923228c9ff994c6cfe4ae16c12408dc5
-	master sha256:8521c3072461fcfe8f32d67f95cc6e6b832a2db2fa29769ffc788bce85ebcd75
+	main sha1:ecf3b3627b498bdcb735cc4343bf165f76964e9a
+	main sha256:fff666109892bb4b1c80cd1649d2d8762a0663db8b5d46c8be98360b64fbba5f
 
 	one_tree sha1:22feea448b023a2d864ef94b013735af34d238ba
 	one_tree sha256:6e4743f4ef2356b881dda5e91f5c7cdffe870faf350bf7b312f80a20935f5d83
@@ -52,8 +55,8 @@
 	two sha1:525b7fb068d59950d185a8779dc957c77eed73ba
 	two sha256:3b21de3440cd38c2a9e9b464adb923f7054949ed4c918e1a0ac4c95cd52774db
 
-	topic_2 sha1:754b754407bf032e9a2f9d5a9ad05ca79a6b228f
-	topic_2 sha256:6c7abaea8a6d8ef4d89877e68462758dc6774690fbbbb0e6d7dd57415c9abde0
+	topic_2 sha1:b4ab76b1a01ea602209932134a44f1e6bd610832
+	topic_2 sha256:380ebae0113f877ce46fcdf39d5bc33e4dc0928db5c5a4d5fdc78381c4d55ae3
 
 	two2 sha1:6134ee8f857693b96ff1cc98d3e2fd62b199e5a8
 	two2 sha256:87a2d3ee29c83a3dc7afd41c0606b11f67603120b910a7be7840accdc18344d4
@@ -80,9 +83,9 @@
 	git tag -a -m "Tag Three file" tag-three-file HEAD^{tree}:file &&
 	git branch three &&
 
-	echo master >> file &&
-	git commit -a -m Master &&
-	git tag -a -m "Tag Master" tag-master &&
+	echo main >> file &&
+	git commit -a -m Main &&
+	git tag -a -m "Tag Main" tag-main &&
 
 	git checkout three &&
 
@@ -91,7 +94,7 @@
 	git config remote.origin.url ../.git/ &&
 
 	git config remote.config-explicit.url ../.git/ &&
-	git config remote.config-explicit.fetch refs/heads/master:remotes/rem/master &&
+	git config remote.config-explicit.fetch refs/heads/main:remotes/rem/main &&
 	git config --add remote.config-explicit.fetch refs/heads/one:remotes/rem/one &&
 	git config --add remote.config-explicit.fetch two:remotes/rem/two &&
 	git config --add remote.config-explicit.fetch refs/heads/three:remotes/rem/three &&
@@ -104,7 +107,7 @@
 	mkdir -p .git/remotes &&
 	{
 		echo "URL: ../.git/"
-		echo "Pull: refs/heads/master:remotes/rem/master"
+		echo "Pull: refs/heads/main:remotes/rem/main"
 		echo "Pull: refs/heads/one:remotes/rem/one"
 		echo "Pull: two:remotes/rem/two"
 		echo "Pull: refs/heads/three:remotes/rem/three"
@@ -149,7 +152,7 @@
 # but does depend on Pull: or fetch lines.
 # Use two branches completely unrelated from the arguments,
 # the clone default and one without branch properties
-for branch in master br-unconfig ; do
+for branch in main br-unconfig ; do
     echo $branch
     for remote in $remotes ; do
 	echo $branch $remote
@@ -158,7 +161,7 @@
 
 # Merge logic does not depend on branch properties
 # neither in the Pull: or .fetch config
-for branch in master br-unconfig ; do
+for branch in main br-unconfig ; do
     cat <<EOF
 $branch ../.git
 $branch ../.git one
diff --git a/t/t5515/fetch.br-branches-default b/t/t5515/fetch.br-branches-default
index a1bc3d5..0bed09c 100644
--- a/t/t5515/fetch.br-branches-default
+++ b/t/t5515/fetch.br-branches-default
@@ -1,6 +1,6 @@
 # br-branches-default
-754b754407bf032e9a2f9d5a9ad05ca79a6b228f		branch 'master' of ../
-6c9dec2b923228c9ff994c6cfe4ae16c12408dc5	not-for-merge	tag 'tag-master' of ../
+b4ab76b1a01ea602209932134a44f1e6bd610832		branch 'main' of ../
+ecf3b3627b498bdcb735cc4343bf165f76964e9a	not-for-merge	tag 'tag-main' of ../
 8e32a6d901327a23ef831511badce7bf3bf46689	not-for-merge	tag 'tag-one' of ../
 22feea448b023a2d864ef94b013735af34d238ba	not-for-merge	tag 'tag-one-tree' of ../
 c61a82b60967180544e3c19f819ddbd0c9f89899	not-for-merge	tag 'tag-three' of ../
diff --git a/t/t5515/fetch.br-branches-default-merge b/t/t5515/fetch.br-branches-default-merge
index 12ab08e..59eef63 100644
--- a/t/t5515/fetch.br-branches-default-merge
+++ b/t/t5515/fetch.br-branches-default-merge
@@ -1,7 +1,7 @@
 # br-branches-default-merge
 0567da4d5edd2ff4bb292a465ba9e64dcad9536b		branch 'three' of ../
-754b754407bf032e9a2f9d5a9ad05ca79a6b228f	not-for-merge	branch 'master' of ../
-6c9dec2b923228c9ff994c6cfe4ae16c12408dc5	not-for-merge	tag 'tag-master' of ../
+b4ab76b1a01ea602209932134a44f1e6bd610832	not-for-merge	branch 'main' of ../
+ecf3b3627b498bdcb735cc4343bf165f76964e9a	not-for-merge	tag 'tag-main' of ../
 8e32a6d901327a23ef831511badce7bf3bf46689	not-for-merge	tag 'tag-one' of ../
 22feea448b023a2d864ef94b013735af34d238ba	not-for-merge	tag 'tag-one-tree' of ../
 c61a82b60967180544e3c19f819ddbd0c9f89899	not-for-merge	tag 'tag-three' of ../
diff --git a/t/t5515/fetch.br-branches-default-merge_branches-default b/t/t5515/fetch.br-branches-default-merge_branches-default
index 5442752..490186c 100644
--- a/t/t5515/fetch.br-branches-default-merge_branches-default
+++ b/t/t5515/fetch.br-branches-default-merge_branches-default
@@ -1,7 +1,7 @@
 # br-branches-default-merge branches-default
 0567da4d5edd2ff4bb292a465ba9e64dcad9536b		branch 'three' of ../
-754b754407bf032e9a2f9d5a9ad05ca79a6b228f	not-for-merge	branch 'master' of ../
-6c9dec2b923228c9ff994c6cfe4ae16c12408dc5	not-for-merge	tag 'tag-master' of ../
+b4ab76b1a01ea602209932134a44f1e6bd610832	not-for-merge	branch 'main' of ../
+ecf3b3627b498bdcb735cc4343bf165f76964e9a	not-for-merge	tag 'tag-main' of ../
 8e32a6d901327a23ef831511badce7bf3bf46689	not-for-merge	tag 'tag-one' of ../
 22feea448b023a2d864ef94b013735af34d238ba	not-for-merge	tag 'tag-one-tree' of ../
 c61a82b60967180544e3c19f819ddbd0c9f89899	not-for-merge	tag 'tag-three' of ../
diff --git a/t/t5515/fetch.br-branches-default-octopus b/t/t5515/fetch.br-branches-default-octopus
index 498a761..d484138 100644
--- a/t/t5515/fetch.br-branches-default-octopus
+++ b/t/t5515/fetch.br-branches-default-octopus
@@ -1,8 +1,8 @@
 # br-branches-default-octopus
 8e32a6d901327a23ef831511badce7bf3bf46689		branch 'one' of ../
 6134ee8f857693b96ff1cc98d3e2fd62b199e5a8		branch 'two' of ../
-754b754407bf032e9a2f9d5a9ad05ca79a6b228f	not-for-merge	branch 'master' of ../
-6c9dec2b923228c9ff994c6cfe4ae16c12408dc5	not-for-merge	tag 'tag-master' of ../
+b4ab76b1a01ea602209932134a44f1e6bd610832	not-for-merge	branch 'main' of ../
+ecf3b3627b498bdcb735cc4343bf165f76964e9a	not-for-merge	tag 'tag-main' of ../
 8e32a6d901327a23ef831511badce7bf3bf46689	not-for-merge	tag 'tag-one' of ../
 22feea448b023a2d864ef94b013735af34d238ba	not-for-merge	tag 'tag-one-tree' of ../
 c61a82b60967180544e3c19f819ddbd0c9f89899	not-for-merge	tag 'tag-three' of ../
diff --git a/t/t5515/fetch.br-branches-default-octopus_branches-default b/t/t5515/fetch.br-branches-default-octopus_branches-default
index 0857f13..b79a5fe 100644
--- a/t/t5515/fetch.br-branches-default-octopus_branches-default
+++ b/t/t5515/fetch.br-branches-default-octopus_branches-default
@@ -1,8 +1,8 @@
 # br-branches-default-octopus branches-default
 8e32a6d901327a23ef831511badce7bf3bf46689		branch 'one' of ../
 6134ee8f857693b96ff1cc98d3e2fd62b199e5a8		branch 'two' of ../
-754b754407bf032e9a2f9d5a9ad05ca79a6b228f	not-for-merge	branch 'master' of ../
-6c9dec2b923228c9ff994c6cfe4ae16c12408dc5	not-for-merge	tag 'tag-master' of ../
+b4ab76b1a01ea602209932134a44f1e6bd610832	not-for-merge	branch 'main' of ../
+ecf3b3627b498bdcb735cc4343bf165f76964e9a	not-for-merge	tag 'tag-main' of ../
 8e32a6d901327a23ef831511badce7bf3bf46689	not-for-merge	tag 'tag-one' of ../
 22feea448b023a2d864ef94b013735af34d238ba	not-for-merge	tag 'tag-one-tree' of ../
 c61a82b60967180544e3c19f819ddbd0c9f89899	not-for-merge	tag 'tag-three' of ../
diff --git a/t/t5515/fetch.br-branches-default_branches-default b/t/t5515/fetch.br-branches-default_branches-default
index 8cbd718..1c866d8 100644
--- a/t/t5515/fetch.br-branches-default_branches-default
+++ b/t/t5515/fetch.br-branches-default_branches-default
@@ -1,6 +1,6 @@
 # br-branches-default branches-default
-754b754407bf032e9a2f9d5a9ad05ca79a6b228f		branch 'master' of ../
-6c9dec2b923228c9ff994c6cfe4ae16c12408dc5	not-for-merge	tag 'tag-master' of ../
+b4ab76b1a01ea602209932134a44f1e6bd610832		branch 'main' of ../
+ecf3b3627b498bdcb735cc4343bf165f76964e9a	not-for-merge	tag 'tag-main' of ../
 8e32a6d901327a23ef831511badce7bf3bf46689	not-for-merge	tag 'tag-one' of ../
 22feea448b023a2d864ef94b013735af34d238ba	not-for-merge	tag 'tag-one-tree' of ../
 c61a82b60967180544e3c19f819ddbd0c9f89899	not-for-merge	tag 'tag-three' of ../
diff --git a/t/t5515/fetch.br-branches-one b/t/t5515/fetch.br-branches-one
index c98f670..6925a77 100644
--- a/t/t5515/fetch.br-branches-one
+++ b/t/t5515/fetch.br-branches-one
@@ -1,6 +1,6 @@
 # br-branches-one
 8e32a6d901327a23ef831511badce7bf3bf46689		branch 'one' of ../
-6c9dec2b923228c9ff994c6cfe4ae16c12408dc5	not-for-merge	tag 'tag-master' of ../
+ecf3b3627b498bdcb735cc4343bf165f76964e9a	not-for-merge	tag 'tag-main' of ../
 8e32a6d901327a23ef831511badce7bf3bf46689	not-for-merge	tag 'tag-one' of ../
 22feea448b023a2d864ef94b013735af34d238ba	not-for-merge	tag 'tag-one-tree' of ../
 c61a82b60967180544e3c19f819ddbd0c9f89899	not-for-merge	tag 'tag-three' of ../
diff --git a/t/t5515/fetch.br-branches-one-merge b/t/t5515/fetch.br-branches-one-merge
index 54a7742..8525703 100644
--- a/t/t5515/fetch.br-branches-one-merge
+++ b/t/t5515/fetch.br-branches-one-merge
@@ -1,7 +1,7 @@
 # br-branches-one-merge
 0567da4d5edd2ff4bb292a465ba9e64dcad9536b		branch 'three' of ../
 8e32a6d901327a23ef831511badce7bf3bf46689	not-for-merge	branch 'one' of ../
-6c9dec2b923228c9ff994c6cfe4ae16c12408dc5	not-for-merge	tag 'tag-master' of ../
+ecf3b3627b498bdcb735cc4343bf165f76964e9a	not-for-merge	tag 'tag-main' of ../
 8e32a6d901327a23ef831511badce7bf3bf46689	not-for-merge	tag 'tag-one' of ../
 22feea448b023a2d864ef94b013735af34d238ba	not-for-merge	tag 'tag-one-tree' of ../
 c61a82b60967180544e3c19f819ddbd0c9f89899	not-for-merge	tag 'tag-three' of ../
diff --git a/t/t5515/fetch.br-branches-one-merge_branches-one b/t/t5515/fetch.br-branches-one-merge_branches-one
index b4d1bb0..3a63a7f 100644
--- a/t/t5515/fetch.br-branches-one-merge_branches-one
+++ b/t/t5515/fetch.br-branches-one-merge_branches-one
@@ -1,7 +1,7 @@
 # br-branches-one-merge branches-one
 0567da4d5edd2ff4bb292a465ba9e64dcad9536b		branch 'three' of ../
 8e32a6d901327a23ef831511badce7bf3bf46689	not-for-merge	branch 'one' of ../
-6c9dec2b923228c9ff994c6cfe4ae16c12408dc5	not-for-merge	tag 'tag-master' of ../
+ecf3b3627b498bdcb735cc4343bf165f76964e9a	not-for-merge	tag 'tag-main' of ../
 8e32a6d901327a23ef831511badce7bf3bf46689	not-for-merge	tag 'tag-one' of ../
 22feea448b023a2d864ef94b013735af34d238ba	not-for-merge	tag 'tag-one-tree' of ../
 c61a82b60967180544e3c19f819ddbd0c9f89899	not-for-merge	tag 'tag-three' of ../
diff --git a/t/t5515/fetch.br-branches-one-octopus b/t/t5515/fetch.br-branches-one-octopus
index 97c4b54..46af763 100644
--- a/t/t5515/fetch.br-branches-one-octopus
+++ b/t/t5515/fetch.br-branches-one-octopus
@@ -1,7 +1,7 @@
 # br-branches-one-octopus
 8e32a6d901327a23ef831511badce7bf3bf46689		branch 'one' of ../
 6134ee8f857693b96ff1cc98d3e2fd62b199e5a8		branch 'two' of ../
-6c9dec2b923228c9ff994c6cfe4ae16c12408dc5	not-for-merge	tag 'tag-master' of ../
+ecf3b3627b498bdcb735cc4343bf165f76964e9a	not-for-merge	tag 'tag-main' of ../
 8e32a6d901327a23ef831511badce7bf3bf46689	not-for-merge	tag 'tag-one' of ../
 22feea448b023a2d864ef94b013735af34d238ba	not-for-merge	tag 'tag-one-tree' of ../
 c61a82b60967180544e3c19f819ddbd0c9f89899	not-for-merge	tag 'tag-three' of ../
diff --git a/t/t5515/fetch.br-branches-one-octopus_branches-one b/t/t5515/fetch.br-branches-one-octopus_branches-one
index df705f7..becfde9 100644
--- a/t/t5515/fetch.br-branches-one-octopus_branches-one
+++ b/t/t5515/fetch.br-branches-one-octopus_branches-one
@@ -1,7 +1,7 @@
 # br-branches-one-octopus branches-one
 8e32a6d901327a23ef831511badce7bf3bf46689		branch 'one' of ../
 6134ee8f857693b96ff1cc98d3e2fd62b199e5a8		branch 'two' of ../
-6c9dec2b923228c9ff994c6cfe4ae16c12408dc5	not-for-merge	tag 'tag-master' of ../
+ecf3b3627b498bdcb735cc4343bf165f76964e9a	not-for-merge	tag 'tag-main' of ../
 8e32a6d901327a23ef831511badce7bf3bf46689	not-for-merge	tag 'tag-one' of ../
 22feea448b023a2d864ef94b013735af34d238ba	not-for-merge	tag 'tag-one-tree' of ../
 c61a82b60967180544e3c19f819ddbd0c9f89899	not-for-merge	tag 'tag-three' of ../
diff --git a/t/t5515/fetch.br-branches-one_branches-one b/t/t5515/fetch.br-branches-one_branches-one
index 96890e5..9ba34c6 100644
--- a/t/t5515/fetch.br-branches-one_branches-one
+++ b/t/t5515/fetch.br-branches-one_branches-one
@@ -1,6 +1,6 @@
 # br-branches-one branches-one
 8e32a6d901327a23ef831511badce7bf3bf46689		branch 'one' of ../
-6c9dec2b923228c9ff994c6cfe4ae16c12408dc5	not-for-merge	tag 'tag-master' of ../
+ecf3b3627b498bdcb735cc4343bf165f76964e9a	not-for-merge	tag 'tag-main' of ../
 8e32a6d901327a23ef831511badce7bf3bf46689	not-for-merge	tag 'tag-one' of ../
 22feea448b023a2d864ef94b013735af34d238ba	not-for-merge	tag 'tag-one-tree' of ../
 c61a82b60967180544e3c19f819ddbd0c9f89899	not-for-merge	tag 'tag-three' of ../
diff --git a/t/t5515/fetch.br-config-explicit b/t/t5515/fetch.br-config-explicit
index 68fc927..7466a73 100644
--- a/t/t5515/fetch.br-config-explicit
+++ b/t/t5515/fetch.br-config-explicit
@@ -1,9 +1,9 @@
 # br-config-explicit
-754b754407bf032e9a2f9d5a9ad05ca79a6b228f		branch 'master' of ../
+b4ab76b1a01ea602209932134a44f1e6bd610832		branch 'main' of ../
 8e32a6d901327a23ef831511badce7bf3bf46689	not-for-merge	branch 'one' of ../
 6134ee8f857693b96ff1cc98d3e2fd62b199e5a8	not-for-merge	branch 'two' of ../
 0567da4d5edd2ff4bb292a465ba9e64dcad9536b	not-for-merge	branch 'three' of ../
-6c9dec2b923228c9ff994c6cfe4ae16c12408dc5	not-for-merge	tag 'tag-master' of ../
+ecf3b3627b498bdcb735cc4343bf165f76964e9a	not-for-merge	tag 'tag-main' of ../
 8e32a6d901327a23ef831511badce7bf3bf46689	not-for-merge	tag 'tag-one' of ../
 22feea448b023a2d864ef94b013735af34d238ba	not-for-merge	tag 'tag-one-tree' of ../
 c61a82b60967180544e3c19f819ddbd0c9f89899	not-for-merge	tag 'tag-three' of ../
diff --git a/t/t5515/fetch.br-config-explicit-merge b/t/t5515/fetch.br-config-explicit-merge
index 5ce764a..9375b7d 100644
--- a/t/t5515/fetch.br-config-explicit-merge
+++ b/t/t5515/fetch.br-config-explicit-merge
@@ -1,9 +1,9 @@
 # br-config-explicit-merge
 0567da4d5edd2ff4bb292a465ba9e64dcad9536b		branch 'three' of ../
-754b754407bf032e9a2f9d5a9ad05ca79a6b228f	not-for-merge	branch 'master' of ../
+b4ab76b1a01ea602209932134a44f1e6bd610832	not-for-merge	branch 'main' of ../
 8e32a6d901327a23ef831511badce7bf3bf46689	not-for-merge	branch 'one' of ../
 6134ee8f857693b96ff1cc98d3e2fd62b199e5a8	not-for-merge	branch 'two' of ../
-6c9dec2b923228c9ff994c6cfe4ae16c12408dc5	not-for-merge	tag 'tag-master' of ../
+ecf3b3627b498bdcb735cc4343bf165f76964e9a	not-for-merge	tag 'tag-main' of ../
 8e32a6d901327a23ef831511badce7bf3bf46689	not-for-merge	tag 'tag-one' of ../
 22feea448b023a2d864ef94b013735af34d238ba	not-for-merge	tag 'tag-one-tree' of ../
 c61a82b60967180544e3c19f819ddbd0c9f89899	not-for-merge	tag 'tag-three' of ../
diff --git a/t/t5515/fetch.br-config-explicit-merge_config-explicit b/t/t5515/fetch.br-config-explicit-merge_config-explicit
index b1152b7..6335e2b 100644
--- a/t/t5515/fetch.br-config-explicit-merge_config-explicit
+++ b/t/t5515/fetch.br-config-explicit-merge_config-explicit
@@ -1,9 +1,9 @@
 # br-config-explicit-merge config-explicit
 0567da4d5edd2ff4bb292a465ba9e64dcad9536b		branch 'three' of ../
-754b754407bf032e9a2f9d5a9ad05ca79a6b228f	not-for-merge	branch 'master' of ../
+b4ab76b1a01ea602209932134a44f1e6bd610832	not-for-merge	branch 'main' of ../
 8e32a6d901327a23ef831511badce7bf3bf46689	not-for-merge	branch 'one' of ../
 6134ee8f857693b96ff1cc98d3e2fd62b199e5a8	not-for-merge	branch 'two' of ../
-6c9dec2b923228c9ff994c6cfe4ae16c12408dc5	not-for-merge	tag 'tag-master' of ../
+ecf3b3627b498bdcb735cc4343bf165f76964e9a	not-for-merge	tag 'tag-main' of ../
 8e32a6d901327a23ef831511badce7bf3bf46689	not-for-merge	tag 'tag-one' of ../
 22feea448b023a2d864ef94b013735af34d238ba	not-for-merge	tag 'tag-one-tree' of ../
 c61a82b60967180544e3c19f819ddbd0c9f89899	not-for-merge	tag 'tag-three' of ../
diff --git a/t/t5515/fetch.br-config-explicit-octopus b/t/t5515/fetch.br-config-explicit-octopus
index 110577b..c379aa9 100644
--- a/t/t5515/fetch.br-config-explicit-octopus
+++ b/t/t5515/fetch.br-config-explicit-octopus
@@ -1,9 +1,9 @@
 # br-config-explicit-octopus
 8e32a6d901327a23ef831511badce7bf3bf46689		branch 'one' of ../
 6134ee8f857693b96ff1cc98d3e2fd62b199e5a8		branch 'two' of ../
-754b754407bf032e9a2f9d5a9ad05ca79a6b228f	not-for-merge	branch 'master' of ../
+b4ab76b1a01ea602209932134a44f1e6bd610832	not-for-merge	branch 'main' of ../
 0567da4d5edd2ff4bb292a465ba9e64dcad9536b	not-for-merge	branch 'three' of ../
-6c9dec2b923228c9ff994c6cfe4ae16c12408dc5	not-for-merge	tag 'tag-master' of ../
+ecf3b3627b498bdcb735cc4343bf165f76964e9a	not-for-merge	tag 'tag-main' of ../
 8e32a6d901327a23ef831511badce7bf3bf46689	not-for-merge	tag 'tag-one' of ../
 22feea448b023a2d864ef94b013735af34d238ba	not-for-merge	tag 'tag-one-tree' of ../
 c61a82b60967180544e3c19f819ddbd0c9f89899	not-for-merge	tag 'tag-three' of ../
diff --git a/t/t5515/fetch.br-config-explicit-octopus_config-explicit b/t/t5515/fetch.br-config-explicit-octopus_config-explicit
index a29dd8b..7fb3a3e 100644
--- a/t/t5515/fetch.br-config-explicit-octopus_config-explicit
+++ b/t/t5515/fetch.br-config-explicit-octopus_config-explicit
@@ -1,9 +1,9 @@
 # br-config-explicit-octopus config-explicit
 8e32a6d901327a23ef831511badce7bf3bf46689		branch 'one' of ../
 6134ee8f857693b96ff1cc98d3e2fd62b199e5a8		branch 'two' of ../
-754b754407bf032e9a2f9d5a9ad05ca79a6b228f	not-for-merge	branch 'master' of ../
+b4ab76b1a01ea602209932134a44f1e6bd610832	not-for-merge	branch 'main' of ../
 0567da4d5edd2ff4bb292a465ba9e64dcad9536b	not-for-merge	branch 'three' of ../
-6c9dec2b923228c9ff994c6cfe4ae16c12408dc5	not-for-merge	tag 'tag-master' of ../
+ecf3b3627b498bdcb735cc4343bf165f76964e9a	not-for-merge	tag 'tag-main' of ../
 8e32a6d901327a23ef831511badce7bf3bf46689	not-for-merge	tag 'tag-one' of ../
 22feea448b023a2d864ef94b013735af34d238ba	not-for-merge	tag 'tag-one-tree' of ../
 c61a82b60967180544e3c19f819ddbd0c9f89899	not-for-merge	tag 'tag-three' of ../
diff --git a/t/t5515/fetch.br-config-explicit_config-explicit b/t/t5515/fetch.br-config-explicit_config-explicit
index b19b016..86045a7 100644
--- a/t/t5515/fetch.br-config-explicit_config-explicit
+++ b/t/t5515/fetch.br-config-explicit_config-explicit
@@ -1,9 +1,9 @@
 # br-config-explicit config-explicit
-754b754407bf032e9a2f9d5a9ad05ca79a6b228f		branch 'master' of ../
+b4ab76b1a01ea602209932134a44f1e6bd610832		branch 'main' of ../
 8e32a6d901327a23ef831511badce7bf3bf46689	not-for-merge	branch 'one' of ../
 6134ee8f857693b96ff1cc98d3e2fd62b199e5a8	not-for-merge	branch 'two' of ../
 0567da4d5edd2ff4bb292a465ba9e64dcad9536b	not-for-merge	branch 'three' of ../
-6c9dec2b923228c9ff994c6cfe4ae16c12408dc5	not-for-merge	tag 'tag-master' of ../
+ecf3b3627b498bdcb735cc4343bf165f76964e9a	not-for-merge	tag 'tag-main' of ../
 8e32a6d901327a23ef831511badce7bf3bf46689	not-for-merge	tag 'tag-one' of ../
 22feea448b023a2d864ef94b013735af34d238ba	not-for-merge	tag 'tag-one-tree' of ../
 c61a82b60967180544e3c19f819ddbd0c9f89899	not-for-merge	tag 'tag-three' of ../
diff --git a/t/t5515/fetch.br-config-glob b/t/t5515/fetch.br-config-glob
index 946d70c..bfeef2b 100644
--- a/t/t5515/fetch.br-config-glob
+++ b/t/t5515/fetch.br-config-glob
@@ -1,9 +1,9 @@
 # br-config-glob
-754b754407bf032e9a2f9d5a9ad05ca79a6b228f	not-for-merge	branch 'master' of ../
+b4ab76b1a01ea602209932134a44f1e6bd610832	not-for-merge	branch 'main' of ../
 8e32a6d901327a23ef831511badce7bf3bf46689	not-for-merge	branch 'one' of ../
 0567da4d5edd2ff4bb292a465ba9e64dcad9536b	not-for-merge	branch 'three' of ../
 6134ee8f857693b96ff1cc98d3e2fd62b199e5a8	not-for-merge	branch 'two' of ../
-6c9dec2b923228c9ff994c6cfe4ae16c12408dc5	not-for-merge	tag 'tag-master' of ../
+ecf3b3627b498bdcb735cc4343bf165f76964e9a	not-for-merge	tag 'tag-main' of ../
 8e32a6d901327a23ef831511badce7bf3bf46689	not-for-merge	tag 'tag-one' of ../
 22feea448b023a2d864ef94b013735af34d238ba	not-for-merge	tag 'tag-one-tree' of ../
 c61a82b60967180544e3c19f819ddbd0c9f89899	not-for-merge	tag 'tag-three' of ../
diff --git a/t/t5515/fetch.br-config-glob-merge b/t/t5515/fetch.br-config-glob-merge
index 89f2596..5376a4a 100644
--- a/t/t5515/fetch.br-config-glob-merge
+++ b/t/t5515/fetch.br-config-glob-merge
@@ -1,9 +1,9 @@
 # br-config-glob-merge
 0567da4d5edd2ff4bb292a465ba9e64dcad9536b		branch 'three' of ../
-754b754407bf032e9a2f9d5a9ad05ca79a6b228f	not-for-merge	branch 'master' of ../
+b4ab76b1a01ea602209932134a44f1e6bd610832	not-for-merge	branch 'main' of ../
 8e32a6d901327a23ef831511badce7bf3bf46689	not-for-merge	branch 'one' of ../
 6134ee8f857693b96ff1cc98d3e2fd62b199e5a8	not-for-merge	branch 'two' of ../
-6c9dec2b923228c9ff994c6cfe4ae16c12408dc5	not-for-merge	tag 'tag-master' of ../
+ecf3b3627b498bdcb735cc4343bf165f76964e9a	not-for-merge	tag 'tag-main' of ../
 8e32a6d901327a23ef831511badce7bf3bf46689	not-for-merge	tag 'tag-one' of ../
 22feea448b023a2d864ef94b013735af34d238ba	not-for-merge	tag 'tag-one-tree' of ../
 c61a82b60967180544e3c19f819ddbd0c9f89899	not-for-merge	tag 'tag-three' of ../
diff --git a/t/t5515/fetch.br-config-glob-merge_config-glob b/t/t5515/fetch.br-config-glob-merge_config-glob
index 2ba4832..7dfc2fe 100644
--- a/t/t5515/fetch.br-config-glob-merge_config-glob
+++ b/t/t5515/fetch.br-config-glob-merge_config-glob
@@ -1,9 +1,9 @@
 # br-config-glob-merge config-glob
 0567da4d5edd2ff4bb292a465ba9e64dcad9536b		branch 'three' of ../
-754b754407bf032e9a2f9d5a9ad05ca79a6b228f	not-for-merge	branch 'master' of ../
+b4ab76b1a01ea602209932134a44f1e6bd610832	not-for-merge	branch 'main' of ../
 8e32a6d901327a23ef831511badce7bf3bf46689	not-for-merge	branch 'one' of ../
 6134ee8f857693b96ff1cc98d3e2fd62b199e5a8	not-for-merge	branch 'two' of ../
-6c9dec2b923228c9ff994c6cfe4ae16c12408dc5	not-for-merge	tag 'tag-master' of ../
+ecf3b3627b498bdcb735cc4343bf165f76964e9a	not-for-merge	tag 'tag-main' of ../
 8e32a6d901327a23ef831511badce7bf3bf46689	not-for-merge	tag 'tag-one' of ../
 22feea448b023a2d864ef94b013735af34d238ba	not-for-merge	tag 'tag-one-tree' of ../
 c61a82b60967180544e3c19f819ddbd0c9f89899	not-for-merge	tag 'tag-three' of ../
diff --git a/t/t5515/fetch.br-config-glob-octopus b/t/t5515/fetch.br-config-glob-octopus
index 64994df..1084030 100644
--- a/t/t5515/fetch.br-config-glob-octopus
+++ b/t/t5515/fetch.br-config-glob-octopus
@@ -1,9 +1,9 @@
 # br-config-glob-octopus
 8e32a6d901327a23ef831511badce7bf3bf46689		branch 'one' of ../
 6134ee8f857693b96ff1cc98d3e2fd62b199e5a8		branch 'two' of ../
-754b754407bf032e9a2f9d5a9ad05ca79a6b228f	not-for-merge	branch 'master' of ../
+b4ab76b1a01ea602209932134a44f1e6bd610832	not-for-merge	branch 'main' of ../
 0567da4d5edd2ff4bb292a465ba9e64dcad9536b	not-for-merge	branch 'three' of ../
-6c9dec2b923228c9ff994c6cfe4ae16c12408dc5	not-for-merge	tag 'tag-master' of ../
+ecf3b3627b498bdcb735cc4343bf165f76964e9a	not-for-merge	tag 'tag-main' of ../
 8e32a6d901327a23ef831511badce7bf3bf46689	not-for-merge	tag 'tag-one' of ../
 22feea448b023a2d864ef94b013735af34d238ba	not-for-merge	tag 'tag-one-tree' of ../
 c61a82b60967180544e3c19f819ddbd0c9f89899	not-for-merge	tag 'tag-three' of ../
diff --git a/t/t5515/fetch.br-config-glob-octopus_config-glob b/t/t5515/fetch.br-config-glob-octopus_config-glob
index 681a725..839866d 100644
--- a/t/t5515/fetch.br-config-glob-octopus_config-glob
+++ b/t/t5515/fetch.br-config-glob-octopus_config-glob
@@ -1,9 +1,9 @@
 # br-config-glob-octopus config-glob
 8e32a6d901327a23ef831511badce7bf3bf46689		branch 'one' of ../
 6134ee8f857693b96ff1cc98d3e2fd62b199e5a8		branch 'two' of ../
-754b754407bf032e9a2f9d5a9ad05ca79a6b228f	not-for-merge	branch 'master' of ../
+b4ab76b1a01ea602209932134a44f1e6bd610832	not-for-merge	branch 'main' of ../
 0567da4d5edd2ff4bb292a465ba9e64dcad9536b	not-for-merge	branch 'three' of ../
-6c9dec2b923228c9ff994c6cfe4ae16c12408dc5	not-for-merge	tag 'tag-master' of ../
+ecf3b3627b498bdcb735cc4343bf165f76964e9a	not-for-merge	tag 'tag-main' of ../
 8e32a6d901327a23ef831511badce7bf3bf46689	not-for-merge	tag 'tag-one' of ../
 22feea448b023a2d864ef94b013735af34d238ba	not-for-merge	tag 'tag-one-tree' of ../
 c61a82b60967180544e3c19f819ddbd0c9f89899	not-for-merge	tag 'tag-three' of ../
diff --git a/t/t5515/fetch.br-config-glob_config-glob b/t/t5515/fetch.br-config-glob_config-glob
index 19daf0c..7b0cb91 100644
--- a/t/t5515/fetch.br-config-glob_config-glob
+++ b/t/t5515/fetch.br-config-glob_config-glob
@@ -1,9 +1,9 @@
 # br-config-glob config-glob
-754b754407bf032e9a2f9d5a9ad05ca79a6b228f	not-for-merge	branch 'master' of ../
+b4ab76b1a01ea602209932134a44f1e6bd610832	not-for-merge	branch 'main' of ../
 8e32a6d901327a23ef831511badce7bf3bf46689	not-for-merge	branch 'one' of ../
 0567da4d5edd2ff4bb292a465ba9e64dcad9536b	not-for-merge	branch 'three' of ../
 6134ee8f857693b96ff1cc98d3e2fd62b199e5a8	not-for-merge	branch 'two' of ../
-6c9dec2b923228c9ff994c6cfe4ae16c12408dc5	not-for-merge	tag 'tag-master' of ../
+ecf3b3627b498bdcb735cc4343bf165f76964e9a	not-for-merge	tag 'tag-main' of ../
 8e32a6d901327a23ef831511badce7bf3bf46689	not-for-merge	tag 'tag-one' of ../
 22feea448b023a2d864ef94b013735af34d238ba	not-for-merge	tag 'tag-one-tree' of ../
 c61a82b60967180544e3c19f819ddbd0c9f89899	not-for-merge	tag 'tag-three' of ../
diff --git a/t/t5515/fetch.br-remote-explicit b/t/t5515/fetch.br-remote-explicit
index ab44bc5..d6619e7 100644
--- a/t/t5515/fetch.br-remote-explicit
+++ b/t/t5515/fetch.br-remote-explicit
@@ -1,9 +1,9 @@
 # br-remote-explicit
-754b754407bf032e9a2f9d5a9ad05ca79a6b228f		branch 'master' of ../
+b4ab76b1a01ea602209932134a44f1e6bd610832		branch 'main' of ../
 8e32a6d901327a23ef831511badce7bf3bf46689	not-for-merge	branch 'one' of ../
 6134ee8f857693b96ff1cc98d3e2fd62b199e5a8	not-for-merge	branch 'two' of ../
 0567da4d5edd2ff4bb292a465ba9e64dcad9536b	not-for-merge	branch 'three' of ../
-6c9dec2b923228c9ff994c6cfe4ae16c12408dc5	not-for-merge	tag 'tag-master' of ../
+ecf3b3627b498bdcb735cc4343bf165f76964e9a	not-for-merge	tag 'tag-main' of ../
 8e32a6d901327a23ef831511badce7bf3bf46689	not-for-merge	tag 'tag-one' of ../
 22feea448b023a2d864ef94b013735af34d238ba	not-for-merge	tag 'tag-one-tree' of ../
 c61a82b60967180544e3c19f819ddbd0c9f89899	not-for-merge	tag 'tag-three' of ../
diff --git a/t/t5515/fetch.br-remote-explicit-merge b/t/t5515/fetch.br-remote-explicit-merge
index d018b35..5b49b7c 100644
--- a/t/t5515/fetch.br-remote-explicit-merge
+++ b/t/t5515/fetch.br-remote-explicit-merge
@@ -1,9 +1,9 @@
 # br-remote-explicit-merge
 0567da4d5edd2ff4bb292a465ba9e64dcad9536b		branch 'three' of ../
-754b754407bf032e9a2f9d5a9ad05ca79a6b228f	not-for-merge	branch 'master' of ../
+b4ab76b1a01ea602209932134a44f1e6bd610832	not-for-merge	branch 'main' of ../
 8e32a6d901327a23ef831511badce7bf3bf46689	not-for-merge	branch 'one' of ../
 6134ee8f857693b96ff1cc98d3e2fd62b199e5a8	not-for-merge	branch 'two' of ../
-6c9dec2b923228c9ff994c6cfe4ae16c12408dc5	not-for-merge	tag 'tag-master' of ../
+ecf3b3627b498bdcb735cc4343bf165f76964e9a	not-for-merge	tag 'tag-main' of ../
 8e32a6d901327a23ef831511badce7bf3bf46689	not-for-merge	tag 'tag-one' of ../
 22feea448b023a2d864ef94b013735af34d238ba	not-for-merge	tag 'tag-one-tree' of ../
 c61a82b60967180544e3c19f819ddbd0c9f89899	not-for-merge	tag 'tag-three' of ../
diff --git a/t/t5515/fetch.br-remote-explicit-merge_remote-explicit b/t/t5515/fetch.br-remote-explicit-merge_remote-explicit
index 0d3d780..417261d 100644
--- a/t/t5515/fetch.br-remote-explicit-merge_remote-explicit
+++ b/t/t5515/fetch.br-remote-explicit-merge_remote-explicit
@@ -1,9 +1,9 @@
 # br-remote-explicit-merge remote-explicit
 0567da4d5edd2ff4bb292a465ba9e64dcad9536b		branch 'three' of ../
-754b754407bf032e9a2f9d5a9ad05ca79a6b228f	not-for-merge	branch 'master' of ../
+b4ab76b1a01ea602209932134a44f1e6bd610832	not-for-merge	branch 'main' of ../
 8e32a6d901327a23ef831511badce7bf3bf46689	not-for-merge	branch 'one' of ../
 6134ee8f857693b96ff1cc98d3e2fd62b199e5a8	not-for-merge	branch 'two' of ../
-6c9dec2b923228c9ff994c6cfe4ae16c12408dc5	not-for-merge	tag 'tag-master' of ../
+ecf3b3627b498bdcb735cc4343bf165f76964e9a	not-for-merge	tag 'tag-main' of ../
 8e32a6d901327a23ef831511badce7bf3bf46689	not-for-merge	tag 'tag-one' of ../
 22feea448b023a2d864ef94b013735af34d238ba	not-for-merge	tag 'tag-one-tree' of ../
 c61a82b60967180544e3c19f819ddbd0c9f89899	not-for-merge	tag 'tag-three' of ../
diff --git a/t/t5515/fetch.br-remote-explicit-octopus b/t/t5515/fetch.br-remote-explicit-octopus
index 6f84304..2edef64 100644
--- a/t/t5515/fetch.br-remote-explicit-octopus
+++ b/t/t5515/fetch.br-remote-explicit-octopus
@@ -1,9 +1,9 @@
 # br-remote-explicit-octopus
 8e32a6d901327a23ef831511badce7bf3bf46689		branch 'one' of ../
 6134ee8f857693b96ff1cc98d3e2fd62b199e5a8		branch 'two' of ../
-754b754407bf032e9a2f9d5a9ad05ca79a6b228f	not-for-merge	branch 'master' of ../
+b4ab76b1a01ea602209932134a44f1e6bd610832	not-for-merge	branch 'main' of ../
 0567da4d5edd2ff4bb292a465ba9e64dcad9536b	not-for-merge	branch 'three' of ../
-6c9dec2b923228c9ff994c6cfe4ae16c12408dc5	not-for-merge	tag 'tag-master' of ../
+ecf3b3627b498bdcb735cc4343bf165f76964e9a	not-for-merge	tag 'tag-main' of ../
 8e32a6d901327a23ef831511badce7bf3bf46689	not-for-merge	tag 'tag-one' of ../
 22feea448b023a2d864ef94b013735af34d238ba	not-for-merge	tag 'tag-one-tree' of ../
 c61a82b60967180544e3c19f819ddbd0c9f89899	not-for-merge	tag 'tag-three' of ../
diff --git a/t/t5515/fetch.br-remote-explicit-octopus_remote-explicit b/t/t5515/fetch.br-remote-explicit-octopus_remote-explicit
index 3546a83..ceb8752 100644
--- a/t/t5515/fetch.br-remote-explicit-octopus_remote-explicit
+++ b/t/t5515/fetch.br-remote-explicit-octopus_remote-explicit
@@ -1,9 +1,9 @@
 # br-remote-explicit-octopus remote-explicit
 8e32a6d901327a23ef831511badce7bf3bf46689		branch 'one' of ../
 6134ee8f857693b96ff1cc98d3e2fd62b199e5a8		branch 'two' of ../
-754b754407bf032e9a2f9d5a9ad05ca79a6b228f	not-for-merge	branch 'master' of ../
+b4ab76b1a01ea602209932134a44f1e6bd610832	not-for-merge	branch 'main' of ../
 0567da4d5edd2ff4bb292a465ba9e64dcad9536b	not-for-merge	branch 'three' of ../
-6c9dec2b923228c9ff994c6cfe4ae16c12408dc5	not-for-merge	tag 'tag-master' of ../
+ecf3b3627b498bdcb735cc4343bf165f76964e9a	not-for-merge	tag 'tag-main' of ../
 8e32a6d901327a23ef831511badce7bf3bf46689	not-for-merge	tag 'tag-one' of ../
 22feea448b023a2d864ef94b013735af34d238ba	not-for-merge	tag 'tag-one-tree' of ../
 c61a82b60967180544e3c19f819ddbd0c9f89899	not-for-merge	tag 'tag-three' of ../
diff --git a/t/t5515/fetch.br-remote-explicit_remote-explicit b/t/t5515/fetch.br-remote-explicit_remote-explicit
index 01e014e..b7abbd2 100644
--- a/t/t5515/fetch.br-remote-explicit_remote-explicit
+++ b/t/t5515/fetch.br-remote-explicit_remote-explicit
@@ -1,9 +1,9 @@
 # br-remote-explicit remote-explicit
-754b754407bf032e9a2f9d5a9ad05ca79a6b228f		branch 'master' of ../
+b4ab76b1a01ea602209932134a44f1e6bd610832		branch 'main' of ../
 8e32a6d901327a23ef831511badce7bf3bf46689	not-for-merge	branch 'one' of ../
 6134ee8f857693b96ff1cc98d3e2fd62b199e5a8	not-for-merge	branch 'two' of ../
 0567da4d5edd2ff4bb292a465ba9e64dcad9536b	not-for-merge	branch 'three' of ../
-6c9dec2b923228c9ff994c6cfe4ae16c12408dc5	not-for-merge	tag 'tag-master' of ../
+ecf3b3627b498bdcb735cc4343bf165f76964e9a	not-for-merge	tag 'tag-main' of ../
 8e32a6d901327a23ef831511badce7bf3bf46689	not-for-merge	tag 'tag-one' of ../
 22feea448b023a2d864ef94b013735af34d238ba	not-for-merge	tag 'tag-one-tree' of ../
 c61a82b60967180544e3c19f819ddbd0c9f89899	not-for-merge	tag 'tag-three' of ../
diff --git a/t/t5515/fetch.br-remote-glob b/t/t5515/fetch.br-remote-glob
index 09bfcee..645412c 100644
--- a/t/t5515/fetch.br-remote-glob
+++ b/t/t5515/fetch.br-remote-glob
@@ -1,9 +1,9 @@
 # br-remote-glob
-754b754407bf032e9a2f9d5a9ad05ca79a6b228f	not-for-merge	branch 'master' of ../
+b4ab76b1a01ea602209932134a44f1e6bd610832	not-for-merge	branch 'main' of ../
 8e32a6d901327a23ef831511badce7bf3bf46689	not-for-merge	branch 'one' of ../
 0567da4d5edd2ff4bb292a465ba9e64dcad9536b	not-for-merge	branch 'three' of ../
 6134ee8f857693b96ff1cc98d3e2fd62b199e5a8	not-for-merge	branch 'two' of ../
-6c9dec2b923228c9ff994c6cfe4ae16c12408dc5	not-for-merge	tag 'tag-master' of ../
+ecf3b3627b498bdcb735cc4343bf165f76964e9a	not-for-merge	tag 'tag-main' of ../
 8e32a6d901327a23ef831511badce7bf3bf46689	not-for-merge	tag 'tag-one' of ../
 22feea448b023a2d864ef94b013735af34d238ba	not-for-merge	tag 'tag-one-tree' of ../
 c61a82b60967180544e3c19f819ddbd0c9f89899	not-for-merge	tag 'tag-three' of ../
diff --git a/t/t5515/fetch.br-remote-glob-merge b/t/t5515/fetch.br-remote-glob-merge
index 7e1a433..8512cfd 100644
--- a/t/t5515/fetch.br-remote-glob-merge
+++ b/t/t5515/fetch.br-remote-glob-merge
@@ -1,9 +1,9 @@
 # br-remote-glob-merge
 0567da4d5edd2ff4bb292a465ba9e64dcad9536b		branch 'three' of ../
-754b754407bf032e9a2f9d5a9ad05ca79a6b228f	not-for-merge	branch 'master' of ../
+b4ab76b1a01ea602209932134a44f1e6bd610832	not-for-merge	branch 'main' of ../
 8e32a6d901327a23ef831511badce7bf3bf46689	not-for-merge	branch 'one' of ../
 6134ee8f857693b96ff1cc98d3e2fd62b199e5a8	not-for-merge	branch 'two' of ../
-6c9dec2b923228c9ff994c6cfe4ae16c12408dc5	not-for-merge	tag 'tag-master' of ../
+ecf3b3627b498bdcb735cc4343bf165f76964e9a	not-for-merge	tag 'tag-main' of ../
 8e32a6d901327a23ef831511badce7bf3bf46689	not-for-merge	tag 'tag-one' of ../
 22feea448b023a2d864ef94b013735af34d238ba	not-for-merge	tag 'tag-one-tree' of ../
 c61a82b60967180544e3c19f819ddbd0c9f89899	not-for-merge	tag 'tag-three' of ../
diff --git a/t/t5515/fetch.br-remote-glob-merge_remote-glob b/t/t5515/fetch.br-remote-glob-merge_remote-glob
index 53571bb..7394164 100644
--- a/t/t5515/fetch.br-remote-glob-merge_remote-glob
+++ b/t/t5515/fetch.br-remote-glob-merge_remote-glob
@@ -1,9 +1,9 @@
 # br-remote-glob-merge remote-glob
 0567da4d5edd2ff4bb292a465ba9e64dcad9536b		branch 'three' of ../
-754b754407bf032e9a2f9d5a9ad05ca79a6b228f	not-for-merge	branch 'master' of ../
+b4ab76b1a01ea602209932134a44f1e6bd610832	not-for-merge	branch 'main' of ../
 8e32a6d901327a23ef831511badce7bf3bf46689	not-for-merge	branch 'one' of ../
 6134ee8f857693b96ff1cc98d3e2fd62b199e5a8	not-for-merge	branch 'two' of ../
-6c9dec2b923228c9ff994c6cfe4ae16c12408dc5	not-for-merge	tag 'tag-master' of ../
+ecf3b3627b498bdcb735cc4343bf165f76964e9a	not-for-merge	tag 'tag-main' of ../
 8e32a6d901327a23ef831511badce7bf3bf46689	not-for-merge	tag 'tag-one' of ../
 22feea448b023a2d864ef94b013735af34d238ba	not-for-merge	tag 'tag-one-tree' of ../
 c61a82b60967180544e3c19f819ddbd0c9f89899	not-for-merge	tag 'tag-three' of ../
diff --git a/t/t5515/fetch.br-remote-glob-octopus b/t/t5515/fetch.br-remote-glob-octopus
index c7c8b6d..0ca4719 100644
--- a/t/t5515/fetch.br-remote-glob-octopus
+++ b/t/t5515/fetch.br-remote-glob-octopus
@@ -1,9 +1,9 @@
 # br-remote-glob-octopus
 8e32a6d901327a23ef831511badce7bf3bf46689		branch 'one' of ../
 6134ee8f857693b96ff1cc98d3e2fd62b199e5a8		branch 'two' of ../
-754b754407bf032e9a2f9d5a9ad05ca79a6b228f	not-for-merge	branch 'master' of ../
+b4ab76b1a01ea602209932134a44f1e6bd610832	not-for-merge	branch 'main' of ../
 0567da4d5edd2ff4bb292a465ba9e64dcad9536b	not-for-merge	branch 'three' of ../
-6c9dec2b923228c9ff994c6cfe4ae16c12408dc5	not-for-merge	tag 'tag-master' of ../
+ecf3b3627b498bdcb735cc4343bf165f76964e9a	not-for-merge	tag 'tag-main' of ../
 8e32a6d901327a23ef831511badce7bf3bf46689	not-for-merge	tag 'tag-one' of ../
 22feea448b023a2d864ef94b013735af34d238ba	not-for-merge	tag 'tag-one-tree' of ../
 c61a82b60967180544e3c19f819ddbd0c9f89899	not-for-merge	tag 'tag-three' of ../
diff --git a/t/t5515/fetch.br-remote-glob-octopus_remote-glob b/t/t5515/fetch.br-remote-glob-octopus_remote-glob
index 36076fb..7e7b0ba 100644
--- a/t/t5515/fetch.br-remote-glob-octopus_remote-glob
+++ b/t/t5515/fetch.br-remote-glob-octopus_remote-glob
@@ -1,9 +1,9 @@
 # br-remote-glob-octopus remote-glob
 8e32a6d901327a23ef831511badce7bf3bf46689		branch 'one' of ../
 6134ee8f857693b96ff1cc98d3e2fd62b199e5a8		branch 'two' of ../
-754b754407bf032e9a2f9d5a9ad05ca79a6b228f	not-for-merge	branch 'master' of ../
+b4ab76b1a01ea602209932134a44f1e6bd610832	not-for-merge	branch 'main' of ../
 0567da4d5edd2ff4bb292a465ba9e64dcad9536b	not-for-merge	branch 'three' of ../
-6c9dec2b923228c9ff994c6cfe4ae16c12408dc5	not-for-merge	tag 'tag-master' of ../
+ecf3b3627b498bdcb735cc4343bf165f76964e9a	not-for-merge	tag 'tag-main' of ../
 8e32a6d901327a23ef831511badce7bf3bf46689	not-for-merge	tag 'tag-one' of ../
 22feea448b023a2d864ef94b013735af34d238ba	not-for-merge	tag 'tag-one-tree' of ../
 c61a82b60967180544e3c19f819ddbd0c9f89899	not-for-merge	tag 'tag-three' of ../
diff --git a/t/t5515/fetch.br-remote-glob_remote-glob b/t/t5515/fetch.br-remote-glob_remote-glob
index 20ba5cb..7bae5ec 100644
--- a/t/t5515/fetch.br-remote-glob_remote-glob
+++ b/t/t5515/fetch.br-remote-glob_remote-glob
@@ -1,9 +1,9 @@
 # br-remote-glob remote-glob
-754b754407bf032e9a2f9d5a9ad05ca79a6b228f	not-for-merge	branch 'master' of ../
+b4ab76b1a01ea602209932134a44f1e6bd610832	not-for-merge	branch 'main' of ../
 8e32a6d901327a23ef831511badce7bf3bf46689	not-for-merge	branch 'one' of ../
 0567da4d5edd2ff4bb292a465ba9e64dcad9536b	not-for-merge	branch 'three' of ../
 6134ee8f857693b96ff1cc98d3e2fd62b199e5a8	not-for-merge	branch 'two' of ../
-6c9dec2b923228c9ff994c6cfe4ae16c12408dc5	not-for-merge	tag 'tag-master' of ../
+ecf3b3627b498bdcb735cc4343bf165f76964e9a	not-for-merge	tag 'tag-main' of ../
 8e32a6d901327a23ef831511badce7bf3bf46689	not-for-merge	tag 'tag-one' of ../
 22feea448b023a2d864ef94b013735af34d238ba	not-for-merge	tag 'tag-one-tree' of ../
 c61a82b60967180544e3c19f819ddbd0c9f89899	not-for-merge	tag 'tag-three' of ../
diff --git a/t/t5515/fetch.br-unconfig b/t/t5515/fetch.br-unconfig
index 887ccfc..ccaa54f 100644
--- a/t/t5515/fetch.br-unconfig
+++ b/t/t5515/fetch.br-unconfig
@@ -1,9 +1,9 @@
 # br-unconfig
-754b754407bf032e9a2f9d5a9ad05ca79a6b228f	not-for-merge	branch 'master' of ../
+b4ab76b1a01ea602209932134a44f1e6bd610832	not-for-merge	branch 'main' of ../
 8e32a6d901327a23ef831511badce7bf3bf46689	not-for-merge	branch 'one' of ../
 0567da4d5edd2ff4bb292a465ba9e64dcad9536b	not-for-merge	branch 'three' of ../
 6134ee8f857693b96ff1cc98d3e2fd62b199e5a8	not-for-merge	branch 'two' of ../
-6c9dec2b923228c9ff994c6cfe4ae16c12408dc5	not-for-merge	tag 'tag-master' of ../
+ecf3b3627b498bdcb735cc4343bf165f76964e9a	not-for-merge	tag 'tag-main' of ../
 8e32a6d901327a23ef831511badce7bf3bf46689	not-for-merge	tag 'tag-one' of ../
 22feea448b023a2d864ef94b013735af34d238ba	not-for-merge	tag 'tag-one-tree' of ../
 c61a82b60967180544e3c19f819ddbd0c9f89899	not-for-merge	tag 'tag-three' of ../
diff --git a/t/t5515/fetch.br-unconfig_--tags_.._.git b/t/t5515/fetch.br-unconfig_--tags_.._.git
index 0f70f66..3afb4f8 100644
--- a/t/t5515/fetch.br-unconfig_--tags_.._.git
+++ b/t/t5515/fetch.br-unconfig_--tags_.._.git
@@ -1,6 +1,6 @@
 # br-unconfig --tags ../.git
 0567da4d5edd2ff4bb292a465ba9e64dcad9536b		../
-6c9dec2b923228c9ff994c6cfe4ae16c12408dc5	not-for-merge	tag 'tag-master' of ../
+ecf3b3627b498bdcb735cc4343bf165f76964e9a	not-for-merge	tag 'tag-main' of ../
 8e32a6d901327a23ef831511badce7bf3bf46689	not-for-merge	tag 'tag-one' of ../
 22feea448b023a2d864ef94b013735af34d238ba	not-for-merge	tag 'tag-one-tree' of ../
 c61a82b60967180544e3c19f819ddbd0c9f89899	not-for-merge	tag 'tag-three' of ../
diff --git a/t/t5515/fetch.br-unconfig_.._.git_one_tag_tag-one_tag_tag-three-file b/t/t5515/fetch.br-unconfig_.._.git_one_tag_tag-one_tag_tag-three-file
index 7411536..525713a 100644
--- a/t/t5515/fetch.br-unconfig_.._.git_one_tag_tag-one_tag_tag-three-file
+++ b/t/t5515/fetch.br-unconfig_.._.git_one_tag_tag-one_tag_tag-three-file
@@ -2,7 +2,7 @@
 8e32a6d901327a23ef831511badce7bf3bf46689		branch 'one' of ../
 8e32a6d901327a23ef831511badce7bf3bf46689		tag 'tag-one' of ../
 0e3b14047d3ee365f4f2a1b673db059c3972589c	not-for-merge	tag 'tag-three-file' of ../
-6c9dec2b923228c9ff994c6cfe4ae16c12408dc5	not-for-merge	tag 'tag-master' of ../
+ecf3b3627b498bdcb735cc4343bf165f76964e9a	not-for-merge	tag 'tag-main' of ../
 22feea448b023a2d864ef94b013735af34d238ba	not-for-merge	tag 'tag-one-tree' of ../
 c61a82b60967180544e3c19f819ddbd0c9f89899	not-for-merge	tag 'tag-three' of ../
 525b7fb068d59950d185a8779dc957c77eed73ba	not-for-merge	tag 'tag-two' of ../
diff --git a/t/t5515/fetch.br-unconfig_.._.git_tag_tag-one-tree_tag_tag-three-file b/t/t5515/fetch.br-unconfig_.._.git_tag_tag-one-tree_tag_tag-three-file
index 7726983..18c871f 100644
--- a/t/t5515/fetch.br-unconfig_.._.git_tag_tag-one-tree_tag_tag-three-file
+++ b/t/t5515/fetch.br-unconfig_.._.git_tag_tag-one-tree_tag_tag-three-file
@@ -1,7 +1,7 @@
 # br-unconfig ../.git tag tag-one-tree tag tag-three-file
 22feea448b023a2d864ef94b013735af34d238ba	not-for-merge	tag 'tag-one-tree' of ../
 0e3b14047d3ee365f4f2a1b673db059c3972589c	not-for-merge	tag 'tag-three-file' of ../
-6c9dec2b923228c9ff994c6cfe4ae16c12408dc5	not-for-merge	tag 'tag-master' of ../
+ecf3b3627b498bdcb735cc4343bf165f76964e9a	not-for-merge	tag 'tag-main' of ../
 8e32a6d901327a23ef831511badce7bf3bf46689	not-for-merge	tag 'tag-one' of ../
 c61a82b60967180544e3c19f819ddbd0c9f89899	not-for-merge	tag 'tag-three' of ../
 525b7fb068d59950d185a8779dc957c77eed73ba	not-for-merge	tag 'tag-two' of ../
diff --git a/t/t5515/fetch.br-unconfig_.._.git_tag_tag-one_tag_tag-three b/t/t5515/fetch.br-unconfig_.._.git_tag_tag-one_tag_tag-three
index 7b3750c..7328d30 100644
--- a/t/t5515/fetch.br-unconfig_.._.git_tag_tag-one_tag_tag-three
+++ b/t/t5515/fetch.br-unconfig_.._.git_tag_tag-one_tag_tag-three
@@ -1,7 +1,7 @@
 # br-unconfig ../.git tag tag-one tag tag-three
 8e32a6d901327a23ef831511badce7bf3bf46689		tag 'tag-one' of ../
 c61a82b60967180544e3c19f819ddbd0c9f89899		tag 'tag-three' of ../
-6c9dec2b923228c9ff994c6cfe4ae16c12408dc5	not-for-merge	tag 'tag-master' of ../
+ecf3b3627b498bdcb735cc4343bf165f76964e9a	not-for-merge	tag 'tag-main' of ../
 22feea448b023a2d864ef94b013735af34d238ba	not-for-merge	tag 'tag-one-tree' of ../
 0e3b14047d3ee365f4f2a1b673db059c3972589c	not-for-merge	tag 'tag-three-file' of ../
 525b7fb068d59950d185a8779dc957c77eed73ba	not-for-merge	tag 'tag-two' of ../
diff --git a/t/t5515/fetch.br-unconfig_branches-default b/t/t5515/fetch.br-unconfig_branches-default
index da30e3c..3d82f94 100644
--- a/t/t5515/fetch.br-unconfig_branches-default
+++ b/t/t5515/fetch.br-unconfig_branches-default
@@ -1,6 +1,6 @@
 # br-unconfig branches-default
-754b754407bf032e9a2f9d5a9ad05ca79a6b228f		branch 'master' of ../
-6c9dec2b923228c9ff994c6cfe4ae16c12408dc5	not-for-merge	tag 'tag-master' of ../
+b4ab76b1a01ea602209932134a44f1e6bd610832		branch 'main' of ../
+ecf3b3627b498bdcb735cc4343bf165f76964e9a	not-for-merge	tag 'tag-main' of ../
 8e32a6d901327a23ef831511badce7bf3bf46689	not-for-merge	tag 'tag-one' of ../
 22feea448b023a2d864ef94b013735af34d238ba	not-for-merge	tag 'tag-one-tree' of ../
 c61a82b60967180544e3c19f819ddbd0c9f89899	not-for-merge	tag 'tag-three' of ../
diff --git a/t/t5515/fetch.br-unconfig_branches-one b/t/t5515/fetch.br-unconfig_branches-one
index e461431..948ed0c 100644
--- a/t/t5515/fetch.br-unconfig_branches-one
+++ b/t/t5515/fetch.br-unconfig_branches-one
@@ -1,6 +1,6 @@
 # br-unconfig branches-one
 8e32a6d901327a23ef831511badce7bf3bf46689		branch 'one' of ../
-6c9dec2b923228c9ff994c6cfe4ae16c12408dc5	not-for-merge	tag 'tag-master' of ../
+ecf3b3627b498bdcb735cc4343bf165f76964e9a	not-for-merge	tag 'tag-main' of ../
 8e32a6d901327a23ef831511badce7bf3bf46689	not-for-merge	tag 'tag-one' of ../
 22feea448b023a2d864ef94b013735af34d238ba	not-for-merge	tag 'tag-one-tree' of ../
 c61a82b60967180544e3c19f819ddbd0c9f89899	not-for-merge	tag 'tag-three' of ../
diff --git a/t/t5515/fetch.br-unconfig_config-explicit b/t/t5515/fetch.br-unconfig_config-explicit
index ed323c9..65aaec8 100644
--- a/t/t5515/fetch.br-unconfig_config-explicit
+++ b/t/t5515/fetch.br-unconfig_config-explicit
@@ -1,9 +1,9 @@
 # br-unconfig config-explicit
-754b754407bf032e9a2f9d5a9ad05ca79a6b228f		branch 'master' of ../
+b4ab76b1a01ea602209932134a44f1e6bd610832		branch 'main' of ../
 8e32a6d901327a23ef831511badce7bf3bf46689	not-for-merge	branch 'one' of ../
 6134ee8f857693b96ff1cc98d3e2fd62b199e5a8	not-for-merge	branch 'two' of ../
 0567da4d5edd2ff4bb292a465ba9e64dcad9536b	not-for-merge	branch 'three' of ../
-6c9dec2b923228c9ff994c6cfe4ae16c12408dc5	not-for-merge	tag 'tag-master' of ../
+ecf3b3627b498bdcb735cc4343bf165f76964e9a	not-for-merge	tag 'tag-main' of ../
 8e32a6d901327a23ef831511badce7bf3bf46689	not-for-merge	tag 'tag-one' of ../
 22feea448b023a2d864ef94b013735af34d238ba	not-for-merge	tag 'tag-one-tree' of ../
 c61a82b60967180544e3c19f819ddbd0c9f89899	not-for-merge	tag 'tag-three' of ../
diff --git a/t/t5515/fetch.br-unconfig_config-glob b/t/t5515/fetch.br-unconfig_config-glob
index 2372ed0..1aa3d45 100644
--- a/t/t5515/fetch.br-unconfig_config-glob
+++ b/t/t5515/fetch.br-unconfig_config-glob
@@ -1,9 +1,9 @@
 # br-unconfig config-glob
-754b754407bf032e9a2f9d5a9ad05ca79a6b228f	not-for-merge	branch 'master' of ../
+b4ab76b1a01ea602209932134a44f1e6bd610832	not-for-merge	branch 'main' of ../
 8e32a6d901327a23ef831511badce7bf3bf46689	not-for-merge	branch 'one' of ../
 0567da4d5edd2ff4bb292a465ba9e64dcad9536b	not-for-merge	branch 'three' of ../
 6134ee8f857693b96ff1cc98d3e2fd62b199e5a8	not-for-merge	branch 'two' of ../
-6c9dec2b923228c9ff994c6cfe4ae16c12408dc5	not-for-merge	tag 'tag-master' of ../
+ecf3b3627b498bdcb735cc4343bf165f76964e9a	not-for-merge	tag 'tag-main' of ../
 8e32a6d901327a23ef831511badce7bf3bf46689	not-for-merge	tag 'tag-one' of ../
 22feea448b023a2d864ef94b013735af34d238ba	not-for-merge	tag 'tag-one-tree' of ../
 c61a82b60967180544e3c19f819ddbd0c9f89899	not-for-merge	tag 'tag-three' of ../
diff --git a/t/t5515/fetch.br-unconfig_remote-explicit b/t/t5515/fetch.br-unconfig_remote-explicit
index 6318dd1..16438d2 100644
--- a/t/t5515/fetch.br-unconfig_remote-explicit
+++ b/t/t5515/fetch.br-unconfig_remote-explicit
@@ -1,9 +1,9 @@
 # br-unconfig remote-explicit
-754b754407bf032e9a2f9d5a9ad05ca79a6b228f		branch 'master' of ../
+b4ab76b1a01ea602209932134a44f1e6bd610832		branch 'main' of ../
 8e32a6d901327a23ef831511badce7bf3bf46689	not-for-merge	branch 'one' of ../
 6134ee8f857693b96ff1cc98d3e2fd62b199e5a8	not-for-merge	branch 'two' of ../
 0567da4d5edd2ff4bb292a465ba9e64dcad9536b	not-for-merge	branch 'three' of ../
-6c9dec2b923228c9ff994c6cfe4ae16c12408dc5	not-for-merge	tag 'tag-master' of ../
+ecf3b3627b498bdcb735cc4343bf165f76964e9a	not-for-merge	tag 'tag-main' of ../
 8e32a6d901327a23ef831511badce7bf3bf46689	not-for-merge	tag 'tag-one' of ../
 22feea448b023a2d864ef94b013735af34d238ba	not-for-merge	tag 'tag-one-tree' of ../
 c61a82b60967180544e3c19f819ddbd0c9f89899	not-for-merge	tag 'tag-three' of ../
diff --git a/t/t5515/fetch.br-unconfig_remote-glob b/t/t5515/fetch.br-unconfig_remote-glob
index 1d9afad..7a01d2e 100644
--- a/t/t5515/fetch.br-unconfig_remote-glob
+++ b/t/t5515/fetch.br-unconfig_remote-glob
@@ -1,9 +1,9 @@
 # br-unconfig remote-glob
-754b754407bf032e9a2f9d5a9ad05ca79a6b228f	not-for-merge	branch 'master' of ../
+b4ab76b1a01ea602209932134a44f1e6bd610832	not-for-merge	branch 'main' of ../
 8e32a6d901327a23ef831511badce7bf3bf46689	not-for-merge	branch 'one' of ../
 0567da4d5edd2ff4bb292a465ba9e64dcad9536b	not-for-merge	branch 'three' of ../
 6134ee8f857693b96ff1cc98d3e2fd62b199e5a8	not-for-merge	branch 'two' of ../
-6c9dec2b923228c9ff994c6cfe4ae16c12408dc5	not-for-merge	tag 'tag-master' of ../
+ecf3b3627b498bdcb735cc4343bf165f76964e9a	not-for-merge	tag 'tag-main' of ../
 8e32a6d901327a23ef831511badce7bf3bf46689	not-for-merge	tag 'tag-one' of ../
 22feea448b023a2d864ef94b013735af34d238ba	not-for-merge	tag 'tag-one-tree' of ../
 c61a82b60967180544e3c19f819ddbd0c9f89899	not-for-merge	tag 'tag-three' of ../
diff --git a/t/t5515/fetch.master_config-explicit b/t/t5515/fetch.main
similarity index 78%
copy from t/t5515/fetch.master_config-explicit
copy to t/t5515/fetch.main
index 251c826..819ed33 100644
--- a/t/t5515/fetch.master_config-explicit
+++ b/t/t5515/fetch.main
@@ -1,9 +1,9 @@
-# master config-explicit
-754b754407bf032e9a2f9d5a9ad05ca79a6b228f		branch 'master' of ../
+# main
+b4ab76b1a01ea602209932134a44f1e6bd610832	not-for-merge	branch 'main' of ../
 8e32a6d901327a23ef831511badce7bf3bf46689	not-for-merge	branch 'one' of ../
-6134ee8f857693b96ff1cc98d3e2fd62b199e5a8	not-for-merge	branch 'two' of ../
 0567da4d5edd2ff4bb292a465ba9e64dcad9536b	not-for-merge	branch 'three' of ../
-6c9dec2b923228c9ff994c6cfe4ae16c12408dc5	not-for-merge	tag 'tag-master' of ../
+6134ee8f857693b96ff1cc98d3e2fd62b199e5a8	not-for-merge	branch 'two' of ../
+ecf3b3627b498bdcb735cc4343bf165f76964e9a	not-for-merge	tag 'tag-main' of ../
 8e32a6d901327a23ef831511badce7bf3bf46689	not-for-merge	tag 'tag-one' of ../
 22feea448b023a2d864ef94b013735af34d238ba	not-for-merge	tag 'tag-one-tree' of ../
 c61a82b60967180544e3c19f819ddbd0c9f89899	not-for-merge	tag 'tag-three' of ../
diff --git a/t/t5515/fetch.master_--tags_.._.git b/t/t5515/fetch.main_--tags_.._.git
similarity index 80%
rename from t/t5515/fetch.master_--tags_.._.git
rename to t/t5515/fetch.main_--tags_.._.git
index ab473a6..ddf67a6 100644
--- a/t/t5515/fetch.master_--tags_.._.git
+++ b/t/t5515/fetch.main_--tags_.._.git
@@ -1,6 +1,6 @@
-# master --tags ../.git
+# main --tags ../.git
 0567da4d5edd2ff4bb292a465ba9e64dcad9536b		../
-6c9dec2b923228c9ff994c6cfe4ae16c12408dc5	not-for-merge	tag 'tag-master' of ../
+ecf3b3627b498bdcb735cc4343bf165f76964e9a	not-for-merge	tag 'tag-main' of ../
 8e32a6d901327a23ef831511badce7bf3bf46689	not-for-merge	tag 'tag-one' of ../
 22feea448b023a2d864ef94b013735af34d238ba	not-for-merge	tag 'tag-one-tree' of ../
 c61a82b60967180544e3c19f819ddbd0c9f89899	not-for-merge	tag 'tag-three' of ../
diff --git a/t/t5515/fetch.master_.._.git b/t/t5515/fetch.main_.._.git
similarity index 72%
rename from t/t5515/fetch.master_.._.git
rename to t/t5515/fetch.main_.._.git
index 66d1aad..285e57e 100644
--- a/t/t5515/fetch.master_.._.git
+++ b/t/t5515/fetch.main_.._.git
@@ -1,2 +1,2 @@
-# master ../.git
+# main ../.git
 0567da4d5edd2ff4bb292a465ba9e64dcad9536b		../
diff --git a/t/t5515/fetch.master_.._.git_one b/t/t5515/fetch.main_.._.git_one
similarity index 74%
rename from t/t5515/fetch.master_.._.git_one
rename to t/t5515/fetch.main_.._.git_one
index 35deddb..f9f511e 100644
--- a/t/t5515/fetch.master_.._.git_one
+++ b/t/t5515/fetch.main_.._.git_one
@@ -1,2 +1,2 @@
-# master ../.git one
+# main ../.git one
 8e32a6d901327a23ef831511badce7bf3bf46689		branch 'one' of ../
diff --git a/t/t5515/fetch.master_.._.git_one_tag_tag-one_tag_tag-three-file b/t/t5515/fetch.main_.._.git_one_tag_tag-one_tag_tag-three-file
similarity index 77%
rename from t/t5515/fetch.master_.._.git_one_tag_tag-one_tag_tag-three-file
rename to t/t5515/fetch.main_.._.git_one_tag_tag-one_tag_tag-three-file
index 0672d12..187643e 100644
--- a/t/t5515/fetch.master_.._.git_one_tag_tag-one_tag_tag-three-file
+++ b/t/t5515/fetch.main_.._.git_one_tag_tag-one_tag_tag-three-file
@@ -1,8 +1,8 @@
-# master ../.git one tag tag-one tag tag-three-file
+# main ../.git one tag tag-one tag tag-three-file
 8e32a6d901327a23ef831511badce7bf3bf46689		branch 'one' of ../
 8e32a6d901327a23ef831511badce7bf3bf46689		tag 'tag-one' of ../
 0e3b14047d3ee365f4f2a1b673db059c3972589c	not-for-merge	tag 'tag-three-file' of ../
-6c9dec2b923228c9ff994c6cfe4ae16c12408dc5	not-for-merge	tag 'tag-master' of ../
+ecf3b3627b498bdcb735cc4343bf165f76964e9a	not-for-merge	tag 'tag-main' of ../
 22feea448b023a2d864ef94b013735af34d238ba	not-for-merge	tag 'tag-one-tree' of ../
 c61a82b60967180544e3c19f819ddbd0c9f89899	not-for-merge	tag 'tag-three' of ../
 525b7fb068d59950d185a8779dc957c77eed73ba	not-for-merge	tag 'tag-two' of ../
diff --git a/t/t5515/fetch.master_.._.git_one_two b/t/t5515/fetch.main_.._.git_one_two
similarity index 83%
rename from t/t5515/fetch.master_.._.git_one_two
rename to t/t5515/fetch.main_.._.git_one_two
index 35ec578..048ad97 100644
--- a/t/t5515/fetch.master_.._.git_one_two
+++ b/t/t5515/fetch.main_.._.git_one_two
@@ -1,3 +1,3 @@
-# master ../.git one two
+# main ../.git one two
 8e32a6d901327a23ef831511badce7bf3bf46689		branch 'one' of ../
 6134ee8f857693b96ff1cc98d3e2fd62b199e5a8		branch 'two' of ../
diff --git a/t/t5515/fetch.master_.._.git_tag_tag-one-tree_tag_tag-three-file b/t/t5515/fetch.main_.._.git_tag_tag-one-tree_tag_tag-three-file
similarity index 75%
rename from t/t5515/fetch.master_.._.git_tag_tag-one-tree_tag_tag-three-file
rename to t/t5515/fetch.main_.._.git_tag_tag-one-tree_tag_tag-three-file
index 0fd737c..df5f2a7 100644
--- a/t/t5515/fetch.master_.._.git_tag_tag-one-tree_tag_tag-three-file
+++ b/t/t5515/fetch.main_.._.git_tag_tag-one-tree_tag_tag-three-file
@@ -1,7 +1,7 @@
-# master ../.git tag tag-one-tree tag tag-three-file
+# main ../.git tag tag-one-tree tag tag-three-file
 22feea448b023a2d864ef94b013735af34d238ba	not-for-merge	tag 'tag-one-tree' of ../
 0e3b14047d3ee365f4f2a1b673db059c3972589c	not-for-merge	tag 'tag-three-file' of ../
-6c9dec2b923228c9ff994c6cfe4ae16c12408dc5	not-for-merge	tag 'tag-master' of ../
+ecf3b3627b498bdcb735cc4343bf165f76964e9a	not-for-merge	tag 'tag-main' of ../
 8e32a6d901327a23ef831511badce7bf3bf46689	not-for-merge	tag 'tag-one' of ../
 c61a82b60967180544e3c19f819ddbd0c9f89899	not-for-merge	tag 'tag-three' of ../
 525b7fb068d59950d185a8779dc957c77eed73ba	not-for-merge	tag 'tag-two' of ../
diff --git a/t/t5515/fetch.master_.._.git_tag_tag-one_tag_tag-three b/t/t5515/fetch.main_.._.git_tag_tag-one_tag_tag-three
similarity index 75%
rename from t/t5515/fetch.master_.._.git_tag_tag-one_tag_tag-three
rename to t/t5515/fetch.main_.._.git_tag_tag-one_tag_tag-three
index e488986..a40b728 100644
--- a/t/t5515/fetch.master_.._.git_tag_tag-one_tag_tag-three
+++ b/t/t5515/fetch.main_.._.git_tag_tag-one_tag_tag-three
@@ -1,7 +1,7 @@
-# master ../.git tag tag-one tag tag-three
+# main ../.git tag tag-one tag tag-three
 8e32a6d901327a23ef831511badce7bf3bf46689		tag 'tag-one' of ../
 c61a82b60967180544e3c19f819ddbd0c9f89899		tag 'tag-three' of ../
-6c9dec2b923228c9ff994c6cfe4ae16c12408dc5	not-for-merge	tag 'tag-master' of ../
+ecf3b3627b498bdcb735cc4343bf165f76964e9a	not-for-merge	tag 'tag-main' of ../
 22feea448b023a2d864ef94b013735af34d238ba	not-for-merge	tag 'tag-one-tree' of ../
 0e3b14047d3ee365f4f2a1b673db059c3972589c	not-for-merge	tag 'tag-three-file' of ../
 525b7fb068d59950d185a8779dc957c77eed73ba	not-for-merge	tag 'tag-two' of ../
diff --git a/t/t5515/fetch.master_branches-one b/t/t5515/fetch.main_branches-default
similarity index 70%
copy from t/t5515/fetch.master_branches-one
copy to t/t5515/fetch.main_branches-default
index 901ce21..e3466e8 100644
--- a/t/t5515/fetch.master_branches-one
+++ b/t/t5515/fetch.main_branches-default
@@ -1,6 +1,6 @@
-# master branches-one
-8e32a6d901327a23ef831511badce7bf3bf46689		branch 'one' of ../
-6c9dec2b923228c9ff994c6cfe4ae16c12408dc5	not-for-merge	tag 'tag-master' of ../
+# main branches-default
+b4ab76b1a01ea602209932134a44f1e6bd610832		branch 'main' of ../
+ecf3b3627b498bdcb735cc4343bf165f76964e9a	not-for-merge	tag 'tag-main' of ../
 8e32a6d901327a23ef831511badce7bf3bf46689	not-for-merge	tag 'tag-one' of ../
 22feea448b023a2d864ef94b013735af34d238ba	not-for-merge	tag 'tag-one-tree' of ../
 c61a82b60967180544e3c19f819ddbd0c9f89899	not-for-merge	tag 'tag-three' of ../
diff --git a/t/t5515/fetch.master_branches-one b/t/t5515/fetch.main_branches-one
similarity index 81%
rename from t/t5515/fetch.master_branches-one
rename to t/t5515/fetch.main_branches-one
index 901ce21..a94f11a 100644
--- a/t/t5515/fetch.master_branches-one
+++ b/t/t5515/fetch.main_branches-one
@@ -1,6 +1,6 @@
-# master branches-one
+# main branches-one
 8e32a6d901327a23ef831511badce7bf3bf46689		branch 'one' of ../
-6c9dec2b923228c9ff994c6cfe4ae16c12408dc5	not-for-merge	tag 'tag-master' of ../
+ecf3b3627b498bdcb735cc4343bf165f76964e9a	not-for-merge	tag 'tag-main' of ../
 8e32a6d901327a23ef831511badce7bf3bf46689	not-for-merge	tag 'tag-one' of ../
 22feea448b023a2d864ef94b013735af34d238ba	not-for-merge	tag 'tag-one-tree' of ../
 c61a82b60967180544e3c19f819ddbd0c9f89899	not-for-merge	tag 'tag-three' of ../
diff --git a/t/t5515/fetch.master_config-explicit b/t/t5515/fetch.main_config-explicit
similarity index 78%
copy from t/t5515/fetch.master_config-explicit
copy to t/t5515/fetch.main_config-explicit
index 251c826..16d04c1 100644
--- a/t/t5515/fetch.master_config-explicit
+++ b/t/t5515/fetch.main_config-explicit
@@ -1,9 +1,9 @@
-# master config-explicit
-754b754407bf032e9a2f9d5a9ad05ca79a6b228f		branch 'master' of ../
+# main config-explicit
+b4ab76b1a01ea602209932134a44f1e6bd610832		branch 'main' of ../
 8e32a6d901327a23ef831511badce7bf3bf46689	not-for-merge	branch 'one' of ../
 6134ee8f857693b96ff1cc98d3e2fd62b199e5a8	not-for-merge	branch 'two' of ../
 0567da4d5edd2ff4bb292a465ba9e64dcad9536b	not-for-merge	branch 'three' of ../
-6c9dec2b923228c9ff994c6cfe4ae16c12408dc5	not-for-merge	tag 'tag-master' of ../
+ecf3b3627b498bdcb735cc4343bf165f76964e9a	not-for-merge	tag 'tag-main' of ../
 8e32a6d901327a23ef831511badce7bf3bf46689	not-for-merge	tag 'tag-one' of ../
 22feea448b023a2d864ef94b013735af34d238ba	not-for-merge	tag 'tag-one-tree' of ../
 c61a82b60967180544e3c19f819ddbd0c9f89899	not-for-merge	tag 'tag-three' of ../
diff --git a/t/t5515/fetch.master_config-explicit b/t/t5515/fetch.main_config-glob
similarity index 78%
copy from t/t5515/fetch.master_config-explicit
copy to t/t5515/fetch.main_config-glob
index 251c826..f6a6f56 100644
--- a/t/t5515/fetch.master_config-explicit
+++ b/t/t5515/fetch.main_config-glob
@@ -1,9 +1,9 @@
-# master config-explicit
-754b754407bf032e9a2f9d5a9ad05ca79a6b228f		branch 'master' of ../
+# main config-glob
+b4ab76b1a01ea602209932134a44f1e6bd610832	not-for-merge	branch 'main' of ../
 8e32a6d901327a23ef831511badce7bf3bf46689	not-for-merge	branch 'one' of ../
-6134ee8f857693b96ff1cc98d3e2fd62b199e5a8	not-for-merge	branch 'two' of ../
 0567da4d5edd2ff4bb292a465ba9e64dcad9536b	not-for-merge	branch 'three' of ../
-6c9dec2b923228c9ff994c6cfe4ae16c12408dc5	not-for-merge	tag 'tag-master' of ../
+6134ee8f857693b96ff1cc98d3e2fd62b199e5a8	not-for-merge	branch 'two' of ../
+ecf3b3627b498bdcb735cc4343bf165f76964e9a	not-for-merge	tag 'tag-main' of ../
 8e32a6d901327a23ef831511badce7bf3bf46689	not-for-merge	tag 'tag-one' of ../
 22feea448b023a2d864ef94b013735af34d238ba	not-for-merge	tag 'tag-one-tree' of ../
 c61a82b60967180544e3c19f819ddbd0c9f89899	not-for-merge	tag 'tag-three' of ../
diff --git a/t/t5515/fetch.master_config-explicit b/t/t5515/fetch.main_remote-explicit
similarity index 78%
rename from t/t5515/fetch.master_config-explicit
rename to t/t5515/fetch.main_remote-explicit
index 251c826..bf4fd65 100644
--- a/t/t5515/fetch.master_config-explicit
+++ b/t/t5515/fetch.main_remote-explicit
@@ -1,9 +1,9 @@
-# master config-explicit
-754b754407bf032e9a2f9d5a9ad05ca79a6b228f		branch 'master' of ../
+# main remote-explicit
+b4ab76b1a01ea602209932134a44f1e6bd610832		branch 'main' of ../
 8e32a6d901327a23ef831511badce7bf3bf46689	not-for-merge	branch 'one' of ../
 6134ee8f857693b96ff1cc98d3e2fd62b199e5a8	not-for-merge	branch 'two' of ../
 0567da4d5edd2ff4bb292a465ba9e64dcad9536b	not-for-merge	branch 'three' of ../
-6c9dec2b923228c9ff994c6cfe4ae16c12408dc5	not-for-merge	tag 'tag-master' of ../
+ecf3b3627b498bdcb735cc4343bf165f76964e9a	not-for-merge	tag 'tag-main' of ../
 8e32a6d901327a23ef831511badce7bf3bf46689	not-for-merge	tag 'tag-one' of ../
 22feea448b023a2d864ef94b013735af34d238ba	not-for-merge	tag 'tag-one-tree' of ../
 c61a82b60967180544e3c19f819ddbd0c9f89899	not-for-merge	tag 'tag-three' of ../
diff --git a/t/t5515/fetch.master_config-explicit b/t/t5515/fetch.main_remote-glob
similarity index 78%
copy from t/t5515/fetch.master_config-explicit
copy to t/t5515/fetch.main_remote-glob
index 251c826..91dc2e2 100644
--- a/t/t5515/fetch.master_config-explicit
+++ b/t/t5515/fetch.main_remote-glob
@@ -1,9 +1,9 @@
-# master config-explicit
-754b754407bf032e9a2f9d5a9ad05ca79a6b228f		branch 'master' of ../
+# main remote-glob
+b4ab76b1a01ea602209932134a44f1e6bd610832	not-for-merge	branch 'main' of ../
 8e32a6d901327a23ef831511badce7bf3bf46689	not-for-merge	branch 'one' of ../
-6134ee8f857693b96ff1cc98d3e2fd62b199e5a8	not-for-merge	branch 'two' of ../
 0567da4d5edd2ff4bb292a465ba9e64dcad9536b	not-for-merge	branch 'three' of ../
-6c9dec2b923228c9ff994c6cfe4ae16c12408dc5	not-for-merge	tag 'tag-master' of ../
+6134ee8f857693b96ff1cc98d3e2fd62b199e5a8	not-for-merge	branch 'two' of ../
+ecf3b3627b498bdcb735cc4343bf165f76964e9a	not-for-merge	tag 'tag-main' of ../
 8e32a6d901327a23ef831511badce7bf3bf46689	not-for-merge	tag 'tag-one' of ../
 22feea448b023a2d864ef94b013735af34d238ba	not-for-merge	tag 'tag-one-tree' of ../
 c61a82b60967180544e3c19f819ddbd0c9f89899	not-for-merge	tag 'tag-three' of ../
diff --git a/t/t5515/fetch.master b/t/t5515/fetch.master
deleted file mode 100644
index 9b29d67..0000000
--- a/t/t5515/fetch.master
+++ /dev/null
@@ -1,11 +0,0 @@
-# master
-754b754407bf032e9a2f9d5a9ad05ca79a6b228f	not-for-merge	branch 'master' of ../
-8e32a6d901327a23ef831511badce7bf3bf46689	not-for-merge	branch 'one' of ../
-0567da4d5edd2ff4bb292a465ba9e64dcad9536b	not-for-merge	branch 'three' of ../
-6134ee8f857693b96ff1cc98d3e2fd62b199e5a8	not-for-merge	branch 'two' of ../
-6c9dec2b923228c9ff994c6cfe4ae16c12408dc5	not-for-merge	tag 'tag-master' of ../
-8e32a6d901327a23ef831511badce7bf3bf46689	not-for-merge	tag 'tag-one' of ../
-22feea448b023a2d864ef94b013735af34d238ba	not-for-merge	tag 'tag-one-tree' of ../
-c61a82b60967180544e3c19f819ddbd0c9f89899	not-for-merge	tag 'tag-three' of ../
-0e3b14047d3ee365f4f2a1b673db059c3972589c	not-for-merge	tag 'tag-three-file' of ../
-525b7fb068d59950d185a8779dc957c77eed73ba	not-for-merge	tag 'tag-two' of ../
diff --git a/t/t5515/fetch.master_branches-default b/t/t5515/fetch.master_branches-default
deleted file mode 100644
index 2eedd3b..0000000
--- a/t/t5515/fetch.master_branches-default
+++ /dev/null
@@ -1,8 +0,0 @@
-# master branches-default
-754b754407bf032e9a2f9d5a9ad05ca79a6b228f		branch 'master' of ../
-6c9dec2b923228c9ff994c6cfe4ae16c12408dc5	not-for-merge	tag 'tag-master' of ../
-8e32a6d901327a23ef831511badce7bf3bf46689	not-for-merge	tag 'tag-one' of ../
-22feea448b023a2d864ef94b013735af34d238ba	not-for-merge	tag 'tag-one-tree' of ../
-c61a82b60967180544e3c19f819ddbd0c9f89899	not-for-merge	tag 'tag-three' of ../
-0e3b14047d3ee365f4f2a1b673db059c3972589c	not-for-merge	tag 'tag-three-file' of ../
-525b7fb068d59950d185a8779dc957c77eed73ba	not-for-merge	tag 'tag-two' of ../
diff --git a/t/t5515/fetch.master_config-glob b/t/t5515/fetch.master_config-glob
deleted file mode 100644
index 27c158e..0000000
--- a/t/t5515/fetch.master_config-glob
+++ /dev/null
@@ -1,11 +0,0 @@
-# master config-glob
-754b754407bf032e9a2f9d5a9ad05ca79a6b228f	not-for-merge	branch 'master' of ../
-8e32a6d901327a23ef831511badce7bf3bf46689	not-for-merge	branch 'one' of ../
-0567da4d5edd2ff4bb292a465ba9e64dcad9536b	not-for-merge	branch 'three' of ../
-6134ee8f857693b96ff1cc98d3e2fd62b199e5a8	not-for-merge	branch 'two' of ../
-6c9dec2b923228c9ff994c6cfe4ae16c12408dc5	not-for-merge	tag 'tag-master' of ../
-8e32a6d901327a23ef831511badce7bf3bf46689	not-for-merge	tag 'tag-one' of ../
-22feea448b023a2d864ef94b013735af34d238ba	not-for-merge	tag 'tag-one-tree' of ../
-c61a82b60967180544e3c19f819ddbd0c9f89899	not-for-merge	tag 'tag-three' of ../
-0e3b14047d3ee365f4f2a1b673db059c3972589c	not-for-merge	tag 'tag-three-file' of ../
-525b7fb068d59950d185a8779dc957c77eed73ba	not-for-merge	tag 'tag-two' of ../
diff --git a/t/t5515/fetch.master_remote-explicit b/t/t5515/fetch.master_remote-explicit
deleted file mode 100644
index b3cfe6b..0000000
--- a/t/t5515/fetch.master_remote-explicit
+++ /dev/null
@@ -1,11 +0,0 @@
-# master remote-explicit
-754b754407bf032e9a2f9d5a9ad05ca79a6b228f		branch 'master' of ../
-8e32a6d901327a23ef831511badce7bf3bf46689	not-for-merge	branch 'one' of ../
-6134ee8f857693b96ff1cc98d3e2fd62b199e5a8	not-for-merge	branch 'two' of ../
-0567da4d5edd2ff4bb292a465ba9e64dcad9536b	not-for-merge	branch 'three' of ../
-6c9dec2b923228c9ff994c6cfe4ae16c12408dc5	not-for-merge	tag 'tag-master' of ../
-8e32a6d901327a23ef831511badce7bf3bf46689	not-for-merge	tag 'tag-one' of ../
-22feea448b023a2d864ef94b013735af34d238ba	not-for-merge	tag 'tag-one-tree' of ../
-c61a82b60967180544e3c19f819ddbd0c9f89899	not-for-merge	tag 'tag-three' of ../
-0e3b14047d3ee365f4f2a1b673db059c3972589c	not-for-merge	tag 'tag-three-file' of ../
-525b7fb068d59950d185a8779dc957c77eed73ba	not-for-merge	tag 'tag-two' of ../
diff --git a/t/t5515/fetch.master_remote-glob b/t/t5515/fetch.master_remote-glob
deleted file mode 100644
index 118befd..0000000
--- a/t/t5515/fetch.master_remote-glob
+++ /dev/null
@@ -1,11 +0,0 @@
-# master remote-glob
-754b754407bf032e9a2f9d5a9ad05ca79a6b228f	not-for-merge	branch 'master' of ../
-8e32a6d901327a23ef831511badce7bf3bf46689	not-for-merge	branch 'one' of ../
-0567da4d5edd2ff4bb292a465ba9e64dcad9536b	not-for-merge	branch 'three' of ../
-6134ee8f857693b96ff1cc98d3e2fd62b199e5a8	not-for-merge	branch 'two' of ../
-6c9dec2b923228c9ff994c6cfe4ae16c12408dc5	not-for-merge	tag 'tag-master' of ../
-8e32a6d901327a23ef831511badce7bf3bf46689	not-for-merge	tag 'tag-one' of ../
-22feea448b023a2d864ef94b013735af34d238ba	not-for-merge	tag 'tag-one-tree' of ../
-c61a82b60967180544e3c19f819ddbd0c9f89899	not-for-merge	tag 'tag-three' of ../
-0e3b14047d3ee365f4f2a1b673db059c3972589c	not-for-merge	tag 'tag-three-file' of ../
-525b7fb068d59950d185a8779dc957c77eed73ba	not-for-merge	tag 'tag-two' of ../
diff --git a/t/t5515/refs.br-branches-default b/t/t5515/refs.br-branches-default
index 21917c1..dc4f2b7 100644
--- a/t/t5515/refs.br-branches-default
+++ b/t/t5515/refs.br-branches-default
@@ -1,10 +1,10 @@
-754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/heads/branches-default
+b4ab76b1a01ea602209932134a44f1e6bd610832 refs/heads/branches-default
 0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/HEAD
-754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/remotes/origin/master
+b4ab76b1a01ea602209932134a44f1e6bd610832 refs/remotes/origin/main
 8e32a6d901327a23ef831511badce7bf3bf46689 refs/remotes/origin/one
 0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/three
 6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 refs/remotes/origin/two
-6c9dec2b923228c9ff994c6cfe4ae16c12408dc5 refs/tags/tag-master
+ecf3b3627b498bdcb735cc4343bf165f76964e9a refs/tags/tag-main
 8e32a6d901327a23ef831511badce7bf3bf46689 refs/tags/tag-one
 22feea448b023a2d864ef94b013735af34d238ba refs/tags/tag-one-tree
 c61a82b60967180544e3c19f819ddbd0c9f89899 refs/tags/tag-three
diff --git a/t/t5515/refs.br-branches-default-merge b/t/t5515/refs.br-branches-default-merge
index 21917c1..dc4f2b7 100644
--- a/t/t5515/refs.br-branches-default-merge
+++ b/t/t5515/refs.br-branches-default-merge
@@ -1,10 +1,10 @@
-754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/heads/branches-default
+b4ab76b1a01ea602209932134a44f1e6bd610832 refs/heads/branches-default
 0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/HEAD
-754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/remotes/origin/master
+b4ab76b1a01ea602209932134a44f1e6bd610832 refs/remotes/origin/main
 8e32a6d901327a23ef831511badce7bf3bf46689 refs/remotes/origin/one
 0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/three
 6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 refs/remotes/origin/two
-6c9dec2b923228c9ff994c6cfe4ae16c12408dc5 refs/tags/tag-master
+ecf3b3627b498bdcb735cc4343bf165f76964e9a refs/tags/tag-main
 8e32a6d901327a23ef831511badce7bf3bf46689 refs/tags/tag-one
 22feea448b023a2d864ef94b013735af34d238ba refs/tags/tag-one-tree
 c61a82b60967180544e3c19f819ddbd0c9f89899 refs/tags/tag-three
diff --git a/t/t5515/refs.br-branches-default-merge_branches-default b/t/t5515/refs.br-branches-default-merge_branches-default
index 21917c1..dc4f2b7 100644
--- a/t/t5515/refs.br-branches-default-merge_branches-default
+++ b/t/t5515/refs.br-branches-default-merge_branches-default
@@ -1,10 +1,10 @@
-754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/heads/branches-default
+b4ab76b1a01ea602209932134a44f1e6bd610832 refs/heads/branches-default
 0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/HEAD
-754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/remotes/origin/master
+b4ab76b1a01ea602209932134a44f1e6bd610832 refs/remotes/origin/main
 8e32a6d901327a23ef831511badce7bf3bf46689 refs/remotes/origin/one
 0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/three
 6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 refs/remotes/origin/two
-6c9dec2b923228c9ff994c6cfe4ae16c12408dc5 refs/tags/tag-master
+ecf3b3627b498bdcb735cc4343bf165f76964e9a refs/tags/tag-main
 8e32a6d901327a23ef831511badce7bf3bf46689 refs/tags/tag-one
 22feea448b023a2d864ef94b013735af34d238ba refs/tags/tag-one-tree
 c61a82b60967180544e3c19f819ddbd0c9f89899 refs/tags/tag-three
diff --git a/t/t5515/refs.br-branches-default-octopus b/t/t5515/refs.br-branches-default-octopus
index 21917c1..dc4f2b7 100644
--- a/t/t5515/refs.br-branches-default-octopus
+++ b/t/t5515/refs.br-branches-default-octopus
@@ -1,10 +1,10 @@
-754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/heads/branches-default
+b4ab76b1a01ea602209932134a44f1e6bd610832 refs/heads/branches-default
 0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/HEAD
-754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/remotes/origin/master
+b4ab76b1a01ea602209932134a44f1e6bd610832 refs/remotes/origin/main
 8e32a6d901327a23ef831511badce7bf3bf46689 refs/remotes/origin/one
 0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/three
 6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 refs/remotes/origin/two
-6c9dec2b923228c9ff994c6cfe4ae16c12408dc5 refs/tags/tag-master
+ecf3b3627b498bdcb735cc4343bf165f76964e9a refs/tags/tag-main
 8e32a6d901327a23ef831511badce7bf3bf46689 refs/tags/tag-one
 22feea448b023a2d864ef94b013735af34d238ba refs/tags/tag-one-tree
 c61a82b60967180544e3c19f819ddbd0c9f89899 refs/tags/tag-three
diff --git a/t/t5515/refs.br-branches-default-octopus_branches-default b/t/t5515/refs.br-branches-default-octopus_branches-default
index 21917c1..dc4f2b7 100644
--- a/t/t5515/refs.br-branches-default-octopus_branches-default
+++ b/t/t5515/refs.br-branches-default-octopus_branches-default
@@ -1,10 +1,10 @@
-754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/heads/branches-default
+b4ab76b1a01ea602209932134a44f1e6bd610832 refs/heads/branches-default
 0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/HEAD
-754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/remotes/origin/master
+b4ab76b1a01ea602209932134a44f1e6bd610832 refs/remotes/origin/main
 8e32a6d901327a23ef831511badce7bf3bf46689 refs/remotes/origin/one
 0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/three
 6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 refs/remotes/origin/two
-6c9dec2b923228c9ff994c6cfe4ae16c12408dc5 refs/tags/tag-master
+ecf3b3627b498bdcb735cc4343bf165f76964e9a refs/tags/tag-main
 8e32a6d901327a23ef831511badce7bf3bf46689 refs/tags/tag-one
 22feea448b023a2d864ef94b013735af34d238ba refs/tags/tag-one-tree
 c61a82b60967180544e3c19f819ddbd0c9f89899 refs/tags/tag-three
diff --git a/t/t5515/refs.br-branches-default_branches-default b/t/t5515/refs.br-branches-default_branches-default
index 21917c1..dc4f2b7 100644
--- a/t/t5515/refs.br-branches-default_branches-default
+++ b/t/t5515/refs.br-branches-default_branches-default
@@ -1,10 +1,10 @@
-754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/heads/branches-default
+b4ab76b1a01ea602209932134a44f1e6bd610832 refs/heads/branches-default
 0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/HEAD
-754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/remotes/origin/master
+b4ab76b1a01ea602209932134a44f1e6bd610832 refs/remotes/origin/main
 8e32a6d901327a23ef831511badce7bf3bf46689 refs/remotes/origin/one
 0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/three
 6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 refs/remotes/origin/two
-6c9dec2b923228c9ff994c6cfe4ae16c12408dc5 refs/tags/tag-master
+ecf3b3627b498bdcb735cc4343bf165f76964e9a refs/tags/tag-main
 8e32a6d901327a23ef831511badce7bf3bf46689 refs/tags/tag-one
 22feea448b023a2d864ef94b013735af34d238ba refs/tags/tag-one-tree
 c61a82b60967180544e3c19f819ddbd0c9f89899 refs/tags/tag-three
diff --git a/t/t5515/refs.br-branches-one b/t/t5515/refs.br-branches-one
index 8a705a5..e8f79bf 100644
--- a/t/t5515/refs.br-branches-one
+++ b/t/t5515/refs.br-branches-one
@@ -1,10 +1,10 @@
 8e32a6d901327a23ef831511badce7bf3bf46689 refs/heads/branches-one
 0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/HEAD
-754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/remotes/origin/master
+b4ab76b1a01ea602209932134a44f1e6bd610832 refs/remotes/origin/main
 8e32a6d901327a23ef831511badce7bf3bf46689 refs/remotes/origin/one
 0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/three
 6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 refs/remotes/origin/two
-6c9dec2b923228c9ff994c6cfe4ae16c12408dc5 refs/tags/tag-master
+ecf3b3627b498bdcb735cc4343bf165f76964e9a refs/tags/tag-main
 8e32a6d901327a23ef831511badce7bf3bf46689 refs/tags/tag-one
 22feea448b023a2d864ef94b013735af34d238ba refs/tags/tag-one-tree
 c61a82b60967180544e3c19f819ddbd0c9f89899 refs/tags/tag-three
diff --git a/t/t5515/refs.br-branches-one-merge b/t/t5515/refs.br-branches-one-merge
index 8a705a5..e8f79bf 100644
--- a/t/t5515/refs.br-branches-one-merge
+++ b/t/t5515/refs.br-branches-one-merge
@@ -1,10 +1,10 @@
 8e32a6d901327a23ef831511badce7bf3bf46689 refs/heads/branches-one
 0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/HEAD
-754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/remotes/origin/master
+b4ab76b1a01ea602209932134a44f1e6bd610832 refs/remotes/origin/main
 8e32a6d901327a23ef831511badce7bf3bf46689 refs/remotes/origin/one
 0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/three
 6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 refs/remotes/origin/two
-6c9dec2b923228c9ff994c6cfe4ae16c12408dc5 refs/tags/tag-master
+ecf3b3627b498bdcb735cc4343bf165f76964e9a refs/tags/tag-main
 8e32a6d901327a23ef831511badce7bf3bf46689 refs/tags/tag-one
 22feea448b023a2d864ef94b013735af34d238ba refs/tags/tag-one-tree
 c61a82b60967180544e3c19f819ddbd0c9f89899 refs/tags/tag-three
diff --git a/t/t5515/refs.br-branches-one-merge_branches-one b/t/t5515/refs.br-branches-one-merge_branches-one
index 8a705a5..e8f79bf 100644
--- a/t/t5515/refs.br-branches-one-merge_branches-one
+++ b/t/t5515/refs.br-branches-one-merge_branches-one
@@ -1,10 +1,10 @@
 8e32a6d901327a23ef831511badce7bf3bf46689 refs/heads/branches-one
 0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/HEAD
-754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/remotes/origin/master
+b4ab76b1a01ea602209932134a44f1e6bd610832 refs/remotes/origin/main
 8e32a6d901327a23ef831511badce7bf3bf46689 refs/remotes/origin/one
 0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/three
 6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 refs/remotes/origin/two
-6c9dec2b923228c9ff994c6cfe4ae16c12408dc5 refs/tags/tag-master
+ecf3b3627b498bdcb735cc4343bf165f76964e9a refs/tags/tag-main
 8e32a6d901327a23ef831511badce7bf3bf46689 refs/tags/tag-one
 22feea448b023a2d864ef94b013735af34d238ba refs/tags/tag-one-tree
 c61a82b60967180544e3c19f819ddbd0c9f89899 refs/tags/tag-three
diff --git a/t/t5515/refs.br-branches-one-octopus b/t/t5515/refs.br-branches-one-octopus
index 8a705a5..e8f79bf 100644
--- a/t/t5515/refs.br-branches-one-octopus
+++ b/t/t5515/refs.br-branches-one-octopus
@@ -1,10 +1,10 @@
 8e32a6d901327a23ef831511badce7bf3bf46689 refs/heads/branches-one
 0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/HEAD
-754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/remotes/origin/master
+b4ab76b1a01ea602209932134a44f1e6bd610832 refs/remotes/origin/main
 8e32a6d901327a23ef831511badce7bf3bf46689 refs/remotes/origin/one
 0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/three
 6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 refs/remotes/origin/two
-6c9dec2b923228c9ff994c6cfe4ae16c12408dc5 refs/tags/tag-master
+ecf3b3627b498bdcb735cc4343bf165f76964e9a refs/tags/tag-main
 8e32a6d901327a23ef831511badce7bf3bf46689 refs/tags/tag-one
 22feea448b023a2d864ef94b013735af34d238ba refs/tags/tag-one-tree
 c61a82b60967180544e3c19f819ddbd0c9f89899 refs/tags/tag-three
diff --git a/t/t5515/refs.br-branches-one-octopus_branches-one b/t/t5515/refs.br-branches-one-octopus_branches-one
index 8a705a5..e8f79bf 100644
--- a/t/t5515/refs.br-branches-one-octopus_branches-one
+++ b/t/t5515/refs.br-branches-one-octopus_branches-one
@@ -1,10 +1,10 @@
 8e32a6d901327a23ef831511badce7bf3bf46689 refs/heads/branches-one
 0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/HEAD
-754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/remotes/origin/master
+b4ab76b1a01ea602209932134a44f1e6bd610832 refs/remotes/origin/main
 8e32a6d901327a23ef831511badce7bf3bf46689 refs/remotes/origin/one
 0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/three
 6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 refs/remotes/origin/two
-6c9dec2b923228c9ff994c6cfe4ae16c12408dc5 refs/tags/tag-master
+ecf3b3627b498bdcb735cc4343bf165f76964e9a refs/tags/tag-main
 8e32a6d901327a23ef831511badce7bf3bf46689 refs/tags/tag-one
 22feea448b023a2d864ef94b013735af34d238ba refs/tags/tag-one-tree
 c61a82b60967180544e3c19f819ddbd0c9f89899 refs/tags/tag-three
diff --git a/t/t5515/refs.br-branches-one_branches-one b/t/t5515/refs.br-branches-one_branches-one
index 8a705a5..e8f79bf 100644
--- a/t/t5515/refs.br-branches-one_branches-one
+++ b/t/t5515/refs.br-branches-one_branches-one
@@ -1,10 +1,10 @@
 8e32a6d901327a23ef831511badce7bf3bf46689 refs/heads/branches-one
 0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/HEAD
-754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/remotes/origin/master
+b4ab76b1a01ea602209932134a44f1e6bd610832 refs/remotes/origin/main
 8e32a6d901327a23ef831511badce7bf3bf46689 refs/remotes/origin/one
 0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/three
 6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 refs/remotes/origin/two
-6c9dec2b923228c9ff994c6cfe4ae16c12408dc5 refs/tags/tag-master
+ecf3b3627b498bdcb735cc4343bf165f76964e9a refs/tags/tag-main
 8e32a6d901327a23ef831511badce7bf3bf46689 refs/tags/tag-one
 22feea448b023a2d864ef94b013735af34d238ba refs/tags/tag-one-tree
 c61a82b60967180544e3c19f819ddbd0c9f89899 refs/tags/tag-three
diff --git a/t/t5515/refs.br-config-explicit b/t/t5515/refs.br-config-explicit
index 9bbbfd9..a28fa5f 100644
--- a/t/t5515/refs.br-config-explicit
+++ b/t/t5515/refs.br-config-explicit
@@ -1,13 +1,13 @@
 0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/HEAD
-754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/remotes/origin/master
+b4ab76b1a01ea602209932134a44f1e6bd610832 refs/remotes/origin/main
 8e32a6d901327a23ef831511badce7bf3bf46689 refs/remotes/origin/one
 0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/three
 6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 refs/remotes/origin/two
-754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/remotes/rem/master
+b4ab76b1a01ea602209932134a44f1e6bd610832 refs/remotes/rem/main
 8e32a6d901327a23ef831511badce7bf3bf46689 refs/remotes/rem/one
 0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/rem/three
 6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 refs/remotes/rem/two
-6c9dec2b923228c9ff994c6cfe4ae16c12408dc5 refs/tags/tag-master
+ecf3b3627b498bdcb735cc4343bf165f76964e9a refs/tags/tag-main
 8e32a6d901327a23ef831511badce7bf3bf46689 refs/tags/tag-one
 22feea448b023a2d864ef94b013735af34d238ba refs/tags/tag-one-tree
 c61a82b60967180544e3c19f819ddbd0c9f89899 refs/tags/tag-three
diff --git a/t/t5515/refs.br-config-explicit-merge b/t/t5515/refs.br-config-explicit-merge
index 9bbbfd9..a28fa5f 100644
--- a/t/t5515/refs.br-config-explicit-merge
+++ b/t/t5515/refs.br-config-explicit-merge
@@ -1,13 +1,13 @@
 0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/HEAD
-754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/remotes/origin/master
+b4ab76b1a01ea602209932134a44f1e6bd610832 refs/remotes/origin/main
 8e32a6d901327a23ef831511badce7bf3bf46689 refs/remotes/origin/one
 0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/three
 6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 refs/remotes/origin/two
-754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/remotes/rem/master
+b4ab76b1a01ea602209932134a44f1e6bd610832 refs/remotes/rem/main
 8e32a6d901327a23ef831511badce7bf3bf46689 refs/remotes/rem/one
 0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/rem/three
 6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 refs/remotes/rem/two
-6c9dec2b923228c9ff994c6cfe4ae16c12408dc5 refs/tags/tag-master
+ecf3b3627b498bdcb735cc4343bf165f76964e9a refs/tags/tag-main
 8e32a6d901327a23ef831511badce7bf3bf46689 refs/tags/tag-one
 22feea448b023a2d864ef94b013735af34d238ba refs/tags/tag-one-tree
 c61a82b60967180544e3c19f819ddbd0c9f89899 refs/tags/tag-three
diff --git a/t/t5515/refs.br-config-explicit-merge_config-explicit b/t/t5515/refs.br-config-explicit-merge_config-explicit
index 9bbbfd9..a28fa5f 100644
--- a/t/t5515/refs.br-config-explicit-merge_config-explicit
+++ b/t/t5515/refs.br-config-explicit-merge_config-explicit
@@ -1,13 +1,13 @@
 0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/HEAD
-754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/remotes/origin/master
+b4ab76b1a01ea602209932134a44f1e6bd610832 refs/remotes/origin/main
 8e32a6d901327a23ef831511badce7bf3bf46689 refs/remotes/origin/one
 0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/three
 6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 refs/remotes/origin/two
-754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/remotes/rem/master
+b4ab76b1a01ea602209932134a44f1e6bd610832 refs/remotes/rem/main
 8e32a6d901327a23ef831511badce7bf3bf46689 refs/remotes/rem/one
 0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/rem/three
 6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 refs/remotes/rem/two
-6c9dec2b923228c9ff994c6cfe4ae16c12408dc5 refs/tags/tag-master
+ecf3b3627b498bdcb735cc4343bf165f76964e9a refs/tags/tag-main
 8e32a6d901327a23ef831511badce7bf3bf46689 refs/tags/tag-one
 22feea448b023a2d864ef94b013735af34d238ba refs/tags/tag-one-tree
 c61a82b60967180544e3c19f819ddbd0c9f89899 refs/tags/tag-three
diff --git a/t/t5515/refs.br-config-explicit-octopus b/t/t5515/refs.br-config-explicit-octopus
index 9bbbfd9..a28fa5f 100644
--- a/t/t5515/refs.br-config-explicit-octopus
+++ b/t/t5515/refs.br-config-explicit-octopus
@@ -1,13 +1,13 @@
 0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/HEAD
-754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/remotes/origin/master
+b4ab76b1a01ea602209932134a44f1e6bd610832 refs/remotes/origin/main
 8e32a6d901327a23ef831511badce7bf3bf46689 refs/remotes/origin/one
 0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/three
 6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 refs/remotes/origin/two
-754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/remotes/rem/master
+b4ab76b1a01ea602209932134a44f1e6bd610832 refs/remotes/rem/main
 8e32a6d901327a23ef831511badce7bf3bf46689 refs/remotes/rem/one
 0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/rem/three
 6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 refs/remotes/rem/two
-6c9dec2b923228c9ff994c6cfe4ae16c12408dc5 refs/tags/tag-master
+ecf3b3627b498bdcb735cc4343bf165f76964e9a refs/tags/tag-main
 8e32a6d901327a23ef831511badce7bf3bf46689 refs/tags/tag-one
 22feea448b023a2d864ef94b013735af34d238ba refs/tags/tag-one-tree
 c61a82b60967180544e3c19f819ddbd0c9f89899 refs/tags/tag-three
diff --git a/t/t5515/refs.br-config-explicit-octopus_config-explicit b/t/t5515/refs.br-config-explicit-octopus_config-explicit
index 9bbbfd9..a28fa5f 100644
--- a/t/t5515/refs.br-config-explicit-octopus_config-explicit
+++ b/t/t5515/refs.br-config-explicit-octopus_config-explicit
@@ -1,13 +1,13 @@
 0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/HEAD
-754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/remotes/origin/master
+b4ab76b1a01ea602209932134a44f1e6bd610832 refs/remotes/origin/main
 8e32a6d901327a23ef831511badce7bf3bf46689 refs/remotes/origin/one
 0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/three
 6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 refs/remotes/origin/two
-754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/remotes/rem/master
+b4ab76b1a01ea602209932134a44f1e6bd610832 refs/remotes/rem/main
 8e32a6d901327a23ef831511badce7bf3bf46689 refs/remotes/rem/one
 0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/rem/three
 6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 refs/remotes/rem/two
-6c9dec2b923228c9ff994c6cfe4ae16c12408dc5 refs/tags/tag-master
+ecf3b3627b498bdcb735cc4343bf165f76964e9a refs/tags/tag-main
 8e32a6d901327a23ef831511badce7bf3bf46689 refs/tags/tag-one
 22feea448b023a2d864ef94b013735af34d238ba refs/tags/tag-one-tree
 c61a82b60967180544e3c19f819ddbd0c9f89899 refs/tags/tag-three
diff --git a/t/t5515/refs.br-config-explicit_config-explicit b/t/t5515/refs.br-config-explicit_config-explicit
index 9bbbfd9..a28fa5f 100644
--- a/t/t5515/refs.br-config-explicit_config-explicit
+++ b/t/t5515/refs.br-config-explicit_config-explicit
@@ -1,13 +1,13 @@
 0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/HEAD
-754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/remotes/origin/master
+b4ab76b1a01ea602209932134a44f1e6bd610832 refs/remotes/origin/main
 8e32a6d901327a23ef831511badce7bf3bf46689 refs/remotes/origin/one
 0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/three
 6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 refs/remotes/origin/two
-754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/remotes/rem/master
+b4ab76b1a01ea602209932134a44f1e6bd610832 refs/remotes/rem/main
 8e32a6d901327a23ef831511badce7bf3bf46689 refs/remotes/rem/one
 0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/rem/three
 6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 refs/remotes/rem/two
-6c9dec2b923228c9ff994c6cfe4ae16c12408dc5 refs/tags/tag-master
+ecf3b3627b498bdcb735cc4343bf165f76964e9a refs/tags/tag-main
 8e32a6d901327a23ef831511badce7bf3bf46689 refs/tags/tag-one
 22feea448b023a2d864ef94b013735af34d238ba refs/tags/tag-one-tree
 c61a82b60967180544e3c19f819ddbd0c9f89899 refs/tags/tag-three
diff --git a/t/t5515/refs.br-config-glob b/t/t5515/refs.br-config-glob
index 9bbbfd9..a28fa5f 100644
--- a/t/t5515/refs.br-config-glob
+++ b/t/t5515/refs.br-config-glob
@@ -1,13 +1,13 @@
 0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/HEAD
-754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/remotes/origin/master
+b4ab76b1a01ea602209932134a44f1e6bd610832 refs/remotes/origin/main
 8e32a6d901327a23ef831511badce7bf3bf46689 refs/remotes/origin/one
 0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/three
 6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 refs/remotes/origin/two
-754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/remotes/rem/master
+b4ab76b1a01ea602209932134a44f1e6bd610832 refs/remotes/rem/main
 8e32a6d901327a23ef831511badce7bf3bf46689 refs/remotes/rem/one
 0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/rem/three
 6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 refs/remotes/rem/two
-6c9dec2b923228c9ff994c6cfe4ae16c12408dc5 refs/tags/tag-master
+ecf3b3627b498bdcb735cc4343bf165f76964e9a refs/tags/tag-main
 8e32a6d901327a23ef831511badce7bf3bf46689 refs/tags/tag-one
 22feea448b023a2d864ef94b013735af34d238ba refs/tags/tag-one-tree
 c61a82b60967180544e3c19f819ddbd0c9f89899 refs/tags/tag-three
diff --git a/t/t5515/refs.br-config-glob-merge b/t/t5515/refs.br-config-glob-merge
index 9bbbfd9..a28fa5f 100644
--- a/t/t5515/refs.br-config-glob-merge
+++ b/t/t5515/refs.br-config-glob-merge
@@ -1,13 +1,13 @@
 0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/HEAD
-754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/remotes/origin/master
+b4ab76b1a01ea602209932134a44f1e6bd610832 refs/remotes/origin/main
 8e32a6d901327a23ef831511badce7bf3bf46689 refs/remotes/origin/one
 0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/three
 6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 refs/remotes/origin/two
-754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/remotes/rem/master
+b4ab76b1a01ea602209932134a44f1e6bd610832 refs/remotes/rem/main
 8e32a6d901327a23ef831511badce7bf3bf46689 refs/remotes/rem/one
 0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/rem/three
 6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 refs/remotes/rem/two
-6c9dec2b923228c9ff994c6cfe4ae16c12408dc5 refs/tags/tag-master
+ecf3b3627b498bdcb735cc4343bf165f76964e9a refs/tags/tag-main
 8e32a6d901327a23ef831511badce7bf3bf46689 refs/tags/tag-one
 22feea448b023a2d864ef94b013735af34d238ba refs/tags/tag-one-tree
 c61a82b60967180544e3c19f819ddbd0c9f89899 refs/tags/tag-three
diff --git a/t/t5515/refs.br-config-glob-merge_config-glob b/t/t5515/refs.br-config-glob-merge_config-glob
index 9bbbfd9..a28fa5f 100644
--- a/t/t5515/refs.br-config-glob-merge_config-glob
+++ b/t/t5515/refs.br-config-glob-merge_config-glob
@@ -1,13 +1,13 @@
 0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/HEAD
-754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/remotes/origin/master
+b4ab76b1a01ea602209932134a44f1e6bd610832 refs/remotes/origin/main
 8e32a6d901327a23ef831511badce7bf3bf46689 refs/remotes/origin/one
 0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/three
 6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 refs/remotes/origin/two
-754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/remotes/rem/master
+b4ab76b1a01ea602209932134a44f1e6bd610832 refs/remotes/rem/main
 8e32a6d901327a23ef831511badce7bf3bf46689 refs/remotes/rem/one
 0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/rem/three
 6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 refs/remotes/rem/two
-6c9dec2b923228c9ff994c6cfe4ae16c12408dc5 refs/tags/tag-master
+ecf3b3627b498bdcb735cc4343bf165f76964e9a refs/tags/tag-main
 8e32a6d901327a23ef831511badce7bf3bf46689 refs/tags/tag-one
 22feea448b023a2d864ef94b013735af34d238ba refs/tags/tag-one-tree
 c61a82b60967180544e3c19f819ddbd0c9f89899 refs/tags/tag-three
diff --git a/t/t5515/refs.br-config-glob-octopus b/t/t5515/refs.br-config-glob-octopus
index 9bbbfd9..a28fa5f 100644
--- a/t/t5515/refs.br-config-glob-octopus
+++ b/t/t5515/refs.br-config-glob-octopus
@@ -1,13 +1,13 @@
 0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/HEAD
-754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/remotes/origin/master
+b4ab76b1a01ea602209932134a44f1e6bd610832 refs/remotes/origin/main
 8e32a6d901327a23ef831511badce7bf3bf46689 refs/remotes/origin/one
 0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/three
 6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 refs/remotes/origin/two
-754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/remotes/rem/master
+b4ab76b1a01ea602209932134a44f1e6bd610832 refs/remotes/rem/main
 8e32a6d901327a23ef831511badce7bf3bf46689 refs/remotes/rem/one
 0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/rem/three
 6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 refs/remotes/rem/two
-6c9dec2b923228c9ff994c6cfe4ae16c12408dc5 refs/tags/tag-master
+ecf3b3627b498bdcb735cc4343bf165f76964e9a refs/tags/tag-main
 8e32a6d901327a23ef831511badce7bf3bf46689 refs/tags/tag-one
 22feea448b023a2d864ef94b013735af34d238ba refs/tags/tag-one-tree
 c61a82b60967180544e3c19f819ddbd0c9f89899 refs/tags/tag-three
diff --git a/t/t5515/refs.br-config-glob-octopus_config-glob b/t/t5515/refs.br-config-glob-octopus_config-glob
index 9bbbfd9..a28fa5f 100644
--- a/t/t5515/refs.br-config-glob-octopus_config-glob
+++ b/t/t5515/refs.br-config-glob-octopus_config-glob
@@ -1,13 +1,13 @@
 0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/HEAD
-754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/remotes/origin/master
+b4ab76b1a01ea602209932134a44f1e6bd610832 refs/remotes/origin/main
 8e32a6d901327a23ef831511badce7bf3bf46689 refs/remotes/origin/one
 0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/three
 6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 refs/remotes/origin/two
-754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/remotes/rem/master
+b4ab76b1a01ea602209932134a44f1e6bd610832 refs/remotes/rem/main
 8e32a6d901327a23ef831511badce7bf3bf46689 refs/remotes/rem/one
 0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/rem/three
 6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 refs/remotes/rem/two
-6c9dec2b923228c9ff994c6cfe4ae16c12408dc5 refs/tags/tag-master
+ecf3b3627b498bdcb735cc4343bf165f76964e9a refs/tags/tag-main
 8e32a6d901327a23ef831511badce7bf3bf46689 refs/tags/tag-one
 22feea448b023a2d864ef94b013735af34d238ba refs/tags/tag-one-tree
 c61a82b60967180544e3c19f819ddbd0c9f89899 refs/tags/tag-three
diff --git a/t/t5515/refs.br-config-glob_config-glob b/t/t5515/refs.br-config-glob_config-glob
index 9bbbfd9..a28fa5f 100644
--- a/t/t5515/refs.br-config-glob_config-glob
+++ b/t/t5515/refs.br-config-glob_config-glob
@@ -1,13 +1,13 @@
 0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/HEAD
-754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/remotes/origin/master
+b4ab76b1a01ea602209932134a44f1e6bd610832 refs/remotes/origin/main
 8e32a6d901327a23ef831511badce7bf3bf46689 refs/remotes/origin/one
 0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/three
 6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 refs/remotes/origin/two
-754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/remotes/rem/master
+b4ab76b1a01ea602209932134a44f1e6bd610832 refs/remotes/rem/main
 8e32a6d901327a23ef831511badce7bf3bf46689 refs/remotes/rem/one
 0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/rem/three
 6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 refs/remotes/rem/two
-6c9dec2b923228c9ff994c6cfe4ae16c12408dc5 refs/tags/tag-master
+ecf3b3627b498bdcb735cc4343bf165f76964e9a refs/tags/tag-main
 8e32a6d901327a23ef831511badce7bf3bf46689 refs/tags/tag-one
 22feea448b023a2d864ef94b013735af34d238ba refs/tags/tag-one-tree
 c61a82b60967180544e3c19f819ddbd0c9f89899 refs/tags/tag-three
diff --git a/t/t5515/refs.br-remote-explicit b/t/t5515/refs.br-remote-explicit
index 9bbbfd9..a28fa5f 100644
--- a/t/t5515/refs.br-remote-explicit
+++ b/t/t5515/refs.br-remote-explicit
@@ -1,13 +1,13 @@
 0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/HEAD
-754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/remotes/origin/master
+b4ab76b1a01ea602209932134a44f1e6bd610832 refs/remotes/origin/main
 8e32a6d901327a23ef831511badce7bf3bf46689 refs/remotes/origin/one
 0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/three
 6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 refs/remotes/origin/two
-754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/remotes/rem/master
+b4ab76b1a01ea602209932134a44f1e6bd610832 refs/remotes/rem/main
 8e32a6d901327a23ef831511badce7bf3bf46689 refs/remotes/rem/one
 0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/rem/three
 6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 refs/remotes/rem/two
-6c9dec2b923228c9ff994c6cfe4ae16c12408dc5 refs/tags/tag-master
+ecf3b3627b498bdcb735cc4343bf165f76964e9a refs/tags/tag-main
 8e32a6d901327a23ef831511badce7bf3bf46689 refs/tags/tag-one
 22feea448b023a2d864ef94b013735af34d238ba refs/tags/tag-one-tree
 c61a82b60967180544e3c19f819ddbd0c9f89899 refs/tags/tag-three
diff --git a/t/t5515/refs.br-remote-explicit-merge b/t/t5515/refs.br-remote-explicit-merge
index 9bbbfd9..a28fa5f 100644
--- a/t/t5515/refs.br-remote-explicit-merge
+++ b/t/t5515/refs.br-remote-explicit-merge
@@ -1,13 +1,13 @@
 0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/HEAD
-754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/remotes/origin/master
+b4ab76b1a01ea602209932134a44f1e6bd610832 refs/remotes/origin/main
 8e32a6d901327a23ef831511badce7bf3bf46689 refs/remotes/origin/one
 0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/three
 6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 refs/remotes/origin/two
-754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/remotes/rem/master
+b4ab76b1a01ea602209932134a44f1e6bd610832 refs/remotes/rem/main
 8e32a6d901327a23ef831511badce7bf3bf46689 refs/remotes/rem/one
 0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/rem/three
 6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 refs/remotes/rem/two
-6c9dec2b923228c9ff994c6cfe4ae16c12408dc5 refs/tags/tag-master
+ecf3b3627b498bdcb735cc4343bf165f76964e9a refs/tags/tag-main
 8e32a6d901327a23ef831511badce7bf3bf46689 refs/tags/tag-one
 22feea448b023a2d864ef94b013735af34d238ba refs/tags/tag-one-tree
 c61a82b60967180544e3c19f819ddbd0c9f89899 refs/tags/tag-three
diff --git a/t/t5515/refs.br-remote-explicit-merge_remote-explicit b/t/t5515/refs.br-remote-explicit-merge_remote-explicit
index 9bbbfd9..a28fa5f 100644
--- a/t/t5515/refs.br-remote-explicit-merge_remote-explicit
+++ b/t/t5515/refs.br-remote-explicit-merge_remote-explicit
@@ -1,13 +1,13 @@
 0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/HEAD
-754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/remotes/origin/master
+b4ab76b1a01ea602209932134a44f1e6bd610832 refs/remotes/origin/main
 8e32a6d901327a23ef831511badce7bf3bf46689 refs/remotes/origin/one
 0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/three
 6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 refs/remotes/origin/two
-754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/remotes/rem/master
+b4ab76b1a01ea602209932134a44f1e6bd610832 refs/remotes/rem/main
 8e32a6d901327a23ef831511badce7bf3bf46689 refs/remotes/rem/one
 0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/rem/three
 6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 refs/remotes/rem/two
-6c9dec2b923228c9ff994c6cfe4ae16c12408dc5 refs/tags/tag-master
+ecf3b3627b498bdcb735cc4343bf165f76964e9a refs/tags/tag-main
 8e32a6d901327a23ef831511badce7bf3bf46689 refs/tags/tag-one
 22feea448b023a2d864ef94b013735af34d238ba refs/tags/tag-one-tree
 c61a82b60967180544e3c19f819ddbd0c9f89899 refs/tags/tag-three
diff --git a/t/t5515/refs.br-remote-explicit-octopus b/t/t5515/refs.br-remote-explicit-octopus
index 9bbbfd9..a28fa5f 100644
--- a/t/t5515/refs.br-remote-explicit-octopus
+++ b/t/t5515/refs.br-remote-explicit-octopus
@@ -1,13 +1,13 @@
 0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/HEAD
-754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/remotes/origin/master
+b4ab76b1a01ea602209932134a44f1e6bd610832 refs/remotes/origin/main
 8e32a6d901327a23ef831511badce7bf3bf46689 refs/remotes/origin/one
 0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/three
 6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 refs/remotes/origin/two
-754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/remotes/rem/master
+b4ab76b1a01ea602209932134a44f1e6bd610832 refs/remotes/rem/main
 8e32a6d901327a23ef831511badce7bf3bf46689 refs/remotes/rem/one
 0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/rem/three
 6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 refs/remotes/rem/two
-6c9dec2b923228c9ff994c6cfe4ae16c12408dc5 refs/tags/tag-master
+ecf3b3627b498bdcb735cc4343bf165f76964e9a refs/tags/tag-main
 8e32a6d901327a23ef831511badce7bf3bf46689 refs/tags/tag-one
 22feea448b023a2d864ef94b013735af34d238ba refs/tags/tag-one-tree
 c61a82b60967180544e3c19f819ddbd0c9f89899 refs/tags/tag-three
diff --git a/t/t5515/refs.br-remote-explicit-octopus_remote-explicit b/t/t5515/refs.br-remote-explicit-octopus_remote-explicit
index 9bbbfd9..a28fa5f 100644
--- a/t/t5515/refs.br-remote-explicit-octopus_remote-explicit
+++ b/t/t5515/refs.br-remote-explicit-octopus_remote-explicit
@@ -1,13 +1,13 @@
 0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/HEAD
-754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/remotes/origin/master
+b4ab76b1a01ea602209932134a44f1e6bd610832 refs/remotes/origin/main
 8e32a6d901327a23ef831511badce7bf3bf46689 refs/remotes/origin/one
 0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/three
 6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 refs/remotes/origin/two
-754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/remotes/rem/master
+b4ab76b1a01ea602209932134a44f1e6bd610832 refs/remotes/rem/main
 8e32a6d901327a23ef831511badce7bf3bf46689 refs/remotes/rem/one
 0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/rem/three
 6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 refs/remotes/rem/two
-6c9dec2b923228c9ff994c6cfe4ae16c12408dc5 refs/tags/tag-master
+ecf3b3627b498bdcb735cc4343bf165f76964e9a refs/tags/tag-main
 8e32a6d901327a23ef831511badce7bf3bf46689 refs/tags/tag-one
 22feea448b023a2d864ef94b013735af34d238ba refs/tags/tag-one-tree
 c61a82b60967180544e3c19f819ddbd0c9f89899 refs/tags/tag-three
diff --git a/t/t5515/refs.br-remote-explicit_remote-explicit b/t/t5515/refs.br-remote-explicit_remote-explicit
index 9bbbfd9..a28fa5f 100644
--- a/t/t5515/refs.br-remote-explicit_remote-explicit
+++ b/t/t5515/refs.br-remote-explicit_remote-explicit
@@ -1,13 +1,13 @@
 0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/HEAD
-754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/remotes/origin/master
+b4ab76b1a01ea602209932134a44f1e6bd610832 refs/remotes/origin/main
 8e32a6d901327a23ef831511badce7bf3bf46689 refs/remotes/origin/one
 0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/three
 6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 refs/remotes/origin/two
-754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/remotes/rem/master
+b4ab76b1a01ea602209932134a44f1e6bd610832 refs/remotes/rem/main
 8e32a6d901327a23ef831511badce7bf3bf46689 refs/remotes/rem/one
 0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/rem/three
 6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 refs/remotes/rem/two
-6c9dec2b923228c9ff994c6cfe4ae16c12408dc5 refs/tags/tag-master
+ecf3b3627b498bdcb735cc4343bf165f76964e9a refs/tags/tag-main
 8e32a6d901327a23ef831511badce7bf3bf46689 refs/tags/tag-one
 22feea448b023a2d864ef94b013735af34d238ba refs/tags/tag-one-tree
 c61a82b60967180544e3c19f819ddbd0c9f89899 refs/tags/tag-three
diff --git a/t/t5515/refs.br-remote-glob b/t/t5515/refs.br-remote-glob
index 9bbbfd9..a28fa5f 100644
--- a/t/t5515/refs.br-remote-glob
+++ b/t/t5515/refs.br-remote-glob
@@ -1,13 +1,13 @@
 0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/HEAD
-754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/remotes/origin/master
+b4ab76b1a01ea602209932134a44f1e6bd610832 refs/remotes/origin/main
 8e32a6d901327a23ef831511badce7bf3bf46689 refs/remotes/origin/one
 0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/three
 6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 refs/remotes/origin/two
-754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/remotes/rem/master
+b4ab76b1a01ea602209932134a44f1e6bd610832 refs/remotes/rem/main
 8e32a6d901327a23ef831511badce7bf3bf46689 refs/remotes/rem/one
 0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/rem/three
 6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 refs/remotes/rem/two
-6c9dec2b923228c9ff994c6cfe4ae16c12408dc5 refs/tags/tag-master
+ecf3b3627b498bdcb735cc4343bf165f76964e9a refs/tags/tag-main
 8e32a6d901327a23ef831511badce7bf3bf46689 refs/tags/tag-one
 22feea448b023a2d864ef94b013735af34d238ba refs/tags/tag-one-tree
 c61a82b60967180544e3c19f819ddbd0c9f89899 refs/tags/tag-three
diff --git a/t/t5515/refs.br-remote-glob-merge b/t/t5515/refs.br-remote-glob-merge
index 9bbbfd9..a28fa5f 100644
--- a/t/t5515/refs.br-remote-glob-merge
+++ b/t/t5515/refs.br-remote-glob-merge
@@ -1,13 +1,13 @@
 0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/HEAD
-754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/remotes/origin/master
+b4ab76b1a01ea602209932134a44f1e6bd610832 refs/remotes/origin/main
 8e32a6d901327a23ef831511badce7bf3bf46689 refs/remotes/origin/one
 0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/three
 6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 refs/remotes/origin/two
-754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/remotes/rem/master
+b4ab76b1a01ea602209932134a44f1e6bd610832 refs/remotes/rem/main
 8e32a6d901327a23ef831511badce7bf3bf46689 refs/remotes/rem/one
 0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/rem/three
 6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 refs/remotes/rem/two
-6c9dec2b923228c9ff994c6cfe4ae16c12408dc5 refs/tags/tag-master
+ecf3b3627b498bdcb735cc4343bf165f76964e9a refs/tags/tag-main
 8e32a6d901327a23ef831511badce7bf3bf46689 refs/tags/tag-one
 22feea448b023a2d864ef94b013735af34d238ba refs/tags/tag-one-tree
 c61a82b60967180544e3c19f819ddbd0c9f89899 refs/tags/tag-three
diff --git a/t/t5515/refs.br-remote-glob-merge_remote-glob b/t/t5515/refs.br-remote-glob-merge_remote-glob
index 9bbbfd9..a28fa5f 100644
--- a/t/t5515/refs.br-remote-glob-merge_remote-glob
+++ b/t/t5515/refs.br-remote-glob-merge_remote-glob
@@ -1,13 +1,13 @@
 0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/HEAD
-754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/remotes/origin/master
+b4ab76b1a01ea602209932134a44f1e6bd610832 refs/remotes/origin/main
 8e32a6d901327a23ef831511badce7bf3bf46689 refs/remotes/origin/one
 0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/three
 6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 refs/remotes/origin/two
-754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/remotes/rem/master
+b4ab76b1a01ea602209932134a44f1e6bd610832 refs/remotes/rem/main
 8e32a6d901327a23ef831511badce7bf3bf46689 refs/remotes/rem/one
 0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/rem/three
 6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 refs/remotes/rem/two
-6c9dec2b923228c9ff994c6cfe4ae16c12408dc5 refs/tags/tag-master
+ecf3b3627b498bdcb735cc4343bf165f76964e9a refs/tags/tag-main
 8e32a6d901327a23ef831511badce7bf3bf46689 refs/tags/tag-one
 22feea448b023a2d864ef94b013735af34d238ba refs/tags/tag-one-tree
 c61a82b60967180544e3c19f819ddbd0c9f89899 refs/tags/tag-three
diff --git a/t/t5515/refs.br-remote-glob-octopus b/t/t5515/refs.br-remote-glob-octopus
index 9bbbfd9..a28fa5f 100644
--- a/t/t5515/refs.br-remote-glob-octopus
+++ b/t/t5515/refs.br-remote-glob-octopus
@@ -1,13 +1,13 @@
 0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/HEAD
-754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/remotes/origin/master
+b4ab76b1a01ea602209932134a44f1e6bd610832 refs/remotes/origin/main
 8e32a6d901327a23ef831511badce7bf3bf46689 refs/remotes/origin/one
 0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/three
 6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 refs/remotes/origin/two
-754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/remotes/rem/master
+b4ab76b1a01ea602209932134a44f1e6bd610832 refs/remotes/rem/main
 8e32a6d901327a23ef831511badce7bf3bf46689 refs/remotes/rem/one
 0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/rem/three
 6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 refs/remotes/rem/two
-6c9dec2b923228c9ff994c6cfe4ae16c12408dc5 refs/tags/tag-master
+ecf3b3627b498bdcb735cc4343bf165f76964e9a refs/tags/tag-main
 8e32a6d901327a23ef831511badce7bf3bf46689 refs/tags/tag-one
 22feea448b023a2d864ef94b013735af34d238ba refs/tags/tag-one-tree
 c61a82b60967180544e3c19f819ddbd0c9f89899 refs/tags/tag-three
diff --git a/t/t5515/refs.br-remote-glob-octopus_remote-glob b/t/t5515/refs.br-remote-glob-octopus_remote-glob
index 9bbbfd9..a28fa5f 100644
--- a/t/t5515/refs.br-remote-glob-octopus_remote-glob
+++ b/t/t5515/refs.br-remote-glob-octopus_remote-glob
@@ -1,13 +1,13 @@
 0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/HEAD
-754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/remotes/origin/master
+b4ab76b1a01ea602209932134a44f1e6bd610832 refs/remotes/origin/main
 8e32a6d901327a23ef831511badce7bf3bf46689 refs/remotes/origin/one
 0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/three
 6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 refs/remotes/origin/two
-754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/remotes/rem/master
+b4ab76b1a01ea602209932134a44f1e6bd610832 refs/remotes/rem/main
 8e32a6d901327a23ef831511badce7bf3bf46689 refs/remotes/rem/one
 0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/rem/three
 6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 refs/remotes/rem/two
-6c9dec2b923228c9ff994c6cfe4ae16c12408dc5 refs/tags/tag-master
+ecf3b3627b498bdcb735cc4343bf165f76964e9a refs/tags/tag-main
 8e32a6d901327a23ef831511badce7bf3bf46689 refs/tags/tag-one
 22feea448b023a2d864ef94b013735af34d238ba refs/tags/tag-one-tree
 c61a82b60967180544e3c19f819ddbd0c9f89899 refs/tags/tag-three
diff --git a/t/t5515/refs.br-remote-glob_remote-glob b/t/t5515/refs.br-remote-glob_remote-glob
index 9bbbfd9..a28fa5f 100644
--- a/t/t5515/refs.br-remote-glob_remote-glob
+++ b/t/t5515/refs.br-remote-glob_remote-glob
@@ -1,13 +1,13 @@
 0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/HEAD
-754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/remotes/origin/master
+b4ab76b1a01ea602209932134a44f1e6bd610832 refs/remotes/origin/main
 8e32a6d901327a23ef831511badce7bf3bf46689 refs/remotes/origin/one
 0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/three
 6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 refs/remotes/origin/two
-754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/remotes/rem/master
+b4ab76b1a01ea602209932134a44f1e6bd610832 refs/remotes/rem/main
 8e32a6d901327a23ef831511badce7bf3bf46689 refs/remotes/rem/one
 0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/rem/three
 6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 refs/remotes/rem/two
-6c9dec2b923228c9ff994c6cfe4ae16c12408dc5 refs/tags/tag-master
+ecf3b3627b498bdcb735cc4343bf165f76964e9a refs/tags/tag-main
 8e32a6d901327a23ef831511badce7bf3bf46689 refs/tags/tag-one
 22feea448b023a2d864ef94b013735af34d238ba refs/tags/tag-one-tree
 c61a82b60967180544e3c19f819ddbd0c9f89899 refs/tags/tag-three
diff --git a/t/t5515/refs.br-unconfig b/t/t5515/refs.br-unconfig
index 13e4ad2..f2ab01f 100644
--- a/t/t5515/refs.br-unconfig
+++ b/t/t5515/refs.br-unconfig
@@ -1,9 +1,9 @@
 0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/HEAD
-754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/remotes/origin/master
+b4ab76b1a01ea602209932134a44f1e6bd610832 refs/remotes/origin/main
 8e32a6d901327a23ef831511badce7bf3bf46689 refs/remotes/origin/one
 0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/three
 6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 refs/remotes/origin/two
-6c9dec2b923228c9ff994c6cfe4ae16c12408dc5 refs/tags/tag-master
+ecf3b3627b498bdcb735cc4343bf165f76964e9a refs/tags/tag-main
 8e32a6d901327a23ef831511badce7bf3bf46689 refs/tags/tag-one
 22feea448b023a2d864ef94b013735af34d238ba refs/tags/tag-one-tree
 c61a82b60967180544e3c19f819ddbd0c9f89899 refs/tags/tag-three
diff --git a/t/t5515/refs.br-unconfig_--tags_.._.git b/t/t5515/refs.br-unconfig_--tags_.._.git
index 13e4ad2..f2ab01f 100644
--- a/t/t5515/refs.br-unconfig_--tags_.._.git
+++ b/t/t5515/refs.br-unconfig_--tags_.._.git
@@ -1,9 +1,9 @@
 0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/HEAD
-754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/remotes/origin/master
+b4ab76b1a01ea602209932134a44f1e6bd610832 refs/remotes/origin/main
 8e32a6d901327a23ef831511badce7bf3bf46689 refs/remotes/origin/one
 0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/three
 6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 refs/remotes/origin/two
-6c9dec2b923228c9ff994c6cfe4ae16c12408dc5 refs/tags/tag-master
+ecf3b3627b498bdcb735cc4343bf165f76964e9a refs/tags/tag-main
 8e32a6d901327a23ef831511badce7bf3bf46689 refs/tags/tag-one
 22feea448b023a2d864ef94b013735af34d238ba refs/tags/tag-one-tree
 c61a82b60967180544e3c19f819ddbd0c9f89899 refs/tags/tag-three
diff --git a/t/t5515/refs.br-unconfig_.._.git b/t/t5515/refs.br-unconfig_.._.git
index 70962ea..4a74b68 100644
--- a/t/t5515/refs.br-unconfig_.._.git
+++ b/t/t5515/refs.br-unconfig_.._.git
@@ -1,5 +1,5 @@
 0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/HEAD
-754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/remotes/origin/master
+b4ab76b1a01ea602209932134a44f1e6bd610832 refs/remotes/origin/main
 8e32a6d901327a23ef831511badce7bf3bf46689 refs/remotes/origin/one
 0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/three
 6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 refs/remotes/origin/two
diff --git a/t/t5515/refs.br-unconfig_.._.git_one b/t/t5515/refs.br-unconfig_.._.git_one
index 70962ea..4a74b68 100644
--- a/t/t5515/refs.br-unconfig_.._.git_one
+++ b/t/t5515/refs.br-unconfig_.._.git_one
@@ -1,5 +1,5 @@
 0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/HEAD
-754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/remotes/origin/master
+b4ab76b1a01ea602209932134a44f1e6bd610832 refs/remotes/origin/main
 8e32a6d901327a23ef831511badce7bf3bf46689 refs/remotes/origin/one
 0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/three
 6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 refs/remotes/origin/two
diff --git a/t/t5515/refs.br-unconfig_.._.git_one_tag_tag-one_tag_tag-three-file b/t/t5515/refs.br-unconfig_.._.git_one_tag_tag-one_tag_tag-three-file
index 13e4ad2..f2ab01f 100644
--- a/t/t5515/refs.br-unconfig_.._.git_one_tag_tag-one_tag_tag-three-file
+++ b/t/t5515/refs.br-unconfig_.._.git_one_tag_tag-one_tag_tag-three-file
@@ -1,9 +1,9 @@
 0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/HEAD
-754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/remotes/origin/master
+b4ab76b1a01ea602209932134a44f1e6bd610832 refs/remotes/origin/main
 8e32a6d901327a23ef831511badce7bf3bf46689 refs/remotes/origin/one
 0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/three
 6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 refs/remotes/origin/two
-6c9dec2b923228c9ff994c6cfe4ae16c12408dc5 refs/tags/tag-master
+ecf3b3627b498bdcb735cc4343bf165f76964e9a refs/tags/tag-main
 8e32a6d901327a23ef831511badce7bf3bf46689 refs/tags/tag-one
 22feea448b023a2d864ef94b013735af34d238ba refs/tags/tag-one-tree
 c61a82b60967180544e3c19f819ddbd0c9f89899 refs/tags/tag-three
diff --git a/t/t5515/refs.br-unconfig_.._.git_one_two b/t/t5515/refs.br-unconfig_.._.git_one_two
index 70962ea..4a74b68 100644
--- a/t/t5515/refs.br-unconfig_.._.git_one_two
+++ b/t/t5515/refs.br-unconfig_.._.git_one_two
@@ -1,5 +1,5 @@
 0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/HEAD
-754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/remotes/origin/master
+b4ab76b1a01ea602209932134a44f1e6bd610832 refs/remotes/origin/main
 8e32a6d901327a23ef831511badce7bf3bf46689 refs/remotes/origin/one
 0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/three
 6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 refs/remotes/origin/two
diff --git a/t/t5515/refs.br-unconfig_.._.git_tag_tag-one-tree_tag_tag-three-file b/t/t5515/refs.br-unconfig_.._.git_tag_tag-one-tree_tag_tag-three-file
index 13e4ad2..f2ab01f 100644
--- a/t/t5515/refs.br-unconfig_.._.git_tag_tag-one-tree_tag_tag-three-file
+++ b/t/t5515/refs.br-unconfig_.._.git_tag_tag-one-tree_tag_tag-three-file
@@ -1,9 +1,9 @@
 0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/HEAD
-754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/remotes/origin/master
+b4ab76b1a01ea602209932134a44f1e6bd610832 refs/remotes/origin/main
 8e32a6d901327a23ef831511badce7bf3bf46689 refs/remotes/origin/one
 0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/three
 6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 refs/remotes/origin/two
-6c9dec2b923228c9ff994c6cfe4ae16c12408dc5 refs/tags/tag-master
+ecf3b3627b498bdcb735cc4343bf165f76964e9a refs/tags/tag-main
 8e32a6d901327a23ef831511badce7bf3bf46689 refs/tags/tag-one
 22feea448b023a2d864ef94b013735af34d238ba refs/tags/tag-one-tree
 c61a82b60967180544e3c19f819ddbd0c9f89899 refs/tags/tag-three
diff --git a/t/t5515/refs.br-unconfig_.._.git_tag_tag-one_tag_tag-three b/t/t5515/refs.br-unconfig_.._.git_tag_tag-one_tag_tag-three
index 13e4ad2..f2ab01f 100644
--- a/t/t5515/refs.br-unconfig_.._.git_tag_tag-one_tag_tag-three
+++ b/t/t5515/refs.br-unconfig_.._.git_tag_tag-one_tag_tag-three
@@ -1,9 +1,9 @@
 0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/HEAD
-754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/remotes/origin/master
+b4ab76b1a01ea602209932134a44f1e6bd610832 refs/remotes/origin/main
 8e32a6d901327a23ef831511badce7bf3bf46689 refs/remotes/origin/one
 0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/three
 6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 refs/remotes/origin/two
-6c9dec2b923228c9ff994c6cfe4ae16c12408dc5 refs/tags/tag-master
+ecf3b3627b498bdcb735cc4343bf165f76964e9a refs/tags/tag-main
 8e32a6d901327a23ef831511badce7bf3bf46689 refs/tags/tag-one
 22feea448b023a2d864ef94b013735af34d238ba refs/tags/tag-one-tree
 c61a82b60967180544e3c19f819ddbd0c9f89899 refs/tags/tag-three
diff --git a/t/t5515/refs.br-unconfig_branches-default b/t/t5515/refs.br-unconfig_branches-default
index 21917c1..dc4f2b7 100644
--- a/t/t5515/refs.br-unconfig_branches-default
+++ b/t/t5515/refs.br-unconfig_branches-default
@@ -1,10 +1,10 @@
-754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/heads/branches-default
+b4ab76b1a01ea602209932134a44f1e6bd610832 refs/heads/branches-default
 0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/HEAD
-754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/remotes/origin/master
+b4ab76b1a01ea602209932134a44f1e6bd610832 refs/remotes/origin/main
 8e32a6d901327a23ef831511badce7bf3bf46689 refs/remotes/origin/one
 0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/three
 6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 refs/remotes/origin/two
-6c9dec2b923228c9ff994c6cfe4ae16c12408dc5 refs/tags/tag-master
+ecf3b3627b498bdcb735cc4343bf165f76964e9a refs/tags/tag-main
 8e32a6d901327a23ef831511badce7bf3bf46689 refs/tags/tag-one
 22feea448b023a2d864ef94b013735af34d238ba refs/tags/tag-one-tree
 c61a82b60967180544e3c19f819ddbd0c9f89899 refs/tags/tag-three
diff --git a/t/t5515/refs.br-unconfig_branches-one b/t/t5515/refs.br-unconfig_branches-one
index 8a705a5..e8f79bf 100644
--- a/t/t5515/refs.br-unconfig_branches-one
+++ b/t/t5515/refs.br-unconfig_branches-one
@@ -1,10 +1,10 @@
 8e32a6d901327a23ef831511badce7bf3bf46689 refs/heads/branches-one
 0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/HEAD
-754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/remotes/origin/master
+b4ab76b1a01ea602209932134a44f1e6bd610832 refs/remotes/origin/main
 8e32a6d901327a23ef831511badce7bf3bf46689 refs/remotes/origin/one
 0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/three
 6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 refs/remotes/origin/two
-6c9dec2b923228c9ff994c6cfe4ae16c12408dc5 refs/tags/tag-master
+ecf3b3627b498bdcb735cc4343bf165f76964e9a refs/tags/tag-main
 8e32a6d901327a23ef831511badce7bf3bf46689 refs/tags/tag-one
 22feea448b023a2d864ef94b013735af34d238ba refs/tags/tag-one-tree
 c61a82b60967180544e3c19f819ddbd0c9f89899 refs/tags/tag-three
diff --git a/t/t5515/refs.br-unconfig_config-explicit b/t/t5515/refs.br-unconfig_config-explicit
index 9bbbfd9..a28fa5f 100644
--- a/t/t5515/refs.br-unconfig_config-explicit
+++ b/t/t5515/refs.br-unconfig_config-explicit
@@ -1,13 +1,13 @@
 0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/HEAD
-754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/remotes/origin/master
+b4ab76b1a01ea602209932134a44f1e6bd610832 refs/remotes/origin/main
 8e32a6d901327a23ef831511badce7bf3bf46689 refs/remotes/origin/one
 0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/three
 6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 refs/remotes/origin/two
-754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/remotes/rem/master
+b4ab76b1a01ea602209932134a44f1e6bd610832 refs/remotes/rem/main
 8e32a6d901327a23ef831511badce7bf3bf46689 refs/remotes/rem/one
 0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/rem/three
 6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 refs/remotes/rem/two
-6c9dec2b923228c9ff994c6cfe4ae16c12408dc5 refs/tags/tag-master
+ecf3b3627b498bdcb735cc4343bf165f76964e9a refs/tags/tag-main
 8e32a6d901327a23ef831511badce7bf3bf46689 refs/tags/tag-one
 22feea448b023a2d864ef94b013735af34d238ba refs/tags/tag-one-tree
 c61a82b60967180544e3c19f819ddbd0c9f89899 refs/tags/tag-three
diff --git a/t/t5515/refs.br-unconfig_config-glob b/t/t5515/refs.br-unconfig_config-glob
index 9bbbfd9..a28fa5f 100644
--- a/t/t5515/refs.br-unconfig_config-glob
+++ b/t/t5515/refs.br-unconfig_config-glob
@@ -1,13 +1,13 @@
 0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/HEAD
-754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/remotes/origin/master
+b4ab76b1a01ea602209932134a44f1e6bd610832 refs/remotes/origin/main
 8e32a6d901327a23ef831511badce7bf3bf46689 refs/remotes/origin/one
 0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/three
 6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 refs/remotes/origin/two
-754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/remotes/rem/master
+b4ab76b1a01ea602209932134a44f1e6bd610832 refs/remotes/rem/main
 8e32a6d901327a23ef831511badce7bf3bf46689 refs/remotes/rem/one
 0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/rem/three
 6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 refs/remotes/rem/two
-6c9dec2b923228c9ff994c6cfe4ae16c12408dc5 refs/tags/tag-master
+ecf3b3627b498bdcb735cc4343bf165f76964e9a refs/tags/tag-main
 8e32a6d901327a23ef831511badce7bf3bf46689 refs/tags/tag-one
 22feea448b023a2d864ef94b013735af34d238ba refs/tags/tag-one-tree
 c61a82b60967180544e3c19f819ddbd0c9f89899 refs/tags/tag-three
diff --git a/t/t5515/refs.br-unconfig_remote-explicit b/t/t5515/refs.br-unconfig_remote-explicit
index 9bbbfd9..a28fa5f 100644
--- a/t/t5515/refs.br-unconfig_remote-explicit
+++ b/t/t5515/refs.br-unconfig_remote-explicit
@@ -1,13 +1,13 @@
 0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/HEAD
-754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/remotes/origin/master
+b4ab76b1a01ea602209932134a44f1e6bd610832 refs/remotes/origin/main
 8e32a6d901327a23ef831511badce7bf3bf46689 refs/remotes/origin/one
 0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/three
 6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 refs/remotes/origin/two
-754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/remotes/rem/master
+b4ab76b1a01ea602209932134a44f1e6bd610832 refs/remotes/rem/main
 8e32a6d901327a23ef831511badce7bf3bf46689 refs/remotes/rem/one
 0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/rem/three
 6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 refs/remotes/rem/two
-6c9dec2b923228c9ff994c6cfe4ae16c12408dc5 refs/tags/tag-master
+ecf3b3627b498bdcb735cc4343bf165f76964e9a refs/tags/tag-main
 8e32a6d901327a23ef831511badce7bf3bf46689 refs/tags/tag-one
 22feea448b023a2d864ef94b013735af34d238ba refs/tags/tag-one-tree
 c61a82b60967180544e3c19f819ddbd0c9f89899 refs/tags/tag-three
diff --git a/t/t5515/refs.br-unconfig_remote-glob b/t/t5515/refs.br-unconfig_remote-glob
index 9bbbfd9..a28fa5f 100644
--- a/t/t5515/refs.br-unconfig_remote-glob
+++ b/t/t5515/refs.br-unconfig_remote-glob
@@ -1,13 +1,13 @@
 0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/HEAD
-754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/remotes/origin/master
+b4ab76b1a01ea602209932134a44f1e6bd610832 refs/remotes/origin/main
 8e32a6d901327a23ef831511badce7bf3bf46689 refs/remotes/origin/one
 0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/three
 6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 refs/remotes/origin/two
-754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/remotes/rem/master
+b4ab76b1a01ea602209932134a44f1e6bd610832 refs/remotes/rem/main
 8e32a6d901327a23ef831511badce7bf3bf46689 refs/remotes/rem/one
 0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/rem/three
 6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 refs/remotes/rem/two
-6c9dec2b923228c9ff994c6cfe4ae16c12408dc5 refs/tags/tag-master
+ecf3b3627b498bdcb735cc4343bf165f76964e9a refs/tags/tag-main
 8e32a6d901327a23ef831511badce7bf3bf46689 refs/tags/tag-one
 22feea448b023a2d864ef94b013735af34d238ba refs/tags/tag-one-tree
 c61a82b60967180544e3c19f819ddbd0c9f89899 refs/tags/tag-three
diff --git a/t/t5515/refs.master b/t/t5515/refs.main
similarity index 81%
rename from t/t5515/refs.master
rename to t/t5515/refs.main
index 13e4ad2..f2ab01f 100644
--- a/t/t5515/refs.master
+++ b/t/t5515/refs.main
@@ -1,9 +1,9 @@
 0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/HEAD
-754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/remotes/origin/master
+b4ab76b1a01ea602209932134a44f1e6bd610832 refs/remotes/origin/main
 8e32a6d901327a23ef831511badce7bf3bf46689 refs/remotes/origin/one
 0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/three
 6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 refs/remotes/origin/two
-6c9dec2b923228c9ff994c6cfe4ae16c12408dc5 refs/tags/tag-master
+ecf3b3627b498bdcb735cc4343bf165f76964e9a refs/tags/tag-main
 8e32a6d901327a23ef831511badce7bf3bf46689 refs/tags/tag-one
 22feea448b023a2d864ef94b013735af34d238ba refs/tags/tag-one-tree
 c61a82b60967180544e3c19f819ddbd0c9f89899 refs/tags/tag-three
diff --git a/t/t5515/refs.master b/t/t5515/refs.main_--tags_.._.git
similarity index 81%
copy from t/t5515/refs.master
copy to t/t5515/refs.main_--tags_.._.git
index 13e4ad2..f2ab01f 100644
--- a/t/t5515/refs.master
+++ b/t/t5515/refs.main_--tags_.._.git
@@ -1,9 +1,9 @@
 0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/HEAD
-754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/remotes/origin/master
+b4ab76b1a01ea602209932134a44f1e6bd610832 refs/remotes/origin/main
 8e32a6d901327a23ef831511badce7bf3bf46689 refs/remotes/origin/one
 0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/three
 6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 refs/remotes/origin/two
-6c9dec2b923228c9ff994c6cfe4ae16c12408dc5 refs/tags/tag-master
+ecf3b3627b498bdcb735cc4343bf165f76964e9a refs/tags/tag-main
 8e32a6d901327a23ef831511badce7bf3bf46689 refs/tags/tag-one
 22feea448b023a2d864ef94b013735af34d238ba refs/tags/tag-one-tree
 c61a82b60967180544e3c19f819ddbd0c9f89899 refs/tags/tag-three
diff --git a/t/t5515/refs.master_.._.git b/t/t5515/refs.main_.._.git
similarity index 79%
rename from t/t5515/refs.master_.._.git
rename to t/t5515/refs.main_.._.git
index 70962ea..4a74b68 100644
--- a/t/t5515/refs.master_.._.git
+++ b/t/t5515/refs.main_.._.git
@@ -1,5 +1,5 @@
 0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/HEAD
-754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/remotes/origin/master
+b4ab76b1a01ea602209932134a44f1e6bd610832 refs/remotes/origin/main
 8e32a6d901327a23ef831511badce7bf3bf46689 refs/remotes/origin/one
 0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/three
 6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 refs/remotes/origin/two
diff --git a/t/t5515/refs.master_.._.git b/t/t5515/refs.main_.._.git_one
similarity index 79%
copy from t/t5515/refs.master_.._.git
copy to t/t5515/refs.main_.._.git_one
index 70962ea..4a74b68 100644
--- a/t/t5515/refs.master_.._.git
+++ b/t/t5515/refs.main_.._.git_one
@@ -1,5 +1,5 @@
 0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/HEAD
-754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/remotes/origin/master
+b4ab76b1a01ea602209932134a44f1e6bd610832 refs/remotes/origin/main
 8e32a6d901327a23ef831511badce7bf3bf46689 refs/remotes/origin/one
 0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/three
 6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 refs/remotes/origin/two
diff --git a/t/t5515/refs.master b/t/t5515/refs.main_.._.git_one_tag_tag-one_tag_tag-three-file
similarity index 81%
copy from t/t5515/refs.master
copy to t/t5515/refs.main_.._.git_one_tag_tag-one_tag_tag-three-file
index 13e4ad2..f2ab01f 100644
--- a/t/t5515/refs.master
+++ b/t/t5515/refs.main_.._.git_one_tag_tag-one_tag_tag-three-file
@@ -1,9 +1,9 @@
 0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/HEAD
-754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/remotes/origin/master
+b4ab76b1a01ea602209932134a44f1e6bd610832 refs/remotes/origin/main
 8e32a6d901327a23ef831511badce7bf3bf46689 refs/remotes/origin/one
 0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/three
 6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 refs/remotes/origin/two
-6c9dec2b923228c9ff994c6cfe4ae16c12408dc5 refs/tags/tag-master
+ecf3b3627b498bdcb735cc4343bf165f76964e9a refs/tags/tag-main
 8e32a6d901327a23ef831511badce7bf3bf46689 refs/tags/tag-one
 22feea448b023a2d864ef94b013735af34d238ba refs/tags/tag-one-tree
 c61a82b60967180544e3c19f819ddbd0c9f89899 refs/tags/tag-three
diff --git a/t/t5515/refs.master_.._.git b/t/t5515/refs.main_.._.git_one_two
similarity index 79%
copy from t/t5515/refs.master_.._.git
copy to t/t5515/refs.main_.._.git_one_two
index 70962ea..4a74b68 100644
--- a/t/t5515/refs.master_.._.git
+++ b/t/t5515/refs.main_.._.git_one_two
@@ -1,5 +1,5 @@
 0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/HEAD
-754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/remotes/origin/master
+b4ab76b1a01ea602209932134a44f1e6bd610832 refs/remotes/origin/main
 8e32a6d901327a23ef831511badce7bf3bf46689 refs/remotes/origin/one
 0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/three
 6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 refs/remotes/origin/two
diff --git a/t/t5515/refs.master b/t/t5515/refs.main_.._.git_tag_tag-one-tree_tag_tag-three-file
similarity index 81%
copy from t/t5515/refs.master
copy to t/t5515/refs.main_.._.git_tag_tag-one-tree_tag_tag-three-file
index 13e4ad2..f2ab01f 100644
--- a/t/t5515/refs.master
+++ b/t/t5515/refs.main_.._.git_tag_tag-one-tree_tag_tag-three-file
@@ -1,9 +1,9 @@
 0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/HEAD
-754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/remotes/origin/master
+b4ab76b1a01ea602209932134a44f1e6bd610832 refs/remotes/origin/main
 8e32a6d901327a23ef831511badce7bf3bf46689 refs/remotes/origin/one
 0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/three
 6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 refs/remotes/origin/two
-6c9dec2b923228c9ff994c6cfe4ae16c12408dc5 refs/tags/tag-master
+ecf3b3627b498bdcb735cc4343bf165f76964e9a refs/tags/tag-main
 8e32a6d901327a23ef831511badce7bf3bf46689 refs/tags/tag-one
 22feea448b023a2d864ef94b013735af34d238ba refs/tags/tag-one-tree
 c61a82b60967180544e3c19f819ddbd0c9f89899 refs/tags/tag-three
diff --git a/t/t5515/refs.master b/t/t5515/refs.main_.._.git_tag_tag-one_tag_tag-three
similarity index 81%
copy from t/t5515/refs.master
copy to t/t5515/refs.main_.._.git_tag_tag-one_tag_tag-three
index 13e4ad2..f2ab01f 100644
--- a/t/t5515/refs.master
+++ b/t/t5515/refs.main_.._.git_tag_tag-one_tag_tag-three
@@ -1,9 +1,9 @@
 0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/HEAD
-754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/remotes/origin/master
+b4ab76b1a01ea602209932134a44f1e6bd610832 refs/remotes/origin/main
 8e32a6d901327a23ef831511badce7bf3bf46689 refs/remotes/origin/one
 0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/three
 6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 refs/remotes/origin/two
-6c9dec2b923228c9ff994c6cfe4ae16c12408dc5 refs/tags/tag-master
+ecf3b3627b498bdcb735cc4343bf165f76964e9a refs/tags/tag-main
 8e32a6d901327a23ef831511badce7bf3bf46689 refs/tags/tag-one
 22feea448b023a2d864ef94b013735af34d238ba refs/tags/tag-one-tree
 c61a82b60967180544e3c19f819ddbd0c9f89899 refs/tags/tag-three
diff --git a/t/t5515/refs.master b/t/t5515/refs.main_branches-default
similarity index 74%
copy from t/t5515/refs.master
copy to t/t5515/refs.main_branches-default
index 13e4ad2..dc4f2b7 100644
--- a/t/t5515/refs.master
+++ b/t/t5515/refs.main_branches-default
@@ -1,9 +1,10 @@
+b4ab76b1a01ea602209932134a44f1e6bd610832 refs/heads/branches-default
 0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/HEAD
-754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/remotes/origin/master
+b4ab76b1a01ea602209932134a44f1e6bd610832 refs/remotes/origin/main
 8e32a6d901327a23ef831511badce7bf3bf46689 refs/remotes/origin/one
 0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/three
 6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 refs/remotes/origin/two
-6c9dec2b923228c9ff994c6cfe4ae16c12408dc5 refs/tags/tag-master
+ecf3b3627b498bdcb735cc4343bf165f76964e9a refs/tags/tag-main
 8e32a6d901327a23ef831511badce7bf3bf46689 refs/tags/tag-one
 22feea448b023a2d864ef94b013735af34d238ba refs/tags/tag-one-tree
 c61a82b60967180544e3c19f819ddbd0c9f89899 refs/tags/tag-three
diff --git a/t/t5515/refs.master_branches-one b/t/t5515/refs.main_branches-one
similarity index 82%
rename from t/t5515/refs.master_branches-one
rename to t/t5515/refs.main_branches-one
index 8a705a5..e8f79bf 100644
--- a/t/t5515/refs.master_branches-one
+++ b/t/t5515/refs.main_branches-one
@@ -1,10 +1,10 @@
 8e32a6d901327a23ef831511badce7bf3bf46689 refs/heads/branches-one
 0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/HEAD
-754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/remotes/origin/master
+b4ab76b1a01ea602209932134a44f1e6bd610832 refs/remotes/origin/main
 8e32a6d901327a23ef831511badce7bf3bf46689 refs/remotes/origin/one
 0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/three
 6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 refs/remotes/origin/two
-6c9dec2b923228c9ff994c6cfe4ae16c12408dc5 refs/tags/tag-master
+ecf3b3627b498bdcb735cc4343bf165f76964e9a refs/tags/tag-main
 8e32a6d901327a23ef831511badce7bf3bf46689 refs/tags/tag-one
 22feea448b023a2d864ef94b013735af34d238ba refs/tags/tag-one-tree
 c61a82b60967180544e3c19f819ddbd0c9f89899 refs/tags/tag-three
diff --git a/t/t5515/refs.master_config-explicit b/t/t5515/refs.main_config-explicit
similarity index 79%
rename from t/t5515/refs.master_config-explicit
rename to t/t5515/refs.main_config-explicit
index 9bbbfd9..a28fa5f 100644
--- a/t/t5515/refs.master_config-explicit
+++ b/t/t5515/refs.main_config-explicit
@@ -1,13 +1,13 @@
 0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/HEAD
-754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/remotes/origin/master
+b4ab76b1a01ea602209932134a44f1e6bd610832 refs/remotes/origin/main
 8e32a6d901327a23ef831511badce7bf3bf46689 refs/remotes/origin/one
 0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/three
 6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 refs/remotes/origin/two
-754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/remotes/rem/master
+b4ab76b1a01ea602209932134a44f1e6bd610832 refs/remotes/rem/main
 8e32a6d901327a23ef831511badce7bf3bf46689 refs/remotes/rem/one
 0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/rem/three
 6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 refs/remotes/rem/two
-6c9dec2b923228c9ff994c6cfe4ae16c12408dc5 refs/tags/tag-master
+ecf3b3627b498bdcb735cc4343bf165f76964e9a refs/tags/tag-main
 8e32a6d901327a23ef831511badce7bf3bf46689 refs/tags/tag-one
 22feea448b023a2d864ef94b013735af34d238ba refs/tags/tag-one-tree
 c61a82b60967180544e3c19f819ddbd0c9f89899 refs/tags/tag-three
diff --git a/t/t5515/refs.master_config-explicit b/t/t5515/refs.main_config-glob
similarity index 79%
copy from t/t5515/refs.master_config-explicit
copy to t/t5515/refs.main_config-glob
index 9bbbfd9..a28fa5f 100644
--- a/t/t5515/refs.master_config-explicit
+++ b/t/t5515/refs.main_config-glob
@@ -1,13 +1,13 @@
 0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/HEAD
-754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/remotes/origin/master
+b4ab76b1a01ea602209932134a44f1e6bd610832 refs/remotes/origin/main
 8e32a6d901327a23ef831511badce7bf3bf46689 refs/remotes/origin/one
 0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/three
 6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 refs/remotes/origin/two
-754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/remotes/rem/master
+b4ab76b1a01ea602209932134a44f1e6bd610832 refs/remotes/rem/main
 8e32a6d901327a23ef831511badce7bf3bf46689 refs/remotes/rem/one
 0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/rem/three
 6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 refs/remotes/rem/two
-6c9dec2b923228c9ff994c6cfe4ae16c12408dc5 refs/tags/tag-master
+ecf3b3627b498bdcb735cc4343bf165f76964e9a refs/tags/tag-main
 8e32a6d901327a23ef831511badce7bf3bf46689 refs/tags/tag-one
 22feea448b023a2d864ef94b013735af34d238ba refs/tags/tag-one-tree
 c61a82b60967180544e3c19f819ddbd0c9f89899 refs/tags/tag-three
diff --git a/t/t5515/refs.master_config-explicit b/t/t5515/refs.main_remote-explicit
similarity index 79%
copy from t/t5515/refs.master_config-explicit
copy to t/t5515/refs.main_remote-explicit
index 9bbbfd9..a28fa5f 100644
--- a/t/t5515/refs.master_config-explicit
+++ b/t/t5515/refs.main_remote-explicit
@@ -1,13 +1,13 @@
 0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/HEAD
-754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/remotes/origin/master
+b4ab76b1a01ea602209932134a44f1e6bd610832 refs/remotes/origin/main
 8e32a6d901327a23ef831511badce7bf3bf46689 refs/remotes/origin/one
 0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/three
 6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 refs/remotes/origin/two
-754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/remotes/rem/master
+b4ab76b1a01ea602209932134a44f1e6bd610832 refs/remotes/rem/main
 8e32a6d901327a23ef831511badce7bf3bf46689 refs/remotes/rem/one
 0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/rem/three
 6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 refs/remotes/rem/two
-6c9dec2b923228c9ff994c6cfe4ae16c12408dc5 refs/tags/tag-master
+ecf3b3627b498bdcb735cc4343bf165f76964e9a refs/tags/tag-main
 8e32a6d901327a23ef831511badce7bf3bf46689 refs/tags/tag-one
 22feea448b023a2d864ef94b013735af34d238ba refs/tags/tag-one-tree
 c61a82b60967180544e3c19f819ddbd0c9f89899 refs/tags/tag-three
diff --git a/t/t5515/refs.master_config-explicit b/t/t5515/refs.main_remote-glob
similarity index 79%
copy from t/t5515/refs.master_config-explicit
copy to t/t5515/refs.main_remote-glob
index 9bbbfd9..a28fa5f 100644
--- a/t/t5515/refs.master_config-explicit
+++ b/t/t5515/refs.main_remote-glob
@@ -1,13 +1,13 @@
 0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/HEAD
-754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/remotes/origin/master
+b4ab76b1a01ea602209932134a44f1e6bd610832 refs/remotes/origin/main
 8e32a6d901327a23ef831511badce7bf3bf46689 refs/remotes/origin/one
 0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/three
 6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 refs/remotes/origin/two
-754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/remotes/rem/master
+b4ab76b1a01ea602209932134a44f1e6bd610832 refs/remotes/rem/main
 8e32a6d901327a23ef831511badce7bf3bf46689 refs/remotes/rem/one
 0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/rem/three
 6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 refs/remotes/rem/two
-6c9dec2b923228c9ff994c6cfe4ae16c12408dc5 refs/tags/tag-master
+ecf3b3627b498bdcb735cc4343bf165f76964e9a refs/tags/tag-main
 8e32a6d901327a23ef831511badce7bf3bf46689 refs/tags/tag-one
 22feea448b023a2d864ef94b013735af34d238ba refs/tags/tag-one-tree
 c61a82b60967180544e3c19f819ddbd0c9f89899 refs/tags/tag-three
diff --git a/t/t5515/refs.master_--tags_.._.git b/t/t5515/refs.master_--tags_.._.git
deleted file mode 100644
index 13e4ad2..0000000
--- a/t/t5515/refs.master_--tags_.._.git
+++ /dev/null
@@ -1,11 +0,0 @@
-0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/HEAD
-754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/remotes/origin/master
-8e32a6d901327a23ef831511badce7bf3bf46689 refs/remotes/origin/one
-0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/three
-6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 refs/remotes/origin/two
-6c9dec2b923228c9ff994c6cfe4ae16c12408dc5 refs/tags/tag-master
-8e32a6d901327a23ef831511badce7bf3bf46689 refs/tags/tag-one
-22feea448b023a2d864ef94b013735af34d238ba refs/tags/tag-one-tree
-c61a82b60967180544e3c19f819ddbd0c9f89899 refs/tags/tag-three
-0e3b14047d3ee365f4f2a1b673db059c3972589c refs/tags/tag-three-file
-525b7fb068d59950d185a8779dc957c77eed73ba refs/tags/tag-two
diff --git a/t/t5515/refs.master_.._.git_one b/t/t5515/refs.master_.._.git_one
deleted file mode 100644
index 70962ea..0000000
--- a/t/t5515/refs.master_.._.git_one
+++ /dev/null
@@ -1,5 +0,0 @@
-0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/HEAD
-754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/remotes/origin/master
-8e32a6d901327a23ef831511badce7bf3bf46689 refs/remotes/origin/one
-0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/three
-6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 refs/remotes/origin/two
diff --git a/t/t5515/refs.master_.._.git_one_tag_tag-one_tag_tag-three-file b/t/t5515/refs.master_.._.git_one_tag_tag-one_tag_tag-three-file
deleted file mode 100644
index 13e4ad2..0000000
--- a/t/t5515/refs.master_.._.git_one_tag_tag-one_tag_tag-three-file
+++ /dev/null
@@ -1,11 +0,0 @@
-0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/HEAD
-754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/remotes/origin/master
-8e32a6d901327a23ef831511badce7bf3bf46689 refs/remotes/origin/one
-0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/three
-6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 refs/remotes/origin/two
-6c9dec2b923228c9ff994c6cfe4ae16c12408dc5 refs/tags/tag-master
-8e32a6d901327a23ef831511badce7bf3bf46689 refs/tags/tag-one
-22feea448b023a2d864ef94b013735af34d238ba refs/tags/tag-one-tree
-c61a82b60967180544e3c19f819ddbd0c9f89899 refs/tags/tag-three
-0e3b14047d3ee365f4f2a1b673db059c3972589c refs/tags/tag-three-file
-525b7fb068d59950d185a8779dc957c77eed73ba refs/tags/tag-two
diff --git a/t/t5515/refs.master_.._.git_one_two b/t/t5515/refs.master_.._.git_one_two
deleted file mode 100644
index 70962ea..0000000
--- a/t/t5515/refs.master_.._.git_one_two
+++ /dev/null
@@ -1,5 +0,0 @@
-0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/HEAD
-754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/remotes/origin/master
-8e32a6d901327a23ef831511badce7bf3bf46689 refs/remotes/origin/one
-0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/three
-6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 refs/remotes/origin/two
diff --git a/t/t5515/refs.master_.._.git_tag_tag-one-tree_tag_tag-three-file b/t/t5515/refs.master_.._.git_tag_tag-one-tree_tag_tag-three-file
deleted file mode 100644
index 13e4ad2..0000000
--- a/t/t5515/refs.master_.._.git_tag_tag-one-tree_tag_tag-three-file
+++ /dev/null
@@ -1,11 +0,0 @@
-0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/HEAD
-754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/remotes/origin/master
-8e32a6d901327a23ef831511badce7bf3bf46689 refs/remotes/origin/one
-0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/three
-6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 refs/remotes/origin/two
-6c9dec2b923228c9ff994c6cfe4ae16c12408dc5 refs/tags/tag-master
-8e32a6d901327a23ef831511badce7bf3bf46689 refs/tags/tag-one
-22feea448b023a2d864ef94b013735af34d238ba refs/tags/tag-one-tree
-c61a82b60967180544e3c19f819ddbd0c9f89899 refs/tags/tag-three
-0e3b14047d3ee365f4f2a1b673db059c3972589c refs/tags/tag-three-file
-525b7fb068d59950d185a8779dc957c77eed73ba refs/tags/tag-two
diff --git a/t/t5515/refs.master_.._.git_tag_tag-one_tag_tag-three b/t/t5515/refs.master_.._.git_tag_tag-one_tag_tag-three
deleted file mode 100644
index 13e4ad2..0000000
--- a/t/t5515/refs.master_.._.git_tag_tag-one_tag_tag-three
+++ /dev/null
@@ -1,11 +0,0 @@
-0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/HEAD
-754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/remotes/origin/master
-8e32a6d901327a23ef831511badce7bf3bf46689 refs/remotes/origin/one
-0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/three
-6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 refs/remotes/origin/two
-6c9dec2b923228c9ff994c6cfe4ae16c12408dc5 refs/tags/tag-master
-8e32a6d901327a23ef831511badce7bf3bf46689 refs/tags/tag-one
-22feea448b023a2d864ef94b013735af34d238ba refs/tags/tag-one-tree
-c61a82b60967180544e3c19f819ddbd0c9f89899 refs/tags/tag-three
-0e3b14047d3ee365f4f2a1b673db059c3972589c refs/tags/tag-three-file
-525b7fb068d59950d185a8779dc957c77eed73ba refs/tags/tag-two
diff --git a/t/t5515/refs.master_branches-default b/t/t5515/refs.master_branches-default
deleted file mode 100644
index 21917c1..0000000
--- a/t/t5515/refs.master_branches-default
+++ /dev/null
@@ -1,12 +0,0 @@
-754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/heads/branches-default
-0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/HEAD
-754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/remotes/origin/master
-8e32a6d901327a23ef831511badce7bf3bf46689 refs/remotes/origin/one
-0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/three
-6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 refs/remotes/origin/two
-6c9dec2b923228c9ff994c6cfe4ae16c12408dc5 refs/tags/tag-master
-8e32a6d901327a23ef831511badce7bf3bf46689 refs/tags/tag-one
-22feea448b023a2d864ef94b013735af34d238ba refs/tags/tag-one-tree
-c61a82b60967180544e3c19f819ddbd0c9f89899 refs/tags/tag-three
-0e3b14047d3ee365f4f2a1b673db059c3972589c refs/tags/tag-three-file
-525b7fb068d59950d185a8779dc957c77eed73ba refs/tags/tag-two
diff --git a/t/t5515/refs.master_config-glob b/t/t5515/refs.master_config-glob
deleted file mode 100644
index 9bbbfd9..0000000
--- a/t/t5515/refs.master_config-glob
+++ /dev/null
@@ -1,15 +0,0 @@
-0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/HEAD
-754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/remotes/origin/master
-8e32a6d901327a23ef831511badce7bf3bf46689 refs/remotes/origin/one
-0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/three
-6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 refs/remotes/origin/two
-754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/remotes/rem/master
-8e32a6d901327a23ef831511badce7bf3bf46689 refs/remotes/rem/one
-0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/rem/three
-6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 refs/remotes/rem/two
-6c9dec2b923228c9ff994c6cfe4ae16c12408dc5 refs/tags/tag-master
-8e32a6d901327a23ef831511badce7bf3bf46689 refs/tags/tag-one
-22feea448b023a2d864ef94b013735af34d238ba refs/tags/tag-one-tree
-c61a82b60967180544e3c19f819ddbd0c9f89899 refs/tags/tag-three
-0e3b14047d3ee365f4f2a1b673db059c3972589c refs/tags/tag-three-file
-525b7fb068d59950d185a8779dc957c77eed73ba refs/tags/tag-two
diff --git a/t/t5515/refs.master_remote-explicit b/t/t5515/refs.master_remote-explicit
deleted file mode 100644
index 9bbbfd9..0000000
--- a/t/t5515/refs.master_remote-explicit
+++ /dev/null
@@ -1,15 +0,0 @@
-0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/HEAD
-754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/remotes/origin/master
-8e32a6d901327a23ef831511badce7bf3bf46689 refs/remotes/origin/one
-0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/three
-6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 refs/remotes/origin/two
-754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/remotes/rem/master
-8e32a6d901327a23ef831511badce7bf3bf46689 refs/remotes/rem/one
-0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/rem/three
-6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 refs/remotes/rem/two
-6c9dec2b923228c9ff994c6cfe4ae16c12408dc5 refs/tags/tag-master
-8e32a6d901327a23ef831511badce7bf3bf46689 refs/tags/tag-one
-22feea448b023a2d864ef94b013735af34d238ba refs/tags/tag-one-tree
-c61a82b60967180544e3c19f819ddbd0c9f89899 refs/tags/tag-three
-0e3b14047d3ee365f4f2a1b673db059c3972589c refs/tags/tag-three-file
-525b7fb068d59950d185a8779dc957c77eed73ba refs/tags/tag-two
diff --git a/t/t5515/refs.master_remote-glob b/t/t5515/refs.master_remote-glob
deleted file mode 100644
index 9bbbfd9..0000000
--- a/t/t5515/refs.master_remote-glob
+++ /dev/null
@@ -1,15 +0,0 @@
-0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/HEAD
-754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/remotes/origin/master
-8e32a6d901327a23ef831511badce7bf3bf46689 refs/remotes/origin/one
-0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/origin/three
-6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 refs/remotes/origin/two
-754b754407bf032e9a2f9d5a9ad05ca79a6b228f refs/remotes/rem/master
-8e32a6d901327a23ef831511badce7bf3bf46689 refs/remotes/rem/one
-0567da4d5edd2ff4bb292a465ba9e64dcad9536b refs/remotes/rem/three
-6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 refs/remotes/rem/two
-6c9dec2b923228c9ff994c6cfe4ae16c12408dc5 refs/tags/tag-master
-8e32a6d901327a23ef831511badce7bf3bf46689 refs/tags/tag-one
-22feea448b023a2d864ef94b013735af34d238ba refs/tags/tag-one-tree
-c61a82b60967180544e3c19f819ddbd0c9f89899 refs/tags/tag-three
-0e3b14047d3ee365f4f2a1b673db059c3972589c refs/tags/tag-three-file
-525b7fb068d59950d185a8779dc957c77eed73ba refs/tags/tag-two
diff --git a/t/t5526-fetch-submodules.sh b/t/t5526-fetch-submodules.sh
index 63205df..a7f6f9f 100755
--- a/t/t5526-fetch-submodules.sh
+++ b/t/t5526-fetch-submodules.sh
@@ -18,7 +18,7 @@
 		head2=$(git rev-parse --short HEAD) &&
 		echo "Fetching submodule submodule" > ../expect.err &&
 		echo "From $pwd/submodule" >> ../expect.err &&
-		echo "   $head1..$head2  master     -> origin/master" >> ../expect.err
+		echo "   $head1..$head2  main       -> origin/main" >> ../expect.err
 	) &&
 	(
 		cd deepsubmodule &&
@@ -30,7 +30,7 @@
 		head2=$(git rev-parse --short HEAD) &&
 		echo "Fetching submodule submodule/subdir/deepsubmodule" >> ../expect.err
 		echo "From $pwd/deepsubmodule" >> ../expect.err &&
-		echo "   $head1..$head2  master     -> origin/master" >> ../expect.err
+		echo "   $head1..$head2  main       -> origin/main" >> ../expect.err
 	)
 }
 
@@ -61,7 +61,7 @@
 	)
 '
 
-test_expect_success "fetch --recurse-submodules recurses into submodules" '
+test_expect_success PREPARE_FOR_MAIN_BRANCH "fetch --recurse-submodules recurses into submodules" '
 	add_upstream_commit &&
 	(
 		cd downstream &&
@@ -71,7 +71,7 @@
 	test_i18ncmp expect.err actual.err
 '
 
-test_expect_success "submodule.recurse option triggers recursive fetch" '
+test_expect_success PREPARE_FOR_MAIN_BRANCH "submodule.recurse option triggers recursive fetch" '
 	add_upstream_commit &&
 	(
 		cd downstream &&
@@ -81,7 +81,7 @@
 	test_i18ncmp expect.err actual.err
 '
 
-test_expect_success "fetch --recurse-submodules -j2 has the same output behaviour" '
+test_expect_success PREPARE_FOR_MAIN_BRANCH "fetch --recurse-submodules -j2 has the same output behaviour" '
 	add_upstream_commit &&
 	(
 		cd downstream &&
@@ -111,7 +111,7 @@
 	test_must_be_empty actual.err
 '
 
-test_expect_success "using fetchRecurseSubmodules=true in .gitmodules recurses into submodules" '
+test_expect_success PREPARE_FOR_MAIN_BRANCH "using fetchRecurseSubmodules=true in .gitmodules recurses into submodules" '
 	(
 		cd downstream &&
 		git config -f .gitmodules submodule.submodule.fetchRecurseSubmodules true &&
@@ -141,7 +141,7 @@
 	test_must_be_empty actual.err
 '
 
-test_expect_success "--recurse-submodules overrides fetchRecurseSubmodules setting from .git/config" '
+test_expect_success PREPARE_FOR_MAIN_BRANCH "--recurse-submodules overrides fetchRecurseSubmodules setting from .git/config" '
 	(
 		cd downstream &&
 		git fetch --recurse-submodules >../actual.out 2>../actual.err &&
@@ -170,7 +170,7 @@
 	test_must_be_empty actual.err
 '
 
-test_expect_success "--dry-run propagates to submodules" '
+test_expect_success PREPARE_FOR_MAIN_BRANCH "--dry-run propagates to submodules" '
 	add_upstream_commit &&
 	(
 		cd downstream &&
@@ -180,7 +180,7 @@
 	test_i18ncmp expect.err actual.err
 '
 
-test_expect_success "Without --dry-run propagates to submodules" '
+test_expect_success PREPARE_FOR_MAIN_BRANCH "Without --dry-run propagates to submodules" '
 	(
 		cd downstream &&
 		git fetch --recurse-submodules >../actual.out 2>../actual.err
@@ -189,7 +189,7 @@
 	test_i18ncmp expect.err actual.err
 '
 
-test_expect_success "recurseSubmodules=true propagates into submodules" '
+test_expect_success PREPARE_FOR_MAIN_BRANCH "recurseSubmodules=true propagates into submodules" '
 	add_upstream_commit &&
 	(
 		cd downstream &&
@@ -200,7 +200,7 @@
 	test_i18ncmp expect.err actual.err
 '
 
-test_expect_success "--recurse-submodules overrides config in submodule" '
+test_expect_success PREPARE_FOR_MAIN_BRANCH "--recurse-submodules overrides config in submodule" '
 	add_upstream_commit &&
 	(
 		cd downstream &&
@@ -225,7 +225,7 @@
 	test_must_be_empty actual.err
 '
 
-test_expect_success "Recursion doesn't happen when no new commits are fetched in the superproject" '
+test_expect_success PREPARE_FOR_MAIN_BRANCH "Recursion doesn't happen when no new commits are fetched in the superproject" '
 	(
 		cd downstream &&
 		(
@@ -239,13 +239,13 @@
 	test_must_be_empty actual.err
 '
 
-test_expect_success "Recursion stops when no new submodule commits are fetched" '
+test_expect_success PREPARE_FOR_MAIN_BRANCH "Recursion stops when no new submodule commits are fetched" '
 	head1=$(git rev-parse --short HEAD) &&
 	git add submodule &&
 	git commit -m "new submodule" &&
 	head2=$(git rev-parse --short HEAD) &&
 	echo "From $pwd/." > expect.err.sub &&
-	echo "   $head1..$head2  master     -> origin/master" >>expect.err.sub &&
+	echo "   $head1..$head2  main       -> origin/main" >>expect.err.sub &&
 	head -3 expect.err >> expect.err.sub &&
 	(
 		cd downstream &&
@@ -255,7 +255,7 @@
 	test_must_be_empty actual.out
 '
 
-test_expect_success "Recursion doesn't happen when new superproject commits don't change any submodules" '
+test_expect_success PREPARE_FOR_MAIN_BRANCH "Recursion doesn't happen when new superproject commits don't change any submodules" '
 	add_upstream_commit &&
 	head1=$(git rev-parse --short HEAD) &&
 	echo a > file &&
@@ -263,7 +263,7 @@
 	git commit -m "new file" &&
 	head2=$(git rev-parse --short HEAD) &&
 	echo "From $pwd/." > expect.err.file &&
-	echo "   $head1..$head2  master     -> origin/master" >> expect.err.file &&
+	echo "   $head1..$head2  main       -> origin/main" >> expect.err.file &&
 	(
 		cd downstream &&
 		git fetch >../actual.out 2>../actual.err
@@ -272,7 +272,7 @@
 	test_i18ncmp expect.err.file actual.err
 '
 
-test_expect_success "Recursion picks up config in submodule" '
+test_expect_success PREPARE_FOR_MAIN_BRANCH "Recursion picks up config in submodule" '
 	(
 		cd downstream &&
 		git fetch --recurse-submodules &&
@@ -287,7 +287,7 @@
 	git commit -m "new submodule" &&
 	head2=$(git rev-parse --short HEAD) &&
 	echo "From $pwd/." > expect.err.sub &&
-	echo "   $head1..$head2  master     -> origin/master" >> expect.err.sub &&
+	echo "   $head1..$head2  main       -> origin/main" >> expect.err.sub &&
 	cat expect.err >> expect.err.sub &&
 	(
 		cd downstream &&
@@ -301,7 +301,7 @@
 	test_must_be_empty actual.out
 '
 
-test_expect_success "Recursion picks up all submodules when necessary" '
+test_expect_success PREPARE_FOR_MAIN_BRANCH "Recursion picks up all submodules when necessary" '
 	add_upstream_commit &&
 	(
 		cd submodule &&
@@ -316,14 +316,14 @@
 		head2=$(git rev-parse --short HEAD) &&
 		echo "Fetching submodule submodule" > ../expect.err.sub &&
 		echo "From $pwd/submodule" >> ../expect.err.sub &&
-		echo "   $head1..$head2  master     -> origin/master" >> ../expect.err.sub
+		echo "   $head1..$head2  main       -> origin/main" >> ../expect.err.sub
 	) &&
 	head1=$(git rev-parse --short HEAD) &&
 	git add submodule &&
 	git commit -m "new submodule" &&
 	head2=$(git rev-parse --short HEAD) &&
 	echo "From $pwd/." > expect.err.2 &&
-	echo "   $head1..$head2  master     -> origin/master" >> expect.err.2 &&
+	echo "   $head1..$head2  main       -> origin/main" >> expect.err.2 &&
 	cat expect.err.sub >> expect.err.2 &&
 	tail -3 expect.err >> expect.err.2 &&
 	(
@@ -334,7 +334,7 @@
 	test_must_be_empty actual.out
 '
 
-test_expect_success "'--recurse-submodules=on-demand' doesn't recurse when no new commits are fetched in the superproject (and ignores config)" '
+test_expect_success PREPARE_FOR_MAIN_BRANCH "'--recurse-submodules=on-demand' doesn't recurse when no new commits are fetched in the superproject (and ignores config)" '
 	add_upstream_commit &&
 	(
 		cd submodule &&
@@ -349,7 +349,7 @@
 		head2=$(git rev-parse --short HEAD) &&
 		echo Fetching submodule submodule > ../expect.err.sub &&
 		echo "From $pwd/submodule" >> ../expect.err.sub &&
-		echo "   $head1..$head2  master     -> origin/master" >> ../expect.err.sub
+		echo "   $head1..$head2  main       -> origin/main" >> ../expect.err.sub
 	) &&
 	(
 		cd downstream &&
@@ -361,14 +361,14 @@
 	test_must_be_empty actual.err
 '
 
-test_expect_success "'--recurse-submodules=on-demand' recurses as deep as necessary (and ignores config)" '
+test_expect_success PREPARE_FOR_MAIN_BRANCH "'--recurse-submodules=on-demand' recurses as deep as necessary (and ignores config)" '
 	head1=$(git rev-parse --short HEAD) &&
 	git add submodule &&
 	git commit -m "new submodule" &&
 	head2=$(git rev-parse --short HEAD) &&
 	tail -3 expect.err > expect.err.deepsub &&
 	echo "From $pwd/." > expect.err &&
-	echo "   $head1..$head2  master     -> origin/master" >>expect.err &&
+	echo "   $head1..$head2  main       -> origin/main" >>expect.err &&
 	cat expect.err.sub >> expect.err &&
 	cat expect.err.deepsub >> expect.err &&
 	(
@@ -389,7 +389,7 @@
 	test_i18ncmp expect.err actual.err
 '
 
-test_expect_success "'--recurse-submodules=on-demand' stops when no new submodule commits are found in the superproject (and ignores config)" '
+test_expect_success PREPARE_FOR_MAIN_BRANCH "'--recurse-submodules=on-demand' stops when no new submodule commits are found in the superproject (and ignores config)" '
 	add_upstream_commit &&
 	head1=$(git rev-parse --short HEAD) &&
 	echo a >> file &&
@@ -397,7 +397,7 @@
 	git commit -m "new file" &&
 	head2=$(git rev-parse --short HEAD) &&
 	echo "From $pwd/." > expect.err.file &&
-	echo "   $head1..$head2  master     -> origin/master" >> expect.err.file &&
+	echo "   $head1..$head2  main       -> origin/main" >> expect.err.file &&
 	(
 		cd downstream &&
 		git fetch --recurse-submodules=on-demand >../actual.out 2>../actual.err
@@ -406,7 +406,7 @@
 	test_i18ncmp expect.err.file actual.err
 '
 
-test_expect_success "'fetch.recurseSubmodules=on-demand' overrides global config" '
+test_expect_success PREPARE_FOR_MAIN_BRANCH "'fetch.recurseSubmodules=on-demand' overrides global config" '
 	(
 		cd downstream &&
 		git fetch --recurse-submodules
@@ -418,7 +418,7 @@
 	git commit -m "new submodule" &&
 	head2=$(git rev-parse --short HEAD) &&
 	echo "From $pwd/." > expect.err.2 &&
-	echo "   $head1..$head2  master     -> origin/master" >>expect.err.2 &&
+	echo "   $head1..$head2  main       -> origin/main" >>expect.err.2 &&
 	head -3 expect.err >> expect.err.2 &&
 	(
 		cd downstream &&
@@ -434,7 +434,7 @@
 	test_i18ncmp expect.err.2 actual.err
 '
 
-test_expect_success "'submodule.<sub>.fetchRecurseSubmodules=on-demand' overrides fetch.recurseSubmodules" '
+test_expect_success PREPARE_FOR_MAIN_BRANCH "'submodule.<sub>.fetchRecurseSubmodules=on-demand' overrides fetch.recurseSubmodules" '
 	(
 		cd downstream &&
 		git fetch --recurse-submodules
@@ -446,7 +446,7 @@
 	git commit -m "new submodule" &&
 	head2=$(git rev-parse --short HEAD) &&
 	echo "From $pwd/." > expect.err.2 &&
-	echo "   $head1..$head2  master     -> origin/master" >>expect.err.2 &&
+	echo "   $head1..$head2  main       -> origin/main" >>expect.err.2 &&
 	head -3 expect.err >> expect.err.2 &&
 	(
 		cd downstream &&
@@ -462,7 +462,7 @@
 	test_i18ncmp expect.err.2 actual.err
 '
 
-test_expect_success "don't fetch submodule when newly recorded commits are already present" '
+test_expect_success PREPARE_FOR_MAIN_BRANCH "don't fetch submodule when newly recorded commits are already present" '
 	(
 		cd submodule &&
 		git checkout -q HEAD^^
@@ -472,7 +472,7 @@
 	git commit -m "submodule rewound" &&
 	head2=$(git rev-parse --short HEAD) &&
 	echo "From $pwd/." > expect.err &&
-	echo "   $head1..$head2  master     -> origin/master" >> expect.err &&
+	echo "   $head1..$head2  main       -> origin/main" >> expect.err &&
 	(
 		cd downstream &&
 		git fetch >../actual.out 2>../actual.err
@@ -485,7 +485,7 @@
 	)
 '
 
-test_expect_success "'fetch.recurseSubmodules=on-demand' works also without .gitmodules entry" '
+test_expect_success PREPARE_FOR_MAIN_BRANCH "'fetch.recurseSubmodules=on-demand' works also without .gitmodules entry" '
 	(
 		cd downstream &&
 		git fetch --recurse-submodules
@@ -497,7 +497,7 @@
 	git commit -m "new submodule without .gitmodules" &&
 	head2=$(git rev-parse --short HEAD) &&
 	echo "From $pwd/." >expect.err.2 &&
-	echo "   $head1..$head2  master     -> origin/master" >>expect.err.2 &&
+	echo "   $head1..$head2  main       -> origin/main" >>expect.err.2 &&
 	head -3 expect.err >>expect.err.2 &&
 	(
 		cd downstream &&
@@ -719,4 +719,67 @@
 	)
 '
 
+add_commit_push () {
+	dir="$1"
+	msg="$2"
+	shift 2
+	git -C "$dir" add "$@" &&
+	git -C "$dir" commit -a -m "$msg" &&
+	git -C "$dir" push
+}
+
+compare_refs_in_dir () {
+	fail= &&
+	if test "x$1" = 'x!'
+	then
+		fail='!' &&
+		shift
+	fi &&
+	git -C "$1" rev-parse --verify "$2" >expect &&
+	git -C "$3" rev-parse --verify "$4" >actual &&
+	eval $fail test_cmp expect actual
+}
+
+
+test_expect_success 'setup nested submodule fetch test' '
+	# does not depend on any previous test setups
+
+	for repo in outer middle inner
+	do
+		(
+			git init --bare $repo &&
+			git clone $repo ${repo}_content &&
+			echo "$repo" >"${repo}_content/file" &&
+			add_commit_push ${repo}_content "initial" file
+		) || return 1
+	done &&
+
+	git clone outer A &&
+	git -C A submodule add "$pwd/middle" &&
+	git -C A/middle/ submodule add "$pwd/inner" &&
+	add_commit_push A/middle/ "adding inner sub" .gitmodules inner &&
+	add_commit_push A/ "adding middle sub" .gitmodules middle &&
+
+	git clone outer B &&
+	git -C B/ submodule update --init middle &&
+
+	compare_refs_in_dir A HEAD B HEAD &&
+	compare_refs_in_dir A/middle HEAD B/middle HEAD &&
+	test -f B/file &&
+	test -f B/middle/file &&
+	! test -f B/middle/inner/file &&
+
+	echo "change on inner repo of A" >"A/middle/inner/file" &&
+	add_commit_push A/middle/inner "change on inner" file &&
+	add_commit_push A/middle "change on inner" inner &&
+	add_commit_push A "change on inner" middle
+'
+
+test_expect_success 'fetching a superproject containing an uninitialized sub/sub project' '
+	# depends on previous test for setup
+
+	git -C B/ fetch &&
+	compare_refs_in_dir A origin/master B origin/master
+'
+
 test_done
diff --git a/t/t5530-upload-pack-error.sh b/t/t5530-upload-pack-error.sh
index 205a263..9dd2d24 100755
--- a/t/t5530-upload-pack-error.sh
+++ b/t/t5530-upload-pack-error.sh
@@ -88,6 +88,23 @@
 	grep "pack-objects died" output.err
 '
 
+test_expect_success 'upload-pack tolerates EOF just after stateless client wants' '
+	test_commit initial &&
+	head=$(git rev-parse HEAD) &&
+
+	{
+		packetize "want $head" &&
+		packetize "shallow $head" &&
+		packetize "deepen 1" &&
+		printf "0000"
+	} >request &&
+
+	printf "0000" >expect &&
+
+	git upload-pack --stateless-rpc . <request >actual &&
+	test_cmp expect actual
+'
+
 test_expect_success 'create empty repository' '
 
 	mkdir foo &&
diff --git a/t/t5533-push-cas.sh b/t/t5533-push-cas.sh
index 0b0eb1d..7813e84 100755
--- a/t/t5533-push-cas.sh
+++ b/t/t5533-push-cas.sh
@@ -13,6 +13,46 @@
 	)
 }
 
+# For tests with "--force-if-includes".
+setup_src_dup_dst () {
+	rm -fr src dup dst &&
+	git init --bare dst &&
+	git clone --no-local dst src &&
+	git clone --no-local dst dup
+	(
+		cd src &&
+		test_commit A &&
+		test_commit B &&
+		test_commit C &&
+		git push origin
+	) &&
+	(
+		cd dup &&
+		git fetch &&
+		git merge origin/master &&
+		git switch -c branch master~2 &&
+		test_commit D &&
+		test_commit E &&
+		git push origin --all
+	) &&
+	(
+		cd src &&
+		git switch master &&
+		git fetch --all &&
+		git branch branch --track origin/branch &&
+		git rebase origin/master
+	) &&
+	(
+		cd dup &&
+		git switch master &&
+		test_commit F &&
+		test_commit G &&
+		git switch branch &&
+		test_commit H &&
+		git push origin --all
+	)
+}
+
 test_expect_success setup '
 	# create template repository
 	test_commit A &&
@@ -256,4 +296,101 @@
 	)
 '
 
+test_expect_success 'background updates to remote can be mitigated with "--force-if-includes"' '
+	setup_src_dup_dst &&
+	test_when_finished "rm -fr dst src dup" &&
+	git ls-remote dst refs/heads/master >expect.master &&
+	git ls-remote dst refs/heads/branch >expect.branch &&
+	(
+		cd src &&
+		git switch branch &&
+		test_commit I &&
+		git switch master &&
+		test_commit J &&
+		git fetch --all &&
+		test_must_fail git push --force-with-lease --force-if-includes --all
+	) &&
+	git ls-remote dst refs/heads/master >actual.master &&
+	git ls-remote dst refs/heads/branch >actual.branch &&
+	test_cmp expect.master actual.master &&
+	test_cmp expect.branch actual.branch
+'
+
+test_expect_success 'background updates to remote can be mitigated with "push.useForceIfIncludes"' '
+	setup_src_dup_dst &&
+	test_when_finished "rm -fr dst src dup" &&
+	git ls-remote dst refs/heads/master >expect.master &&
+	(
+		cd src &&
+		git switch branch &&
+		test_commit I &&
+		git switch master &&
+		test_commit J &&
+		git fetch --all &&
+		git config --local push.useForceIfIncludes true &&
+		test_must_fail git push --force-with-lease=master origin master
+	) &&
+	git ls-remote dst refs/heads/master >actual.master &&
+	test_cmp expect.master actual.master
+'
+
+test_expect_success '"--force-if-includes" should be disabled for --force-with-lease="<refname>:<expect>"' '
+	setup_src_dup_dst &&
+	test_when_finished "rm -fr dst src dup" &&
+	git ls-remote dst refs/heads/master >expect.master &&
+	(
+		cd src &&
+		git switch branch &&
+		test_commit I &&
+		git switch master &&
+		test_commit J &&
+		remote_head="$(git rev-parse refs/remotes/origin/master)" &&
+		git fetch --all &&
+		test_must_fail git push --force-if-includes --force-with-lease="master:$remote_head" 2>err &&
+		grep "stale info" err
+	) &&
+	git ls-remote dst refs/heads/master >actual.master &&
+	test_cmp expect.master actual.master
+'
+
+test_expect_success '"--force-if-includes" should allow forced update after a rebase ("pull --rebase")' '
+	setup_src_dup_dst &&
+	test_when_finished "rm -fr dst src dup" &&
+	(
+		cd src &&
+		git switch branch &&
+		test_commit I &&
+		git switch master &&
+		test_commit J &&
+		git pull --rebase origin master &&
+		git push --force-if-includes --force-with-lease="master"
+	)
+'
+
+test_expect_success '"--force-if-includes" should allow forced update after a rebase ("pull --rebase", local rebase)' '
+	setup_src_dup_dst &&
+	test_when_finished "rm -fr dst src dup" &&
+	(
+		cd src &&
+		git switch branch &&
+		test_commit I &&
+		git switch master &&
+		test_commit J &&
+		git pull --rebase origin master &&
+		git rebase --onto HEAD~4 HEAD~1 &&
+		git push --force-if-includes --force-with-lease="master"
+	)
+'
+
+test_expect_success '"--force-if-includes" should allow deletes' '
+	setup_src_dup_dst &&
+	test_when_finished "rm -fr dst src dup" &&
+	(
+		cd src &&
+		git switch branch &&
+		git pull --rebase origin branch &&
+		git push --force-if-includes --force-with-lease="branch" origin :branch
+	)
+'
+
 test_done
diff --git a/t/t5570-git-daemon.sh b/t/t5570-git-daemon.sh
index 34487bb..8f69a78 100755
--- a/t/t5570-git-daemon.sh
+++ b/t/t5570-git-daemon.sh
@@ -147,18 +147,18 @@
 }
 
 msg="access denied or repository not exported"
-test_expect_success 'clone non-existent' "test_remote_error    '$msg' clone nowhere.git    "
+test_expect_success 'clone non-existent' "test_remote_error    '$msg' clone nowhere.git"
 test_expect_success 'push disabled'      "test_remote_error    '$msg' push  repo.git master"
-test_expect_success 'read access denied' "test_remote_error -x '$msg' fetch repo.git       "
-test_expect_success 'not exported'       "test_remote_error -n '$msg' fetch repo.git       "
+test_expect_success 'read access denied' "test_remote_error -x '$msg' fetch repo.git"
+test_expect_success 'not exported'       "test_remote_error -n '$msg' fetch repo.git"
 
 stop_git_daemon
 start_git_daemon --informative-errors
 
-test_expect_success 'clone non-existent' "test_remote_error    'no such repository'      clone nowhere.git    "
+test_expect_success 'clone non-existent' "test_remote_error    'no such repository'      clone nowhere.git"
 test_expect_success 'push disabled'      "test_remote_error    'service not enabled'     push  repo.git master"
-test_expect_success 'read access denied' "test_remote_error -x 'no such repository'      fetch repo.git       "
-test_expect_success 'not exported'       "test_remote_error -n 'repository not exported' fetch repo.git       "
+test_expect_success 'read access denied' "test_remote_error -x 'no such repository'      fetch repo.git"
+test_expect_success 'not exported'       "test_remote_error -n 'repository not exported' fetch repo.git"
 
 stop_git_daemon
 start_git_daemon --interpolated-path="$GIT_DAEMON_DOCUMENT_ROOT_PATH/%H%D"
diff --git a/t/t5572-pull-submodule.sh b/t/t5572-pull-submodule.sh
index 1d75e3b..37fd06b 100755
--- a/t/t5572-pull-submodule.sh
+++ b/t/t5572-pull-submodule.sh
@@ -101,7 +101,12 @@
 	test_path_is_file super/sub/merge_strategy_4.t
 '
 
-test_expect_success 'recursive rebasing pull' '
+test_expect_success 'pull --rebase --recurse-submodules (remote superproject submodule changes, local submodule changes)' '
+	# This tests the following scenario :
+	# - local submodule has new commits
+	# - local superproject does not have new commits
+	# - upstream superproject has new commits that change the submodule pointer
+
 	# change upstream
 	test_commit -C child rebase_strategy &&
 	git -C parent submodule update --remote &&
@@ -116,7 +121,10 @@
 	test_path_is_file super/sub/local_stuff.t
 '
 
-test_expect_success 'pull rebase recursing fails with conflicts' '
+test_expect_success 'pull --rebase --recurse-submodules fails if both sides record submodule changes' '
+	# This tests the following scenario :
+	# - local superproject has new commits that change the submodule pointer
+	# - upstream superproject has new commits that change the submodule pointer
 
 	# local changes in submodule recorded in superproject:
 	test_commit -C super/sub local_stuff_2 &&
@@ -136,6 +144,50 @@
 	test_i18ngrep "locally recorded submodule modifications" err
 '
 
+test_expect_success 'pull --rebase --recurse-submodules (no submodule changes, no fork-point)' '
+	# This tests the following scenario :
+	# - local submodule does not have new commits
+	# - local superproject has new commits that *do not* change the submodule pointer
+	# - upstream superproject has new commits that *do not* change the submodule pointer
+	# - local superproject branch has no fork-point with its remote-tracking counter-part
+
+	# create upstream superproject
+	test_create_repo submodule &&
+	test_commit -C submodule first_in_sub &&
+
+	test_create_repo superprojet &&
+	test_commit -C superprojet first_in_super &&
+	git -C superprojet submodule add ../submodule &&
+	git -C superprojet commit -m "add submodule" &&
+	test_commit -C superprojet third_in_super &&
+
+	# clone superproject
+	git clone --recurse-submodules superprojet superclone &&
+
+	# add commits upstream
+	test_commit -C superprojet fourth_in_super &&
+
+	# create topic branch in clone, not based on any remote-tracking branch
+	git -C superclone checkout -b feat HEAD~1 &&
+	test_commit -C superclone first_on_feat &&
+	git -C superclone pull --rebase --recurse-submodules origin master
+'
+
+# NOTE:
+#
+# This test is particular because there is only a single commit in the upstream superproject
+# 'parent' (which adds the submodule 'a-submodule'). The clone of the superproject
+# ('child') hard-resets its branch to a new root commit with the same tree as the one
+# from the upstream superproject, so that its branch has no merge-base with its
+# remote-tracking counterpart, and then calls 'git pull --recurse-submodules --rebase'.
+# The result is that the local branch is reset to the remote-tracking branch (as it was
+# originally before the hard-reset).
+
+# The only commit in the range generated by 'submodule.c::submodule_touches_in_range' and
+# passed to 'submodule.c::collect_changed_submodules' is the new (regenerated) initial commit,
+# which adds the submodule.
+# However, 'submodule_touches_in_range' does not error (even though this commit adds the submodule)
+# because 'combine-diff.c::diff_tree_combined' returns early, as the initial commit has no parents.
 test_expect_success 'branch has no merge base with remote-tracking counterpart' '
 	rm -rf parent child &&
 
diff --git a/t/t5606-clone-options.sh b/t/t5606-clone-options.sh
index e69427f..7f082fb 100755
--- a/t/t5606-clone-options.sh
+++ b/t/t5606-clone-options.sh
@@ -15,7 +15,73 @@
 test_expect_success 'clone -o' '
 
 	git clone -o foo parent clone-o &&
-	(cd clone-o && git rev-parse --verify refs/remotes/foo/master)
+	git -C clone-o rev-parse --verify refs/remotes/foo/master
+
+'
+
+test_expect_success 'rejects invalid -o/--origin' '
+
+	test_must_fail git clone -o "bad...name" parent clone-bad-name 2>err &&
+	test_i18ngrep "'\''bad...name'\'' is not a valid remote name" err
+
+'
+
+test_expect_success 'disallows --bare with --origin' '
+
+	test_must_fail git clone -o foo --bare parent clone-bare-o 2>err &&
+	test_debug "cat err" &&
+	test_i18ngrep -e "--bare and --origin foo options are incompatible" err
+
+'
+
+test_expect_success 'disallows --bare with --separate-git-dir' '
+
+	test_must_fail git clone --bare --separate-git-dir dot-git-destiation parent clone-bare-sgd 2>err &&
+	test_debug "cat err" &&
+	test_i18ngrep -e "--bare and --separate-git-dir are incompatible" err
+
+'
+
+test_expect_success 'uses "origin" for default remote name' '
+
+	git clone parent clone-default-origin &&
+	git -C clone-default-origin rev-parse --verify refs/remotes/origin/master
+
+'
+
+test_expect_success 'prefers --template config over normal config' '
+
+	template="$TRASH_DIRECTORY/template-with-config" &&
+	mkdir "$template" &&
+	git config --file "$template/config" foo.bar from_template &&
+	test_config_global foo.bar from_global &&
+	git clone "--template=$template" parent clone-template-config &&
+	test "$(git -C clone-template-config config --local foo.bar)" = "from_template"
+
+'
+
+test_expect_success 'prefers -c config over --template config' '
+
+	template="$TRASH_DIRECTORY/template-with-ignored-config" &&
+	mkdir "$template" &&
+	git config --file "$template/config" foo.bar from_template &&
+	git clone "--template=$template" -c foo.bar=inline parent clone-template-inline-config &&
+	test "$(git -C clone-template-inline-config config --local foo.bar)" = "inline"
+
+'
+
+test_expect_success 'prefers config "clone.defaultRemoteName" over default' '
+
+	test_config_global clone.defaultRemoteName from_config &&
+	git clone parent clone-config-origin &&
+	git -C clone-config-origin rev-parse --verify refs/remotes/from_config/master
+
+'
+
+test_expect_success 'prefers --origin over -c config' '
+
+	git clone -c clone.defaultRemoteName=inline --origin from_option parent clone-o-and-inline-config &&
+	git -C clone-o-and-inline-config rev-parse --verify refs/remotes/from_option/master
 
 '
 
@@ -37,6 +103,7 @@
 
 test_expect_success 'chooses correct default initial branch name' '
 	git init --bare empty &&
+	GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME= \
 	git -c init.defaultBranch=up clone empty whats-up &&
 	test refs/heads/up = $(git -C whats-up symbolic-ref HEAD) &&
 	test refs/heads/up = $(git -C whats-up config branch.up.merge)
@@ -51,9 +118,11 @@
 
 	git -c init.defaultBranch=none init --bare no-head &&
 	git -C initial-branch push ../no-head guess abc &&
+	GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME= \
 	git clone no-head is-it2 &&
 	test_must_fail git -C is-it2 symbolic-ref refs/remotes/origin/HEAD &&
 	git -C no-head update-ref --no-deref HEAD refs/heads/guess &&
+	GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME= \
 	git -c init.defaultBranch=guess clone no-head is-it3 &&
 	test refs/remotes/origin/guess = \
 		$(git -C is-it3 symbolic-ref refs/remotes/origin/HEAD)
diff --git a/t/t5703-upload-pack-ref-in-want.sh b/t/t5703-upload-pack-ref-in-want.sh
index d9ecf0f..b46940b 100755
--- a/t/t5703-upload-pack-ref-in-want.sh
+++ b/t/t5703-upload-pack-ref-in-want.sh
@@ -383,14 +383,14 @@
 	test_cmp expected actual
 '
 
-test_expect_success 'server loses a ref - ref in want' '
+test_expect_success PREPARE_FOR_MAIN_BRANCH 'server loses a ref - ref in want' '
 	git -C "$REPO" config uploadpack.allowRefInWant true &&
 	rm -rf local &&
 	cp -r "$LOCAL_PRISTINE" local &&
-	echo "s/master/raster/" >"$HTTPD_ROOT_PATH/one-time-perl" &&
+	echo "s/main/rain/" >"$HTTPD_ROOT_PATH/one-time-perl" &&
 	test_must_fail git -C local fetch 2>err &&
 
-	test_i18ngrep "fatal: remote error: unknown ref refs/heads/raster" err
+	test_i18ngrep "fatal: remote error: unknown ref refs/heads/rain" err
 '
 
 # DO NOT add non-httpd-specific tests here, because the last part of this
diff --git a/t/t6006-rev-list-format.sh b/t/t6006-rev-list-format.sh
index bc95da8..99a1eaf 100755
--- a/t/t6006-rev-list-format.sh
+++ b/t/t6006-rev-list-format.sh
@@ -339,7 +339,7 @@
 .. (hinzugef${added_utf8_part_iso88591}gt) foo
 EOF
 
-test_expect_success 'prepare expected messages (for test %b)' '
+test_expect_success 'setup expected messages (for test %b)' '
 	cat <<-EOF >expected.utf-8 &&
 	commit $head3
 	This commit message is much longer than the others,
diff --git a/t/t6012-rev-list-simplify.sh b/t/t6012-rev-list-simplify.sh
index 7fc10f8..fd202fc 100755
--- a/t/t6012-rev-list-simplify.sh
+++ b/t/t6012-rev-list-simplify.sh
@@ -168,7 +168,7 @@
 #
 # This example is explained in Documentation/rev-list-options.txt
 
-test_expect_success 'rebuild repo' '
+test_expect_success 'setup rebuild repo' '
 	rm -rf .git * &&
 	git init &&
 	git switch -c topic &&
diff --git a/t/t6200-fmt-merge-msg.sh b/t/t6200-fmt-merge-msg.sh
index 7d54974..f3e66ea 100755
--- a/t/t6200-fmt-merge-msg.sh
+++ b/t/t6200-fmt-merge-msg.sh
@@ -556,7 +556,7 @@
 	head -n1 full.2 >actual &&
 	grep -e "Merge branch .side. into master$" actual &&
 
-	git -c merge.suppressDest="ma??er" fmt-merge-msg <.git/FETCH_HEAD >full.3 &&
+	git -c merge.suppressDest="ma?*[rn]" fmt-merge-msg <.git/FETCH_HEAD >full.3 &&
 	head -n1 full.3 >actual &&
 	grep -e "Merge branch .side." actual &&
 	! grep -e " into master$" actual
diff --git a/t/t6302-for-each-ref-filter.sh b/t/t6302-for-each-ref-filter.sh
index 781e470..0a21669 100755
--- a/t/t6302-for-each-ref-filter.sh
+++ b/t/t6302-for-each-ref-filter.sh
@@ -113,9 +113,9 @@
 	test_must_fail git for-each-ref --format="%(color)%(refname)"
 '
 
-test_expect_success 'left alignment is default' '
+test_expect_success PREPARE_FOR_MAIN_BRANCH 'left alignment is default' '
 	cat >expect <<-\EOF &&
-	refname is refs/heads/master  |refs/heads/master
+	refname is refs/heads/main    |refs/heads/main
 	refname is refs/heads/side    |refs/heads/side
 	refname is refs/odd/spot      |refs/odd/spot
 	refname is refs/tags/annotated-tag|refs/tags/annotated-tag
@@ -131,9 +131,9 @@
 	test_cmp expect actual
 '
 
-test_expect_success 'middle alignment' '
+test_expect_success PREPARE_FOR_MAIN_BRANCH 'middle alignment' '
 	cat >expect <<-\EOF &&
-	| refname is refs/heads/master |refs/heads/master
+	|  refname is refs/heads/main  |refs/heads/main
 	|  refname is refs/heads/side  |refs/heads/side
 	|   refname is refs/odd/spot   |refs/odd/spot
 	|refname is refs/tags/annotated-tag|refs/tags/annotated-tag
@@ -149,9 +149,9 @@
 	test_cmp expect actual
 '
 
-test_expect_success 'right alignment' '
+test_expect_success PREPARE_FOR_MAIN_BRANCH 'right alignment' '
 	cat >expect <<-\EOF &&
-	|  refname is refs/heads/master|refs/heads/master
+	|    refname is refs/heads/main|refs/heads/main
 	|    refname is refs/heads/side|refs/heads/side
 	|      refname is refs/odd/spot|refs/odd/spot
 	|refname is refs/tags/annotated-tag|refs/tags/annotated-tag
@@ -168,7 +168,7 @@
 '
 
 cat >expect <<-\EOF
-|       refname is refs/heads/master       |refs/heads/master
+|        refname is refs/heads/main        |refs/heads/main
 |        refname is refs/heads/side        |refs/heads/side
 |         refname is refs/odd/spot         |refs/odd/spot
 |    refname is refs/tags/annotated-tag    |refs/tags/annotated-tag
@@ -184,7 +184,7 @@
 test_align_permutations() {
 	while read -r option
 	do
-		test_expect_success "align:$option" '
+		test_expect_success PREPARE_FOR_MAIN_BRANCH "align:$option" '
 			git for-each-ref --format="|%(align:$option)refname is %(refname)%(end)|%(refname)" >actual &&
 			test_cmp expect actual
 		'
@@ -213,9 +213,9 @@
 
 # Individual atoms inside %(align:...) and %(end) must not be quoted.
 
-test_expect_success 'alignment with format quote' "
+test_expect_success PREPARE_FOR_MAIN_BRANCH 'alignment with format quote' "
 	cat >expect <<-\EOF &&
-	|'      '\''master| A U Thor'\''      '|
+	|'       '\''main| A U Thor'\''       '|
 	|'       '\''side| A U Thor'\''       '|
 	|'     '\''odd/spot| A U Thor'\''     '|
 	|'      '\''annotated-tag| '\''       '|
@@ -231,9 +231,9 @@
 	test_cmp expect actual
 "
 
-test_expect_success 'nested alignment with quote formatting' "
+test_expect_success PREPARE_FOR_MAIN_BRANCH 'nested alignment with quote formatting' "
 	cat >expect <<-\EOF &&
-	|'         master               '|
+	|'           main               '|
 	|'           side               '|
 	|'       odd/spot               '|
 	|'  annotated-tag               '|
diff --git a/t/t6400-merge-df.sh b/t/t6400-merge-df.sh
index f1b8461..9da0838 100755
--- a/t/t6400-merge-df.sh
+++ b/t/t6400-merge-df.sh
@@ -81,7 +81,12 @@
 
 	test 5 -eq $(git ls-files -s | wc -l) &&
 	test 4 -eq $(git ls-files -u | wc -l) &&
-	test 1 -eq $(git ls-files -o | wc -l) &&
+	if test "$GIT_TEST_MERGE_ALGORITHM" = ort
+	then
+		test 0 -eq $(git ls-files -o | wc -l)
+	else
+		test 1 -eq $(git ls-files -o | wc -l)
+	fi &&
 
 	test_path_is_file letters/file &&
 	test_path_is_file letters.txt &&
@@ -97,7 +102,12 @@
 
 	test 5 -eq $(git ls-files -s | wc -l) &&
 	test 4 -eq $(git ls-files -u | wc -l) &&
-	test 1 -eq $(git ls-files -o | wc -l) &&
+	if test "$GIT_TEST_MERGE_ALGORITHM" = ort
+	then
+		test 0 -eq $(git ls-files -o | wc -l)
+	else
+		test 1 -eq $(git ls-files -o | wc -l)
+	fi &&
 
 	test_path_is_file letters/file &&
 	test_path_is_file letters.txt &&
diff --git a/t/t6402-merge-rename.sh b/t/t6402-merge-rename.sh
index bbbba3d..3f64f62 100755
--- a/t/t6402-merge-rename.sh
+++ b/t/t6402-merge-rename.sh
@@ -320,7 +320,12 @@
 
 	test_i18ngrep "CONFLICT (modify/delete): dir/file-in-the-way" output &&
 	test_i18ngrep "Auto-merging dir" output &&
-	test_i18ngrep "Adding as dir~HEAD instead" output &&
+	if test "$GIT_TEST_MERGE_ALGORITHM" = ort
+	then
+		test_i18ngrep "moving it to dir~HEAD instead" output
+	else
+		test_i18ngrep "Adding as dir~HEAD instead" output
+	fi &&
 
 	test 3 -eq "$(git ls-files -u | wc -l)" &&
 	test 2 -eq "$(git ls-files -u dir/file-in-the-way | wc -l)" &&
@@ -342,7 +347,12 @@
 	! grep "error: refusing to lose untracked file at" errors &&
 	test_i18ngrep "CONFLICT (modify/delete): dir/file-in-the-way" output &&
 	test_i18ngrep "Auto-merging dir" output &&
-	test_i18ngrep "Adding as dir~renamed-file-has-no-conflicts instead" output &&
+	if test "$GIT_TEST_MERGE_ALGORITHM" = ort
+	then
+		test_i18ngrep "moving it to dir~renamed-file-has-no-conflicts instead" output
+	else
+		test_i18ngrep "Adding as dir~renamed-file-has-no-conflicts instead" output
+	fi &&
 
 	test 3 -eq "$(git ls-files -u | wc -l)" &&
 	test 2 -eq "$(git ls-files -u dir/file-in-the-way | wc -l)" &&
@@ -397,7 +407,12 @@
 	test_must_fail git merge --strategy=recursive dir-in-way &&
 
 	test 5 -eq "$(git ls-files -u | wc -l)" &&
-	test 3 -eq "$(git ls-files -u dir | grep -v file-in-the-way | wc -l)" &&
+	if test "$GIT_TEST_MERGE_ALGORITHM" = ort
+	then
+		test 3 -eq "$(git ls-files -u dir~HEAD | wc -l)"
+	else
+		test 3 -eq "$(git ls-files -u dir | grep -v file-in-the-way | wc -l)"
+	fi &&
 	test 2 -eq "$(git ls-files -u dir/file-in-the-way | wc -l)" &&
 
 	test_must_fail git diff --quiet &&
@@ -415,7 +430,12 @@
 	test_must_fail git merge --strategy=recursive renamed-file-has-conflicts &&
 
 	test 5 -eq "$(git ls-files -u | wc -l)" &&
-	test 3 -eq "$(git ls-files -u dir | grep -v file-in-the-way | wc -l)" &&
+	if test "$GIT_TEST_MERGE_ALGORITHM" = ort
+	then
+		test 3 -eq "$(git ls-files -u dir~renamed-file-has-conflicts | wc -l)"
+	else
+		test 3 -eq "$(git ls-files -u dir | grep -v file-in-the-way | wc -l)"
+	fi &&
 	test 2 -eq "$(git ls-files -u dir/file-in-the-way | wc -l)" &&
 
 	test_must_fail git diff --quiet &&
@@ -471,7 +491,12 @@
 	git checkout -q rename-dest^0 &&
 	test_must_fail git merge --strategy=recursive source-conflict &&
 
-	test 1 -eq "$(git ls-files -u | wc -l)" &&
+	if test "$GIT_TEST_MERGE_ALGORITHM" = ort
+	then
+		test 2 -eq "$(git ls-files -u | wc -l)"
+	else
+		test 1 -eq "$(git ls-files -u | wc -l)"
+	fi &&
 
 	test_must_fail git diff --quiet &&
 
@@ -505,34 +530,63 @@
 	git commit -m "Rename one/file -> two"
 '
 
-test_expect_success 'pair rename to parent of other (D/F conflicts) w/ untracked dir' '
-	git checkout -q rename-one^0 &&
-	mkdir one &&
-	test_must_fail git merge --strategy=recursive rename-two &&
+if test "$GIT_TEST_MERGE_ALGORITHM" = ort
+then
+	test_expect_success 'pair rename to parent of other (D/F conflicts) w/ untracked dir' '
+		git checkout -q rename-one^0 &&
+		mkdir one &&
+		test_must_fail git merge --strategy=recursive rename-two &&
 
-	test 2 -eq "$(git ls-files -u | wc -l)" &&
-	test 1 -eq "$(git ls-files -u one | wc -l)" &&
-	test 1 -eq "$(git ls-files -u two | wc -l)" &&
+		test 4 -eq "$(git ls-files -u | wc -l)" &&
+		test 2 -eq "$(git ls-files -u one | wc -l)" &&
+		test 2 -eq "$(git ls-files -u two | wc -l)" &&
 
-	test_must_fail git diff --quiet &&
+		test_must_fail git diff --quiet &&
 
-	test 4 -eq $(find . | grep -v .git | wc -l) &&
+		test 3 -eq $(find . | grep -v .git | wc -l) &&
 
-	test_path_is_dir one &&
-	test_path_is_file one~rename-two &&
-	test_path_is_file two &&
-	test "other" = $(cat one~rename-two) &&
-	test "stuff" = $(cat two)
-'
+		test_path_is_file one &&
+		test_path_is_file two &&
+		test "other" = $(cat one) &&
+		test "stuff" = $(cat two)
+	'
+else
+	test_expect_success 'pair rename to parent of other (D/F conflicts) w/ untracked dir' '
+		git checkout -q rename-one^0 &&
+		mkdir one &&
+		test_must_fail git merge --strategy=recursive rename-two &&
+
+		test 2 -eq "$(git ls-files -u | wc -l)" &&
+		test 1 -eq "$(git ls-files -u one | wc -l)" &&
+		test 1 -eq "$(git ls-files -u two | wc -l)" &&
+
+		test_must_fail git diff --quiet &&
+
+		test 4 -eq $(find . | grep -v .git | wc -l) &&
+
+		test_path_is_dir one &&
+		test_path_is_file one~rename-two &&
+		test_path_is_file two &&
+		test "other" = $(cat one~rename-two) &&
+		test "stuff" = $(cat two)
+	'
+fi
 
 test_expect_success 'pair rename to parent of other (D/F conflicts) w/ clean start' '
 	git reset --hard &&
 	git clean -fdqx &&
 	test_must_fail git merge --strategy=recursive rename-two &&
 
-	test 2 -eq "$(git ls-files -u | wc -l)" &&
-	test 1 -eq "$(git ls-files -u one | wc -l)" &&
-	test 1 -eq "$(git ls-files -u two | wc -l)" &&
+	if test "$GIT_TEST_MERGE_ALGORITHM" = ort
+	then
+		test 4 -eq "$(git ls-files -u | wc -l)" &&
+		test 2 -eq "$(git ls-files -u one | wc -l)" &&
+		test 2 -eq "$(git ls-files -u two | wc -l)"
+	else
+		test 2 -eq "$(git ls-files -u | wc -l)" &&
+		test 1 -eq "$(git ls-files -u one | wc -l)" &&
+		test 1 -eq "$(git ls-files -u two | wc -l)"
+	fi &&
 
 	test_must_fail git diff --quiet &&
 
@@ -572,12 +626,22 @@
 	git checkout -q first-rename^0 &&
 	test_must_fail git merge --strategy=recursive second-rename &&
 
-	test 5 -eq "$(git ls-files -s | wc -l)" &&
-	test 3 -eq "$(git ls-files -u | wc -l)" &&
-	test 1 -eq "$(git ls-files -u one | wc -l)" &&
-	test 1 -eq "$(git ls-files -u two | wc -l)" &&
-	test 1 -eq "$(git ls-files -u original | wc -l)" &&
-	test 2 -eq "$(git ls-files -o | wc -l)" &&
+	if test "$GIT_TEST_MERGE_ALGORITHM" = ort
+	then
+		test 5 -eq "$(git ls-files -s | wc -l)" &&
+		test 3 -eq "$(git ls-files -u | wc -l)" &&
+		test 1 -eq "$(git ls-files -u one~HEAD | wc -l)" &&
+		test 1 -eq "$(git ls-files -u two~second-rename | wc -l)" &&
+		test 1 -eq "$(git ls-files -u original | wc -l)" &&
+		test 0 -eq "$(git ls-files -o | wc -l)"
+	else
+		test 5 -eq "$(git ls-files -s | wc -l)" &&
+		test 3 -eq "$(git ls-files -u | wc -l)" &&
+		test 1 -eq "$(git ls-files -u one | wc -l)" &&
+		test 1 -eq "$(git ls-files -u two | wc -l)" &&
+		test 1 -eq "$(git ls-files -u original | wc -l)" &&
+		test 2 -eq "$(git ls-files -o | wc -l)"
+	fi &&
 
 	test_path_is_file one/file &&
 	test_path_is_file two/file &&
diff --git a/t/t6404-recursive-merge.sh b/t/t6404-recursive-merge.sh
index 332cfc5..b1c3d4d 100755
--- a/t/t6404-recursive-merge.sh
+++ b/t/t6404-recursive-merge.sh
@@ -118,12 +118,22 @@
 	test_tick &&
 	git commit -m rename &&
 	test_must_fail git merge delete &&
-	test 1 = $(git ls-files --unmerged | wc -l) &&
+	if test "$GIT_TEST_MERGE_ALGORITHM" = ort
+	then
+		test 2 = $(git ls-files --unmerged | wc -l)
+	else
+		test 1 = $(git ls-files --unmerged | wc -l)
+	fi &&
 	git rev-parse --verify :2:a2 &&
 	test_must_fail git rev-parse --verify :3:a2 &&
 	git checkout -f delete &&
 	test_must_fail git merge rename &&
-	test 1 = $(git ls-files --unmerged | wc -l) &&
+	if test "$GIT_TEST_MERGE_ALGORITHM" = ort
+	then
+		test 2 = $(git ls-files --unmerged | wc -l)
+	else
+		test 1 = $(git ls-files --unmerged | wc -l)
+	fi &&
 	test_must_fail git rev-parse --verify :2:a2 &&
 	git rev-parse --verify :3:a2
 '
diff --git a/t/t6416-recursive-corner-cases.sh b/t/t6416-recursive-corner-cases.sh
index fd98989..887c219 100755
--- a/t/t6416-recursive-corner-cases.sh
+++ b/t/t6416-recursive-corner-cases.sh
@@ -3,6 +3,7 @@
 test_description='recursive merge corner cases involving criss-cross merges'
 
 . ./test-lib.sh
+. "$TEST_DIRECTORY"/lib-merge.sh
 
 #
 #  L1  L2
@@ -537,9 +538,15 @@
 
 		git checkout B^0 &&
 		test_must_fail git merge C^0 &&
-		git clean -fd &&
-		git rm -rf a/ &&
-		git rm a &&
+		if test "$GIT_TEST_MERGE_ALGORITHM" = ort
+		then
+			git rm -rf a/ &&
+			git rm a~HEAD
+		else
+			git clean -fd &&
+			git rm -rf a/ &&
+			git rm a
+		fi &&
 		git cat-file -p B:a >a2 &&
 		git add a2 &&
 		git commit -m D2 &&
@@ -558,7 +565,12 @@
 
 		git checkout C^0 &&
 		test_must_fail git merge B^0 &&
-		git clean -fd &&
+		if test "$GIT_TEST_MERGE_ALGORITHM" = ort
+		then
+			git rm a~B^0
+		else
+			git clean -fd
+		fi &&
 		git rm -rf a/ &&
 		test_write_lines 1 2 3 4 5 6 7 8 >a &&
 		git add a &&
@@ -567,9 +579,15 @@
 
 		git checkout C^0 &&
 		test_must_fail git merge B^0 &&
-		git clean -fd &&
-		git rm -rf a/ &&
-		git rm a &&
+		if test "$GIT_TEST_MERGE_ALGORITHM" = ort
+		then
+			git rm -rf a/ &&
+			git rm a~B^0
+		else
+			git clean -fd &&
+			git rm -rf a/ &&
+			git rm a
+		fi &&
 		test_write_lines 1 2 3 4 5 6 7 8 >a2 &&
 		git add a2 &&
 		git commit -m E4 &&
@@ -587,18 +605,34 @@
 
 		test_must_fail git merge -s recursive E1^0 &&
 
-		git ls-files -s >out &&
-		test_line_count = 2 out &&
-		git ls-files -u >out &&
-		test_line_count = 1 out &&
-		git ls-files -o >out &&
-		test_line_count = 1 out &&
+		if test "$GIT_TEST_MERGE_ALGORITHM" = ort
+		then
+			git ls-files -s >out &&
+			test_line_count = 3 out &&
+			git ls-files -u >out &&
+			test_line_count = 2 out &&
+			git ls-files -o >out &&
+			test_line_count = 1 out &&
 
-		git rev-parse >expect    \
-			A:ignore-me  B:a &&
-		git rev-parse   >actual   \
-			:0:ignore-me :2:a &&
-		test_cmp expect actual
+			git rev-parse >expect    \
+				A:ignore-me  B:a  D1:a &&
+			git rev-parse   >actual   \
+				:0:ignore-me :1:a :2:a &&
+			test_cmp expect actual
+		else
+			git ls-files -s >out &&
+			test_line_count = 2 out &&
+			git ls-files -u >out &&
+			test_line_count = 1 out &&
+			git ls-files -o >out &&
+			test_line_count = 1 out &&
+
+			git rev-parse >expect    \
+				A:ignore-me  B:a &&
+			git rev-parse   >actual   \
+				:0:ignore-me :2:a &&
+			test_cmp expect actual
+		fi
 	)
 '
 
@@ -612,18 +646,34 @@
 
 		test_must_fail git merge -s recursive D1^0 &&
 
-		git ls-files -s >out &&
-		test_line_count = 2 out &&
-		git ls-files -u >out &&
-		test_line_count = 1 out &&
-		git ls-files -o >out &&
-		test_line_count = 1 out &&
+		if test "$GIT_TEST_MERGE_ALGORITHM" = ort
+		then
+			git ls-files -s >out &&
+			test_line_count = 3 out &&
+			git ls-files -u >out &&
+			test_line_count = 2 out &&
+			git ls-files -o >out &&
+			test_line_count = 1 out &&
 
-		git rev-parse >expect    \
-			A:ignore-me  B:a &&
-		git rev-parse   >actual   \
-			:0:ignore-me :3:a &&
-		test_cmp expect actual
+			git rev-parse >expect    \
+				A:ignore-me  B:a  D1:a &&
+			git rev-parse   >actual   \
+				:0:ignore-me :1:a :3:a &&
+			test_cmp expect actual
+		else
+			git ls-files -s >out &&
+			test_line_count = 2 out &&
+			git ls-files -u >out &&
+			test_line_count = 1 out &&
+			git ls-files -o >out &&
+			test_line_count = 1 out &&
+
+			git rev-parse >expect    \
+				A:ignore-me  B:a &&
+			git rev-parse   >actual   \
+				:0:ignore-me :3:a &&
+			test_cmp expect actual
+		fi
 	)
 '
 
@@ -637,17 +687,32 @@
 
 		test_must_fail git merge -s recursive E2^0 &&
 
-		git ls-files -s >out &&
-		test_line_count = 4 out &&
-		git ls-files -u >out &&
-		test_line_count = 3 out &&
-		git ls-files -o >out &&
-		test_line_count = 2 out &&
+		if test "$GIT_TEST_MERGE_ALGORITHM" = ort
+		then
+			git ls-files -s >out &&
+			test_line_count = 5 out &&
+			git ls-files -u >out &&
+			test_line_count = 4 out &&
+			git ls-files -o >out &&
+			test_line_count = 1 out &&
 
-		git rev-parse >expect    \
-			B:a   E2:a/file  C:a/file   A:ignore-me &&
-		git rev-parse   >actual   \
-			:2:a  :3:a/file  :1:a/file  :0:ignore-me &&
+			git rev-parse >expect    \
+				B:a       D1:a      E2:a/file  C:a/file   A:ignore-me &&
+			git rev-parse   >actual   \
+				:1:a~HEAD :2:a~HEAD :3:a/file  :1:a/file  :0:ignore-me
+		else
+			git ls-files -s >out &&
+			test_line_count = 4 out &&
+			git ls-files -u >out &&
+			test_line_count = 3 out &&
+			git ls-files -o >out &&
+			test_line_count = 2 out &&
+
+			git rev-parse >expect    \
+				B:a    E2:a/file  C:a/file   A:ignore-me &&
+			git rev-parse   >actual   \
+				:2:a   :3:a/file  :1:a/file  :0:ignore-me
+		fi &&
 		test_cmp expect actual &&
 
 		test_path_is_file a~HEAD
@@ -664,17 +729,32 @@
 
 		test_must_fail git merge -s recursive D1^0 &&
 
-		git ls-files -s >out &&
-		test_line_count = 4 out &&
-		git ls-files -u >out &&
-		test_line_count = 3 out &&
-		git ls-files -o >out &&
-		test_line_count = 2 out &&
+		if test "$GIT_TEST_MERGE_ALGORITHM" = ort
+		then
+			git ls-files -s >out &&
+			test_line_count = 5 out &&
+			git ls-files -u >out &&
+			test_line_count = 4 out &&
+			git ls-files -o >out &&
+			test_line_count = 1 out &&
 
-		git rev-parse >expect    \
-			B:a   E2:a/file  C:a/file   A:ignore-me &&
-		git rev-parse   >actual   \
-			:3:a  :2:a/file  :1:a/file  :0:ignore-me &&
+			git rev-parse >expect    \
+				B:a       D1:a      E2:a/file  C:a/file   A:ignore-me &&
+			git rev-parse   >actual   \
+				:1:a~D1^0 :3:a~D1^0 :2:a/file  :1:a/file  :0:ignore-me
+		else
+			git ls-files -s >out &&
+			test_line_count = 4 out &&
+			git ls-files -u >out &&
+			test_line_count = 3 out &&
+			git ls-files -o >out &&
+			test_line_count = 2 out &&
+
+			git rev-parse >expect    \
+				B:a   E2:a/file  C:a/file   A:ignore-me &&
+			git rev-parse   >actual   \
+				:3:a  :2:a/file  :1:a/file  :0:ignore-me
+		fi &&
 		test_cmp expect actual &&
 
 		test_path_is_file a~D1^0
@@ -706,7 +786,7 @@
 	)
 '
 
-test_expect_success 'merge of D1 & E4 notifies user a and a2 are related' '
+test_expect_merge_algorithm failure success 'merge of D1 & E4 puts merge of a and a2 in both a and a2' '
 	test_when_finished "git -C directory-file reset --hard" &&
 	test_when_finished "git -C directory-file clean -fdqx" &&
 	(
@@ -724,7 +804,7 @@
 		test_line_count = 1 out &&
 
 		git rev-parse >expect                  \
-			A:ignore-me  B:a   D1:a  E4:a2 &&
+			A:ignore-me  B:a   E4:a2  E4:a2 &&
 		git rev-parse   >actual                \
 			:0:ignore-me :1:a~Temporary\ merge\ branch\ 2  :2:a  :3:a2 &&
 		test_cmp expect actual
@@ -1069,7 +1149,7 @@
 	)
 '
 
-test_expect_failure 'check symlink modify/modify' '
+test_expect_merge_algorithm failure success 'check symlink modify/modify' '
 	(
 		cd symlink-modify-modify &&
 
@@ -1135,7 +1215,7 @@
 	)
 '
 
-test_expect_failure 'check symlink add/add' '
+test_expect_merge_algorithm failure success 'check symlink add/add' '
 	(
 		cd symlink-add-add &&
 
@@ -1223,7 +1303,7 @@
 	)
 '
 
-test_expect_failure 'check submodule modify/modify' '
+test_expect_merge_algorithm failure success 'check submodule modify/modify' '
 	(
 		cd submodule-modify-modify &&
 
@@ -1311,7 +1391,7 @@
 	)
 '
 
-test_expect_failure 'check submodule add/add' '
+test_expect_merge_algorithm failure success 'check submodule add/add' '
 	(
 		cd submodule-add-add &&
 
@@ -1386,7 +1466,7 @@
 	)
 '
 
-test_expect_failure 'check conflicting entry types (submodule vs symlink)' '
+test_expect_merge_algorithm failure success 'check conflicting entry types (submodule vs symlink)' '
 	(
 		cd submodule-symlink-add-add &&
 
diff --git a/t/t6422-merge-rename-corner-cases.sh b/t/t6422-merge-rename-corner-cases.sh
index 3375eaf..78bfaf1 100755
--- a/t/t6422-merge-rename-corner-cases.sh
+++ b/t/t6422-merge-rename-corner-cases.sh
@@ -4,6 +4,7 @@
 # t6036 has corner cases that involve both criss-cross merges and renames
 
 . ./test-lib.sh
+. "$TEST_DIRECTORY"/lib-merge.sh
 
 test_setup_rename_delete_untracked () {
 	test_create_repo rename-delete-untracked &&
@@ -312,15 +313,18 @@
 		git ls-files -u >out &&
 		test_line_count = 1 out &&
 		git ls-files -o >out &&
-		test_line_count = 2 out &&
+		if test "$GIT_TEST_MERGE_ALGORITHM" = ort
+		then
+			test_line_count = 1 out
+		else
+			test_line_count = 2 out
+		fi &&
 
 		echo 0 >expect &&
 		git cat-file -p base:file >>expect &&
 		echo 7 >>expect &&
 		test_cmp expect newfile~HEAD &&
 
-		test $(git rev-parse :2:newfile) = $(git hash-object expect) &&
-
 		test_path_is_file newfile/realfile &&
 		test_path_is_file newfile~HEAD
 	)
@@ -343,7 +347,12 @@
 		git ls-files -u >out &&
 		test_line_count = 3 out &&
 		git ls-files -o >out &&
-		test_line_count = 2 out &&
+		if test "$GIT_TEST_MERGE_ALGORITHM" = ort
+		then
+			test_line_count = 1 out
+		else
+			test_line_count = 2 out
+		fi &&
 
 		git cat-file -p left-conflict:newfile >left &&
 		git cat-file -p base:file    >base &&
@@ -355,10 +364,16 @@
 			left base right &&
 		test_cmp left newfile~HEAD &&
 
-		git rev-parse >expect                                 \
-			base:file   left-conflict:newfile  right:file &&
-		git rev-parse >actual                                 \
-			:1:newfile  :2:newfile             :3:newfile &&
+		git rev-parse >expect   \
+			base:file       left-conflict:newfile right:file &&
+		if test "$GIT_TEST_MERGE_ALGORITHM" = ort
+		then
+			git rev-parse >actual \
+				:1:newfile~HEAD :2:newfile~HEAD :3:newfile~HEAD
+		else
+			git rev-parse >actual \
+				:1:newfile      :2:newfile      :3:newfile
+		fi &&
 		test_cmp expect actual &&
 
 		test_path_is_file newfile/realfile &&
@@ -878,7 +893,7 @@
 	)
 }
 
-test_expect_failure 'rad-check: rename/add/delete conflict' '
+test_expect_merge_algorithm failure success 'rad-check: rename/add/delete conflict' '
 	test_setup_rad &&
 	(
 		cd rad &&
@@ -951,7 +966,7 @@
 	)
 }
 
-test_expect_failure 'rrdd-check: rename/rename(2to1)/delete/delete conflict' '
+test_expect_merge_algorithm failure success 'rrdd-check: rename/rename(2to1)/delete/delete conflict' '
 	test_setup_rrdd &&
 	(
 		cd rrdd &&
@@ -1040,7 +1055,7 @@
 	)
 }
 
-test_expect_failure 'mod6-check: chains of rename/rename(1to2) and rename/rename(2to1)' '
+test_expect_merge_algorithm failure success 'mod6-check: chains of rename/rename(1to2) and rename/rename(2to1)' '
 	test_setup_mod6 &&
 	(
 		cd mod6 &&
diff --git a/t/t6423-merge-rename-directories.sh b/t/t6423-merge-rename-directories.sh
index f7ecbb8..4ab133f 100755
--- a/t/t6423-merge-rename-directories.sh
+++ b/t/t6423-merge-rename-directories.sh
@@ -26,6 +26,7 @@
 #                     files that might be renamed into each other's paths.)
 
 . ./test-lib.sh
+. "$TEST_DIRECTORY"/lib-merge.sh
 
 
 ###########################################################################
@@ -301,11 +302,20 @@
 		git cat-file -p :2:x/wham >expect &&
 		git cat-file -p :3:x/wham >other &&
 		>empty &&
-		test_must_fail git merge-file \
-			-L "HEAD" \
-			-L "" \
-			-L "B^0" \
-			expect empty other &&
+		if test "$GIT_TEST_MERGE_ALGORITHM" = ort
+		then
+			test_must_fail git merge-file \
+				-L "HEAD:y/wham" \
+				-L "" \
+				-L "B^0:z/wham" \
+				expect empty other
+		else
+			test_must_fail git merge-file \
+				-L "HEAD" \
+				-L "" \
+				-L "B^0" \
+				expect empty other
+		fi &&
 		test_cmp expect x/wham
 	)
 '
@@ -1176,10 +1186,18 @@
 		git ls-files -u >out &&
 		test_line_count = 1 out &&
 		git ls-files -o >out &&
-		test_line_count = 2 out &&
+		if test "$GIT_TEST_MERGE_ALGORITHM" = ort
+		then
+			test_line_count = 1 out &&
 
-		git rev-parse >actual \
-			:0:y/b :0:y/c :0:z/d :0:y/f :2:y/d :0:y/d/e &&
+			git rev-parse >actual \
+			    :0:y/b :0:y/c :0:z/d :0:y/f :2:y/d~HEAD :0:y/d/e
+		else
+			test_line_count = 2 out &&
+
+			git rev-parse >actual \
+			    :0:y/b :0:y/c :0:z/d :0:y/f :2:y/d      :0:y/d/e
+		fi &&
 		git rev-parse >expect \
 			 O:z/b  O:z/c  B:z/d  B:z/f  A:y/d  B:y/d/e &&
 		test_cmp expect actual &&
@@ -1262,35 +1280,144 @@
 		test_must_fail git -c merge.directoryRenames=true merge -s recursive B^0 >out &&
 		test_i18ngrep "CONFLICT (rename/delete).*z/c.*y/c" out &&
 
-		git ls-files -s >out &&
-		test_line_count = 2 out &&
-		git ls-files -u >out &&
-		test_line_count = 1 out &&
-		git ls-files -o >out &&
-		test_line_count = 1 out &&
+		if test "$GIT_TEST_MERGE_ALGORITHM" = ort
+		then
+			git ls-files -s >out &&
+			test_line_count = 3 out &&
+			git ls-files -u >out &&
+			test_line_count = 2 out &&
+			git ls-files -o >out &&
+			test_line_count = 1 out &&
 
-		git rev-parse >actual \
-			:0:y/b :3:y/c &&
-		git rev-parse >expect \
-			 O:z/b  O:z/c &&
+			git rev-parse >actual \
+				:0:y/b :1:y/c :3:y/c &&
+			git rev-parse >expect \
+				 O:z/b  O:z/c  O:z/c
+		else
+			git ls-files -s >out &&
+			test_line_count = 2 out &&
+			git ls-files -u >out &&
+			test_line_count = 1 out &&
+			git ls-files -o >out &&
+			test_line_count = 1 out &&
+
+			git rev-parse >actual \
+				:0:y/b :3:y/c &&
+			git rev-parse >expect \
+				 O:z/b  O:z/c
+		fi &&
 		test_cmp expect actual
 	)
 '
 
-# Testcase 6b, Same rename done on both sides
+# Testcase 6b1, Same rename done on both sides
+#   (Related to testcase 6b2 and 8e)
+#   Commit O: z/{b,c,d,e}
+#   Commit A: y/{b,c,d}, x/e
+#   Commit B: y/{b,c,d}, z/{e,f}
+#   Expected: y/{b,c,d,f}, x/e
+#   Note: Directory rename detection says A renamed z/ -> y/ (3 paths renamed
+#         to y/ and only 1 renamed to x/), therefore the new file 'z/f' in B
+#         should be moved to 'y/f'.
+#
+#         This is a bit of an edge case where any behavior might surprise users,
+#         whether that is treating A as renaming z/ -> y/, treating A as renaming
+#         z/ -> x/, or treating A as not doing any directory rename.  However, I
+#         think this answer is the least confusing and most consistent with the
+#         rules elsewhere.
+#
+#         A note about z/ -> x/, since it may not be clear how that could come
+#         about: If we were to ignore files renamed by both sides
+#         (i.e. z/{b,c,d}), as directory rename detection did in git-2.18 thru
+#         at least git-2.28, then we would note there are no renames from z/ to
+#         y/ and one rename from z/ to x/ and thus come to the conclusion that
+#         A renamed z/ -> x/.  This seems more confusing for end users than a
+#         rename of z/ to y/, it makes directory rename detection behavior
+#         harder for them to predict.  As such, we modified the rule, changed
+#         the behavior on testcases 6b2 and 8e, and introduced this 6b1 testcase.
+
+test_setup_6b1 () {
+	test_create_repo 6b1 &&
+	(
+		cd 6b1 &&
+
+		mkdir z &&
+		echo b >z/b &&
+		echo c >z/c &&
+		echo d >z/d &&
+		echo e >z/e &&
+		git add z &&
+		test_tick &&
+		git commit -m "O" &&
+
+		git branch O &&
+		git branch A &&
+		git branch B &&
+
+		git checkout A &&
+		git mv z y &&
+		mkdir x &&
+		git mv y/e x/e &&
+		test_tick &&
+		git commit -m "A" &&
+
+		git checkout B &&
+		git mv z y &&
+		mkdir z &&
+		git mv y/e z/e &&
+		echo f >z/f &&
+		git add z/f &&
+		test_tick &&
+		git commit -m "B"
+	)
+}
+
+test_expect_merge_algorithm failure success '6b1: Same renames done on both sides, plus another rename' '
+	test_setup_6b1 &&
+	(
+		cd 6b1 &&
+
+		git checkout A^0 &&
+
+		git -c merge.directoryRenames=true merge -s recursive B^0 &&
+
+		git ls-files -s >out &&
+		test_line_count = 5 out &&
+		git ls-files -u >out &&
+		test_line_count = 0 out &&
+		git ls-files -o >out &&
+		test_line_count = 1 out &&
+
+		git rev-parse >actual \
+			HEAD:y/b HEAD:y/c HEAD:y/d HEAD:x/e HEAD:y/f &&
+		git rev-parse >expect \
+			O:z/b    O:z/c    O:z/d    O:z/e    B:z/f &&
+		test_cmp expect actual
+	)
+'
+
+# Testcase 6b2, Same rename done on both sides
 #   (Related to testcases 6c and 8e)
 #   Commit O: z/{b,c}
 #   Commit A: y/{b,c}
 #   Commit B: y/{b,c}, z/d
-#   Expected: y/{b,c}, z/d
-#   Note: If we did directory rename detection here, we'd move z/d into y/,
-#         but B did that rename and still decided to put the file into z/,
-#         so we probably shouldn't apply directory rename detection for it.
+#   Expected: y/{b,c,d}
+#   Alternate: y/{b,c}, z/d
+#   Note: Directory rename detection says A renamed z/ -> y/, therefore the new
+#         file 'z/d' in B should be moved to 'y/d'.
+#
+#         We could potentially ignore the renames of z/{b,c} on side A since
+#         those were renamed on both sides.  However, it's a bit of a corner
+#         case because what if there was also a z/e that side A moved to x/e
+#         and side B left alone?  If we used the "ignore renames done on both
+#         sides" logic, then we'd compute that A renamed z/ -> x/, and move
+#         z/d to x/d.  That seems more surprising and uglier than allowing
+#         the z/ -> y/ rename.
 
-test_setup_6b () {
-	test_create_repo 6b &&
+test_setup_6b2 () {
+	test_create_repo 6b2 &&
 	(
-		cd 6b &&
+		cd 6b2 &&
 
 		mkdir z &&
 		echo b >z/b &&
@@ -1318,10 +1445,10 @@
 	)
 }
 
-test_expect_success '6b: Same rename done on both sides' '
-	test_setup_6b &&
+test_expect_merge_algorithm failure success '6b2: Same rename done on both sides' '
+	test_setup_6b2 &&
 	(
-		cd 6b &&
+		cd 6b2 &&
 
 		git checkout A^0 &&
 
@@ -1335,7 +1462,7 @@
 		test_line_count = 1 out &&
 
 		git rev-parse >actual \
-			HEAD:y/b HEAD:y/c HEAD:z/d &&
+			HEAD:y/b HEAD:y/c HEAD:y/d &&
 		git rev-parse >expect \
 			O:z/b    O:z/c    B:z/d &&
 		test_cmp expect actual
@@ -1343,7 +1470,7 @@
 '
 
 # Testcase 6c, Rename only done on same side
-#   (Related to testcases 6b and 8e)
+#   (Related to testcases 6b1, 6b2, and 8e)
 #   Commit O: z/{b,c}
 #   Commit A: z/{b,c} (no change)
 #   Commit B: y/{b,c}, z/d
@@ -1705,11 +1832,20 @@
 		git cat-file -p :2:y/d >expect &&
 		git cat-file -p :3:y/d >other &&
 		>empty &&
-		test_must_fail git merge-file \
-			-L "HEAD" \
-			-L "" \
-			-L "B^0" \
-			expect empty other &&
+		if test "$GIT_TEST_MERGE_ALGORITHM" = ort
+		then
+			test_must_fail git merge-file \
+				-L "HEAD:y/d" \
+				-L "" \
+				-L "B^0:z/d" \
+				expect empty other
+		else
+			test_must_fail git merge-file \
+				-L "HEAD" \
+				-L "" \
+				-L "B^0" \
+				expect empty other
+		fi &&
 		test_cmp expect y/d
 	)
 '
@@ -1831,17 +1967,32 @@
 		test_must_fail git -c merge.directoryRenames=true merge -s recursive B^0 >out &&
 		test_i18ngrep "CONFLICT (rename/delete).*x/d.*y/d" out &&
 
-		git ls-files -s >out &&
-		test_line_count = 3 out &&
-		git ls-files -u >out &&
-		test_line_count = 1 out &&
-		git ls-files -o >out &&
-		test_line_count = 1 out &&
+		if test "$GIT_TEST_MERGE_ALGORITHM" = ort
+		then
+			git ls-files -s >out &&
+			test_line_count = 4 out &&
+			git ls-files -u >out &&
+			test_line_count = 2 out &&
+			git ls-files -o >out &&
+			test_line_count = 1 out &&
 
-		git rev-parse >actual \
-			:0:y/b :0:y/c :3:y/d &&
-		git rev-parse >expect \
-			 O:z/b  O:z/c  O:x/d &&
+			git rev-parse >actual \
+				:0:y/b :0:y/c :1:y/d :3:y/d &&
+			git rev-parse >expect \
+				 O:z/b  O:z/c  O:x/d  O:x/d
+		else
+			git ls-files -s >out &&
+			test_line_count = 3 out &&
+			git ls-files -u >out &&
+			test_line_count = 1 out &&
+			git ls-files -o >out &&
+			test_line_count = 1 out &&
+
+			git rev-parse >actual \
+				:0:y/b :0:y/c :3:y/d &&
+			git rev-parse >expect \
+				 O:z/b  O:z/c  O:x/d
+		fi &&
 		test_cmp expect actual
 	)
 '
@@ -1922,17 +2073,32 @@
 		test_must_fail git -c merge.directoryRenames=true merge -s recursive B^0 >out &&
 		test_i18ngrep "CONFLICT (rename/delete).*x/d.*y/d" out &&
 
-		git ls-files -s >out &&
-		test_line_count = 5 out &&
-		git ls-files -u >out &&
-		test_line_count = 1 out &&
-		git ls-files -o >out &&
-		test_line_count = 2 out &&
+		if test "$GIT_TEST_MERGE_ALGORITHM" = ort
+		then
+			git ls-files -s >out &&
+			test_line_count = 6 out &&
+			git ls-files -u >out &&
+			test_line_count = 2 out &&
+			git ls-files -o >out &&
+			test_line_count = 1 out &&
 
-		git rev-parse >actual \
-			:0:x/d/f :0:y/d/g :0:y/b :0:y/c :3:y/d &&
-		git rev-parse >expect \
-			 A:x/d/f  A:y/d/g  O:z/b  O:z/c  O:x/d &&
+			git rev-parse >actual \
+				:0:x/d/f :0:y/d/g :0:y/b :0:y/c :1:y/d~B^0 :3:y/d~B^0 &&
+			git rev-parse >expect \
+				 A:x/d/f  A:y/d/g  O:z/b  O:z/c  O:x/d      O:x/d
+		else
+			git ls-files -s >out &&
+			test_line_count = 5 out &&
+			git ls-files -u >out &&
+			test_line_count = 1 out &&
+			git ls-files -o >out &&
+			test_line_count = 2 out &&
+
+			git rev-parse >actual \
+				:0:x/d/f :0:y/d/g :0:y/b :0:y/c :3:y/d &&
+			git rev-parse >expect \
+				 A:x/d/f  A:y/d/g  O:z/b  O:z/c  O:x/d
+		fi &&
 		test_cmp expect actual &&
 
 		git hash-object y/d~B^0 >actual &&
@@ -2269,14 +2435,22 @@
 # Notes: In commit A, directory z got renamed to y.  In commit B, directory z
 #        did NOT get renamed; the directory is still present; instead it is
 #        considered to have just renamed a subset of paths in directory z
-#        elsewhere.  However, this is much like testcase 6b (where commit B
-#        moves all the original paths out of z/ but opted to keep d
-#        within z/).  This makes it hard to judge where d should end up.
+#        elsewhere.  This is much like testcase 6b2 (where commit B moves all
+#        the original paths out of z/ but opted to keep d within z/).
 #
-#        It's possible that users would get confused about this, but what
-#        should we do instead?  It's not at all clear to me whether z/d or
-#        y/d or something else is a better resolution here, and other cases
-#        start getting really tricky, so I just picked one.
+#        It was not clear in the past what should be done with this testcase;
+#        in fact, I noted that I "just picked one" previously.  However,
+#        following the new logic for testcase 6b2, we should take the rename
+#        and move z/d to y/d.
+#
+#        6b1, 6b2, and this case are definitely somewhat fuzzy in terms of
+#        whether they are optimal for end users, but (a) the default for
+#        directory rename detection is to mark these all as conflicts
+#        anyway, (b) it feels like this is less prone to higher order corner
+#        case confusion, and (c) the current algorithm requires less global
+#        knowledge (i.e. less coupling in the algorithm between renames done
+#        on both sides) which thus means users are better able to predict
+#        the behavior, and predict it without computing as many details.
 
 test_setup_8e () {
 	test_create_repo 8e &&
@@ -3040,6 +3214,7 @@
 		echo important >z/d &&
 
 		test_must_fail git -c merge.directoryRenames=true merge -s recursive B^0 >out 2>err &&
+		test_path_is_missing .git/MERGE_HEAD &&
 		test_i18ngrep "The following untracked working tree files would be overwritten by merge" err &&
 
 		git ls-files -s >out &&
@@ -3109,21 +3284,34 @@
 		echo contents >y/e &&
 
 		test_must_fail git -c merge.directoryRenames=true merge -s recursive B^0 >out 2>err &&
-		test_i18ngrep "CONFLICT (rename/delete).*Version B\^0 of y/d left in tree at y/d~B\^0" out &&
-		test_i18ngrep "Error: Refusing to lose untracked file at y/e; writing to y/e~B\^0 instead" out &&
+		if test "$GIT_TEST_MERGE_ALGORITHM" = ort
+		then
+			test_path_is_missing .git/MERGE_HEAD &&
+			test_i18ngrep "error: The following untracked working tree files would be overwritten by merge" err &&
 
-		git ls-files -s >out &&
-		test_line_count = 3 out &&
-		git ls-files -u >out &&
-		test_line_count = 2 out &&
-		git ls-files -o >out &&
-		test_line_count = 5 out &&
+			git ls-files -s >out &&
+			test_line_count = 1 out &&
+			git ls-files -u >out &&
+			test_line_count = 0 out &&
+			git ls-files -o >out &&
+			test_line_count = 5 out
+		else
+			test_i18ngrep "CONFLICT (rename/delete).*Version B\^0 of y/d left in tree at y/d~B\^0" out &&
+			test_i18ngrep "Error: Refusing to lose untracked file at y/e; writing to y/e~B\^0 instead" out &&
 
-		git rev-parse >actual \
-			:0:y/b :3:y/d :3:y/e &&
-		git rev-parse >expect \
-			O:z/b  O:z/c  B:z/e &&
-		test_cmp expect actual &&
+			git ls-files -s >out &&
+			test_line_count = 3 out &&
+			git ls-files -u >out &&
+			test_line_count = 2 out &&
+			git ls-files -o >out &&
+			test_line_count = 5 out &&
+
+			git rev-parse >actual \
+				:0:y/b :3:y/d :3:y/e &&
+			git rev-parse >expect \
+				O:z/b  O:z/c  B:z/e &&
+			test_cmp expect actual
+		fi &&
 
 		echo very >expect &&
 		test_cmp expect y/c &&
@@ -3186,25 +3374,38 @@
 		echo important >y/c &&
 
 		test_must_fail git -c merge.directoryRenames=true merge -s recursive B^0 >out 2>err &&
-		test_i18ngrep "CONFLICT (rename/rename)" out &&
-		test_i18ngrep "Refusing to lose untracked file at y/c; adding as y/c~B\^0 instead" out &&
+		if test "$GIT_TEST_MERGE_ALGORITHM" = ort
+		then
+			test_path_is_missing .git/MERGE_HEAD &&
+			test_i18ngrep "error: The following untracked working tree files would be overwritten by merge" err &&
 
-		git ls-files -s >out &&
-		test_line_count = 6 out &&
-		git ls-files -u >out &&
-		test_line_count = 3 out &&
-		git ls-files -o >out &&
-		test_line_count = 3 out &&
+			git ls-files -s >out &&
+			test_line_count = 4 out &&
+			git ls-files -u >out &&
+			test_line_count = 0 out &&
+			git ls-files -o >out &&
+			test_line_count = 3 out
+		else
+			test_i18ngrep "CONFLICT (rename/rename)" out &&
+			test_i18ngrep "Refusing to lose untracked file at y/c; adding as y/c~B\^0 instead" out &&
 
-		git rev-parse >actual \
-			:0:y/a :0:y/b :0:x/d :1:x/c :2:w/c :3:y/c &&
-		git rev-parse >expect \
-			 O:z/a  O:z/b  O:x/d  O:x/c  O:x/c  O:x/c &&
-		test_cmp expect actual &&
+			git ls-files -s >out &&
+			test_line_count = 6 out &&
+			git ls-files -u >out &&
+			test_line_count = 3 out &&
+			git ls-files -o >out &&
+			test_line_count = 3 out &&
 
-		git hash-object y/c~B^0 >actual &&
-		git rev-parse O:x/c >expect &&
-		test_cmp expect actual &&
+			git rev-parse >actual \
+				:0:y/a :0:y/b :0:x/d :1:x/c :2:w/c :3:y/c &&
+			git rev-parse >expect \
+				 O:z/a  O:z/b  O:x/d  O:x/c  O:x/c  O:x/c &&
+			test_cmp expect actual &&
+
+			git hash-object y/c~B^0 >actual &&
+			git rev-parse O:x/c >expect &&
+			test_cmp expect actual
+		fi &&
 
 		echo important >expect &&
 		test_cmp expect y/c
@@ -3224,25 +3425,38 @@
 		echo important >y/c &&
 
 		test_must_fail git -c merge.directoryRenames=true merge -s recursive A^0 >out 2>err &&
-		test_i18ngrep "CONFLICT (rename/rename)" out &&
-		test_i18ngrep "Refusing to lose untracked file at y/c; adding as y/c~HEAD instead" out &&
+		if test "$GIT_TEST_MERGE_ALGORITHM" = ort
+		then
+			test_path_is_missing .git/MERGE_HEAD &&
+			test_i18ngrep "error: The following untracked working tree files would be overwritten by merge" err &&
 
-		git ls-files -s >out &&
-		test_line_count = 6 out &&
-		git ls-files -u >out &&
-		test_line_count = 3 out &&
-		git ls-files -o >out &&
-		test_line_count = 3 out &&
+			git ls-files -s >out &&
+			test_line_count = 4 out &&
+			git ls-files -u >out &&
+			test_line_count = 0 out &&
+			git ls-files -o >out &&
+			test_line_count = 3 out
+		else
+			test_i18ngrep "CONFLICT (rename/rename)" out &&
+			test_i18ngrep "Refusing to lose untracked file at y/c; adding as y/c~HEAD instead" out &&
 
-		git rev-parse >actual \
-			:0:y/a :0:y/b :0:x/d :1:x/c :3:w/c :2:y/c &&
-		git rev-parse >expect \
-			 O:z/a  O:z/b  O:x/d  O:x/c  O:x/c  O:x/c &&
-		test_cmp expect actual &&
+			git ls-files -s >out &&
+			test_line_count = 6 out &&
+			git ls-files -u >out &&
+			test_line_count = 3 out &&
+			git ls-files -o >out &&
+			test_line_count = 3 out &&
 
-		git hash-object y/c~HEAD >actual &&
-		git rev-parse O:x/c >expect &&
-		test_cmp expect actual &&
+			git rev-parse >actual \
+				:0:y/a :0:y/b :0:x/d :1:x/c :3:w/c :2:y/c &&
+			git rev-parse >expect \
+				 O:z/a  O:z/b  O:x/d  O:x/c  O:x/c  O:x/c &&
+			test_cmp expect actual &&
+
+			git hash-object y/c~HEAD >actual &&
+			git rev-parse O:x/c >expect &&
+			test_cmp expect actual
+		fi &&
 
 		echo important >expect &&
 		test_cmp expect y/c
@@ -3300,37 +3514,50 @@
 		echo important >y/wham &&
 
 		test_must_fail git -c merge.directoryRenames=true merge -s recursive B^0 >out 2>err &&
-		test_i18ngrep "CONFLICT (rename/rename)" out &&
-		test_i18ngrep "Refusing to lose untracked file at y/wham" out &&
+		if test "$GIT_TEST_MERGE_ALGORITHM" = ort
+		then
+			test_path_is_missing .git/MERGE_HEAD &&
+			test_i18ngrep "error: The following untracked working tree files would be overwritten by merge" err &&
 
-		git ls-files -s >out &&
-		test_line_count = 6 out &&
-		git ls-files -u >out &&
-		test_line_count = 2 out &&
-		git ls-files -o >out &&
-		test_line_count = 3 out &&
+			git ls-files -s >out &&
+			test_line_count = 6 out &&
+			git ls-files -u >out &&
+			test_line_count = 0 out &&
+			git ls-files -o >out &&
+			test_line_count = 3 out
+		else
+			test_i18ngrep "CONFLICT (rename/rename)" out &&
+			test_i18ngrep "Refusing to lose untracked file at y/wham" out &&
 
-		git rev-parse >actual \
-			:0:y/a :0:y/b :0:y/d :0:y/e :2:y/wham :3:y/wham &&
-		git rev-parse >expect \
-			 O:z/a  O:z/b  O:x/d  O:x/e  O:z/c     O:x/f &&
-		test_cmp expect actual &&
+			git ls-files -s >out &&
+			test_line_count = 6 out &&
+			git ls-files -u >out &&
+			test_line_count = 2 out &&
+			git ls-files -o >out &&
+			test_line_count = 3 out &&
 
-		test_must_fail git rev-parse :1:y/wham &&
+			git rev-parse >actual \
+				:0:y/a :0:y/b :0:y/d :0:y/e :2:y/wham :3:y/wham &&
+			git rev-parse >expect \
+				 O:z/a  O:z/b  O:x/d  O:x/e  O:z/c     O:x/f &&
+			test_cmp expect actual &&
+
+			test_must_fail git rev-parse :1:y/wham &&
+
+			# Test that two-way merge in y/wham~merged is as expected
+			git cat-file -p :2:y/wham >expect &&
+			git cat-file -p :3:y/wham >other &&
+			>empty &&
+			test_must_fail git merge-file \
+				-L "HEAD" \
+				-L "" \
+				-L "B^0" \
+				expect empty other &&
+			test_cmp expect y/wham~merged
+		fi &&
 
 		echo important >expect &&
-		test_cmp expect y/wham &&
-
-		# Test that the two-way merge in y/wham~merged is as expected
-		git cat-file -p :2:y/wham >expect &&
-		git cat-file -p :3:y/wham >other &&
-		>empty &&
-		test_must_fail git merge-file \
-			-L "HEAD" \
-			-L "" \
-			-L "B^0" \
-			expect empty other &&
-		test_cmp expect y/wham~merged
+		test_cmp expect y/wham
 	)
 '
 
@@ -3369,7 +3596,7 @@
 	)
 }
 
-test_expect_failure '10e: Does git complain about untracked file that is not really in the way?' '
+test_expect_merge_algorithm failure success '10e: Does git complain about untracked file that is not really in the way?' '
 	test_setup_10e &&
 	(
 		cd 10e &&
@@ -3460,28 +3687,35 @@
 		echo stuff >>z/c &&
 
 		test_must_fail git -c merge.directoryRenames=true merge -s recursive B^0 >out 2>err &&
-		test_i18ngrep "Refusing to lose dirty file at z/c" out &&
+		if test "$GIT_TEST_MERGE_ALGORITHM" = ort
+		then
+			test_path_is_missing .git/MERGE_HEAD &&
+			test_i18ngrep "error: Your local changes to the following files would be overwritten by merge" err
+		else
+			test_i18ngrep "Refusing to lose dirty file at z/c" out &&
+
+			git ls-files -s >out &&
+			test_line_count = 2 out &&
+			git ls-files -u >out &&
+			test_line_count = 1 out &&
+			git ls-files -o >out &&
+			test_line_count = 3 out &&
+
+			git rev-parse >actual \
+				:0:z/a :2:z/c &&
+			git rev-parse >expect \
+				 O:z/a  B:z/b &&
+			test_cmp expect actual &&
+
+			git hash-object z/c~HEAD >actual &&
+			git rev-parse B:z/b >expect &&
+			test_cmp expect actual
+		fi &&
 
 		test_seq 1 10 >expected &&
 		echo stuff >>expected &&
-		test_cmp expected z/c &&
+		test_cmp expected z/c
 
-		git ls-files -s >out &&
-		test_line_count = 2 out &&
-		git ls-files -u >out &&
-		test_line_count = 1 out &&
-		git ls-files -o >out &&
-		test_line_count = 4 out &&
-
-		git rev-parse >actual \
-			:0:z/a :2:z/c &&
-		git rev-parse >expect \
-			 O:z/a  B:z/b &&
-		test_cmp expect actual &&
-
-		git hash-object z/c~HEAD >actual &&
-		git rev-parse B:z/b >expect &&
-		test_cmp expect actual
 	)
 '
 
@@ -3532,32 +3766,39 @@
 		git checkout A^0 &&
 		echo stuff >>z/c &&
 
-		git -c merge.directoryRenames=true merge -s recursive B^0 >out 2>err &&
-		test_i18ngrep "Refusing to lose dirty file at z/c" out &&
+		if test "$GIT_TEST_MERGE_ALGORITHM" = ort
+		then
+			test_must_fail git -c merge.directoryRenames=true merge -s recursive B^0 >out 2>err &&
+			test_path_is_missing .git/MERGE_HEAD &&
+			test_i18ngrep "error: Your local changes to the following files would be overwritten by merge" err
+		else
+			git -c merge.directoryRenames=true merge -s recursive B^0 >out 2>err &&
+			test_i18ngrep "Refusing to lose dirty file at z/c" out &&
+
+			git ls-files -s >out &&
+			test_line_count = 3 out &&
+			git ls-files -u >out &&
+			test_line_count = 0 out &&
+			git ls-files -m >out &&
+			test_line_count = 0 out &&
+			git ls-files -o >out &&
+			test_line_count = 3 out &&
+
+			git rev-parse >actual \
+				:0:x/b :0:y/a :0:y/c &&
+			git rev-parse >expect \
+				 O:x/b  O:z/a  B:x/c &&
+			test_cmp expect actual &&
+
+			git hash-object y/c >actual &&
+			git rev-parse B:x/c >expect &&
+			test_cmp expect actual
+		fi &&
 
 		grep -q stuff z/c &&
 		test_seq 1 10 >expected &&
 		echo stuff >>expected &&
-		test_cmp expected z/c &&
-
-		git ls-files -s >out &&
-		test_line_count = 3 out &&
-		git ls-files -u >out &&
-		test_line_count = 0 out &&
-		git ls-files -m >out &&
-		test_line_count = 0 out &&
-		git ls-files -o >out &&
-		test_line_count = 4 out &&
-
-		git rev-parse >actual \
-			:0:x/b :0:y/a :0:y/c &&
-		git rev-parse >expect \
-			 O:x/b  O:z/a  B:x/c &&
-		test_cmp expect actual &&
-
-		git hash-object y/c >actual &&
-		git rev-parse B:x/c >expect &&
-		test_cmp expect actual
+		test_cmp expected z/c
 	)
 '
 
@@ -3609,7 +3850,13 @@
 		echo stuff >>y/c &&
 
 		test_must_fail git -c merge.directoryRenames=true merge -s recursive B^0 >out 2>err &&
-		test_i18ngrep "following files would be overwritten by merge" err &&
+		if test "$GIT_TEST_MERGE_ALGORITHM" = ort
+		then
+			test_path_is_missing .git/MERGE_HEAD &&
+			test_i18ngrep "error: Your local changes to the following files would be overwritten by merge" err
+		else
+			test_i18ngrep "following files would be overwritten by merge" err
+		fi &&
 
 		grep -q stuff y/c &&
 		test_seq 1 10 >expected &&
@@ -3677,29 +3924,35 @@
 		echo stuff >>z/c &&
 
 		test_must_fail git -c merge.directoryRenames=true merge -s recursive B^0 >out 2>err &&
-		test_i18ngrep "Refusing to lose dirty file at z/c" out &&
+		if test "$GIT_TEST_MERGE_ALGORITHM" = ort
+		then
+			test_path_is_missing .git/MERGE_HEAD &&
+			test_i18ngrep "error: Your local changes to the following files would be overwritten by merge" err
+		else
+			test_i18ngrep "Refusing to lose dirty file at z/c" out &&
+
+			git ls-files -s >out &&
+			test_line_count = 4 out &&
+			git ls-files -u >out &&
+			test_line_count = 1 out &&
+			git ls-files -o >out &&
+			test_line_count = 4 out &&
+
+			git rev-parse >actual \
+				:0:x/b :0:y/a :0:y/c/d :3:y/c &&
+			git rev-parse >expect \
+				 O:x/b  O:z/a  B:y/c/d  B:x/c &&
+			test_cmp expect actual &&
+
+			git hash-object y/c~HEAD >actual &&
+			git rev-parse B:x/c >expect &&
+			test_cmp expect actual
+		fi &&
 
 		grep -q stuff z/c &&
 		test_seq 1 10 >expected &&
 		echo stuff >>expected &&
-		test_cmp expected z/c &&
-
-		git ls-files -s >out &&
-		test_line_count = 4 out &&
-		git ls-files -u >out &&
-		test_line_count = 1 out &&
-		git ls-files -o >out &&
-		test_line_count = 5 out &&
-
-		git rev-parse >actual \
-			:0:x/b :0:y/a :0:y/c/d :3:y/c &&
-		git rev-parse >expect \
-			 O:x/b  O:z/a  B:y/c/d  B:x/c &&
-		test_cmp expect actual &&
-
-		git hash-object y/c~HEAD >actual &&
-		git rev-parse B:x/c >expect &&
-		test_cmp expect actual
+		test_cmp expected z/c
 	)
 '
 
@@ -3757,37 +4010,43 @@
 		echo mods >>y/c &&
 
 		test_must_fail git -c merge.directoryRenames=true merge -s recursive B^0 >out 2>err &&
-		test_i18ngrep "CONFLICT (rename/rename)" out &&
-		test_i18ngrep "Refusing to lose dirty file at y/c" out &&
+		if test "$GIT_TEST_MERGE_ALGORITHM" = ort
+		then
+			test_path_is_missing .git/MERGE_HEAD &&
+			test_i18ngrep "error: Your local changes to the following files would be overwritten by merge" err
+		else
+			test_i18ngrep "CONFLICT (rename/rename)" out &&
+			test_i18ngrep "Refusing to lose dirty file at y/c" out &&
 
-		git ls-files -s >out &&
-		test_line_count = 7 out &&
-		git ls-files -u >out &&
-		test_line_count = 4 out &&
-		git ls-files -o >out &&
-		test_line_count = 3 out &&
+			git ls-files -s >out &&
+			test_line_count = 7 out &&
+			git ls-files -u >out &&
+			test_line_count = 4 out &&
+			git ls-files -o >out &&
+			test_line_count = 3 out &&
+
+			git rev-parse >actual \
+				:0:y/a :0:y/b :0:x/d :1:x/c :2:w/c :2:y/c :3:y/c &&
+			git rev-parse >expect \
+				 O:z/a  O:z/b  O:x/d  O:x/c  O:x/c  A:y/c  O:x/c &&
+			test_cmp expect actual &&
+
+			# See if y/c~merged has expected contents; requires manually
+			# doing the expected file merge
+			git cat-file -p A:y/c >c1 &&
+			git cat-file -p B:z/c >c2 &&
+			>empty &&
+			test_must_fail git merge-file \
+				-L "HEAD" \
+				-L "" \
+				-L "B^0" \
+				c1 empty c2 &&
+			test_cmp c1 y/c~merged
+		fi &&
 
 		echo different >expected &&
 		echo mods >>expected &&
-		test_cmp expected y/c &&
-
-		git rev-parse >actual \
-			:0:y/a :0:y/b :0:x/d :1:x/c :2:w/c :2:y/c :3:y/c &&
-		git rev-parse >expect \
-			 O:z/a  O:z/b  O:x/d  O:x/c  O:x/c  A:y/c  O:x/c &&
-		test_cmp expect actual &&
-
-		# See if y/c~merged has expected contents; requires manually
-		# doing the expected file merge
-		git cat-file -p A:y/c >c1 &&
-		git cat-file -p B:z/c >c2 &&
-		>empty &&
-		test_must_fail git merge-file \
-			-L "HEAD" \
-			-L "" \
-			-L "B^0" \
-			c1 empty c2 &&
-		test_cmp c1 y/c~merged
+		test_cmp expected y/c
 	)
 '
 
@@ -3840,38 +4099,44 @@
 		echo important >>y/wham &&
 
 		test_must_fail git -c merge.directoryRenames=true merge -s recursive B^0 >out 2>err &&
-		test_i18ngrep "CONFLICT (rename/rename)" out &&
-		test_i18ngrep "Refusing to lose dirty file at y/wham" out &&
+		if test "$GIT_TEST_MERGE_ALGORITHM" = ort
+		then
+			test_path_is_missing .git/MERGE_HEAD &&
+			test_i18ngrep "error: Your local changes to the following files would be overwritten by merge" err
+		else
+			test_i18ngrep "CONFLICT (rename/rename)" out &&
+			test_i18ngrep "Refusing to lose dirty file at y/wham" out &&
 
-		git ls-files -s >out &&
-		test_line_count = 4 out &&
-		git ls-files -u >out &&
-		test_line_count = 2 out &&
-		git ls-files -o >out &&
-		test_line_count = 3 out &&
+			git ls-files -s >out &&
+			test_line_count = 4 out &&
+			git ls-files -u >out &&
+			test_line_count = 2 out &&
+			git ls-files -o >out &&
+			test_line_count = 3 out &&
+
+			test_must_fail git rev-parse :1:y/wham &&
+
+			git rev-parse >actual \
+				:0:y/a :0:y/b :2:y/wham :3:y/wham &&
+			git rev-parse >expect \
+				 O:z/a  O:z/b  O:x/c     O:x/d &&
+			test_cmp expect actual &&
+
+			# Test that two-way merge in y/wham~merged is as expected
+			git cat-file -p :2:y/wham >expect &&
+			git cat-file -p :3:y/wham >other &&
+			>empty &&
+			test_must_fail git merge-file \
+				-L "HEAD" \
+				-L "" \
+				-L "B^0" \
+				expect empty other &&
+			test_cmp expect y/wham~merged
+		fi &&
 
 		test_seq 1 10 >expected &&
 		echo important >>expected &&
-		test_cmp expected y/wham &&
-
-		test_must_fail git rev-parse :1:y/wham &&
-
-		git rev-parse >actual \
-			:0:y/a :0:y/b :2:y/wham :3:y/wham &&
-		git rev-parse >expect \
-			 O:z/a  O:z/b  O:x/c     O:x/d &&
-		test_cmp expect actual &&
-
-		# Test that the two-way merge in y/wham~merged is as expected
-		git cat-file -p :2:y/wham >expect &&
-		git cat-file -p :3:y/wham >other &&
-		>empty &&
-		test_must_fail git merge-file \
-			-L "HEAD" \
-			-L "" \
-			-L "B^0" \
-			expect empty other &&
-		test_cmp expect y/wham~merged
+		test_cmp expected y/wham
 	)
 '
 
@@ -3947,31 +4212,35 @@
 	)
 '
 
-# Testcase 12b, Moving two directory hierarchies into each other
+# Testcase 12b1, Moving two directory hierarchies into each other
 #   (Related to testcases 1c and 12c)
 #   Commit O: node1/{leaf1, leaf2}, node2/{leaf3, leaf4}
 #   Commit A: node1/{leaf1, leaf2, node2/{leaf3, leaf4}}
 #   Commit B: node2/{leaf3, leaf4, node1/{leaf1, leaf2}}
-#   Expected: node1/node2/node1/{leaf1, leaf2},
-#             node2/node1/node2/{leaf3, leaf4}
-#   NOTE: Without directory renames, we would expect
-#                   node2/node1/{leaf1, leaf2},
-#                   node1/node2/{leaf3, leaf4}
-#         with directory rename detection, we note that
+#   Expected: node1/node2/{leaf3, leaf4}
+#             node2/node1/{leaf1, leaf2}
+#   NOTE: If there were new files added to the old node1/ or node2/ directories,
+#         then we would need to detect renames for those directories and would
+#         find that:
 #             commit A renames node2/ -> node1/node2/
 #             commit B renames node1/ -> node2/node1/
-#         therefore, applying those directory renames to the initial result
-#         (making all four paths experience a transitive renaming), yields
-#         the expected result.
-#
-#         You may ask, is it weird to have two directories rename each other?
-#         To which, I can do no more than shrug my shoulders and say that
-#         even simple rules give weird results when given weird inputs.
+#         Applying those directory renames to the initial result (making all
+#         four paths experience a transitive renaming), yields
+#             node1/node2/node1/{leaf1, leaf2}
+#             node2/node1/node2/{leaf3, leaf4}
+#         as the result.  It may be really weird to have two directories
+#         rename each other, but simple rules give weird results when given
+#         weird inputs.  HOWEVER, the "If" at the beginning of those NOTE was
+#         false; there were no new files added and thus there is no directory
+#         rename detection to perform.  As such, we just have simple renames
+#         and the expected answer is:
+#             node1/node2/{leaf3, leaf4}
+#             node2/node1/{leaf1, leaf2}
 
-test_setup_12b () {
-	test_create_repo 12b &&
+test_setup_12b1 () {
+	test_create_repo 12b1 &&
 	(
-		cd 12b &&
+		cd 12b1 &&
 
 		mkdir -p node1 node2 &&
 		echo leaf1 >node1/leaf1 &&
@@ -3998,10 +4267,10 @@
 	)
 }
 
-test_expect_success '12b: Moving two directory hierarchies into each other' '
-	test_setup_12b &&
+test_expect_merge_algorithm failure success '12b1: Moving two directory hierarchies into each other' '
+	test_setup_12b1 &&
 	(
-		cd 12b &&
+		cd 12b1 &&
 
 		git checkout A^0 &&
 
@@ -4011,10 +4280,10 @@
 		test_line_count = 4 out &&
 
 		git rev-parse >actual \
-			HEAD:node1/node2/node1/leaf1 \
-			HEAD:node1/node2/node1/leaf2 \
-			HEAD:node2/node1/node2/leaf3 \
-			HEAD:node2/node1/node2/leaf4 &&
+			HEAD:node2/node1/leaf1 \
+			HEAD:node2/node1/leaf2 \
+			HEAD:node1/node2/leaf3 \
+			HEAD:node1/node2/leaf4 &&
 		git rev-parse >expect \
 			O:node1/leaf1 \
 			O:node1/leaf2 \
@@ -4024,7 +4293,104 @@
 	)
 '
 
-# Testcase 12c, Moving two directory hierarchies into each other w/ content merge
+# Testcase 12b2, Moving two directory hierarchies into each other
+#   (Related to testcases 1c and 12c)
+#   Commit O: node1/{leaf1, leaf2}, node2/{leaf3, leaf4}
+#   Commit A: node1/{leaf1, leaf2, leaf5, node2/{leaf3, leaf4}}
+#   Commit B: node2/{leaf3, leaf4, leaf6, node1/{leaf1, leaf2}}
+#   Expected: node1/node2/{node1/{leaf1, leaf2}, leaf6}
+#             node2/node1/{node2/{leaf3, leaf4}, leaf5}
+#   NOTE: Without directory renames, we would expect
+#             A: node2/leaf3 -> node1/node2/leaf3
+#             A: node2/leaf1 -> node1/node2/leaf4
+#             A: Adds           node1/leaf5
+#             B: node1/leaf1 -> node2/node1/leaf1
+#             B: node1/leaf2 -> node2/node1/leaf2
+#             B: Adds           node2/leaf6
+#         with directory rename detection, we note that
+#             commit A renames node2/ -> node1/node2/
+#             commit B renames node1/ -> node2/node1/
+#         therefore, applying A's directory rename to the paths added in B gives:
+#             B: node1/leaf1 -> node1/node2/node1/leaf1
+#             B: node1/leaf2 -> node1/node2/node1/leaf2
+#             B: Adds           node1/node2/leaf6
+#         and applying B's directory rename to the paths added in A gives:
+#             A: node2/leaf3 -> node2/node1/node2/leaf3
+#             A: node2/leaf1 -> node2/node1/node2/leaf4
+#             A: Adds           node2/node1/leaf5
+#         resulting in the expected
+#             node1/node2/{node1/{leaf1, leaf2}, leaf6}
+#             node2/node1/{node2/{leaf3, leaf4}, leaf5}
+#
+#         You may ask, is it weird to have two directories rename each other?
+#         To which, I can do no more than shrug my shoulders and say that
+#         even simple rules give weird results when given weird inputs.
+
+test_setup_12b2 () {
+	test_create_repo 12b2 &&
+	(
+		cd 12b2 &&
+
+		mkdir -p node1 node2 &&
+		echo leaf1 >node1/leaf1 &&
+		echo leaf2 >node1/leaf2 &&
+		echo leaf3 >node2/leaf3 &&
+		echo leaf4 >node2/leaf4 &&
+		git add node1 node2 &&
+		test_tick &&
+		git commit -m "O" &&
+
+		git branch O &&
+		git branch A &&
+		git branch B &&
+
+		git checkout A &&
+		git mv node2/ node1/ &&
+		echo leaf5 >node1/leaf5 &&
+		git add node1/leaf5 &&
+		test_tick &&
+		git commit -m "A" &&
+
+		git checkout B &&
+		git mv node1/ node2/ &&
+		echo leaf6 >node2/leaf6 &&
+		git add node2/leaf6 &&
+		test_tick &&
+		git commit -m "B"
+	)
+}
+
+test_expect_success '12b2: Moving two directory hierarchies into each other' '
+	test_setup_12b2 &&
+	(
+		cd 12b2 &&
+
+		git checkout A^0 &&
+
+		git -c merge.directoryRenames=true merge -s recursive B^0 &&
+
+		git ls-files -s >out &&
+		test_line_count = 6 out &&
+
+		git rev-parse >actual \
+			HEAD:node1/node2/node1/leaf1 \
+			HEAD:node1/node2/node1/leaf2 \
+			HEAD:node2/node1/node2/leaf3 \
+			HEAD:node2/node1/node2/leaf4 \
+			HEAD:node2/node1/leaf5       \
+			HEAD:node1/node2/leaf6       &&
+		git rev-parse >expect \
+			O:node1/leaf1 \
+			O:node1/leaf2 \
+			O:node2/leaf3 \
+			O:node2/leaf4 \
+			A:node1/leaf5 \
+			B:node2/leaf6 &&
+		test_cmp expect actual
+	)
+'
+
+# Testcase 12c1, Moving two directory hierarchies into each other w/ content merge
 #   (Related to testcase 12b)
 #   Commit O: node1/{       leaf1_1, leaf2_1}, node2/{leaf3_1, leaf4_1}
 #   Commit A: node1/{       leaf1_2, leaf2_2,  node2/{leaf3_2, leaf4_2}}
@@ -4032,13 +4398,13 @@
 #   Expected: Content merge conflicts for each of:
 #               node1/node2/node1/{leaf1, leaf2},
 #               node2/node1/node2/{leaf3, leaf4}
-#   NOTE: This is *exactly* like 12c, except that every path is modified on
+#   NOTE: This is *exactly* like 12b1, except that every path is modified on
 #         each side of the merge.
 
-test_setup_12c () {
-	test_create_repo 12c &&
+test_setup_12c1 () {
+	test_create_repo 12c1 &&
 	(
-		cd 12c &&
+		cd 12c1 &&
 
 		mkdir -p node1 node2 &&
 		printf "1\n2\n3\n4\n5\n6\n7\n8\nleaf1\n" >node1/leaf1 &&
@@ -4069,10 +4435,10 @@
 	)
 }
 
-test_expect_success '12c: Moving one directory hierarchy into another w/ content merge' '
-	test_setup_12c &&
+test_expect_merge_algorithm failure success '12c1: Moving one directory hierarchy into another w/ content merge' '
+	test_setup_12c1 &&
 	(
-		cd 12c &&
+		cd 12c1 &&
 
 		git checkout A^0 &&
 
@@ -4082,6 +4448,102 @@
 		test_line_count = 12 out &&
 
 		git rev-parse >actual \
+			:1:node2/node1/leaf1 \
+			:1:node2/node1/leaf2 \
+			:1:node1/node2/leaf3 \
+			:1:node1/node2/leaf4 \
+			:2:node2/node1/leaf1 \
+			:2:node2/node1/leaf2 \
+			:2:node1/node2/leaf3 \
+			:2:node1/node2/leaf4 \
+			:3:node2/node1/leaf1 \
+			:3:node2/node1/leaf2 \
+			:3:node1/node2/leaf3 \
+			:3:node1/node2/leaf4 &&
+		git rev-parse >expect \
+			O:node1/leaf1 \
+			O:node1/leaf2 \
+			O:node2/leaf3 \
+			O:node2/leaf4 \
+			A:node1/leaf1 \
+			A:node1/leaf2 \
+			A:node1/node2/leaf3 \
+			A:node1/node2/leaf4 \
+			B:node2/node1/leaf1 \
+			B:node2/node1/leaf2 \
+			B:node2/leaf3 \
+			B:node2/leaf4 &&
+		test_cmp expect actual
+	)
+'
+
+# Testcase 12c2, Moving two directory hierarchies into each other w/ content merge
+#   (Related to testcase 12b)
+#   Commit O: node1/{       leaf1_1, leaf2_1}, node2/{leaf3_1, leaf4_1}
+#   Commit A: node1/{       leaf1_2, leaf2_2,  node2/{leaf3_2, leaf4_2}, leaf5}
+#   Commit B: node2/{node1/{leaf1_3, leaf2_3},        leaf3_3, leaf4_3,  leaf6}
+#   Expected: Content merge conflicts for each of:
+#               node1/node2/node1/{leaf1, leaf2}
+#               node2/node1/node2/{leaf3, leaf4}
+#             plus
+#               node2/node1/leaf5
+#               node1/node2/leaf6
+#   NOTE: This is *exactly* like 12b2, except that every path from O is modified
+#         on each side of the merge.
+
+test_setup_12c2 () {
+	test_create_repo 12c2 &&
+	(
+		cd 12c2 &&
+
+		mkdir -p node1 node2 &&
+		printf "1\n2\n3\n4\n5\n6\n7\n8\nleaf1\n" >node1/leaf1 &&
+		printf "1\n2\n3\n4\n5\n6\n7\n8\nleaf2\n" >node1/leaf2 &&
+		printf "1\n2\n3\n4\n5\n6\n7\n8\nleaf3\n" >node2/leaf3 &&
+		printf "1\n2\n3\n4\n5\n6\n7\n8\nleaf4\n" >node2/leaf4 &&
+		git add node1 node2 &&
+		test_tick &&
+		git commit -m "O" &&
+
+		git branch O &&
+		git branch A &&
+		git branch B &&
+
+		git checkout A &&
+		git mv node2/ node1/ &&
+		for i in `git ls-files`; do echo side A >>$i; done &&
+		git add -u &&
+		echo leaf5 >node1/leaf5 &&
+		git add node1/leaf5 &&
+		test_tick &&
+		git commit -m "A" &&
+
+		git checkout B &&
+		git mv node1/ node2/ &&
+		for i in `git ls-files`; do echo side B >>$i; done &&
+		git add -u &&
+		echo leaf6 >node2/leaf6 &&
+		git add node2/leaf6 &&
+		test_tick &&
+		git commit -m "B"
+	)
+}
+
+test_expect_success '12c2: Moving one directory hierarchy into another w/ content merge' '
+	test_setup_12c2 &&
+	(
+		cd 12c2 &&
+
+		git checkout A^0 &&
+
+		test_must_fail git -c merge.directoryRenames=true merge -s recursive B^0 &&
+
+		git ls-files -s >out &&
+		test_line_count = 14 out &&
+		git ls-files -u >out &&
+		test_line_count = 12 out &&
+
+		git rev-parse >actual \
 			:1:node1/node2/node1/leaf1 \
 			:1:node1/node2/node1/leaf2 \
 			:1:node2/node1/node2/leaf3 \
@@ -4093,7 +4555,9 @@
 			:3:node1/node2/node1/leaf1 \
 			:3:node1/node2/node1/leaf2 \
 			:3:node2/node1/node2/leaf3 \
-			:3:node2/node1/node2/leaf4 &&
+			:3:node2/node1/node2/leaf4 \
+			:0:node2/node1/leaf5       \
+			:0:node1/node2/leaf6       &&
 		git rev-parse >expect \
 			O:node1/leaf1 \
 			O:node1/leaf2 \
@@ -4106,7 +4570,9 @@
 			B:node2/node1/leaf1 \
 			B:node2/node1/leaf2 \
 			B:node2/leaf3 \
-			B:node2/leaf4 &&
+			B:node2/leaf4 \
+			A:node1/leaf5 \
+			B:node2/leaf6 &&
 		test_cmp expect actual
 	)
 '
@@ -4227,6 +4693,208 @@
 	)
 '
 
+# Testcase 12f, Rebase of patches with big directory rename
+#   Commit O:
+#              dir/subdir/{a,b,c,d,e_O,Makefile_TOP_O}
+#              dir/subdir/tweaked/{f,g,h,Makefile_SUB_O}
+#              dir/unchanged/<LOTS OF FILES>
+#   Commit A:
+#     (Remove f & g, move e into newsubdir, rename dir/->folder/, modify files)
+#              folder/subdir/{a,b,c,d,Makefile_TOP_A}
+#              folder/subdir/newsubdir/e_A
+#              folder/subdir/tweaked/{h,Makefile_SUB_A}
+#              folder/unchanged/<LOTS OF FILES>
+#   Commit B1:
+#     (add newfile.{c,py}, modify underscored files)
+#              dir/{a,b,c,d,e_B1,Makefile_TOP_B1,newfile.c}
+#              dir/tweaked/{f,g,h,Makefile_SUB_B1,newfile.py}
+#              dir/unchanged/<LOTS OF FILES>
+#   Commit B2:
+#     (Modify e further, add newfile.rs)
+#              dir/{a,b,c,d,e_B2,Makefile_TOP_B1,newfile.c,newfile.rs}
+#              dir/tweaked/{f,g,h,Makefile_SUB_B1,newfile.py}
+#              dir/unchanged/<LOTS OF FILES>
+#   Expected:
+#          B1-picked:
+#              folder/subdir/{a,b,c,d,Makefile_TOP_Merge1,newfile.c}
+#              folder/subdir/newsubdir/e_Merge1
+#              folder/subdir/tweaked/{h,Makefile_SUB_Merge1,newfile.py}
+#              folder/unchanged/<LOTS OF FILES>
+#          B2-picked:
+#              folder/subdir/{a,b,c,d,Makefile_TOP_Merge1,newfile.c,newfile.rs}
+#              folder/subdir/newsubdir/e_Merge2
+#              folder/subdir/tweaked/{h,Makefile_SUB_Merge1,newfile.py}
+#              folder/unchanged/<LOTS OF FILES>
+# Things being checked here:
+#   1. dir/subdir/newfile.c does not get pushed into folder/subdir/newsubdir/.
+#      dir/subdir/{a,b,c,d} -> folder/subdir/{a,b,c,d} looks like
+#          dir/ -> folder/,
+#      whereas dir/subdir/e -> folder/subdir/newsubdir/e looks like
+#          dir/subdir/ -> folder/subdir/newsubdir/
+#      and if we note that newfile.c is found in dir/subdir/, we might overlook
+#      the dir/ -> folder/ rule that has more weight.  Older git versions did
+#      this.
+#   2. The code to do trivial directory resolves.  Note that
+#      dir/subdir/unchanged/ is unchanged and can be deleted, and files in the
+#      new folder/subdir/unchanged/ are not needed as a target to any renames.
+#      Thus, in the second collect_merge_info_callback() we can just resolve
+#      these two directories trivially without recursing.)
+#   3. Exercising the codepaths for caching renames and deletes from one cherry
+#      pick and re-applying them in the subsequent one.
+
+test_setup_12f () {
+	test_create_repo 12f &&
+	(
+		cd 12f &&
+
+		mkdir -p dir/unchanged &&
+		mkdir -p dir/subdir/tweaked &&
+		echo a >dir/subdir/a &&
+		echo b >dir/subdir/b &&
+		echo c >dir/subdir/c &&
+		echo d >dir/subdir/d &&
+		test_seq 1 10 >dir/subdir/e &&
+		test_seq 10 20 >dir/subdir/Makefile &&
+		echo f >dir/subdir/tweaked/f &&
+		echo g >dir/subdir/tweaked/g &&
+		echo h >dir/subdir/tweaked/h &&
+		test_seq 20 30 >dir/subdir/tweaked/Makefile &&
+		for i in `test_seq 1 88`; do
+			echo content $i >dir/unchanged/file_$i
+		done &&
+		git add . &&
+		git commit -m "O" &&
+
+		git branch O &&
+		git branch A &&
+		git branch B &&
+
+		git switch A &&
+		git rm dir/subdir/tweaked/f dir/subdir/tweaked/g &&
+		test_seq 2 10 >dir/subdir/e &&
+		test_seq 11 20 >dir/subdir/Makefile &&
+		test_seq 21 30 >dir/subdir/tweaked/Makefile &&
+		mkdir dir/subdir/newsubdir &&
+		git mv dir/subdir/e dir/subdir/newsubdir/ &&
+		git mv dir folder &&
+		git add . &&
+		git commit -m "A" &&
+
+		git switch B &&
+		mkdir dir/subdir/newsubdir/ &&
+		echo c code >dir/subdir/newfile.c &&
+		echo python code >dir/subdir/newsubdir/newfile.py &&
+		test_seq 1 11 >dir/subdir/e &&
+		test_seq 10 21 >dir/subdir/Makefile &&
+		test_seq 20 31 >dir/subdir/tweaked/Makefile &&
+		git add . &&
+		git commit -m "B1" &&
+
+		echo rust code >dir/subdir/newfile.rs &&
+		test_seq 1 12 >dir/subdir/e &&
+		git add . &&
+		git commit -m "B2"
+	)
+}
+
+test_expect_merge_algorithm failure success '12f: Trivial directory resolve, caching, all kinds of fun' '
+	test_setup_12f &&
+	(
+		cd 12f &&
+
+		git checkout A^0 &&
+		git branch Bmod B &&
+
+		GIT_TRACE2_PERF="$(pwd)/trace.output" git -c merge.directoryRenames=true rebase A Bmod &&
+
+		echo Checking the pick of B1... &&
+
+		test_must_fail git rev-parse Bmod~1:dir &&
+
+		git ls-tree -r Bmod~1 >out &&
+		test_line_count = 98 out &&
+
+		git diff --name-status A Bmod~1 >actual &&
+		q_to_tab >expect <<-\EOF &&
+		MQfolder/subdir/Makefile
+		AQfolder/subdir/newfile.c
+		MQfolder/subdir/newsubdir/e
+		AQfolder/subdir/newsubdir/newfile.py
+		MQfolder/subdir/tweaked/Makefile
+		EOF
+		test_cmp expect actual &&
+
+		# Three-way merged files
+		test_seq  2 11 >e_Merge1 &&
+		test_seq 11 21 >Makefile_TOP &&
+		test_seq 21 31 >Makefile_SUB &&
+		git hash-object >expect      \
+			e_Merge1             \
+			Makefile_TOP         \
+			Makefile_SUB         &&
+		git rev-parse >actual              \
+			Bmod~1:folder/subdir/newsubdir/e     \
+			Bmod~1:folder/subdir/Makefile        \
+			Bmod~1:folder/subdir/tweaked/Makefile &&
+		test_cmp expect actual &&
+
+		# New files showed up at the right location with right contents
+		git rev-parse >expect                \
+			B~1:dir/subdir/newfile.c            \
+			B~1:dir/subdir/newsubdir/newfile.py &&
+		git rev-parse >actual                      \
+			Bmod~1:folder/subdir/newfile.c            \
+			Bmod~1:folder/subdir/newsubdir/newfile.py &&
+		test_cmp expect actual &&
+
+		# Removed files
+		test_path_is_missing folder/subdir/tweaked/f &&
+		test_path_is_missing folder/subdir/tweaked/g &&
+
+		# Unchanged files or directories
+		git rev-parse >actual        \
+			Bmod~1:folder/subdir/a          \
+			Bmod~1:folder/subdir/b          \
+			Bmod~1:folder/subdir/c          \
+			Bmod~1:folder/subdir/d          \
+			Bmod~1:folder/unchanged         \
+			Bmod~1:folder/subdir/tweaked/h &&
+		git rev-parse >expect          \
+			O:dir/subdir/a         \
+			O:dir/subdir/b         \
+			O:dir/subdir/c         \
+			O:dir/subdir/d         \
+			O:dir/unchanged        \
+			O:dir/subdir/tweaked/h &&
+		test_cmp expect actual &&
+
+		echo Checking the pick of B2... &&
+
+		test_must_fail git rev-parse Bmod:dir &&
+
+		git ls-tree -r Bmod >out &&
+		test_line_count = 99 out &&
+
+		git diff --name-status Bmod~1 Bmod >actual &&
+		q_to_tab >expect <<-\EOF &&
+		AQfolder/subdir/newfile.rs
+		MQfolder/subdir/newsubdir/e
+		EOF
+		test_cmp expect actual &&
+
+		# Three-way merged file
+		test_seq  2 12 >e_Merge2 &&
+		git hash-object e_Merge2 >expect &&
+		git rev-parse Bmod:folder/subdir/newsubdir/e >actual &&
+		test_cmp expect actual &&
+
+		grep region_enter.*collect_merge_info trace.output >collect &&
+		test_line_count = 4 collect &&
+		grep region_enter.*process_entries$ trace.output >process &&
+		test_line_count = 2 process
+	)
+'
+
 ###########################################################################
 # SECTION 13: Checking informational and conflict messages
 #
diff --git a/t/t6426-merge-skip-unneeded-updates.sh b/t/t6426-merge-skip-unneeded-updates.sh
index 6998136..d7eeee4 100755
--- a/t/t6426-merge-skip-unneeded-updates.sh
+++ b/t/t6426-merge-skip-unneeded-updates.sh
@@ -23,6 +23,7 @@
 #                     files that might be renamed into each other's paths.)
 
 . ./test-lib.sh
+. "$TEST_DIRECTORY"/lib-merge.sh
 
 
 ###########################################################################
@@ -666,7 +667,7 @@
 #   correct requires doing the merge in-memory first, then realizing that no
 #   updates to the file are necessary, and thus that we can just leave the path
 #   alone.
-test_expect_failure '4a: Change on A, change on B subset of A, dirty mods present' '
+test_expect_merge_algorithm failure success '4a: Change on A, change on B subset of A, dirty mods present' '
 	test_setup_4a &&
 	(
 		cd 4a &&
diff --git a/t/t6430-merge-recursive.sh b/t/t6430-merge-recursive.sh
index a328260..9c08e63 100755
--- a/t/t6430-merge-recursive.sh
+++ b/t/t6430-merge-recursive.sh
@@ -3,6 +3,7 @@
 test_description='merge-recursive backend test'
 
 . ./test-lib.sh
+. "$TEST_DIRECTORY"/lib-merge.sh
 
 test_expect_success 'setup 1' '
 
@@ -641,7 +642,7 @@
 	test_cmp expected actual
 '
 
-test_expect_failure 'merge-recursive rename vs. rename/symlink' '
+test_expect_merge_algorithm failure success 'merge-recursive rename vs. rename/symlink' '
 
 	git checkout -f rename &&
 	git merge rename-ln &&
diff --git a/t/t6436-merge-overwrite.sh b/t/t6436-merge-overwrite.sh
index dd8ab7e..dd93768 100755
--- a/t/t6436-merge-overwrite.sh
+++ b/t/t6436-merge-overwrite.sh
@@ -97,11 +97,19 @@
 	git mv c1.c other.c &&
 	git commit -m rename &&
 	cp important other.c &&
-	test_must_fail git merge c1a >out &&
-	test_i18ngrep "Refusing to lose dirty file at other.c" out &&
-	test_path_is_file other.c~HEAD &&
-	test $(git hash-object other.c~HEAD) = $(git rev-parse c1a:c1.c) &&
-	test_cmp important other.c
+	if test "$GIT_TEST_MERGE_ALGORITHM" = ort
+	then
+		test_must_fail git merge c1a >out 2>err &&
+		test_i18ngrep "would be overwritten by merge" err &&
+		test_cmp important other.c &&
+		test_path_is_missing .git/MERGE_HEAD
+	else
+		test_must_fail git merge c1a >out &&
+		test_i18ngrep "Refusing to lose dirty file at other.c" out &&
+		test_path_is_file other.c~HEAD &&
+		test $(git hash-object other.c~HEAD) = $(git rev-parse c1a:c1.c) &&
+		test_cmp important other.c
+	fi
 '
 
 test_expect_success 'will not overwrite untracked subtree' '
diff --git a/t/t6437-submodule-merge.sh b/t/t6437-submodule-merge.sh
index 6a1e5f8..3ead2b7 100755
--- a/t/t6437-submodule-merge.sh
+++ b/t/t6437-submodule-merge.sh
@@ -127,7 +127,12 @@
 	 git checkout -b test-nonforward b &&
 	 (cd sub &&
 	  git rev-parse sub-d > ../expect) &&
-	 test_must_fail git merge c 2> actual  &&
+	  if test "$GIT_TEST_MERGE_ALGORITHM" = ort
+	  then
+		test_must_fail git merge c >actual
+	  else
+		test_must_fail git merge c 2> actual
+	  fi &&
 	 grep $(cat expect) actual > /dev/null &&
 	 git reset --hard)
 '
@@ -138,9 +143,21 @@
 	(cd sub &&
 	 git checkout -b ambiguous sub-b &&
 	 git merge sub-c &&
-	 git rev-parse sub-d > ../expect1 &&
-	 git rev-parse ambiguous > ../expect2) &&
-	test_must_fail git merge c 2> actual &&
+	 if test "$GIT_TEST_MERGE_ALGORITHM" = ort
+	 then
+		git rev-parse --short sub-d >../expect1 &&
+		git rev-parse --short ambiguous >../expect2
+	 else
+		git rev-parse sub-d > ../expect1 &&
+		git rev-parse ambiguous > ../expect2
+	 fi
+	 ) &&
+	 if test "$GIT_TEST_MERGE_ALGORITHM" = ort
+	 then
+		test_must_fail git merge c >actual
+	 else
+		test_must_fail git merge c 2> actual
+	 fi &&
 	grep $(cat expect1) actual > /dev/null &&
 	grep $(cat expect2) actual > /dev/null &&
 	git reset --hard)
diff --git a/t/t7006-pager.sh b/t/t7006-pager.sh
index 00e09a3..fdb450e 100755
--- a/t/t7006-pager.sh
+++ b/t/t7006-pager.sh
@@ -19,7 +19,7 @@
 test_expect_success TTY 'some commands use a pager' '
 	rm -f paginated.out &&
 	test_terminal git log &&
-	test -e paginated.out
+	test_path_is_file paginated.out
 '
 
 test_expect_failure TTY 'pager runs from subdir' '
@@ -65,49 +65,49 @@
 test_expect_success TTY 'some commands do not use a pager' '
 	rm -f paginated.out &&
 	test_terminal git rev-list HEAD &&
-	! test -e paginated.out
+	test_path_is_missing paginated.out
 '
 
 test_expect_success 'no pager when stdout is a pipe' '
 	rm -f paginated.out &&
 	git log | cat &&
-	! test -e paginated.out
+	test_path_is_missing paginated.out
 '
 
 test_expect_success 'no pager when stdout is a regular file' '
 	rm -f paginated.out &&
 	git log >file &&
-	! test -e paginated.out
+	test_path_is_missing paginated.out
 '
 
 test_expect_success TTY 'git --paginate rev-list uses a pager' '
 	rm -f paginated.out &&
 	test_terminal git --paginate rev-list HEAD &&
-	test -e paginated.out
+	test_path_is_file paginated.out
 '
 
 test_expect_success 'no pager even with --paginate when stdout is a pipe' '
 	rm -f file paginated.out &&
 	git --paginate log | cat &&
-	! test -e paginated.out
+	test_path_is_missing paginated.out
 '
 
 test_expect_success TTY 'no pager with --no-pager' '
 	rm -f paginated.out &&
 	test_terminal git --no-pager log &&
-	! test -e paginated.out
+	test_path_is_missing paginated.out
 '
 
 test_expect_success TTY 'configuration can disable pager' '
 	rm -f paginated.out &&
 	test_unconfig pager.grep &&
 	test_terminal git grep initial &&
-	test -e paginated.out &&
+	test_path_is_file paginated.out &&
 
 	rm -f paginated.out &&
 	test_config pager.grep false &&
 	test_terminal git grep initial &&
-	! test -e paginated.out
+	test_path_is_missing paginated.out
 '
 
 test_expect_success TTY 'configuration can enable pager (from subdir)' '
@@ -122,107 +122,107 @@
 		test_terminal git bundle unbundle ../test.bundle
 	) &&
 	{
-		test -e paginated.out ||
-		test -e subdir/paginated.out
+		test_path_is_file paginated.out ||
+		test_path_is_file subdir/paginated.out
 	}
 '
 
 test_expect_success TTY 'git tag -l defaults to paging' '
 	rm -f paginated.out &&
 	test_terminal git tag -l &&
-	test -e paginated.out
+	test_path_is_file paginated.out
 '
 
 test_expect_success TTY 'git tag -l respects pager.tag' '
 	rm -f paginated.out &&
 	test_terminal git -c pager.tag=false tag -l &&
-	! test -e paginated.out
+	test_path_is_missing paginated.out
 '
 
 test_expect_success TTY 'git tag -l respects --no-pager' '
 	rm -f paginated.out &&
 	test_terminal git -c pager.tag --no-pager tag -l &&
-	! test -e paginated.out
+	test_path_is_missing paginated.out
 '
 
 test_expect_success TTY 'git tag with no args defaults to paging' '
 	# no args implies -l so this should page like -l
 	rm -f paginated.out &&
 	test_terminal git tag &&
-	test -e paginated.out
+	test_path_is_file paginated.out
 '
 
 test_expect_success TTY 'git tag with no args respects pager.tag' '
 	# no args implies -l so this should page like -l
 	rm -f paginated.out &&
 	test_terminal git -c pager.tag=false tag &&
-	! test -e paginated.out
+	test_path_is_missing paginated.out
 '
 
 test_expect_success TTY 'git tag --contains defaults to paging' '
 	# --contains implies -l so this should page like -l
 	rm -f paginated.out &&
 	test_terminal git tag --contains &&
-	test -e paginated.out
+	test_path_is_file paginated.out
 '
 
 test_expect_success TTY 'git tag --contains respects pager.tag' '
 	# --contains implies -l so this should page like -l
 	rm -f paginated.out &&
 	test_terminal git -c pager.tag=false tag --contains &&
-	! test -e paginated.out
+	test_path_is_missing paginated.out
 '
 
 test_expect_success TTY 'git tag -a defaults to not paging' '
 	test_when_finished "git tag -d newtag" &&
 	rm -f paginated.out &&
 	test_terminal git tag -am message newtag &&
-	! test -e paginated.out
+	test_path_is_missing paginated.out
 '
 
 test_expect_success TTY 'git tag -a ignores pager.tag' '
 	test_when_finished "git tag -d newtag" &&
 	rm -f paginated.out &&
 	test_terminal git -c pager.tag tag -am message newtag &&
-	! test -e paginated.out
+	test_path_is_missing paginated.out
 '
 
 test_expect_success TTY 'git tag -a respects --paginate' '
 	test_when_finished "git tag -d newtag" &&
 	rm -f paginated.out &&
 	test_terminal git --paginate tag -am message newtag &&
-	test -e paginated.out
+	test_path_is_file paginated.out
 '
 
 test_expect_success TTY 'git tag as alias ignores pager.tag with -a' '
 	test_when_finished "git tag -d newtag" &&
 	rm -f paginated.out &&
 	test_terminal git -c pager.tag -c alias.t=tag t -am message newtag &&
-	! test -e paginated.out
+	test_path_is_missing paginated.out
 '
 
 test_expect_success TTY 'git tag as alias respects pager.tag with -l' '
 	rm -f paginated.out &&
 	test_terminal git -c pager.tag=false -c alias.t=tag t -l &&
-	! test -e paginated.out
+	test_path_is_missing paginated.out
 '
 
 test_expect_success TTY 'git branch defaults to paging' '
 	rm -f paginated.out &&
 	test_terminal git branch &&
-	test -e paginated.out
+	test_path_is_file paginated.out
 '
 
 test_expect_success TTY 'git branch respects pager.branch' '
 	rm -f paginated.out &&
 	test_terminal git -c pager.branch=false branch &&
-	! test -e paginated.out
+	test_path_is_missing paginated.out
 '
 
 test_expect_success TTY 'git branch respects --no-pager' '
 	rm -f paginated.out &&
 	test_terminal git --no-pager branch &&
-	! test -e paginated.out
+	test_path_is_missing paginated.out
 '
 
 test_expect_success TTY 'git branch --edit-description ignores pager.branch' '
@@ -232,8 +232,8 @@
 		touch editor.used
 	EOF
 	EDITOR=./editor test_terminal git -c pager.branch branch --edit-description &&
-	! test -e paginated.out &&
-	test -e editor.used
+	test_path_is_missing paginated.out &&
+	test_path_is_file editor.used
 '
 
 test_expect_success TTY 'git branch --set-upstream-to ignores pager.branch' '
@@ -242,13 +242,13 @@
 	test_when_finished "git branch -D other" &&
 	test_terminal git -c pager.branch branch --set-upstream-to=other &&
 	test_when_finished "git branch --unset-upstream" &&
-	! test -e paginated.out
+	test_path_is_missing paginated.out
 '
 
 test_expect_success TTY 'git config ignores pager.config when setting' '
 	rm -f paginated.out &&
 	test_terminal git -c pager.config config foo.bar bar &&
-	! test -e paginated.out
+	test_path_is_missing paginated.out
 '
 
 test_expect_success TTY 'git config --edit ignores pager.config' '
@@ -257,33 +257,33 @@
 		touch editor.used
 	EOF
 	EDITOR=./editor test_terminal git -c pager.config config --edit &&
-	! test -e paginated.out &&
-	test -e editor.used
+	test_path_is_missing paginated.out &&
+	test_path_is_file editor.used
 '
 
 test_expect_success TTY 'git config --get ignores pager.config' '
 	rm -f paginated.out &&
 	test_terminal git -c pager.config config --get foo.bar &&
-	! test -e paginated.out
+	test_path_is_missing paginated.out
 '
 
 test_expect_success TTY 'git config --get-urlmatch defaults to paging' '
 	rm -f paginated.out &&
 	test_terminal git -c http."https://foo.com/".bar=foo \
 			  config --get-urlmatch http https://foo.com &&
-	test -e paginated.out
+	test_path_is_file paginated.out
 '
 
 test_expect_success TTY 'git config --get-all respects pager.config' '
 	rm -f paginated.out &&
 	test_terminal git -c pager.config=false config --get-all foo.bar &&
-	! test -e paginated.out
+	test_path_is_missing paginated.out
 '
 
 test_expect_success TTY 'git config --list defaults to paging' '
 	rm -f paginated.out &&
 	test_terminal git config --list &&
-	test -e paginated.out
+	test_path_is_file paginated.out
 '
 
 
@@ -392,7 +392,7 @@
 			export PATH &&
 			$full_command
 		) &&
-		test -e default_pager_used
+		test_path_is_file default_pager_used
 	"
 }
 
@@ -406,7 +406,7 @@
 		PAGER='wc >PAGER_used' &&
 		export PAGER &&
 		$full_command &&
-		test -e PAGER_used
+		test_path_is_file PAGER_used
 	"
 }
 
@@ -432,7 +432,7 @@
 		export PAGER &&
 		test_config core.pager 'wc >core.pager_used' &&
 		$full_command &&
-		${if_local_config}test -e core.pager_used
+		${if_local_config}test_path_is_file core.pager_used
 	"
 }
 
@@ -464,7 +464,7 @@
 			cd sub &&
 			$full_command
 		) &&
-		${if_local_config}test -e core.pager_used
+		${if_local_config}test_path_is_file core.pager_used
 	"
 }
 
@@ -477,7 +477,7 @@
 		GIT_PAGER='wc >GIT_PAGER_used' &&
 		export GIT_PAGER &&
 		$full_command &&
-		test -e GIT_PAGER_used
+		test_path_is_file GIT_PAGER_used
 	"
 }
 
@@ -489,7 +489,7 @@
 		GIT_PAGER='wc >GIT_PAGER_used' &&
 		export GIT_PAGER &&
 		$full_command &&
-		! test -e GIT_PAGER_used
+		test_path_is_missing GIT_PAGER_used
 	"
 }
 
diff --git a/t/t7101-reset-empty-subdirs.sh b/t/t7101-reset-empty-subdirs.sh
index 96e163f..bfce05a 100755
--- a/t/t7101-reset-empty-subdirs.sh
+++ b/t/t7101-reset-empty-subdirs.sh
@@ -6,16 +6,15 @@
 test_description='git reset should cull empty subdirs'
 . ./test-lib.sh
 
-test_expect_success \
-    'creating initial files' \
-    'mkdir path0 &&
+test_expect_success 'creating initial files' '
+     mkdir path0 &&
      cp "$TEST_DIRECTORY"/../COPYING path0/COPYING &&
      git add path0/COPYING &&
-     git commit -m add -a'
+     git commit -m add -a
+'
 
-test_expect_success \
-    'creating second files' \
-    'mkdir path1 &&
+test_expect_success 'creating second files' '
+     mkdir path1 &&
      mkdir path1/path2 &&
      cp "$TEST_DIRECTORY"/../COPYING path1/path2/COPYING &&
      cp "$TEST_DIRECTORY"/../COPYING path1/COPYING &&
@@ -25,39 +24,40 @@
      git add path1/COPYING &&
      git add COPYING &&
      git add path0/COPYING-TOO &&
-     git commit -m change -a'
+     git commit -m change -a
+'
 
-test_expect_success \
-    'resetting tree HEAD^' \
-    'git reset --hard HEAD^'
+test_expect_success 'resetting tree HEAD^' '
+     git reset --hard HEAD^
+'
 
-test_expect_success \
-    'checking initial files exist after rewind' \
-    'test -d path0 &&
-     test -f path0/COPYING'
+test_expect_success 'checking initial files exist after rewind' '
+     test -d path0 &&
+     test -f path0/COPYING
+'
 
-test_expect_success \
-    'checking lack of path1/path2/COPYING' \
-    '! test -f path1/path2/COPYING'
+test_expect_success 'checking lack of path1/path2/COPYING' '
+    ! test -f path1/path2/COPYING
+'
 
-test_expect_success \
-    'checking lack of path1/COPYING' \
-    '! test -f path1/COPYING'
+test_expect_success 'checking lack of path1/COPYING' '
+    ! test -f path1/COPYING
+'
 
-test_expect_success \
-    'checking lack of COPYING' \
-    '! test -f COPYING'
+test_expect_success 'checking lack of COPYING' '
+     ! test -f COPYING
+'
 
-test_expect_success \
-    'checking checking lack of path1/COPYING-TOO' \
-    '! test -f path0/COPYING-TOO'
+test_expect_success 'checking checking lack of path1/COPYING-TOO' '
+     ! test -f path0/COPYING-TOO
+'
 
-test_expect_success \
-    'checking lack of path1/path2' \
-    '! test -d path1/path2'
+test_expect_success 'checking lack of path1/path2' '
+     ! test -d path1/path2
+'
 
-test_expect_success \
-    'checking lack of path1' \
-    '! test -d path1'
+test_expect_success 'checking lack of path1' '
+     ! test -d path1
+'
 
 test_done
diff --git a/t/t7102-reset.sh b/t/t7102-reset.sh
index 22161b3..b1affb0 100755
--- a/t/t7102-reset.sh
+++ b/t/t7102-reset.sh
@@ -70,27 +70,27 @@
 
 test_expect_success 'reset --hard message' '
 	hex=$(git log -1 --format="%h") &&
-	git reset --hard > .actual &&
-	echo HEAD is now at $hex $(commit_msg) > .expected &&
+	git reset --hard >.actual &&
+	echo HEAD is now at $hex $(commit_msg) >.expected &&
 	test_i18ncmp .expected .actual
 '
 
 test_expect_success 'reset --hard message (ISO8859-1 logoutputencoding)' '
 	hex=$(git log -1 --format="%h") &&
-	git -c "i18n.logOutputEncoding=$test_encoding" reset --hard > .actual &&
-	echo HEAD is now at $hex $(commit_msg $test_encoding) > .expected &&
+	git -c "i18n.logOutputEncoding=$test_encoding" reset --hard >.actual &&
+	echo HEAD is now at $hex $(commit_msg $test_encoding) >.expected &&
 	test_i18ncmp .expected .actual
 '
 
->.diff_expect
->.cached_expect
-cat >.cat_expect <<EOF
-secondfile:
-1st line 2nd file
-2nd line 2nd file
-EOF
-
 test_expect_success 'giving a non existing revision should fail' '
+	>.diff_expect &&
+	>.cached_expect &&
+	cat >.cat_expect <<-\EOF &&
+	secondfile:
+	1st line 2nd file
+	2nd line 2nd file
+	EOF
+
 	test_must_fail git reset aaaaaa &&
 	test_must_fail git reset --mixed aaaaaa &&
 	test_must_fail git reset --soft aaaaaa &&
@@ -107,8 +107,7 @@
 	git rm --cached -- un
 '
 
-test_expect_success \
-	'giving paths with options different than --mixed should fail' '
+test_expect_success 'giving paths with options different than --mixed should fail' '
 	test_must_fail git reset --soft -- first &&
 	test_must_fail git reset --hard -- first &&
 	test_must_fail git reset --soft HEAD^ -- first &&
@@ -128,8 +127,7 @@
 	check_changes $head5
 '
 
-test_expect_success \
-	'trying to do reset --soft with pending merge should fail' '
+test_expect_success 'trying to do reset --soft with pending merge should fail' '
 	git branch branch1 &&
 	git branch branch2 &&
 
@@ -152,8 +150,7 @@
 	check_changes $head5
 '
 
-test_expect_success \
-	'trying to do reset --soft with pending checkout merge should fail' '
+test_expect_success 'trying to do reset --soft with pending checkout merge should fail' '
 	git branch branch3 &&
 	git branch branch4 &&
 
@@ -175,8 +172,7 @@
 	check_changes $head5
 '
 
-test_expect_success \
-	'resetting to HEAD with no changes should succeed and do nothing' '
+test_expect_success 'resetting to HEAD with no changes should succeed and do nothing' '
 	git reset --hard &&
 		check_changes $head5 &&
 	git reset --hard HEAD &&
@@ -195,39 +191,38 @@
 		check_changes $head5
 '
 
->.diff_expect
-cat >.cached_expect <<EOF
-diff --git a/secondfile b/secondfile
-index $head5p1s..$head5s 100644
---- a/secondfile
-+++ b/secondfile
-@@ -1 +1,2 @@
--2nd file
-+1st line 2nd file
-+2nd line 2nd file
-EOF
-cat >.cat_expect <<EOF
-secondfile:
-1st line 2nd file
-2nd line 2nd file
-EOF
 test_expect_success '--soft reset only should show changes in diff --cached' '
+	>.diff_expect &&
+	cat >.cached_expect <<-EOF &&
+	diff --git a/secondfile b/secondfile
+	index $head5p1s..$head5s 100644
+	--- a/secondfile
+	+++ b/secondfile
+	@@ -1 +1,2 @@
+	-2nd file
+	+1st line 2nd file
+	+2nd line 2nd file
+	EOF
+	cat >.cat_expect <<-\EOF &&
+	secondfile:
+	1st line 2nd file
+	2nd line 2nd file
+	EOF
 	git reset --soft HEAD^ &&
 	check_changes $head5p1 &&
 	test "$(git rev-parse ORIG_HEAD)" = \
 			$head5
 '
 
->.diff_expect
->.cached_expect
-cat >.cat_expect <<EOF
-secondfile:
-1st line 2nd file
-2nd line 2nd file
-3rd line 2nd file
-EOF
-test_expect_success \
-	'changing files and redo the last commit should succeed' '
+test_expect_success 'changing files and redo the last commit should succeed' '
+	>.diff_expect &&
+	>.cached_expect &&
+	cat >.cat_expect <<-\EOF &&
+	secondfile:
+	1st line 2nd file
+	2nd line 2nd file
+	3rd line 2nd file
+	EOF
 	echo "3rd line 2nd file" >>secondfile &&
 	git commit -a -C ORIG_HEAD &&
 	head4=$(git rev-parse --verify HEAD) &&
@@ -236,56 +231,54 @@
 			$head5
 '
 
->.diff_expect
->.cached_expect
-cat >.cat_expect <<EOF
-first:
-1st file
-2nd line 1st file
-second:
-2nd file
-EOF
-test_expect_success \
-	'--hard reset should change the files and undo commits permanently' '
+test_expect_success '--hard reset should change the files and undo commits permanently' '
+	>.diff_expect &&
+	>.cached_expect &&
+	cat >.cat_expect <<-\EOF &&
+	first:
+	1st file
+	2nd line 1st file
+	second:
+	2nd file
+	EOF
 	git reset --hard HEAD~2 &&
 	check_changes $head5p2 &&
 	test "$(git rev-parse ORIG_HEAD)" = \
 			$head4
 '
 
->.diff_expect
-cat >.cached_expect <<EOF
-diff --git a/first b/first
-deleted file mode 100644
-index $head5p2f..0000000
---- a/first
-+++ /dev/null
-@@ -1,2 +0,0 @@
--1st file
--2nd line 1st file
-diff --git a/second b/second
-deleted file mode 100644
-index $head5p1s..0000000
---- a/second
-+++ /dev/null
-@@ -1 +0,0 @@
--2nd file
-diff --git a/secondfile b/secondfile
-new file mode 100644
-index 0000000..$head5s
---- /dev/null
-+++ b/secondfile
-@@ -0,0 +1,2 @@
-+1st line 2nd file
-+2nd line 2nd file
-EOF
-cat >.cat_expect <<EOF
-secondfile:
-1st line 2nd file
-2nd line 2nd file
-EOF
-test_expect_success \
-	'redoing changes adding them without commit them should succeed' '
+test_expect_success 'redoing changes adding them without commit them should succeed' '
+	>.diff_expect &&
+	cat >.cached_expect <<-EOF &&
+	diff --git a/first b/first
+	deleted file mode 100644
+	index $head5p2f..0000000
+	--- a/first
+	+++ /dev/null
+	@@ -1,2 +0,0 @@
+	-1st file
+	-2nd line 1st file
+	diff --git a/second b/second
+	deleted file mode 100644
+	index $head5p1s..0000000
+	--- a/second
+	+++ /dev/null
+	@@ -1 +0,0 @@
+	-2nd file
+	diff --git a/secondfile b/secondfile
+	new file mode 100644
+	index 0000000..$head5s
+	--- /dev/null
+	+++ b/secondfile
+	@@ -0,0 +1,2 @@
+	+1st line 2nd file
+	+2nd line 2nd file
+	EOF
+	cat >.cat_expect <<-\EOF &&
+	secondfile:
+	1st line 2nd file
+	2nd line 2nd file
+	EOF
 	git rm first &&
 	git mv second secondfile &&
 
@@ -295,46 +288,45 @@
 	check_changes $head5p2
 '
 
-cat >.diff_expect <<EOF
-diff --git a/first b/first
-deleted file mode 100644
-index $head5p2f..0000000
---- a/first
-+++ /dev/null
-@@ -1,2 +0,0 @@
--1st file
--2nd line 1st file
-diff --git a/second b/second
-deleted file mode 100644
-index $head5p1s..0000000
---- a/second
-+++ /dev/null
-@@ -1 +0,0 @@
--2nd file
-EOF
->.cached_expect
-cat >.cat_expect <<EOF
-secondfile:
-1st line 2nd file
-2nd line 2nd file
-EOF
 test_expect_success '--mixed reset to HEAD should unadd the files' '
+	cat >.diff_expect <<-EOF &&
+	diff --git a/first b/first
+	deleted file mode 100644
+	index $head5p2f..0000000
+	--- a/first
+	+++ /dev/null
+	@@ -1,2 +0,0 @@
+	-1st file
+	-2nd line 1st file
+	diff --git a/second b/second
+	deleted file mode 100644
+	index $head5p1s..0000000
+	--- a/second
+	+++ /dev/null
+	@@ -1 +0,0 @@
+	-2nd file
+	EOF
+	>.cached_expect &&
+	cat >.cat_expect <<-\EOF &&
+	secondfile:
+	1st line 2nd file
+	2nd line 2nd file
+	EOF
 	git reset &&
 	check_changes $head5p2 &&
 	test "$(git rev-parse ORIG_HEAD)" = $head5p2
 '
 
->.diff_expect
->.cached_expect
-cat >.cat_expect <<EOF
-secondfile:
-1st line 2nd file
-2nd line 2nd file
-EOF
 test_expect_success 'redoing the last two commits should succeed' '
+	>.diff_expect &&
+	>.cached_expect &&
+	cat >.cat_expect <<-\EOF &&
+	secondfile:
+	1st line 2nd file
+	2nd line 2nd file
+	EOF
 	git add secondfile &&
 	git reset --hard $head5p2 &&
-
 	git rm first &&
 	git mv second secondfile &&
 	git commit -a -m "remove 1st and rename 2nd" &&
@@ -347,15 +339,15 @@
 	check_changes $head5
 '
 
->.diff_expect
->.cached_expect
-cat >.cat_expect <<EOF
-secondfile:
-1st line 2nd file
-2nd line 2nd file
-3rd line in branch2
-EOF
 test_expect_success '--hard reset to HEAD should clear a failed merge' '
+	>.diff_expect &&
+	>.cached_expect &&
+	cat >.cat_expect <<-\EOF &&
+	secondfile:
+	1st line 2nd file
+	2nd line 2nd file
+	3rd line in branch2
+	EOF
 	git branch branch1 &&
 	git branch branch2 &&
 
@@ -373,15 +365,14 @@
 	check_changes $head3
 '
 
->.diff_expect
->.cached_expect
-cat >.cat_expect <<EOF
-secondfile:
-1st line 2nd file
-2nd line 2nd file
-EOF
-test_expect_success \
-	'--hard reset to ORIG_HEAD should clear a fast-forward merge' '
+test_expect_success '--hard reset to ORIG_HEAD should clear a fast-forward merge' '
+	>.diff_expect &&
+	>.cached_expect &&
+	cat >.cat_expect <<-\EOF &&
+	secondfile:
+	1st line 2nd file
+	2nd line 2nd file
+	EOF
 	git reset --hard HEAD^ &&
 	check_changes $head5 &&
 
@@ -395,25 +386,25 @@
 '
 
 test_expect_success 'test --mixed <paths>' '
-	echo 1 > file1 &&
-	echo 2 > file2 &&
+	echo 1 >file1 &&
+	echo 2 >file2 &&
 	git add file1 file2 &&
 	test_tick &&
 	git commit -m files &&
 	before1=$(git rev-parse --short HEAD:file1) &&
 	before2=$(git rev-parse --short HEAD:file2) &&
 	git rm file2 &&
-	echo 3 > file3 &&
-	echo 4 > file4 &&
-	echo 5 > file1 &&
+	echo 3 >file3 &&
+	echo 4 >file4 &&
+	echo 5 >file1 &&
 	after1=$(git rev-parse --short $(git hash-object file1)) &&
 	after4=$(git rev-parse --short $(git hash-object file4)) &&
 	git add file1 file3 file4 &&
 	git reset HEAD -- file1 file2 file3 &&
 	test_must_fail git diff --quiet &&
-	git diff > output &&
+	git diff >output &&
 
-	cat > expect <<-EOF &&
+	cat >expect <<-EOF &&
 	diff --git a/file1 b/file1
 	index $before1..$after1 100644
 	--- a/file1
@@ -431,9 +422,9 @@
 	EOF
 
 	test_cmp expect output &&
-	git diff --cached > output &&
+	git diff --cached >output &&
 
-	cat > cached_expect <<-EOF &&
+	cat >cached_expect <<-EOF &&
 	diff --git a/file4 b/file4
 	new file mode 100644
 	index 0000000..$after4
@@ -447,7 +438,6 @@
 '
 
 test_expect_success 'test resetting the index at give paths' '
-
 	mkdir sub &&
 	>sub/file1 &&
 	>sub/file2 &&
@@ -460,7 +450,6 @@
 	echo "$U" &&
 	test_must_fail git diff-index --cached --exit-code "$T" &&
 	test "$T" != "$U"
-
 '
 
 test_expect_success 'resetting an unmodified path is a no-op' '
@@ -470,14 +459,13 @@
 	git diff-index --cached --exit-code HEAD
 '
 
-cat > expect << EOF
-Unstaged changes after reset:
-M	file2
-EOF
-
 test_expect_success '--mixed refreshes the index' '
-	echo 123 >> file2 &&
-	git reset --mixed HEAD > output &&
+	cat >expect <<-\EOF &&
+	Unstaged changes after reset:
+	M	file2
+	EOF
+	echo 123 >>file2 &&
+	git reset --mixed HEAD >output &&
 	test_i18ncmp expect output
 '
 
@@ -498,7 +486,6 @@
 '
 
 test_expect_success 'disambiguation (1)' '
-
 	git reset --hard &&
 	>secondfile &&
 	git add secondfile &&
@@ -507,11 +494,9 @@
 	test -z "$(git diff --cached --name-only)" &&
 	test -f secondfile &&
 	test_must_be_empty secondfile
-
 '
 
 test_expect_success 'disambiguation (2)' '
-
 	git reset --hard &&
 	>secondfile &&
 	git add secondfile &&
@@ -519,11 +504,9 @@
 	test_must_fail git reset secondfile &&
 	test -n "$(git diff --cached --name-only -- secondfile)" &&
 	test ! -f secondfile
-
 '
 
 test_expect_success 'disambiguation (3)' '
-
 	git reset --hard &&
 	>secondfile &&
 	git add secondfile &&
@@ -532,11 +515,9 @@
 	test_must_fail git diff --quiet &&
 	test -z "$(git diff --cached --name-only)" &&
 	test ! -f secondfile
-
 '
 
 test_expect_success 'disambiguation (4)' '
-
 	git reset --hard &&
 	>secondfile &&
 	git add secondfile &&
diff --git a/t/t7201-co.sh b/t/t7201-co.sh
index 4d62b9b..b36a930 100755
--- a/t/t7201-co.sh
+++ b/t/t7201-co.sh
@@ -33,8 +33,7 @@
 
 
 test_expect_success setup '
-
-	fill x y z > same &&
+	fill x y z >same &&
 	fill 1 2 3 4 5 6 7 8 >one &&
 	fill a b c d e >two &&
 	git add same one two &&
@@ -56,14 +55,13 @@
 
 	git checkout -b simple master &&
 	rm -f one &&
-	fill a c e > two &&
+	fill a c e >two &&
 	git commit -a -m "Simple D one, M two" &&
 
 	git checkout master
 '
 
-test_expect_success "checkout from non-existing branch" '
-
+test_expect_success 'checkout from non-existing branch' '
 	git checkout -b delete-me master &&
 	git update-ref -d --no-deref refs/heads/delete-me &&
 	test refs/heads/delete-me = "$(git symbolic-ref HEAD)" &&
@@ -71,8 +69,7 @@
 	test refs/heads/master = "$(git symbolic-ref HEAD)"
 '
 
-test_expect_success "checkout with dirty tree without -m" '
-
+test_expect_success 'checkout with dirty tree without -m' '
 	fill 0 1 2 3 4 5 6 7 8 >one &&
 	if git checkout side
 	then
@@ -81,11 +78,9 @@
 	else
 		echo "happy - failed correctly"
 	fi
-
 '
 
-test_expect_success "checkout with unrelated dirty tree without -m" '
-
+test_expect_success 'checkout with unrelated dirty tree without -m' '
 	git checkout -f master &&
 	fill 0 1 2 3 4 5 6 7 8 >same &&
 	cp same kept &&
@@ -95,13 +90,12 @@
 	test_cmp messages.expect messages
 '
 
-test_expect_success "checkout -m with dirty tree" '
-
+test_expect_success 'checkout -m with dirty tree' '
 	git checkout -f master &&
 	git clean -f &&
 
 	fill 0 1 2 3 4 5 6 7 8 >one &&
-	git checkout -m side > messages &&
+	git checkout -m side >messages &&
 
 	test "$(git symbolic-ref HEAD)" = "refs/heads/side" &&
 
@@ -120,8 +114,7 @@
 	test_must_be_empty current.index
 '
 
-test_expect_success "checkout -m with dirty tree, renamed" '
-
+test_expect_success 'checkout -m with dirty tree, renamed' '
 	git checkout -f master && git clean -f &&
 
 	fill 1 2 3 4 5 7 8 >one &&
@@ -139,11 +132,9 @@
 	! test -f one &&
 	git diff --cached >current &&
 	test_must_be_empty current
-
 '
 
 test_expect_success 'checkout -m with merge conflict' '
-
 	git checkout -f master && git clean -f &&
 
 	fill 1 T 3 4 5 6 S 8 >one &&
@@ -166,10 +157,10 @@
 '
 
 test_expect_success 'format of merge conflict from checkout -m' '
+	git checkout -f master &&
+	git clean -f &&
 
-	git checkout -f master && git clean -f &&
-
-	fill b d > two &&
+	fill b d >two &&
 	git checkout -m simple &&
 
 	git ls-files >current &&
@@ -190,10 +181,11 @@
 '
 
 test_expect_success 'checkout --merge --conflict=diff3 <branch>' '
+	git checkout -f master &&
+	git reset --hard &&
+	git clean -f &&
 
-	git checkout -f master && git reset --hard && git clean -f &&
-
-	fill b d > two &&
+	fill b d >two &&
 	git checkout --merge --conflict=diff3 simple &&
 
 	cat <<-EOF >expect &&
@@ -216,8 +208,9 @@
 '
 
 test_expect_success 'switch to another branch while carrying a deletion' '
-
-	git checkout -f master && git reset --hard && git clean -f &&
+	git checkout -f master &&
+	git reset --hard &&
+	git clean -f &&
 	git rm two &&
 
 	test_must_fail git checkout simple 2>errs &&
@@ -228,10 +221,10 @@
 '
 
 test_expect_success 'checkout to detach HEAD (with advice declined)' '
-
 	git config advice.detachedHead false &&
 	rev=$(git rev-parse --short renamer^) &&
-	git checkout -f renamer && git clean -f &&
+	git checkout -f renamer &&
+	git clean -f &&
 	git checkout renamer^ 2>messages &&
 	test_i18ngrep "HEAD is now at $rev" messages &&
 	test_line_count = 1 messages &&
@@ -250,7 +243,8 @@
 test_expect_success 'checkout to detach HEAD' '
 	git config advice.detachedHead true &&
 	rev=$(git rev-parse --short renamer^) &&
-	git checkout -f renamer && git clean -f &&
+	git checkout -f renamer &&
+	git clean -f &&
 	GIT_TEST_GETTEXT_POISON=false git checkout renamer^ 2>messages &&
 	grep "HEAD is now at $rev" messages &&
 	test_line_count -gt 1 messages &&
@@ -267,8 +261,8 @@
 '
 
 test_expect_success 'checkout to detach HEAD with branchname^' '
-
-	git checkout -f master && git clean -f &&
+	git checkout -f master &&
+	git clean -f &&
 	git checkout renamer^ &&
 	H=$(git rev-parse --verify HEAD) &&
 	M=$(git show-ref -s --verify refs/heads/master) &&
@@ -283,8 +277,8 @@
 '
 
 test_expect_success 'checkout to detach HEAD with :/message' '
-
-	git checkout -f master && git clean -f &&
+	git checkout -f master &&
+	git clean -f &&
 	git checkout ":/Initial" &&
 	H=$(git rev-parse --verify HEAD) &&
 	M=$(git show-ref -s --verify refs/heads/master) &&
@@ -299,8 +293,8 @@
 '
 
 test_expect_success 'checkout to detach HEAD with HEAD^0' '
-
-	git checkout -f master && git clean -f &&
+	git checkout -f master &&
+	git clean -f &&
 	git checkout HEAD^0 &&
 	H=$(git rev-parse --verify HEAD) &&
 	M=$(git show-ref -s --verify refs/heads/master) &&
@@ -315,7 +309,6 @@
 '
 
 test_expect_success 'checkout with ambiguous tag/branch names' '
-
 	git tag both side &&
 	git branch both master &&
 	git reset --hard &&
@@ -327,11 +320,9 @@
 	test "z$H" = "z$M" &&
 	name=$(git symbolic-ref HEAD 2>/dev/null) &&
 	test "z$name" = zrefs/heads/both
-
 '
 
 test_expect_success 'checkout with ambiguous tag/branch names' '
-
 	git reset --hard &&
 	git checkout master &&
 
@@ -351,26 +342,19 @@
 	else
 		: happy
 	fi
-
 '
 
 test_expect_success 'switch branches while in subdirectory' '
-
 	git reset --hard &&
 	git checkout master &&
 
 	mkdir subs &&
-	(
-		cd subs &&
-		git checkout side
-	) &&
+	git -C subs checkout side &&
 	! test -f subs/one &&
 	rm -fr subs
-
 '
 
 test_expect_success 'checkout specific path while in subdirectory' '
-
 	git reset --hard &&
 	git checkout side &&
 	mkdir subs &&
@@ -380,30 +364,26 @@
 
 	git checkout master &&
 	mkdir -p subs &&
-	(
-		cd subs &&
-		git checkout side -- bero
-	) &&
+	git -C subs checkout side -- bero &&
 	test -f subs/bero
-
 '
 
-test_expect_success \
-    'checkout w/--track sets up tracking' '
+test_expect_success 'checkout w/--track sets up tracking' '
     git config branch.autosetupmerge false &&
     git checkout master &&
     git checkout --track -b track1 &&
     test "$(git config branch.track1.remote)" &&
-    test "$(git config branch.track1.merge)"'
+    test "$(git config branch.track1.merge)"
+'
 
-test_expect_success \
-    'checkout w/autosetupmerge=always sets up tracking' '
+test_expect_success 'checkout w/autosetupmerge=always sets up tracking' '
     test_when_finished git config branch.autosetupmerge false &&
     git config branch.autosetupmerge always &&
     git checkout master &&
     git checkout -b track2 &&
     test "$(git config branch.track2.remote)" &&
-    test "$(git config branch.track2.merge)"'
+    test "$(git config branch.track2.merge)"
+'
 
 test_expect_success 'checkout w/--track from non-branch HEAD fails' '
     git checkout master^0 &&
@@ -435,8 +415,7 @@
     test "z$(git rev-parse --verify refs/heads/master)" = "z$here"
 '
 
-test_expect_success \
-    'checkout with --track fakes a sensible -b <name>' '
+test_expect_success 'checkout with --track fakes a sensible -b <name>' '
     git config remote.origin.fetch "+refs/heads/*:refs/remotes/origin/*" &&
     git update-ref refs/remotes/origin/koala/bear renamer &&
 
@@ -457,9 +436,9 @@
     test "$(git rev-parse HEAD)" = "$(git rev-parse renamer)"
 '
 
-test_expect_success \
-    'checkout with --track, but without -b, fails with too short tracked name' '
-    test_must_fail git checkout --track renamer'
+test_expect_success 'checkout with --track, but without -b, fails with too short tracked name' '
+    test_must_fail git checkout --track renamer
+'
 
 setup_conflicting_index () {
 	rm -f .git/index &&
@@ -609,7 +588,6 @@
 	test $(git symbolic-ref HEAD) = refs/heads/master &&
 	git diff --exit-code &&
 	git diff --cached --exit-code
-
 '
 
 test_expect_success 'switch out of non-branch' '
diff --git a/t/t7518-ident-corner-cases.sh b/t/t7518-ident-corner-cases.sh
index dc3e9c8..905957b 100755
--- a/t/t7518-ident-corner-cases.sh
+++ b/t/t7518-ident-corner-cases.sh
@@ -13,7 +13,7 @@
 		sane_unset GIT_AUTHOR_EMAIL &&
 		GIT_AUTHOR_NAME= &&
 		test_must_fail git commit --allow-empty -m foo 2>err &&
-		test_i18ngrep ! null err
+		test_i18ngrep ! "(null)" err
 	)
 '
 
diff --git a/t/t7601-merge-pull-config.sh b/t/t7601-merge-pull-config.sh
index c5c4ea5..6774e9d 100755
--- a/t/t7601-merge-pull-config.sh
+++ b/t/t7601-merge-pull-config.sh
@@ -29,8 +29,11 @@
 
 test_expect_success 'pull.rebase not set' '
 	git reset --hard c0 &&
-	git pull . c1 2>err &&
-	test_i18ngrep "Pulling without specifying how to reconcile" err
+	git -c color.advice=always pull . c1 2>err &&
+	test_decode_color <err >decoded &&
+	test_i18ngrep "<YELLOW>hint: " decoded &&
+	test_i18ngrep "Pulling without specifying how to reconcile" decoded
+
 '
 
 test_expect_success 'pull.rebase not set and pull.ff=true' '
diff --git a/t/t7602-merge-octopus-many.sh b/t/t7602-merge-octopus-many.sh
index 6abe441..13859ec 100755
--- a/t/t7602-merge-octopus-many.sh
+++ b/t/t7602-merge-octopus-many.sh
@@ -77,6 +77,12 @@
 EOF
 
 test_expect_success 'merge reduces irrelevant remote heads' '
+	if test "$GIT_TEST_MERGE_ALGORITHM" = ort
+	then
+		mv expected expected.tmp &&
+		sed s/recursive/ort/ expected.tmp >expected &&
+		rm expected.tmp
+	fi &&
 	GIT_MERGE_VERBOSITY=0 git merge c4 c5 >actual &&
 	test_i18ncmp expected actual
 '
diff --git a/t/t7610-mergetool.sh b/t/t7610-mergetool.sh
index ad288dd..70afdd0 100755
--- a/t/t7610-mergetool.sh
+++ b/t/t7610-mergetool.sh
@@ -532,7 +532,14 @@
 	yes "" | git mergetool file1 file2 spaced\ name subdir/file3 &&
 	yes "" | git mergetool both &&
 	yes "d" | git mergetool file11 file12 &&
-	yes "l" | git mergetool submod &&
+	if test "$GIT_TEST_MERGE_ALGORITHM" = ort
+	then
+		yes "c" | git mergetool submod~HEAD &&
+		git rm submod &&
+		git mv submod~HEAD submod
+	else
+		yes "l" | git mergetool submod
+	fi &&
 	git submodule update -N &&
 	echo "not a submodule" >expect &&
 	test_cmp expect submod &&
@@ -549,7 +556,15 @@
 	yes "" | git mergetool file1 file2 spaced\ name subdir/file3 &&
 	yes "" | git mergetool both &&
 	yes "d" | git mergetool file11 file12 &&
-	yes "r" | git mergetool submod &&
+	if test "$GIT_TEST_MERGE_ALGORITHM" = ort
+	then
+		mv submod submod.orig &&
+		git rm --cached submod &&
+		yes "c" | git mergetool submod~test19 &&
+		git mv submod~test19 submod
+	else
+		yes "r" | git mergetool submod
+	fi &&
 	test -d submod.orig &&
 	git submodule update -N &&
 	echo "not a submodule" >expect &&
@@ -567,6 +582,10 @@
 	yes "" | git mergetool both &&
 	yes "d" | git mergetool file11 file12 &&
 	yes "l" | git mergetool submod &&
+	if test "$GIT_TEST_MERGE_ALGORITHM" = ort
+	then
+		yes "d" | git mergetool submod~test19
+	fi &&
 	echo "master submodule" >expect &&
 	test_cmp expect submod/bar &&
 	git submodule update -N &&
@@ -664,7 +683,14 @@
 	test_must_fail git merge master &&
 	test -n "$(git ls-files -u)" &&
 	test ! -e submod.orig &&
-	yes "r" | git mergetool submod &&
+	if test "$GIT_TEST_MERGE_ALGORITHM" = ort
+	then
+		yes "r" | git mergetool submod~master &&
+		git mv submod submod.orig &&
+		git mv submod~master submod
+	else
+		yes "r" | git mergetool submod
+	fi &&
 	test -d submod.orig &&
 	echo "not a submodule" >expect &&
 	test_cmp expect submod.orig/file16 &&
diff --git a/t/t7800-difftool.sh b/t/t7800-difftool.sh
index 524f30f..a578b35 100755
--- a/t/t7800-difftool.sh
+++ b/t/t7800-difftool.sh
@@ -728,6 +728,19 @@
 	git difftool --dir-diff --extcmd ls
 '
 
+test_expect_success 'difftool --cached with unmerged files' '
+	test_when_finished git reset --hard &&
+
+	test_commit conflicting &&
+	test_commit conflict-a conflict.t a &&
+	git reset --hard conflicting &&
+	test_commit conflict-b conflict.t b &&
+	test_must_fail git merge conflict-a &&
+
+	git difftool --cached --no-prompt >output &&
+	test_must_be_empty output
+'
+
 test_expect_success 'outside worktree' '
 	echo 1 >1 &&
 	echo 2 >2 &&
diff --git a/t/t7900-maintenance.sh b/t/t7900-maintenance.sh
index 53c8835..d9e68bb 100755
--- a/t/t7900-maintenance.sh
+++ b/t/t7900-maintenance.sh
@@ -5,10 +5,11 @@
 . ./test-lib.sh
 
 GIT_TEST_COMMIT_GRAPH=0
+GIT_TEST_MULTI_PACK_INDEX=0
 
 test_expect_success 'help text' '
 	test_expect_code 129 git maintenance -h 2>err &&
-	test_i18ngrep "usage: git maintenance run" err &&
+	test_i18ngrep "usage: git maintenance <subcommand>" err &&
 	test_expect_code 128 git maintenance barf 2>err &&
 	test_i18ngrep "invalid subcommand: barf" err &&
 	test_expect_code 129 git maintenance 2>err &&
@@ -27,6 +28,19 @@
 	test_subcommand git gc --no-quiet <run-no-quiet.txt
 '
 
+test_expect_success 'maintenance.auto config option' '
+	GIT_TRACE2_EVENT="$(pwd)/default" git commit --quiet --allow-empty -m 1 &&
+	test_subcommand git maintenance run --auto --quiet <default &&
+	GIT_TRACE2_EVENT="$(pwd)/true" \
+		git -c maintenance.auto=true \
+		commit --quiet --allow-empty -m 2 &&
+	test_subcommand git maintenance run --auto --quiet  <true &&
+	GIT_TRACE2_EVENT="$(pwd)/false" \
+		git -c maintenance.auto=false \
+		commit --quiet --allow-empty -m 3 &&
+	test_subcommand ! git maintenance run --auto --quiet  <false
+'
+
 test_expect_success 'maintenance.<task>.enabled' '
 	git config maintenance.gc.enabled false &&
 	git config maintenance.commit-graph.enabled true &&
@@ -52,6 +66,43 @@
 	test_subcommand git commit-graph write --split --reachable --no-progress <run-both.txt
 '
 
+test_expect_success 'core.commitGraph=false prevents write process' '
+	GIT_TRACE2_EVENT="$(pwd)/no-commit-graph.txt" \
+		git -c core.commitGraph=false maintenance run \
+		--task=commit-graph 2>/dev/null &&
+	test_subcommand ! git commit-graph write --split --reachable --no-progress \
+		<no-commit-graph.txt
+'
+
+test_expect_success 'commit-graph auto condition' '
+	COMMAND="maintenance run --task=commit-graph --auto --quiet" &&
+
+	GIT_TRACE2_EVENT="$(pwd)/cg-no.txt" \
+		git -c maintenance.commit-graph.auto=1 $COMMAND &&
+	GIT_TRACE2_EVENT="$(pwd)/cg-negative-means-yes.txt" \
+		git -c maintenance.commit-graph.auto="-1" $COMMAND &&
+
+	test_commit first &&
+
+	GIT_TRACE2_EVENT="$(pwd)/cg-zero-means-no.txt" \
+		git -c maintenance.commit-graph.auto=0 $COMMAND &&
+	GIT_TRACE2_EVENT="$(pwd)/cg-one-satisfied.txt" \
+		git -c maintenance.commit-graph.auto=1 $COMMAND &&
+
+	git commit --allow-empty -m "second" &&
+	git commit --allow-empty -m "third" &&
+
+	GIT_TRACE2_EVENT="$(pwd)/cg-two-satisfied.txt" \
+		git -c maintenance.commit-graph.auto=2 $COMMAND &&
+
+	COMMIT_GRAPH_WRITE="git commit-graph write --split --reachable --no-progress" &&
+	test_subcommand ! $COMMIT_GRAPH_WRITE <cg-no.txt &&
+	test_subcommand $COMMIT_GRAPH_WRITE <cg-negative-means-yes.txt &&
+	test_subcommand ! $COMMIT_GRAPH_WRITE <cg-zero-means-no.txt &&
+	test_subcommand $COMMIT_GRAPH_WRITE <cg-one-satisfied.txt &&
+	test_subcommand $COMMIT_GRAPH_WRITE <cg-two-satisfied.txt
+'
+
 test_expect_success 'run --task=bogus' '
 	test_must_fail git maintenance run --task=bogus 2>err &&
 	test_i18ngrep "is not a valid task" err
@@ -62,4 +113,332 @@
 	test_i18ngrep "cannot be selected multiple times" err
 '
 
+test_expect_success 'run --task=prefetch with no remotes' '
+	git maintenance run --task=prefetch 2>err &&
+	test_must_be_empty err
+'
+
+test_expect_success 'prefetch multiple remotes' '
+	git clone . clone1 &&
+	git clone . clone2 &&
+	git remote add remote1 "file://$(pwd)/clone1" &&
+	git remote add remote2 "file://$(pwd)/clone2" &&
+	git -C clone1 switch -c one &&
+	git -C clone2 switch -c two &&
+	test_commit -C clone1 one &&
+	test_commit -C clone2 two &&
+	GIT_TRACE2_EVENT="$(pwd)/run-prefetch.txt" git maintenance run --task=prefetch 2>/dev/null &&
+	fetchargs="--prune --no-tags --no-write-fetch-head --recurse-submodules=no --refmap= --quiet" &&
+	test_subcommand git fetch remote1 $fetchargs +refs/heads/\\*:refs/prefetch/remote1/\\* <run-prefetch.txt &&
+	test_subcommand git fetch remote2 $fetchargs +refs/heads/\\*:refs/prefetch/remote2/\\* <run-prefetch.txt &&
+	test_path_is_missing .git/refs/remotes &&
+	git log prefetch/remote1/one &&
+	git log prefetch/remote2/two &&
+	git fetch --all &&
+	test_cmp_rev refs/remotes/remote1/one refs/prefetch/remote1/one &&
+	test_cmp_rev refs/remotes/remote2/two refs/prefetch/remote2/two
+'
+
+test_expect_success 'loose-objects task' '
+	# Repack everything so we know the state of the object dir
+	git repack -adk &&
+
+	# Hack to stop maintenance from running during "git commit"
+	echo in use >.git/objects/maintenance.lock &&
+
+	# Assuming that "git commit" creates at least one loose object
+	test_commit create-loose-object &&
+	rm .git/objects/maintenance.lock &&
+
+	ls .git/objects >obj-dir-before &&
+	test_file_not_empty obj-dir-before &&
+	ls .git/objects/pack/*.pack >packs-before &&
+	test_line_count = 1 packs-before &&
+
+	# The first run creates a pack-file
+	# but does not delete loose objects.
+	git maintenance run --task=loose-objects &&
+	ls .git/objects >obj-dir-between &&
+	test_cmp obj-dir-before obj-dir-between &&
+	ls .git/objects/pack/*.pack >packs-between &&
+	test_line_count = 2 packs-between &&
+	ls .git/objects/pack/loose-*.pack >loose-packs &&
+	test_line_count = 1 loose-packs &&
+
+	# The second run deletes loose objects
+	# but does not create a pack-file.
+	git maintenance run --task=loose-objects &&
+	ls .git/objects >obj-dir-after &&
+	cat >expect <<-\EOF &&
+	info
+	pack
+	EOF
+	test_cmp expect obj-dir-after &&
+	ls .git/objects/pack/*.pack >packs-after &&
+	test_cmp packs-between packs-after
+'
+
+test_expect_success 'maintenance.loose-objects.auto' '
+	git repack -adk &&
+	GIT_TRACE2_EVENT="$(pwd)/trace-lo1.txt" \
+		git -c maintenance.loose-objects.auto=1 maintenance \
+		run --auto --task=loose-objects 2>/dev/null &&
+	test_subcommand ! git prune-packed --quiet <trace-lo1.txt &&
+	printf data-A | git hash-object -t blob --stdin -w &&
+	GIT_TRACE2_EVENT="$(pwd)/trace-loA" \
+		git -c maintenance.loose-objects.auto=2 \
+		maintenance run --auto --task=loose-objects 2>/dev/null &&
+	test_subcommand ! git prune-packed --quiet <trace-loA &&
+	printf data-B | git hash-object -t blob --stdin -w &&
+	GIT_TRACE2_EVENT="$(pwd)/trace-loB" \
+		git -c maintenance.loose-objects.auto=2 \
+		maintenance run --auto --task=loose-objects 2>/dev/null &&
+	test_subcommand git prune-packed --quiet <trace-loB &&
+	GIT_TRACE2_EVENT="$(pwd)/trace-loC" \
+		git -c maintenance.loose-objects.auto=2 \
+		maintenance run --auto --task=loose-objects 2>/dev/null &&
+	test_subcommand git prune-packed --quiet <trace-loC
+'
+
+test_expect_success 'incremental-repack task' '
+	packDir=.git/objects/pack &&
+	for i in $(test_seq 1 5)
+	do
+		test_commit $i || return 1
+	done &&
+
+	# Create three disjoint pack-files with size BIG, small, small.
+	echo HEAD~2 | git pack-objects --revs $packDir/test-1 &&
+	test_tick &&
+	git pack-objects --revs $packDir/test-2 <<-\EOF &&
+	HEAD~1
+	^HEAD~2
+	EOF
+	test_tick &&
+	git pack-objects --revs $packDir/test-3 <<-\EOF &&
+	HEAD
+	^HEAD~1
+	EOF
+	rm -f $packDir/pack-* &&
+	rm -f $packDir/loose-* &&
+	ls $packDir/*.pack >packs-before &&
+	test_line_count = 3 packs-before &&
+
+	# the job repacks the two into a new pack, but does not
+	# delete the old ones.
+	git maintenance run --task=incremental-repack &&
+	ls $packDir/*.pack >packs-between &&
+	test_line_count = 4 packs-between &&
+
+	# the job deletes the two old packs, and does not write
+	# a new one because the batch size is not high enough to
+	# pack the largest pack-file.
+	git maintenance run --task=incremental-repack &&
+	ls .git/objects/pack/*.pack >packs-after &&
+	test_line_count = 2 packs-after
+'
+
+test_expect_success EXPENSIVE 'incremental-repack 2g limit' '
+	for i in $(test_seq 1 5)
+	do
+		test-tool genrandom foo$i $((512 * 1024 * 1024 + 1)) >>big ||
+		return 1
+	done &&
+	git add big &&
+	git commit -m "Add big file (1)" &&
+
+	# ensure any possible loose objects are in a pack-file
+	git maintenance run --task=loose-objects &&
+
+	rm big &&
+	for i in $(test_seq 6 10)
+	do
+		test-tool genrandom foo$i $((512 * 1024 * 1024 + 1)) >>big ||
+		return 1
+	done &&
+	git add big &&
+	git commit -m "Add big file (2)" &&
+
+	# ensure any possible loose objects are in a pack-file
+	git maintenance run --task=loose-objects &&
+
+	# Now run the incremental-repack task and check the batch-size
+	GIT_TRACE2_EVENT="$(pwd)/run-2g.txt" git maintenance run \
+		--task=incremental-repack 2>/dev/null &&
+	test_subcommand git multi-pack-index repack \
+		 --no-progress --batch-size=2147483647 <run-2g.txt
+'
+
+test_expect_success 'maintenance.incremental-repack.auto' '
+	git repack -adk &&
+	git config core.multiPackIndex true &&
+	git multi-pack-index write &&
+	GIT_TRACE2_EVENT="$(pwd)/midx-init.txt" git \
+		-c maintenance.incremental-repack.auto=1 \
+		maintenance run --auto --task=incremental-repack 2>/dev/null &&
+	test_subcommand ! git multi-pack-index write --no-progress <midx-init.txt &&
+	test_commit A &&
+	git pack-objects --revs .git/objects/pack/pack <<-\EOF &&
+	HEAD
+	^HEAD~1
+	EOF
+	GIT_TRACE2_EVENT=$(pwd)/trace-A git \
+		-c maintenance.incremental-repack.auto=2 \
+		maintenance run --auto --task=incremental-repack 2>/dev/null &&
+	test_subcommand ! git multi-pack-index write --no-progress <trace-A &&
+	test_commit B &&
+	git pack-objects --revs .git/objects/pack/pack <<-\EOF &&
+	HEAD
+	^HEAD~1
+	EOF
+	GIT_TRACE2_EVENT=$(pwd)/trace-B git \
+		-c maintenance.incremental-repack.auto=2 \
+		maintenance run --auto --task=incremental-repack 2>/dev/null &&
+	test_subcommand git multi-pack-index write --no-progress <trace-B
+'
+
+test_expect_success '--auto and --schedule incompatible' '
+	test_must_fail git maintenance run --auto --schedule=daily 2>err &&
+	test_i18ngrep "at most one" err
+'
+
+test_expect_success 'invalid --schedule value' '
+	test_must_fail git maintenance run --schedule=annually 2>err &&
+	test_i18ngrep "unrecognized --schedule" err
+'
+
+test_expect_success '--schedule inheritance weekly -> daily -> hourly' '
+	git config maintenance.loose-objects.enabled true &&
+	git config maintenance.loose-objects.schedule hourly &&
+	git config maintenance.commit-graph.enabled true &&
+	git config maintenance.commit-graph.schedule daily &&
+	git config maintenance.incremental-repack.enabled true &&
+	git config maintenance.incremental-repack.schedule weekly &&
+
+	GIT_TRACE2_EVENT="$(pwd)/hourly.txt" \
+		git maintenance run --schedule=hourly 2>/dev/null &&
+	test_subcommand git prune-packed --quiet <hourly.txt &&
+	test_subcommand ! git commit-graph write --split --reachable \
+		--no-progress <hourly.txt &&
+	test_subcommand ! git multi-pack-index write --no-progress <hourly.txt &&
+
+	GIT_TRACE2_EVENT="$(pwd)/daily.txt" \
+		git maintenance run --schedule=daily 2>/dev/null &&
+	test_subcommand git prune-packed --quiet <daily.txt &&
+	test_subcommand git commit-graph write --split --reachable \
+		--no-progress <daily.txt &&
+	test_subcommand ! git multi-pack-index write --no-progress <daily.txt &&
+
+	GIT_TRACE2_EVENT="$(pwd)/weekly.txt" \
+		git maintenance run --schedule=weekly 2>/dev/null &&
+	test_subcommand git prune-packed --quiet <weekly.txt &&
+	test_subcommand git commit-graph write --split --reachable \
+		--no-progress <weekly.txt &&
+	test_subcommand git multi-pack-index write --no-progress <weekly.txt
+'
+
+test_expect_success 'maintenance.strategy inheritance' '
+	for task in commit-graph loose-objects incremental-repack
+	do
+		git config --unset maintenance.$task.schedule || return 1
+	done &&
+
+	test_when_finished git config --unset maintenance.strategy &&
+	git config maintenance.strategy incremental &&
+
+	GIT_TRACE2_EVENT="$(pwd)/incremental-hourly.txt" \
+		git maintenance run --schedule=hourly --quiet &&
+	GIT_TRACE2_EVENT="$(pwd)/incremental-daily.txt" \
+		git maintenance run --schedule=daily --quiet &&
+
+	test_subcommand git commit-graph write --split --reachable \
+		--no-progress <incremental-hourly.txt &&
+	test_subcommand ! git prune-packed --quiet <incremental-hourly.txt &&
+	test_subcommand ! git multi-pack-index write --no-progress \
+		<incremental-hourly.txt &&
+
+	test_subcommand git commit-graph write --split --reachable \
+		--no-progress <incremental-daily.txt &&
+	test_subcommand git prune-packed --quiet <incremental-daily.txt &&
+	test_subcommand git multi-pack-index write --no-progress \
+		<incremental-daily.txt &&
+
+	# Modify defaults
+	git config maintenance.commit-graph.schedule daily &&
+	git config maintenance.loose-objects.schedule hourly &&
+	git config maintenance.incremental-repack.enabled false &&
+
+	GIT_TRACE2_EVENT="$(pwd)/modified-hourly.txt" \
+		git maintenance run --schedule=hourly --quiet &&
+	GIT_TRACE2_EVENT="$(pwd)/modified-daily.txt" \
+		git maintenance run --schedule=daily --quiet &&
+
+	test_subcommand ! git commit-graph write --split --reachable \
+		--no-progress <modified-hourly.txt &&
+	test_subcommand git prune-packed --quiet <modified-hourly.txt &&
+	test_subcommand ! git multi-pack-index write --no-progress \
+		<modified-hourly.txt &&
+
+	test_subcommand git commit-graph write --split --reachable \
+		--no-progress <modified-daily.txt &&
+	test_subcommand git prune-packed --quiet <modified-daily.txt &&
+	test_subcommand ! git multi-pack-index write --no-progress \
+		<modified-daily.txt
+'
+
+test_expect_success 'register and unregister' '
+	test_when_finished git config --global --unset-all maintenance.repo &&
+	git config --global --add maintenance.repo /existing1 &&
+	git config --global --add maintenance.repo /existing2 &&
+	git config --global --get-all maintenance.repo >before &&
+
+	git maintenance register &&
+	test_cmp_config false maintenance.auto &&
+	git config --global --get-all maintenance.repo >between &&
+	cp before expect &&
+	pwd >>expect &&
+	test_cmp expect between &&
+
+	git maintenance unregister &&
+	git config --global --get-all maintenance.repo >actual &&
+	test_cmp before actual
+'
+
+test_expect_success 'start from empty cron table' '
+	GIT_TEST_CRONTAB="test-tool crontab cron.txt" git maintenance start &&
+
+	# start registers the repo
+	git config --get --global maintenance.repo "$(pwd)" &&
+
+	grep "for-each-repo --config=maintenance.repo maintenance run --schedule=daily" cron.txt &&
+	grep "for-each-repo --config=maintenance.repo maintenance run --schedule=hourly" cron.txt &&
+	grep "for-each-repo --config=maintenance.repo maintenance run --schedule=weekly" cron.txt
+'
+
+test_expect_success 'stop from existing schedule' '
+	GIT_TEST_CRONTAB="test-tool crontab cron.txt" git maintenance stop &&
+
+	# stop does not unregister the repo
+	git config --get --global maintenance.repo "$(pwd)" &&
+
+	# Operation is idempotent
+	GIT_TEST_CRONTAB="test-tool crontab cron.txt" git maintenance stop &&
+	test_must_be_empty cron.txt
+'
+
+test_expect_success 'start preserves existing schedule' '
+	echo "Important information!" >cron.txt &&
+	GIT_TEST_CRONTAB="test-tool crontab cron.txt" git maintenance start &&
+	grep "Important information!" cron.txt
+'
+
+test_expect_success 'register preserves existing strategy' '
+	git config maintenance.strategy none &&
+	git maintenance register &&
+	test_config maintenance.strategy none &&
+	git config --unset maintenance.strategy &&
+	git maintenance register &&
+	test_config maintenance.strategy incremental
+'
+
 test_done
diff --git a/t/t8013-blame-ignore-revs.sh b/t/t8013-blame-ignore-revs.sh
index 24ae501..b18633d 100755
--- a/t/t8013-blame-ignore-revs.sh
+++ b/t/t8013-blame-ignore-revs.sh
@@ -39,10 +39,10 @@
 	test_must_fail git blame --ignore-rev X^{tree} file
 '
 
-# Ensure bogus --ignore-revs-file requests are caught
+# Ensure bogus --ignore-revs-file requests are silently accepted
 test_expect_success 'validate --ignore-revs-file' '
 	git rev-parse X^{tree} >ignore_x &&
-	test_must_fail git blame --ignore-revs-file ignore_x file
+	git blame --ignore-revs-file ignore_x file
 '
 
 for I in X XT
diff --git a/t/t9303-fast-import-compression.sh b/t/t9303-fast-import-compression.sh
index 5045f02..57d9165 100755
--- a/t/t9303-fast-import-compression.sh
+++ b/t/t9303-fast-import-compression.sh
@@ -3,12 +3,6 @@
 test_description='compression setting of fast-import utility'
 . ./test-lib.sh
 
-# This should be moved to test-lib.sh together with the
-# copy in t0021 after both topics have graduated to 'master'.
-file_size () {
-	test-tool path-utils file-size "$1"
-}
-
 import_large () {
 	(
 		echo blob
@@ -24,7 +18,7 @@
 		test_when_finished "rm -f .git/objects/pack/pack-*.*" &&
 		test_when_finished "rm -rf .git/objects/??" &&
 		import_large -c fastimport.unpacklimit=0 $config &&
-		sz=$(file_size .git/objects/pack/pack-*.pack) &&
+		sz=$(test_file_size .git/objects/pack/pack-*.pack) &&
 		case "$expect" in
 		small) test "$sz" -le 100000 ;;
 		large) test "$sz" -ge 100000 ;;
@@ -47,7 +41,7 @@
 		test_when_finished "rm -f .git/objects/pack/pack-*.*" &&
 		test_when_finished "rm -rf .git/objects/??" &&
 		import_large -c fastimport.unpacklimit=9 $config &&
-		sz=$(file_size .git/objects/??/????*) &&
+		sz=$(test_file_size .git/objects/??/????*) &&
 		case "$expect" in
 		small) test "$sz" -le 100000 ;;
 		large) test "$sz" -ge 100000 ;;
diff --git a/t/t9304-fast-import-marks.sh b/t/t9304-fast-import-marks.sh
new file mode 100755
index 0000000..d4359db
--- /dev/null
+++ b/t/t9304-fast-import-marks.sh
@@ -0,0 +1,51 @@
+#!/bin/sh
+
+test_description='test exotic situations with marks'
+. ./test-lib.sh
+
+test_expect_success 'setup dump of basic history' '
+	test_commit one &&
+	git fast-export --export-marks=marks HEAD >dump
+'
+
+test_expect_success 'setup large marks file' '
+	# normally a marks file would have a lot of useful, unique
+	# marks. But for our purposes, just having a lot of nonsense
+	# ones is fine. Start at 1024 to avoid clashing with marks
+	# legitimately used in our tiny dump.
+	blob=$(git rev-parse HEAD:one.t) &&
+	for i in $(test_seq 1024 16384)
+	do
+		echo ":$i $blob"
+	done >>marks
+'
+
+test_expect_success 'import with large marks file' '
+	git fast-import --import-marks=marks <dump
+'
+
+test_expect_success 'setup dump with submodule' '
+	git submodule add "$PWD" sub &&
+	git commit -m "add submodule" &&
+	git fast-export HEAD >dump
+'
+
+test_expect_success 'setup submodule mapping with large id' '
+	old=$(git rev-parse HEAD:sub) &&
+	new=$(echo $old | sed s/./a/g) &&
+	echo ":12345 $old" >from &&
+	echo ":12345 $new" >to
+'
+
+test_expect_success 'import with submodule mapping' '
+	git init dst &&
+	git -C dst fast-import \
+		--rewrite-submodules-from=sub:../from \
+		--rewrite-submodules-to=sub:../to \
+		<dump &&
+	git -C dst rev-parse HEAD:sub >actual &&
+	echo "$new" >expect &&
+	test_cmp expect actual
+'
+
+test_done
diff --git a/t/t9603-cvsimport-patchsets.sh b/t/t9603-cvsimport-patchsets.sh
index 3e64b11..e7a9161 100755
--- a/t/t9603-cvsimport-patchsets.sh
+++ b/t/t9603-cvsimport-patchsets.sh
@@ -17,23 +17,23 @@
 setup_cvs_test_repository t9603
 
 test_expect_failure PERL 'import with criss cross times on revisions' '
-
-    git cvsimport -p"-x" -C module-git module &&
-    (cd module-git &&
-        git log --pretty=format:%s > ../actual-master &&
-        git log A~2..A --pretty="format:%s %ad" -- > ../actual-A &&
-        echo "" >> ../actual-master &&
-	echo "" >> ../actual-A
-    ) &&
-    echo "Rev 4
+	git cvsimport -p"-x" -C module-git module &&
+	(
+		cd module-git &&
+		git log --pretty=format:%s > ../actual-master &&
+		git log A~2..A --pretty="format:%s %ad" -- > ../actual-A &&
+		echo "" >> ../actual-master &&
+		echo "" >> ../actual-A
+	) &&
+	echo "Rev 4
 Rev 3
 Rev 2
 Rev 1" > expect-master &&
-    test_cmp expect-master actual-master &&
+	test_cmp expect-master actual-master &&
 
-    echo "Rev 5 Branch A Wed Mar 11 19:09:10 2009 +0000
+	echo "Rev 5 Branch A Wed Mar 11 19:09:10 2009 +0000
 Rev 4 Branch A Wed Mar 11 19:03:52 2009 +0000" > expect-A &&
-    test_cmp expect-A actual-A
+	test_cmp expect-A actual-A
 '
 
 test_done
diff --git a/t/t9801-git-p4-branch.sh b/t/t9801-git-p4-branch.sh
index 67ff271..a3abd77 100755
--- a/t/t9801-git-p4-branch.sh
+++ b/t/t9801-git-p4-branch.sh
@@ -67,7 +67,7 @@
 	(
 		cd "$git" &&
 		git log --oneline --graph --decorate --all &&
-		git rev-list master >wc &&
+		git rev-list master -- >wc &&
 		test_line_count = 4 wc
 	)
 '
@@ -78,7 +78,7 @@
 	(
 		cd "$git" &&
 		git log --oneline --graph --decorate --all &&
-		git rev-list master >wc &&
+		git rev-list master -- >wc &&
 		test_line_count = 2 wc
 	)
 '
@@ -89,7 +89,7 @@
 	(
 		cd "$git" &&
 		git log --oneline --graph --decorate --all &&
-		git rev-list master >wc &&
+		git rev-list master -- >wc &&
 		test_line_count = 2 wc
 	)
 '
@@ -100,7 +100,7 @@
 	(
 		cd "$git" &&
 		git log --oneline --graph --decorate --all &&
-		git rev-list master >wc &&
+		git rev-list master -- >wc &&
 		test_line_count = 8 wc
 	)
 '
@@ -114,7 +114,7 @@
 		git log --oneline --graph --decorate --all &&
 
 		# 4 main commits
-		git rev-list master >wc &&
+		git rev-list master -- >wc &&
 		test_line_count = 4 wc &&
 
 		# 3 main, 1 integrate, 1 on branch2
@@ -137,7 +137,7 @@
 		git log --oneline --graph --decorate --all &&
 
 		# 4 main commits
-		git rev-list master >wc &&
+		git rev-list master -- >wc &&
 		test_line_count = 4 wc &&
 
 		# 3 main, 1 integrate, 1 on branch2
diff --git a/t/t9832-unshelve.sh b/t/t9832-unshelve.sh
index 7194fb2..6b3cb04 100755
--- a/t/t9832-unshelve.sh
+++ b/t/t9832-unshelve.sh
@@ -68,7 +68,8 @@
 		cd "$git" &&
 		change=$(last_shelved_change) &&
 		git p4 unshelve $change &&
-		git show refs/remotes/p4-unshelved/$change | grep -q "Further description" &&
+		git show refs/remotes/p4-unshelved/$change >actual &&
+		grep -q "Further description" actual &&
 		git cherry-pick refs/remotes/p4-unshelved/$change &&
 		test_path_is_file file2 &&
 		test_cmp file1 "$cli"/file1 &&
diff --git a/t/t9902-completion.sh b/t/t9902-completion.sh
index 7b7bc6e..5c01c75 100755
--- a/t/t9902-completion.sh
+++ b/t/t9902-completion.sh
@@ -1,6 +1,6 @@
 #!/bin/sh
 #
-# Copyright (c) 2012 Felipe Contreras
+# Copyright (c) 2012-2020 Felipe Contreras
 #
 
 test_description='test bash completion'
@@ -1055,13 +1055,13 @@
 	git -C otherrepo branch -D matching/branch-in-other
 '
 
-test_expect_success '__git_refs - for-each-ref format specifiers in prefix' '
+test_expect_success PREPARE_FOR_MAIN_BRANCH '__git_refs - for-each-ref format specifiers in prefix' '
 	cat >expected <<-EOF &&
 	evil-%%-%42-%(refname)..master
 	EOF
 	(
-		cur="evil-%%-%42-%(refname)..mas" &&
-		__git_refs "" "" "evil-%%-%42-%(refname).." mas >"$actual"
+		cur="evil-%%-%42-%(refname)..mai" &&
+		__git_refs "" "" "evil-%%-%42-%(refname).." mai >"$actual"
 	) &&
 	test_cmp expected "$actual"
 '
@@ -1360,6 +1360,58 @@
 	EOF
 '
 
+test_expect_success 'git checkout - with checkout.guess = false, only completes refs' '
+	test_config checkout.guess false &&
+	test_completion "git checkout " <<-\EOF
+	HEAD Z
+	master Z
+	matching-branch Z
+	matching-tag Z
+	other/branch-in-other Z
+	other/master-in-other Z
+	EOF
+'
+
+test_expect_success 'git checkout - with checkout.guess = true, completes refs and unique remote branches for DWIM' '
+	test_config checkout.guess true &&
+	test_completion "git checkout " <<-\EOF
+	HEAD Z
+	branch-in-other Z
+	master Z
+	master-in-other Z
+	matching-branch Z
+	matching-tag Z
+	other/branch-in-other Z
+	other/master-in-other Z
+	EOF
+'
+
+test_expect_success 'git checkout - a later --guess overrides previous checkout.guess = false, complete refs and unique remote branches for DWIM' '
+	test_config checkout.guess false &&
+	test_completion "git checkout --guess " <<-\EOF
+	HEAD Z
+	branch-in-other Z
+	master Z
+	master-in-other Z
+	matching-branch Z
+	matching-tag Z
+	other/branch-in-other Z
+	other/master-in-other Z
+	EOF
+'
+
+test_expect_success 'git checkout - a later --no-guess overrides previous checkout.guess = true, complete only refs' '
+	test_config checkout.guess true &&
+	test_completion "git checkout --no-guess " <<-\EOF
+	HEAD Z
+	master Z
+	matching-branch Z
+	matching-tag Z
+	other/branch-in-other Z
+	other/master-in-other Z
+	EOF
+'
+
 test_expect_success 'git switch - with --detach, complete all references' '
 	test_completion "git switch --detach " <<-\EOF
 	HEAD Z
@@ -2143,6 +2195,25 @@
 	test_completion "git add mom" "momified"
 '
 
+test_expect_success "simple alias" '
+	test_config alias.co checkout &&
+	test_completion "git co m" <<-\EOF
+	master Z
+	mybranch Z
+	mytag Z
+	EOF
+'
+
+test_expect_success "recursive alias" '
+	test_config alias.co checkout &&
+	test_config alias.cod "co --detached" &&
+	test_completion "git cod m" <<-\EOF
+	master Z
+	mybranch Z
+	mytag Z
+	EOF
+'
+
 test_expect_success "completion uses <cmd> completion for alias: !sh -c 'git <cmd> ...'" '
 	test_config alias.co "!sh -c '"'"'git checkout ...'"'"'" &&
 	test_completion "git co m" <<-\EOF
diff --git a/t/test-lib-functions.sh b/t/test-lib-functions.sh
index 8d59b90..7ba3011 100644
--- a/t/test-lib-functions.sh
+++ b/t/test-lib-functions.sh
@@ -423,7 +423,7 @@
 # - Explicitly using test_have_prereq.
 #
 # - Implicitly by specifying the prerequisite tag in the calls to
-#   test_expect_{success,failure,code}.
+#   test_expect_{success,failure} and test_external{,_without_stderr}.
 #
 # The single parameter is the prerequisite tag (a simple word, in all
 # capital letters by convention).
@@ -474,15 +474,15 @@
 
 test_run_lazy_prereq_ () {
 	script='
-mkdir -p "$TRASH_DIRECTORY/prereq-test-dir" &&
+mkdir -p "$TRASH_DIRECTORY/prereq-test-dir-'"$1"'" &&
 (
-	cd "$TRASH_DIRECTORY/prereq-test-dir" &&'"$2"'
+	cd "$TRASH_DIRECTORY/prereq-test-dir-'"$1"'" &&'"$2"'
 )'
 	say >&3 "checking prerequisite: $1"
 	say >&3 "$script"
 	test_eval_ "$script"
 	eval_ret=$?
-	rm -rf "$TRASH_DIRECTORY/prereq-test-dir"
+	rm -rf "$TRASH_DIRECTORY/prereq-test-dir-$1"
 	if test "$eval_ret" = 0; then
 		say >&3 "prerequisite $1 ok"
 	else
@@ -783,6 +783,10 @@
 	fi
 }
 
+test_file_size () {
+	test-tool path-utils file-size "$1"
+}
+
 # Returns success if a comma separated string of keywords ($1) contains a
 # given keyword ($2).
 # Examples:
@@ -952,13 +956,7 @@
 # - not all diff versions understand "-u"
 
 test_cmp() {
-	test $# -eq 2 || BUG "test_cmp requires two arguments"
-	if ! eval "$GIT_TEST_CMP" '"$@"'
-	then
-		test "x$1" = x- || test -e "$1" || BUG "test_cmp '$1' missing"
-		test "x$2" = x- || test -e "$2" || BUG "test_cmp '$2' missing"
-		return 1
-	fi
+	eval "$GIT_TEST_CMP" '"$@"'
 }
 
 # Check that the given config key has the expected value.
@@ -987,13 +985,7 @@
 # test_cmp_bin - helper to compare binary files
 
 test_cmp_bin() {
-	test $# -eq 2 || BUG "test_cmp_bin requires two arguments"
-	if ! cmp "$@"
-	then
-		test "x$1" = x- || test -e "$1" || BUG "test_cmp_bin '$1' missing"
-		test "x$2" = x- || test -e "$2" || BUG "test_cmp_bin '$2' missing"
-		return 1
-	fi
+	cmp "$@"
 }
 
 # Use this instead of test_cmp to compare files that contain expected and
diff --git a/t/test-lib.sh b/t/test-lib.sh
index ef31f40..a863cce 100644
--- a/t/test-lib.sh
+++ b/t/test-lib.sh
@@ -499,6 +499,12 @@
 	export GIT_INDEX_VERSION
 fi
 
+if test -n "$GIT_TEST_PERL_FATAL_WARNINGS"
+then
+	GIT_PERL_FATAL_WARNINGS=1
+	export GIT_PERL_FATAL_WARNINGS
+fi
+
 # Add libc MALLOC and MALLOC_PERTURB test
 # only if we are not executing the test with valgrind
 if test -n "$valgrind" ||
@@ -769,15 +775,17 @@
 }
 
 match_test_selector_list () {
+	operation="$1"
+	shift
 	title="$1"
 	shift
 	arg="$1"
 	shift
 	test -z "$1" && return 0
 
-	# Both commas and whitespace are accepted as separators.
+	# Commas are accepted as separators.
 	OLDIFS=$IFS
-	IFS=' 	,'
+	IFS=','
 	set -- $1
 	IFS=$OLDIFS
 
@@ -805,13 +813,13 @@
 			*-*)
 				if expr "z${selector%%-*}" : "z[0-9]*[^0-9]" >/dev/null
 				then
-					echo "error: $title: invalid non-numeric in range" \
+					echo "error: $operation: invalid non-numeric in range" \
 						"start: '$orig_selector'" >&2
 					exit 1
 				fi
 				if expr "z${selector#*-}" : "z[0-9]*[^0-9]" >/dev/null
 				then
-					echo "error: $title: invalid non-numeric in range" \
+					echo "error: $operation: invalid non-numeric in range" \
 						"end: '$orig_selector'" >&2
 					exit 1
 				fi
@@ -819,9 +827,11 @@
 			*)
 				if expr "z$selector" : "z[0-9]*[^0-9]" >/dev/null
 				then
-					echo "error: $title: invalid non-numeric in test" \
-						"selector: '$orig_selector'" >&2
-					exit 1
+					case "$title" in *${selector}*)
+						include=$positive
+						;;
+					esac
+					continue
 				fi
 		esac
 
@@ -1031,7 +1041,7 @@
 		skipped_reason="GIT_SKIP_TESTS"
 	fi
 	if test -z "$to_skip" && test -n "$run_list" &&
-	   ! match_test_selector_list '--run' $test_count "$run_list"
+	   ! match_test_selector_list '--run' "$1" $test_count "$run_list"
 	then
 		to_skip=t
 		skipped_reason="--run"
@@ -1058,7 +1068,6 @@
 				"      <skipped message=\"$message\" />"
 		fi
 
-		say_color skip >&3 "skipping test: $@"
 		say_color skip "ok $test_count # skip $1 ($skipped_reason)"
 		: true
 		;;
@@ -1702,3 +1711,17 @@
 test_lazy_prereq REBASE_P '
 	test -z "$GIT_TEST_SKIP_REBASE_P"
 '
+
+# Special-purpose prereq for transitioning to a new default branch name:
+# Some tests need more than just a mindless (case-preserving) s/master/main/g
+# replacement. The non-trivial adjustments are guarded behind this
+# prerequisite, acting kind of as a feature flag
+test_lazy_prereq PREPARE_FOR_MAIN_BRANCH '
+	test "$GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME" = main
+'
+
+# Ensure that no test accidentally triggers a Git command
+# that runs 'crontab', affecting a user's cron schedule.
+# Tests that verify the cron integration must set this locally
+# to avoid errors.
+GIT_TEST_CRONTAB="exit 1"
diff --git a/templates/hooks--push-to-checkout.sample b/templates/hooks--push-to-checkout.sample
new file mode 100755
index 0000000..af5a0c0
--- /dev/null
+++ b/templates/hooks--push-to-checkout.sample
@@ -0,0 +1,78 @@
+#!/bin/sh
+
+# An example hook script to update a checked-out tree on a git push.
+#
+# This hook is invoked by git-receive-pack(1) when it reacts to git
+# push and updates reference(s) in its repository, and when the push
+# tries to update the branch that is currently checked out and the
+# receive.denyCurrentBranch configuration variable is set to
+# updateInstead.
+#
+# By default, such a push is refused if the working tree and the index
+# of the remote repository has any difference from the currently
+# checked out commit; when both the working tree and the index match
+# the current commit, they are updated to match the newly pushed tip
+# of the branch. This hook is to be used to override the default
+# behaviour; however the code below reimplements the default behaviour
+# as a starting point for convenient modification.
+#
+# The hook receives the commit with which the tip of the current
+# branch is going to be updated:
+commit=$1
+
+# It can exit with a non-zero status to refuse the push (when it does
+# so, it must not modify the index or the working tree).
+die () {
+	echo >&2 "$*"
+	exit 1
+}
+
+# Or it can make any necessary changes to the working tree and to the
+# index to bring them to the desired state when the tip of the current
+# branch is updated to the new commit, and exit with a zero status.
+#
+# For example, the hook can simply run git read-tree -u -m HEAD "$1"
+# in order to emulate git fetch that is run in the reverse direction
+# with git push, as the two-tree form of git read-tree -u -m is
+# essentially the same as git switch or git checkout that switches
+# branches while keeping the local changes in the working tree that do
+# not interfere with the difference between the branches.
+
+# The below is a more-or-less exact translation to shell of the C code
+# for the default behaviour for git's push-to-checkout hook defined in
+# the push_to_deploy() function in builtin/receive-pack.c.
+#
+# Note that the hook will be executed from the repository directory,
+# not from the working tree, so if you want to perform operations on
+# the working tree, you will have to adapt your code accordingly, e.g.
+# by adding "cd .." or using relative paths.
+
+if ! git update-index -q --ignore-submodules --refresh
+then
+	die "Up-to-date check failed"
+fi
+
+if ! git diff-files --quiet --ignore-submodules --
+then
+	die "Working directory has unstaged changes"
+fi
+
+# This is a rough translation of:
+#
+#   head_has_history() ? "HEAD" : EMPTY_TREE_SHA1_HEX
+if git cat-file -e HEAD 2>/dev/null
+then
+	head=HEAD
+else
+	head=$(git hash-object -t tree --stdin </dev/null)
+fi
+
+if ! git diff-index --quiet --cached --ignore-submodules $head --
+then
+	die "Working directory has staged changes"
+fi
+
+if ! git read-tree -u -m "$commit"
+then
+	die "Could not update working tree to new HEAD"
+fi
diff --git a/transport-helper.c b/transport-helper.c
index b573b6c..5f6e0b3 100644
--- a/transport-helper.c
+++ b/transport-helper.c
@@ -827,6 +827,10 @@
 			status = REF_STATUS_REJECT_STALE;
 			FREE_AND_NULL(msg);
 		}
+		else if (!strcmp(msg, "remote ref updated since checkout")) {
+			status = REF_STATUS_REJECT_REMOTE_UPDATED;
+			FREE_AND_NULL(msg);
+		}
 		else if (!strcmp(msg, "forced update")) {
 			forced = 1;
 			FREE_AND_NULL(msg);
@@ -934,6 +938,11 @@
 		if (set_helper_option(transport, TRANS_OPT_ATOMIC, "true") != 0)
 			die(_("helper %s does not support --atomic"), name);
 
+	if (flags & TRANSPORT_PUSH_FORCE_IF_INCLUDES)
+		if (set_helper_option(transport, TRANS_OPT_FORCE_IF_INCLUDES, "true") != 0)
+			die(_("helper %s does not support --%s"),
+			    name, TRANS_OPT_FORCE_IF_INCLUDES);
+
 	if (flags & TRANSPORT_PUSH_OPTIONS) {
 		struct string_list_item *item;
 		for_each_string_list_item(item, transport->push_options)
@@ -967,6 +976,7 @@
 		case REF_STATUS_REJECT_NONFASTFORWARD:
 		case REF_STATUS_REJECT_STALE:
 		case REF_STATUS_REJECT_ALREADY_EXISTS:
+		case REF_STATUS_REJECT_REMOTE_UPDATED:
 			if (atomic) {
 				reject_atomic_push(remote_refs, mirror);
 				string_list_clear(&cas_options, 0);
diff --git a/transport.c b/transport.c
index ffe2115..47da955 100644
--- a/transport.c
+++ b/transport.c
@@ -633,6 +633,11 @@
 				 "stale info",
 				 report, porcelain, summary_width);
 		break;
+	case REF_STATUS_REJECT_REMOTE_UPDATED:
+		print_ref_status('!', "[rejected]", ref, ref->peer_ref,
+				 "remote ref updated since checkout",
+				 report, porcelain, summary_width);
+		break;
 	case REF_STATUS_REJECT_SHALLOW:
 		print_ref_status('!', "[rejected]", ref, ref->peer_ref,
 				 "new shallow roots not allowed",
@@ -743,6 +748,8 @@
 			*reject_reasons |= REJECT_FETCH_FIRST;
 		} else if (ref->status == REF_STATUS_REJECT_NEEDS_FORCE) {
 			*reject_reasons |= REJECT_NEEDS_FORCE;
+		} else if (ref->status == REF_STATUS_REJECT_REMOTE_UPDATED) {
+			*reject_reasons |= REJECT_REF_NEEDS_UPDATE;
 		}
 	}
 	free(head);
@@ -1185,6 +1192,7 @@
 		if (!r->peer_ref) continue;
 		if (r->status == REF_STATUS_REJECT_NONFASTFORWARD) continue;
 		if (r->status == REF_STATUS_REJECT_STALE) continue;
+		if (r->status == REF_STATUS_REJECT_REMOTE_UPDATED) continue;
 		if (r->status == REF_STATUS_UPTODATE) continue;
 
 		strbuf_reset(&buf);
diff --git a/transport.h b/transport.h
index ca409ea..24558c0 100644
--- a/transport.h
+++ b/transport.h
@@ -136,6 +136,7 @@
 #define TRANSPORT_PUSH_ATOMIC			(1<<13)
 #define TRANSPORT_PUSH_OPTIONS			(1<<14)
 #define TRANSPORT_RECURSE_SUBMODULES_ONLY	(1<<15)
+#define TRANSPORT_PUSH_FORCE_IF_INCLUDES	(1<<16)
 
 int transport_summary_width(const struct ref *refs);
 
@@ -208,6 +209,9 @@
 /* Request atomic (all-or-nothing) updates when pushing */
 #define TRANS_OPT_ATOMIC "atomic"
 
+/* Require remote changes to be integrated locally. */
+#define TRANS_OPT_FORCE_IF_INCLUDES "force-if-includes"
+
 /**
  * Returns 0 if the option was used, non-zero otherwise. Prints a
  * message to stderr if the option is not used.
@@ -217,11 +221,12 @@
 void transport_set_verbosity(struct transport *transport, int verbosity,
 	int force_progress);
 
-#define REJECT_NON_FF_HEAD     0x01
-#define REJECT_NON_FF_OTHER    0x02
-#define REJECT_ALREADY_EXISTS  0x04
-#define REJECT_FETCH_FIRST     0x08
-#define REJECT_NEEDS_FORCE     0x10
+#define REJECT_NON_FF_HEAD      0x01
+#define REJECT_NON_FF_OTHER     0x02
+#define REJECT_ALREADY_EXISTS   0x04
+#define REJECT_FETCH_FIRST      0x08
+#define REJECT_NEEDS_FORCE      0x10
+#define REJECT_REF_NEEDS_UPDATE 0x20
 
 int transport_push(struct repository *repo,
 		   struct transport *connection,
diff --git a/upload-pack.c b/upload-pack.c
index d4f7192..1006beb 100644
--- a/upload-pack.c
+++ b/upload-pack.c
@@ -1345,7 +1345,18 @@
 				   PACKET_READ_DIE_ON_ERR_PACKET);
 
 		receive_needs(&data, &reader);
-		if (data.want_obj.nr) {
+
+		/*
+		 * An EOF at this exact point in negotiation should be
+		 * acceptable from stateless clients as they will consume the
+		 * shallow list before doing subsequent rpc with haves/etc.
+		 */
+		if (data.stateless_rpc)
+			reader.options |= PACKET_READ_GENTLE_ON_EOF;
+
+		if (data.want_obj.nr &&
+		    packet_reader_peek(&reader) != PACKET_READ_EOF) {
+			reader.options &= ~PACKET_READ_GENTLE_ON_EOF;
 			get_common_commits(&data, &reader);
 			create_pack_file(&data, NULL);
 		}
diff --git a/usage.c b/usage.c
index 58fb5ff..0666582 100644
--- a/usage.c
+++ b/usage.c
@@ -108,33 +108,33 @@
 
 /* If we are in a dlopen()ed .so write to a global variable would segfault
  * (ugh), so keep things static. */
-static NORETURN_PTR void (*usage_routine)(const char *err, va_list params) = usage_builtin;
-static NORETURN_PTR void (*die_routine)(const char *err, va_list params) = die_builtin;
-static void (*error_routine)(const char *err, va_list params) = error_builtin;
-static void (*warn_routine)(const char *err, va_list params) = warn_builtin;
+static NORETURN_PTR report_fn usage_routine = usage_builtin;
+static NORETURN_PTR report_fn die_routine = die_builtin;
+static report_fn error_routine = error_builtin;
+static report_fn warn_routine = warn_builtin;
 static int (*die_is_recursing)(void) = die_is_recursing_builtin;
 
-void set_die_routine(NORETURN_PTR void (*routine)(const char *err, va_list params))
+void set_die_routine(NORETURN_PTR report_fn routine)
 {
 	die_routine = routine;
 }
 
-void set_error_routine(void (*routine)(const char *err, va_list params))
+void set_error_routine(report_fn routine)
 {
 	error_routine = routine;
 }
 
-void (*get_error_routine(void))(const char *err, va_list params)
+report_fn get_error_routine(void)
 {
 	return error_routine;
 }
 
-void set_warn_routine(void (*routine)(const char *warn, va_list params))
+void set_warn_routine(report_fn routine)
 {
 	warn_routine = routine;
 }
 
-void (*get_warn_routine(void))(const char *warn, va_list params)
+report_fn get_warn_routine(void)
 {
 	return warn_routine;
 }
diff --git a/userdiff.c b/userdiff.c
index fde02f2..3f81a22 100644
--- a/userdiff.c
+++ b/userdiff.c
@@ -23,6 +23,27 @@
 	 "[a-zA-Z][a-zA-Z0-9_]*"
 	 "|[-+]?[0-9][0-9#_.aAbBcCdDeEfF]*([eE][+-]?[0-9_]+)?"
 	 "|=>|\\.\\.|\\*\\*|:=|/=|>=|<=|<<|>>|<>"),
+PATTERNS("bash",
+	 /* Optional leading indentation */
+	 "^[ \t]*"
+	 /* Start of captured text */
+	 "("
+	 "("
+	     /* POSIX identifier with mandatory parentheses */
+	     "[a-zA-Z_][a-zA-Z0-9_]*[ \t]*\\([ \t]*\\))"
+	 "|"
+	     /* Bashism identifier with optional parentheses */
+	     "(function[ \t]+[a-zA-Z_][a-zA-Z0-9_]*(([ \t]*\\([ \t]*\\))|([ \t]+))"
+	 ")"
+	 /* Optional whitespace */
+	 "[ \t]*"
+	 /* Compound command starting with `{`, `(`, `((` or `[[` */
+	 "(\\{|\\(\\(?|\\[\\[)"
+	 /* End of captured text */
+	 ")",
+	 /* -- */
+	 /* Characters not in the default $IFS value */
+	 "[^ \t]+"),
 PATTERNS("dts",
 	 "!;\n"
 	 "!=\n"
@@ -147,7 +168,7 @@
 	 "|=~|!~"
 	 "|<<|<>|<=>|>>"),
 PATTERNS("php",
-	 "^[\t ]*(((public|protected|private|static)[\t ]+)*function.*)$\n"
+	 "^[\t ]*(((public|protected|private|static|abstract|final)[\t ]+)*function.*)$\n"
 	 "^[\t ]*((((final|abstract)[\t ]+)?class|interface|trait).*)$",
 	 /* -- */
 	 "[a-zA-Z_][a-zA-Z0-9_]*"
@@ -165,7 +186,7 @@
 	 "|[-+0-9.e]+|0[xXbB]?[0-9a-fA-F]+|\\?(\\\\C-)?(\\\\M-)?."
 	 "|//=?|[-+*/<>%&^|=!]=|<<=?|>>=?|===|\\.{1,3}|::|[!=]~"),
 PATTERNS("rust",
-	 "^[\t ]*((pub(\\([^\\)]+\\))?[\t ]+)?((async|const|unsafe|extern([\t ]+\"[^\"]+\"))[\t ]+)?(struct|enum|union|mod|trait|fn|impl)[< \t]+[^;]*)$",
+	 "^[\t ]*((pub(\\([^\\)]+\\))?[\t ]+)?((async|const|unsafe|extern([\t ]+\"[^\"]+\"))[\t ]+)?(struct|enum|union|mod|trait|fn|impl|macro_rules!)[< \t]+[^;]*)$",
 	 /* -- */
 	 "[a-zA-Z_][a-zA-Z0-9_]*"
 	 "|[0-9][0-9_a-fA-Fiosuxz]*(\\.([0-9]*[eE][+-]?)?[0-9_fF]*)?"
@@ -200,7 +221,7 @@
 	 "|[-+*/<>%&^|=!]=|--|\\+\\+|<<=?|>>=?|&&|\\|\\||::|->"),
 IPATTERN("css",
 	 "![:;][[:space:]]*$\n"
-	 "^[_a-z0-9].*$",
+	 "^[:[@.#]?[_a-z0-9].*$",
 	 /* -- */
 	 /*
 	  * This regex comes from W3C CSS specs. Should theoretically also
diff --git a/xdiff/xdiff.h b/xdiff/xdiff.h
index 032e3a9..7a04605 100644
--- a/xdiff/xdiff.h
+++ b/xdiff/xdiff.h
@@ -79,6 +79,10 @@
 typedef struct s_xpparam {
 	unsigned long flags;
 
+	/* -I<regex> */
+	regex_t **ignore_regex;
+	size_t ignore_regex_nr;
+
 	/* See Documentation/diff-options.txt. */
 	char **anchors;
 	size_t anchors_nr;
diff --git a/xdiff/xdiffi.c b/xdiff/xdiffi.c
index bd03513..380eb72 100644
--- a/xdiff/xdiffi.c
+++ b/xdiff/xdiffi.c
@@ -998,7 +998,7 @@
 	return 0;
 }
 
-static void xdl_mark_ignorable(xdchange_t *xscr, xdfenv_t *xe, long flags)
+static void xdl_mark_ignorable_lines(xdchange_t *xscr, xdfenv_t *xe, long flags)
 {
 	xdchange_t *xch;
 
@@ -1019,6 +1019,46 @@
 	}
 }
 
+static int record_matches_regex(xrecord_t *rec, xpparam_t const *xpp) {
+	regmatch_t regmatch;
+	int i;
+
+	for (i = 0; i < xpp->ignore_regex_nr; i++)
+		if (!regexec_buf(xpp->ignore_regex[i], rec->ptr, rec->size, 1,
+				 &regmatch, 0))
+			return 1;
+
+	return 0;
+}
+
+static void xdl_mark_ignorable_regex(xdchange_t *xscr, const xdfenv_t *xe,
+				     xpparam_t const *xpp)
+{
+	xdchange_t *xch;
+
+	for (xch = xscr; xch; xch = xch->next) {
+		xrecord_t **rec;
+		int ignore = 1;
+		long i;
+
+		/*
+		 * Do not override --ignore-blank-lines.
+		 */
+		if (xch->ignore)
+			continue;
+
+		rec = &xe->xdf1.recs[xch->i1];
+		for (i = 0; i < xch->chg1 && ignore; i++)
+			ignore = record_matches_regex(rec[i], xpp);
+
+		rec = &xe->xdf2.recs[xch->i2];
+		for (i = 0; i < xch->chg2 && ignore; i++)
+			ignore = record_matches_regex(rec[i], xpp);
+
+		xch->ignore = ignore;
+	}
+}
+
 int xdl_diff(mmfile_t *mf1, mmfile_t *mf2, xpparam_t const *xpp,
 	     xdemitconf_t const *xecfg, xdemitcb_t *ecb) {
 	xdchange_t *xscr;
@@ -1038,7 +1078,10 @@
 	}
 	if (xscr) {
 		if (xpp->flags & XDF_IGNORE_BLANK_LINES)
-			xdl_mark_ignorable(xscr, &xe, xpp->flags);
+			xdl_mark_ignorable_lines(xscr, &xe, xpp->flags);
+
+		if (xpp->ignore_regex)
+			xdl_mark_ignorable_regex(xscr, &xe, xpp);
 
 		if (ef(&xe, xscr, ecb, xecfg) < 0) {
 
diff --git a/xdiff/xhistogram.c b/xdiff/xhistogram.c
index c7b35a9..e694bfd 100644
--- a/xdiff/xhistogram.c
+++ b/xdiff/xhistogram.c
@@ -235,6 +235,8 @@
 		int line1, int count1, int line2, int count2)
 {
 	xpparam_t xpparam;
+
+	memset(&xpparam, 0, sizeof(xpparam));
 	xpparam.flags = xpp->flags & ~XDF_DIFF_ALGORITHM_MASK;
 
 	return xdl_fall_back_diff(env, &xpparam,
diff --git a/xdiff/xpatience.c b/xdiff/xpatience.c
index 3c5601b..20699a6 100644
--- a/xdiff/xpatience.c
+++ b/xdiff/xpatience.c
@@ -318,6 +318,8 @@
 		int line1, int count1, int line2, int count2)
 {
 	xpparam_t xpp;
+
+	memset(&xpp, 0, sizeof(xpp));
 	xpp.flags = map->xpp->flags & ~XDF_DIFF_ALGORITHM_MASK;
 
 	return xdl_fall_back_diff(map->env, &xpp,