Merge branch 'tr/diff-words-test'
authorJunio C Hamano <gitster@pobox.com>
Thu, 10 Feb 2011 00:41:17 +0000 (16:41 -0800)
committerJunio C Hamano <gitster@pobox.com>
Thu, 10 Feb 2011 00:41:17 +0000 (16:41 -0800)
* tr/diff-words-test:
t4034 (diff --word-diff): add a minimum Perl drier test vector
t4034 (diff --word-diff): style suggestions
userdiff: simplify word-diff safeguard
t4034: bulk verify builtin word regex sanity

57 files changed:
Documentation/RelNotes/1.7.4.txt
Documentation/config.txt
Documentation/fetch-options.txt
Documentation/git-cherry-pick.txt
Documentation/git-diff.txt
Documentation/git-fast-import.txt
Documentation/git-pull.txt
Documentation/git-reset.txt
Documentation/git-revert.txt
Documentation/git.txt
Documentation/howto/using-merge-subtree.txt
GIT-VERSION-GEN
Makefile
builtin/diff.c
builtin/merge.c
builtin/remote-ext.c
builtin/revert.c
bundle.c
commit.c
commit.h
contrib/examples/git-revert.sh
contrib/hooks/post-receive-email
exec_cmd.c
fast-import.c
git-rebase--interactive.sh
git-rebase.sh
git.c
gitweb/INSTALL
gitweb/gitweb.perl
ll-merge.c
merge-recursive.h
quote.h
run-command.c
setup.c
sha1_file.c
t/README
t/t0070-fundamental.sh
t/t1501-worktree.sh
t/t1510-repo-setup.sh
t/t3032-merge-recursive-options.sh
t/t3509-cherry-pick-merge-df.sh
t/t4013-diff-various.sh
t/t4013/diff.diff_--cached [new file with mode: 0644]
t/t4013/diff.diff_--cached_--_file0 [new file with mode: 0644]
t/t4120-apply-popt.sh
t/t5526-fetch-submodules.sh
t/t7407-submodule-foreach.sh
t/t9300-fast-import.sh
t/t9301-fast-import-notes.sh
t/test-lib.sh
tag.c
tag.h
test-mktemp.c [new file with mode: 0644]
unpack-trees.c
userdiff.c
vcs-svn/svndump.c
wrapper.c
index 84d0e1dc13ca59a6bb0ab300dd91abdc210ffbe6..d5bca731b589dde2b8a1edad2977e9376e0ec433 100644 (file)
@@ -1,5 +1,5 @@
-Git v1.7.4 Release Notes (draft)
-================================
+Git v1.7.4 Release Notes
+========================
 
 Updates since v1.7.3
 --------------------
@@ -66,7 +66,7 @@ Updates since v1.7.3
    objects unnecessarily.
 
  * "git diff" and "git grep" learned what functions and subroutines
-   in Fortran and Perl look like.
+   in Fortran, Pascal and Perl look like.
 
  * "git fetch" learned the "--recurse-submodules" option.
 
@@ -146,14 +146,11 @@ release, unless otherwise noted.
 
  * "git push --progress" shows progress indicators now.
 
+ * "git rebase -i" showed a confusing error message when given a
+   branch name that does not exist.
+
  * "git repack" places its temporary packs under $GIT_OBJECT_DIRECTORY/pack
    instead of $GIT_OBJECT_DIRECTORY/ to avoid cross directory renames.
 
  * "git submodule update --recursive --other-flags" passes flags down
    to its subinvocations.
-
----
-exec >/var/tmp/1
-O=v1.7.4-rc2
-echo O=$(git describe master)
-git shortlog --no-merges ^maint ^$O master
index ff7c225467b5da3263b6e8f8924adefeea404a8a..c5e183516a104e6efb7ed597fb4498d75560ab68 100644 (file)
@@ -317,17 +317,26 @@ false), while all other repositories are assumed to be bare (bare
 = true).
 
 core.worktree::
-       Set the path to the working tree.  The value will not be
-       used in combination with repositories found automatically in
-       a .git directory (i.e. $GIT_DIR is not set).
+       Set the path to the root of the working tree.
        This can be overridden by the GIT_WORK_TREE environment
-       variable and the '--work-tree' command line option. It can be
-       an absolute path or relative path to the directory specified by
-       --git-dir or GIT_DIR.
-       Note: If --git-dir or GIT_DIR are specified but none of
+       variable and the '--work-tree' command line option.
+       The value can an absolute path or relative to the path to
+       the .git directory, which is either specified by --git-dir
+       or GIT_DIR, or automatically discovered.
+       If --git-dir or GIT_DIR is specified but none of
        --work-tree, GIT_WORK_TREE and core.worktree is specified,
-       the current working directory is regarded as the top directory
+       the current working directory is regarded as the top level
        of your working tree.
++
+Note that this variable is honored even when set in a configuration
+file in a ".git" subdirectory of a directory and its value differs
+from the latter directory (e.g. "/path/to/.git/config" has
+core.worktree set to "/different/path"), which is most likely a
+misconfiguration.  Running git commands in the "/path/to" directory will
+still use "/different/path" as the root of the work tree and can cause
+confusion unless you know what you are doing (e.g. you are creating a
+read-only snapshot of the same index to a location different from the
+repository's usual working tree).
 
 core.logAllRefUpdates::
        Enable the reflog. Updates to a ref <ref> is logged to the file
index 695696da1b6e78639014388e1d4ac8bf09a0e12d..f37276e5add75583fd363af2cd0b7ba051771a97 100644 (file)
@@ -64,13 +64,11 @@ ifndef::git-pull[]
        downloaded. The default behavior for a remote may be
        specified with the remote.<name>.tagopt setting. See
        linkgit:git-config[1].
-endif::git-pull[]
 
 --[no-]recurse-submodules::
        This option controls if new commits of all populated submodules should
        be fetched too (see linkgit:git-config[1] and linkgit:gitmodules[5]).
 
-ifndef::git-pull[]
 --submodule-prefix=<path>::
        Prepend <path> to paths printed in informative messages
        such as "Fetching submodule foo".  This option is used
index 73008705ebe304c8d2a2d089e9328be369c50fc6..749d68a72bf720d82260fe175be0824f7ad069eb 100644 (file)
@@ -79,6 +79,16 @@ effect to your index in a row.
        cherry-pick'ed commit, then a fast forward to this commit will
        be performed.
 
+--strategy=<strategy>::
+       Use the given merge strategy.  Should only be used once.
+       See the MERGE STRATEGIES section in linkgit:git-merge[1]
+       for details.
+
+-X<option>::
+--strategy-option=<option>::
+       Pass the merge strategy-specific option through to the
+       merge strategy.  See linkgit:git-merge[1] for details.
+
 EXAMPLES
 --------
 git cherry-pick master::
@@ -120,6 +130,28 @@ git rev-list --reverse master \-- README | git cherry-pick -n --stdin::
        so the result can be inspected and made into a single new
        commit if suitable.
 
+The following sequence attempts to backport a patch, bails out because
+the code the patch applies to has changed too much, and then tries
+again, this time exercising more care about matching up context lines.
+
+------------
+$ git cherry-pick topic^             <1>
+$ git diff                           <2>
+$ git reset --merge ORIG_HEAD        <3>
+$ git cherry-pick -Xpatience topic^  <4>
+------------
+<1> apply the change that would be shown by `git show topic^`.
+In this example, the patch does not apply cleanly, so
+information about the conflict is written to the index and
+working tree and no new commit results.
+<2> summarize changes to be reconciled
+<3> cancel the cherry-pick.  In other words, return to the
+pre-cherry-pick state, preserving any local modifications you had in
+the working tree.
+<4> try to apply the change introduced by `topic^` again,
+spending extra time to avoid mistakes based on incorrectly matching
+context lines.
+
 Author
 ------
 Written by Junio C Hamano <gitster@pobox.com>
index f6ac847507a635759323565be44b088b479d8bf0..49105102dbf899c62833572fdda51cefaed53476 100644 (file)
@@ -38,6 +38,8 @@ directories. This behavior can be forced by --no-index.
        commit relative to the named <commit>.  Typically you
        would want comparison with the latest commit, so if you
        do not give <commit>, it defaults to HEAD.
+       If HEAD does not exist (e.g. unborned branches) and
+       <commit> is not given, it shows all staged changes.
        --staged is a synonym of --cached.
 
 'git diff' [--options] <commit> [--] [<path>...]::
index f56dfcabb96d1510abfd61a13c36135f3824b744..c3a2766b206609bb5f313db3ff37a1ebb40f8261 100644 (file)
@@ -78,6 +78,10 @@ OPTIONS
        set of marks.  If a mark is defined to different values,
        the last file wins.
 
+--import-marks-if-exists=<file>::
+       Like --import-marks but instead of erroring out, silently
+       skips the file if it does not exist.
+
 --relative-marks::
        After specifying --relative-marks= the paths specified
        with --import-marks= and --export-marks= are relative
@@ -534,9 +538,6 @@ start with double quote (`"`).
 If an `LF` or double quote must be encoded into `<path>` shell-style
 quoting should be used, e.g. `"path/with\n and \" in it"`.
 
-Additionally, in `040000` mode, `<path>` may also be an empty string
-(`""`) to specify the root of the tree.
-
 The value of `<path>` must be in canonical form. That is it must not:
 
 * contain an empty directory component (e.g. `foo//bar` is invalid),
@@ -545,6 +546,8 @@ The value of `<path>` must be in canonical form. That is it must not:
 * contain the special component `.` or `..` (e.g. `foo/./bar` and
   `foo/../bar` are invalid).
 
+The root of the tree can be represented by an empty string as `<path>`.
+
 It is recommended that `<path>` always be encoded using UTF-8.
 
 `filedelete`
@@ -905,7 +908,7 @@ The `<dataref>` can be either a mark reference (`:<idnum>`)
 set previously or a full 40-byte SHA-1 of a Git blob, preexisting or
 ready to be written.
 
-output uses the same format as `git cat-file --batch`:
+Output uses the same format as `git cat-file --batch`:
 
 ====
        <sha1> SP 'blob' SP <size> LF
@@ -949,6 +952,13 @@ cat-blob::
        rather than wasting time on the early part of an import
        before the unsupported command is detected.
 
+notes::
+       Require that the backend support the 'notemodify' (N)
+       subcommand to the 'commit' command.
+       Versions of fast-import not supporting notes will exit
+       with a message indicating so.
+
+
 `option`
 ~~~~~~~~
 Processes the specified option so that git fast-import behaves in a
index 30466917dad52eefd76de95aead3fdc12ad8425d..b33e6be872508778faa59f478229cd6e16bddad7 100644 (file)
@@ -84,6 +84,15 @@ must be given before the options meant for 'git fetch'.
 --verbose::
        Pass --verbose to git-fetch and git-merge.
 
+--[no-]recurse-submodules::
+       This option controls if new commits of all populated submodules should
+       be fetched too (see linkgit:git-config[1] and linkgit:gitmodules[5]).
+       That might be necessary to get the data needed for merging submodule
+       commits, a feature git learned in 1.7.3. Notice that the result of a
+       merge will not be checked out in the submodule, "git submodule update"
+       has to be called afterwards to bring the work tree up to date with the
+       merge result.
+
 Options related to merging
 ~~~~~~~~~~~~~~~~~~~~~~~~~~
 
index fd72976371cee0fcd25e3419138eb13382dc6ab8..927ecee2f26cdf0bd30457d5016b654c01a23a14 100644 (file)
@@ -76,15 +76,10 @@ In other words, --merge does something like a 'git read-tree -u -m <commit>',
 but carries forward unmerged index entries.
 
 --keep::
-       Resets the index, updates files in the working tree that are
-       different between <commit> and HEAD, but keeps those
-       which are different between HEAD and the working tree (i.e.
-       which have local changes).
+       Resets index entries and updates files in the working tree that are
+       different between <commit> and HEAD.
        If a file that is different between <commit> and HEAD has local changes,
        reset is aborted.
-+
-In other words, --keep does a 2-way merge between <commit> and HEAD followed by
-'git reset --mixed <commit>'.
 --
 
 If you want to undo a commit other than the latest on a branch,
index 752fc88e768e4b8e1afddad4bdd7833cf20978c7..45be851750c2ce81500765f6dfbd23578c68abda 100644 (file)
@@ -80,6 +80,16 @@ effect to your index in a row.
 --signoff::
        Add Signed-off-by line at the end of the commit message.
 
+--strategy=<strategy>::
+       Use the given merge strategy.  Should only be used once.
+       See the MERGE STRATEGIES section in linkgit:git-merge[1]
+       for details.
+
+-X<option>::
+--strategy-option=<option>::
+       Pass the merge strategy-specific option through to the
+       merge strategy.  See linkgit:git-merge[1] for details.
+
 EXAMPLES
 --------
 git revert HEAD~3::
index 4e5fe4d4b53f3706be2f7daa72beb20f376de603..e968ed4aa09705d98530add23135e76141ec75c2 100644 (file)
@@ -44,6 +44,11 @@ unreleased) version of git, that is available from 'master'
 branch of the `git.git` repository.
 Documentation for older releases are available here:
 
+* link:v1.7.4/git.html[documentation for release 1.7.4]
+
+* release notes for
+  link:RelNotes/1.7.4.txt[1.7.4].
+
 * link:v1.7.3.5/git.html[documentation for release 1.7.3.5]
 
 * release notes for
@@ -291,17 +296,12 @@ help ...`.
        path or relative path to current working directory.
 
 --work-tree=<path>::
-       Set the path to the working tree.  The value will not be
-       used in combination with repositories found automatically in
-       a .git directory (i.e. $GIT_DIR is not set).
+       Set the path to the working tree. It can be an absolute path
+       or a path relative to the current working directory.
        This can also be controlled by setting the GIT_WORK_TREE
        environment variable and the core.worktree configuration
-       variable. It can be an absolute path or relative path to
-       current working directory.
-       Note: If --git-dir or GIT_DIR are specified but none of
-       --work-tree, GIT_WORK_TREE and core.worktree is specified,
-       the current working directory is regarded as the top directory
-       of your working tree.
+       variable (see core.worktree in linkgit:git-config[1] for a
+       more detailed discussion).
 
 --bare::
        Treat the repository as a bare repository.  If GIT_DIR
index 0953a50b693307976977c81a4c0b611fd5dfb490..2933056120bf0a0d6249c6951ab1e964ae40674b 100644 (file)
@@ -71,5 +71,5 @@ Additional tips
   relevant parts of your tree.
 
 - Please note that if the other project merges from you, then it will
-  connects its history to yours, which can be something they don't want
+  connect its history to yours, which can be something they don't want
   to.
index ccfc298b18439f6463d0c709819402edcec04102..92fe7a59dbf81b0a055280f9351811641ce7044a 100755 (executable)
@@ -1,7 +1,7 @@
 #!/bin/sh
 
 GVF=GIT-VERSION-FILE
-DEF_VER=v1.7.4-rc2
+DEF_VER=v1.7.4
 
 LF='
 '
index 775ee838c332c7311df34a98448fc3723c6bd95e..ade79232f4c3c080fa7d35c4b55870c416e49da6 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -435,6 +435,7 @@ TEST_PROGRAMS_NEED_X += test-subprocess
 TEST_PROGRAMS_NEED_X += test-svn-fe
 TEST_PROGRAMS_NEED_X += test-treap
 TEST_PROGRAMS_NEED_X += test-index-version
+TEST_PROGRAMS_NEED_X += test-mktemp
 
 TEST_PROGRAMS = $(patsubst %,%$X,$(TEST_PROGRAMS_NEED_X))
 
index 945e7583a8294f0612682f3228687498e5c61822..42822cd5374dbcf0e63c17078a55284c432ddc77 100644 (file)
@@ -330,8 +330,11 @@ int cmd_diff(int argc, const char **argv, const char *prefix)
                        else if (!strcmp(arg, "--cached") ||
                                 !strcmp(arg, "--staged")) {
                                add_head_to_pending(&rev);
-                               if (!rev.pending.nr)
-                                       die("No HEAD commit to compare with (yet)");
+                               if (!rev.pending.nr) {
+                                       struct tree *tree;
+                                       tree = lookup_tree((const unsigned char*)EMPTY_TREE_SHA1_BIN);
+                                       add_pending_object(&rev, &tree->object, "HEAD");
+                               }
                                break;
                        }
                }
index 42fff387e69d9b5412e8e776aed3272b78ebe758..9403747b6afeb89a9079e7203f5a027014411495 100644 (file)
@@ -582,7 +582,8 @@ static void write_tree_trivial(unsigned char *sha1)
                die("git write-tree failed to write a tree");
 }
 
-int try_merge_command(const char *strategy, struct commit_list *common,
+int try_merge_command(const char *strategy, size_t xopts_nr,
+                     const char **xopts, struct commit_list *common,
                      const char *head_arg, struct commit_list *remotes)
 {
        const char **args;
@@ -680,7 +681,8 @@ static int try_merge_strategy(const char *strategy, struct commit_list *common,
                rollback_lock_file(lock);
                return clean ? 0 : 1;
        } else {
-               return try_merge_command(strategy, common, head_arg, remoteheads);
+               return try_merge_command(strategy, xopts_nr, xopts,
+                                               common, head_arg, remoteheads);
        }
 }
 
index 1f773171cbdde76cc105e37928cc5f2ecb2ed93f..ea71977c8360e1a7899bbd035cf26f93d889800b 100644 (file)
@@ -212,16 +212,16 @@ static int command_loop(const char *child)
        char buffer[MAXCOMMAND];
 
        while (1) {
-               size_t length;
+               size_t i;
                if (!fgets(buffer, MAXCOMMAND - 1, stdin)) {
                        if (ferror(stdin))
                                die("Comammand input error");
                        exit(0);
                }
                /* Strip end of line characters. */
-               length = strlen(buffer);
-               while (isspace((unsigned char)buffer[length - 1]))
-                       buffer[--length] = 0;
+               i = strlen(buffer);
+               while (i > 0 && isspace(buffer[i - 1]))
+                       buffer[--i] = 0;
 
                if (!strcmp(buffer, "capabilities")) {
                        printf("*connect\n\n");
index bb6e9e83b756b47dae449064ca7762fe3558fc0e..dc1b702edc6b4bd95ebf41c12bf1da6fe9d6850d 100644 (file)
@@ -44,7 +44,11 @@ static const char **commit_argv;
 static int allow_rerere_auto;
 
 static const char *me;
+
+/* Merge strategy. */
 static const char *strategy;
+static const char **xopts;
+static size_t xopts_nr, xopts_alloc;
 
 #define GIT_REFLOG_ACTION "GIT_REFLOG_ACTION"
 
@@ -55,6 +59,17 @@ static const char * const *revert_or_cherry_pick_usage(void)
        return action == REVERT ? revert_usage : cherry_pick_usage;
 }
 
+static int option_parse_x(const struct option *opt,
+                         const char *arg, int unset)
+{
+       if (unset)
+               return 0;
+
+       ALLOC_GROW(xopts, xopts_nr + 1, xopts_alloc);
+       xopts[xopts_nr++] = xstrdup(arg);
+       return 0;
+}
+
 static void parse_args(int argc, const char **argv)
 {
        const char * const * usage_str = revert_or_cherry_pick_usage();
@@ -67,6 +82,8 @@ static void parse_args(int argc, const char **argv)
                OPT_INTEGER('m', "mainline", &mainline, "parent number"),
                OPT_RERERE_AUTOUPDATE(&allow_rerere_auto),
                OPT_STRING(0, "strategy", &strategy, "strategy", "merge strategy"),
+               OPT_CALLBACK('X', "strategy-option", &xopts, "option",
+                       "option for merge strategy", option_parse_x),
                OPT_END(),
                OPT_END(),
                OPT_END(),
@@ -311,18 +328,13 @@ static int do_recursive_merge(struct commit *base, struct commit *next,
        struct merge_options o;
        struct tree *result, *next_tree, *base_tree, *head_tree;
        int clean, index_fd;
+       const char **xopt;
        static struct lock_file index_lock;
 
        index_fd = hold_locked_index(&index_lock, 1);
 
        read_cache();
 
-       /*
-        * NEEDSWORK: cherry-picking between branches with
-        * different end-of-line normalization is a pain;
-        * plumb in an option to set o.renormalize?
-        * (or better: arbitrary -X options)
-        */
        init_merge_options(&o);
        o.ancestor = base ? base_label : "(empty tree)";
        o.branch1 = "HEAD";
@@ -332,6 +344,9 @@ static int do_recursive_merge(struct commit *base, struct commit *next,
        next_tree = next ? next->tree : empty_tree();
        base_tree = base ? base->tree : empty_tree();
 
+       for (xopt = xopts; xopt != xopts + xopts_nr; xopt++)
+               parse_merge_opt(&o, *xopt);
+
        clean = merge_trees(&o,
                            head_tree,
                            next_tree, base_tree, &result);
@@ -503,7 +518,7 @@ static int do_pick_commit(void)
 
                commit_list_insert(base, &common);
                commit_list_insert(next, &remotes);
-               res = try_merge_command(strategy, common,
+               res = try_merge_command(strategy, xopts_nr, xopts, common,
                                        sha1_to_hex(head), remotes);
                free_commit_list(common);
                free_commit_list(remotes);
index 65ea26bdb8c2cef671030c3a62d87d84612e8144..f48fd7d4c1c706b68e879e4dfabdd3fb8597a328 100644 (file)
--- a/bundle.c
+++ b/bundle.c
@@ -200,7 +200,7 @@ int create_bundle(struct bundle_header *header, const char *path,
        int bundle_fd = -1;
        int bundle_to_stdout;
        const char **argv_boundary = xmalloc((argc + 4) * sizeof(const char *));
-       const char **argv_pack = xmalloc(5 * sizeof(const char *));
+       const char **argv_pack = xmalloc(6 * sizeof(const char *));
        int i, ref_count = 0;
        char buffer[1024];
        struct rev_info revs;
@@ -346,7 +346,8 @@ int create_bundle(struct bundle_header *header, const char *path,
        argv_pack[1] = "--all-progress-implied";
        argv_pack[2] = "--stdout";
        argv_pack[3] = "--thin";
-       argv_pack[4] = NULL;
+       argv_pack[4] = "--delta-base-offset";
+       argv_pack[5] = NULL;
        memset(&rls, 0, sizeof(rls));
        rls.argv = argv_pack;
        rls.in = -1;
index 74d66018800d7a2a2b3a3365e87a23049690da6b..ac337c7d7dc1724fa918f9340816d3102edb10bd 100644 (file)
--- a/commit.c
+++ b/commit.c
@@ -245,10 +245,10 @@ int unregister_shallow(const unsigned char *sha1)
        return 0;
 }
 
-int parse_commit_buffer(struct commit *item, void *buffer, unsigned long size)
+int parse_commit_buffer(struct commit *item, const void *buffer, unsigned long size)
 {
-       char *tail = buffer;
-       char *bufptr = buffer;
+       const char *tail = buffer;
+       const char *bufptr = buffer;
        unsigned char parent[20];
        struct commit_list **pptr;
        struct commit_graft *graft;
index eb6c5af1f6b18546b3b3f1683142b15bb0ae9e34..659c87c3ee90c23064f617e3bcf3ace12e32ea04 100644 (file)
--- a/commit.h
+++ b/commit.h
@@ -38,7 +38,7 @@ struct commit *lookup_commit_reference_gently(const unsigned char *sha1,
                                              int quiet);
 struct commit *lookup_commit_reference_by_name(const char *name);
 
-int parse_commit_buffer(struct commit *item, void *buffer, unsigned long size);
+int parse_commit_buffer(struct commit *item, const void *buffer, unsigned long size);
 int parse_commit(struct commit *item);
 
 /* Find beginning and length of commit subject. */
index 60a05a8b978345224c0313edb8060f5a7c2ccb54..6bf155cbdb61498bdaf84712a2dea6fb05361ce2 100755 (executable)
@@ -26,6 +26,7 @@ require_work_tree
 cd_to_toplevel
 
 no_commit=
+xopt=
 while case "$#" in 0) break ;; esac
 do
        case "$1" in
@@ -44,6 +45,16 @@ do
        -x|--i-really-want-to-expose-my-private-commit-object-name)
                replay=
                ;;
+       -X?*)
+               xopt="$xopt$(git rev-parse --sq-quote "--${1#-X}")"
+               ;;
+       --strategy-option=*)
+               xopt="$xopt$(git rev-parse --sq-quote "--${1#--strategy-option=}")"
+               ;;
+       -X|--strategy-option)
+               shift
+               xopt="$xopt$(git rev-parse --sq-quote "--$1")"
+               ;;
        -*)
                usage
                ;;
@@ -159,7 +170,7 @@ export GITHEAD_$head GITHEAD_$next
 # and $prev on top of us (when reverting), or the change between
 # $prev and $commit on top of us (when cherry-picking or replaying).
 
-git-merge-recursive $base -- $head $next &&
+eval "git merge-recursive $xopt $base -- $head $next" &&
 result=$(git-write-tree 2>/dev/null) || {
        mv -f .msg "$GIT_DIR/MERGE_MSG"
        {
index f99ea9585014face001849aeeefa5f20e79bc1e2..21989fc6ab84c0503cdc9418673d9d0bf06f9d49 100755 (executable)
@@ -709,7 +709,7 @@ if [ -z "$GIT_DIR" ]; then
        exit 1
 fi
 
-projectdesc=$(sed -ne '1p' "$GIT_DIR/description")
+projectdesc=$(sed -ne '1p' "$GIT_DIR/description" 2>/dev/null)
 # Check if the description is unchanged from it's default, and shorten it to
 # a more manageable length if it is
 if expr "$projectdesc" : "Unnamed repository.*$" >/dev/null
index bf225706ee377b89035eb21f76f9957cfaf6363b..38545e8bfd72c8cd4f91e0d33257b143db86bac5 100644 (file)
@@ -3,7 +3,6 @@
 #include "quote.h"
 #define MAX_ARGS       32
 
-extern char **environ;
 static const char *argv_exec_path;
 static const char *argv0_path;
 
index 785776086ccc22dcd5488e3ac0bad3318f57043e..3886a1b46415ddbf66e5c2be401ad7fd2c012363 100644 (file)
@@ -329,6 +329,7 @@ static struct mark_set *marks;
 static const char *export_marks_file;
 static const char *import_marks_file;
 static int import_marks_file_from_stream;
+static int import_marks_file_ignore_missing;
 static int relative_marks_paths;
 
 /* Our last blob */
@@ -1795,7 +1796,11 @@ static void read_marks(void)
 {
        char line[512];
        FILE *f = fopen(import_marks_file, "r");
-       if (!f)
+       if (f)
+               ;
+       else if (import_marks_file_ignore_missing && errno == ENOENT)
+               return; /* Marks file does not exist */
+       else
                die_errno("cannot read '%s'", import_marks_file);
        while (fgets(line, sizeof(line), f)) {
                uintmax_t mark;
@@ -2231,6 +2236,12 @@ static void file_change_m(struct branch *b)
                p = uq.buf;
        }
 
+       /* Git does not track empty, non-toplevel directories. */
+       if (S_ISDIR(mode) && !memcmp(sha1, EMPTY_TREE_SHA1_BIN, 20) && *p) {
+               tree_content_remove(&b->branch_tree, p, NULL);
+               return;
+       }
+
        if (S_ISGITLINK(mode)) {
                if (inline_data)
                        die("Git links cannot be specified 'inline': %s",
@@ -2861,7 +2872,8 @@ static char* make_fast_import_path(const char *path)
        return strbuf_detach(&abs_path, NULL);
 }
 
-static void option_import_marks(const char *marks, int from_stream)
+static void option_import_marks(const char *marks,
+                                       int from_stream, int ignore_missing)
 {
        if (import_marks_file) {
                if (from_stream)
@@ -2875,6 +2887,7 @@ static void option_import_marks(const char *marks, int from_stream)
        import_marks_file = make_fast_import_path(marks);
        safe_create_leading_directories_const(import_marks_file);
        import_marks_file_from_stream = from_stream;
+       import_marks_file_ignore_missing = ignore_missing;
 }
 
 static void option_date_format(const char *fmt)
@@ -2974,7 +2987,10 @@ static int parse_one_feature(const char *feature, int from_stream)
        if (!prefixcmp(feature, "date-format=")) {
                option_date_format(feature + 12);
        } else if (!prefixcmp(feature, "import-marks=")) {
-               option_import_marks(feature + 13, from_stream);
+               option_import_marks(feature + 13, from_stream, 0);
+       } else if (!prefixcmp(feature, "import-marks-if-exists=")) {
+               option_import_marks(feature + strlen("import-marks-if-exists="),
+                                       from_stream, 1);
        } else if (!prefixcmp(feature, "export-marks=")) {
                option_export_marks(feature + 13);
        } else if (!strcmp(feature, "cat-blob")) {
@@ -2985,6 +3001,8 @@ static int parse_one_feature(const char *feature, int from_stream)
                relative_marks_paths = 0;
        } else if (!prefixcmp(feature, "force")) {
                force_update = 1;
+       } else if (!strcmp(feature, "notes")) {
+               ; /* do nothing; we have the feature */
        } else {
                return 0;
        }
index a5ffd9a31eea0f361774d77867c83f444847279b..5873ba4bc3b2a94cd7754ae572072fd745dc059d 100755 (executable)
@@ -894,7 +894,7 @@ first and then run 'git rebase --continue' again."
 
                if test ! -z "$1"
                then
-                       output git checkout "$1" ||
+                       output git checkout "$1" -- ||
                                die "Could not checkout $1"
                fi
 
@@ -1021,7 +1021,7 @@ first and then run 'git rebase --continue' again."
 #  e, edit = use commit, but stop for amending
 #  s, squash = use commit, but meld into previous commit
 #  f, fixup = like "squash", but discard this commit's log message
-#  x <cmd>, exec <cmd> = Run a shell command <cmd>, and stop if it fails
+#  x, exec = run command (the rest of the line) using shell
 #
 # If you remove a line here THAT COMMIT WILL BE LOST.
 # However, if you remove everything, the rebase will be aborted.
index d8e190302668ca352fd58cd052a677347a29cdcd..cbb0ea90ed410d5af68ce814b7fd93a90829f3ee 100755 (executable)
@@ -482,6 +482,7 @@ case "$#" in
        then
                head_name="detached HEAD"
        else
+               echo >&2 "fatal: no such branch: $1"
                usage
        fi
        ;;
@@ -513,7 +514,7 @@ then
        if test -z "$force_rebase"
        then
                # Lazily switch to the target branch if needed...
-               test -z "$switch_to" || git checkout "$switch_to"
+               test -z "$switch_to" || git checkout "$switch_to" --
                say "Current branch $branch_name is up to date."
                exit 0
        else
diff --git a/git.c b/git.c
index 68334f6a3134bb76a8ffc59e4da773400c59a388..23610aa0366ebe36e65e78fb8c5fba3f2d0b8f77 100644 (file)
--- a/git.c
+++ b/git.c
@@ -177,24 +177,24 @@ static int handle_alias(int *argcp, const char ***argv)
        alias_string = alias_lookup(alias_command);
        if (alias_string) {
                if (alias_string[0] == '!') {
+                       const char **alias_argv;
+                       int argc = *argcp, i;
+
                        commit_pager_choice();
-                       if (*argcp > 1) {
-                               struct strbuf buf;
-
-                               strbuf_init(&buf, PATH_MAX);
-                               strbuf_addstr(&buf, alias_string);
-                               sq_quote_argv(&buf, (*argv) + 1, PATH_MAX);
-                               free(alias_string);
-                               alias_string = buf.buf;
-                       }
-                       trace_printf("trace: alias to shell cmd: %s => %s\n",
-                                    alias_command, alias_string + 1);
-                       ret = system(alias_string + 1);
-                       if (ret >= 0 && WIFEXITED(ret) &&
-                           WEXITSTATUS(ret) != 127)
-                               exit(WEXITSTATUS(ret));
-                       die("Failed to run '%s' when expanding alias '%s'",
-                           alias_string + 1, alias_command);
+
+                       /* build alias_argv */
+                       alias_argv = xmalloc(sizeof(*alias_argv) * (argc + 1));
+                       alias_argv[0] = alias_string + 1;
+                       for (i = 1; i < argc; ++i)
+                               alias_argv[i] = (*argv)[i];
+                       alias_argv[argc] = NULL;
+
+                       ret = run_command_v_opt(alias_argv, RUN_USING_SHELL);
+                       if (ret >= 0)   /* normal exit */
+                               exit(ret);
+
+                       die_errno("While expanding alias '%s': '%s'",
+                           alias_command, alias_string + 1);
                }
                count = split_cmdline(alias_string, &new_argv);
                if (count < 0)
index 823053173c92e4097dad54945db16f42b4b5d994..4964a679b3013caa9bfa2f438dc110eaa0274b69 100644 (file)
@@ -237,6 +237,12 @@ Requirements
  - Perl modules: CGI, Encode, Fcntl, File::Find, File::Basename.
  - web server
 
+The following optional Perl modules are required for extra features
+ - Digest::MD5 - for gravatar support
+ - CGI::Fast and FCGI - for running gitweb as FastCGI script
+ - HTML::TagCloud - for fancy tag cloud in project list view
+ - HTTP::Date or Time::ParseDate - to support If-Modified-Since for feeds
+
 
 Example web server configuration
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
index 1025c2f7165a7941ac8d13bff0e693cb3783b475..0779f12d6178c23a47f4b9a08152176d0e19a2a8 100755 (executable)
@@ -3468,7 +3468,7 @@ sub run_highlighter {
        close $fd;
        open $fd, quote_command(git_cmd(), "cat-file", "blob", $hash)." | ".
                  quote_command($highlight_bin).
-                 " --xhtml --fragment --syntax $syntax |"
+                 " --fragment --syntax $syntax |"
                or die_error(500, "Couldn't open file or run syntax highlighter");
        return $fd;
 }
index 007dd3e4d38ff657a29a06e559173b796f193763..6ce512efc4cce8042481e8a6947d033c272e78e6 100644 (file)
@@ -351,16 +351,13 @@ int ll_merge(mmbuffer_t *result_buf,
             const struct ll_merge_options *opts)
 {
        static struct git_attr_check check[2];
+       static const struct ll_merge_options default_opts;
        const char *ll_driver_name = NULL;
        int marker_size = DEFAULT_CONFLICT_MARKER_SIZE;
        const struct ll_merge_driver *driver;
 
-       if (!opts) {
-               struct ll_merge_options default_opts = {0};
-               return ll_merge(result_buf, path, ancestor, ancestor_label,
-                               ours, our_label, theirs, their_label,
-                               &default_opts);
-       }
+       if (!opts)
+               opts = &default_opts;
 
        if (opts->renormalize) {
                normalize_file(ancestor, path);
index c8135b0ec70cc2eb92e5a6fd9353a134fda6b7bf..981ed6ac94b5ed73f15a3b0dca723586374ca0b8 100644 (file)
@@ -57,6 +57,8 @@ struct tree *write_tree_from_memory(struct merge_options *o);
 int parse_merge_opt(struct merge_options *out, const char *s);
 
 /* builtin/merge.c */
-int try_merge_command(const char *strategy, struct commit_list *common, const char *head_arg, struct commit_list *remotes);
+int try_merge_command(const char *strategy, size_t xopts_nr,
+               const char **xopts, struct commit_list *common,
+               const char *head_arg, struct commit_list *remotes);
 
 #endif
diff --git a/quote.h b/quote.h
index 38003bff5f97a11e051b106522a8548d43d24f6c..024e21d80ceaa37ec1f893acc907a62092560d21 100644 (file)
--- a/quote.h
+++ b/quote.h
@@ -1,8 +1,7 @@
 #ifndef QUOTE_H
 #define QUOTE_H
 
-#include <stddef.h>
-#include <stdio.h>
+struct strbuf;
 
 /* Help to copy the thing properly quoted for the shell safety.
  * any single quote is replaced with '\'', any exclamation point
index 2a1041ef6599c84fff6a8d9faf5dea23a2af3ab0..f91e446c86be8e27f98554567143d7ce6f934bd1 100644 (file)
@@ -194,6 +194,7 @@ int start_command(struct child_process *cmd)
        }
 
        trace_argv_printf(cmd->argv, "trace: run_command:");
+       fflush(NULL);
 
 #ifndef WIN32
 {
@@ -201,7 +202,6 @@ int start_command(struct child_process *cmd)
        if (pipe(notify_pipe))
                notify_pipe[0] = notify_pipe[1] = -1;
 
-       fflush(NULL);
        cmd->pid = fork();
        if (!cmd->pid) {
                /*
diff --git a/setup.c b/setup.c
index 3d732697af600ccc3c6017844c73e1d3b0dac738..021d0133ae1d6cf7f3a6a8284cb5b6e9a42dbe0d 100644 (file)
--- a/setup.c
+++ b/setup.c
@@ -7,10 +7,13 @@ static int inside_work_tree = -1;
 char *prefix_path(const char *prefix, int len, const char *path)
 {
        const char *orig = path;
-       char *sanitized = xmalloc(len + strlen(path) + 1);
-       if (is_absolute_path(orig))
-               strcpy(sanitized, path);
-       else {
+       char *sanitized;
+       if (is_absolute_path(orig)) {
+               const char *temp = make_absolute_path(path);
+               sanitized = xmalloc(len + strlen(temp) + 1);
+               strcpy(sanitized, temp);
+       } else {
+               sanitized = xmalloc(len + strlen(path) + 1);
                if (len)
                        memcpy(sanitized, prefix, len);
                strcpy(sanitized + len, path);
@@ -411,6 +414,15 @@ static const char *setup_discovered_git_dir(const char *gitdir,
        if (check_repository_format_gently(gitdir, nongit_ok))
                return NULL;
 
+       /* --work-tree is set without --git-dir; use discovered one */
+       if (getenv(GIT_WORK_TREE_ENVIRONMENT) || git_work_tree_cfg) {
+               if (offset != len && !is_absolute_path(gitdir))
+                       gitdir = xstrdup(make_absolute_path(gitdir));
+               if (chdir(cwd))
+                       die_errno("Could not come back to cwd");
+               return setup_explicit_git_dir(gitdir, cwd, len, nongit_ok);
+       }
+
        /* #16.2, #17.2, #20.2, #21.2, #24, #25, #28, #29 (see t1510) */
        if (is_bare_repository_cfg > 0) {
                set_git_dir(offset == len ? gitdir : make_absolute_path(gitdir));
@@ -443,6 +455,16 @@ static const char *setup_bare_git_dir(char *cwd, int offset, int len, int *nongi
        if (check_repository_format_gently(".", nongit_ok))
                return NULL;
 
+       /* --work-tree is set without --git-dir; use discovered one */
+       if (getenv(GIT_WORK_TREE_ENVIRONMENT) || git_work_tree_cfg) {
+               const char *gitdir;
+
+               gitdir = offset == len ? "." : xmemdupz(cwd, offset);
+               if (chdir(cwd))
+                       die_errno("Could not come back to cwd");
+               return setup_explicit_git_dir(gitdir, cwd, len, nongit_ok);
+       }
+
        inside_git_dir = 1;
        inside_work_tree = 0;
        if (offset != len) {
index 1cafdfa617a833ec757b481826dc62282be8f374..0b830c8642fa2b141c9888c68713a29fc4df2ef2 100644 (file)
@@ -37,6 +37,41 @@ const unsigned char null_sha1[20];
 
 static int git_open_noatime(const char *name, struct packed_git *p);
 
+/*
+ * This is meant to hold a *small* number of objects that you would
+ * want read_sha1_file() to be able to return, but yet you do not want
+ * to write them into the object store (e.g. a browse-only
+ * application).
+ */
+static struct cached_object {
+       unsigned char sha1[20];
+       enum object_type type;
+       void *buf;
+       unsigned long size;
+} *cached_objects;
+static int cached_object_nr, cached_object_alloc;
+
+static struct cached_object empty_tree = {
+       EMPTY_TREE_SHA1_BIN,
+       OBJ_TREE,
+       "",
+       0
+};
+
+static struct cached_object *find_cached_object(const unsigned char *sha1)
+{
+       int i;
+       struct cached_object *co = cached_objects;
+
+       for (i = 0; i < cached_object_nr; i++, co++) {
+               if (!hashcmp(co->sha1, sha1))
+                       return co;
+       }
+       if (!hashcmp(sha1, empty_tree.sha1))
+               return &empty_tree;
+       return NULL;
+}
+
 int safe_create_leading_directories(char *path)
 {
        char *pos = path + offset_1st_component(path);
@@ -1985,9 +2020,17 @@ static int sha1_loose_object_info(const unsigned char *sha1, unsigned long *size
 
 int sha1_object_info(const unsigned char *sha1, unsigned long *sizep)
 {
+       struct cached_object *co;
        struct pack_entry e;
        int status;
 
+       co = find_cached_object(sha1);
+       if (co) {
+               if (sizep)
+                       *sizep = co->size;
+               return co->type;
+       }
+
        if (!find_pack_entry(sha1, &e)) {
                /* Most likely it's a loose object. */
                status = sha1_loose_object_info(sha1, sizep);
@@ -2033,41 +2076,6 @@ static void *read_packed_sha1(const unsigned char *sha1,
        return data;
 }
 
-/*
- * This is meant to hold a *small* number of objects that you would
- * want read_sha1_file() to be able to return, but yet you do not want
- * to write them into the object store (e.g. a browse-only
- * application).
- */
-static struct cached_object {
-       unsigned char sha1[20];
-       enum object_type type;
-       void *buf;
-       unsigned long size;
-} *cached_objects;
-static int cached_object_nr, cached_object_alloc;
-
-static struct cached_object empty_tree = {
-       EMPTY_TREE_SHA1_BIN,
-       OBJ_TREE,
-       "",
-       0
-};
-
-static struct cached_object *find_cached_object(const unsigned char *sha1)
-{
-       int i;
-       struct cached_object *co = cached_objects;
-
-       for (i = 0; i < cached_object_nr; i++, co++) {
-               if (!hashcmp(co->sha1, sha1))
-                       return co;
-       }
-       if (!hashcmp(sha1, empty_tree.sha1))
-               return &empty_tree;
-       return NULL;
-}
-
 int pretend_sha1_file(void *buf, unsigned long len, enum object_type type,
                      unsigned char *sha1)
 {
@@ -2141,7 +2149,7 @@ void *read_sha1_file_repl(const unsigned char *sha1,
                return data;
        }
 
-       if (errno != ENOENT)
+       if (errno && errno != ENOENT)
                die_errno("failed to read object %s", sha1_to_hex(sha1));
 
        /* die if we replaced an object with one that does not exist */
index 892d443f63428aea6d6b92458bdaa4575bc46da0..25f7d2d2e3cf70d54f5b854ad4199c831a74ae2a 100644 (file)
--- a/t/README
+++ b/t/README
@@ -283,6 +283,12 @@ Do:
    Tests that are likely to smoke out future regressions are better
    than tests that just inflate the coverage metrics.
 
+ - When a test checks for an absolute path that a git command generated,
+   construct the expected value using $(pwd) rather than $PWD,
+   $TEST_DIRECTORY, or $TRASH_DIRECTORY. It makes a difference on
+   Windows, where the shell (MSYS bash) mangles absolute path names.
+   For details, see the commit message of 4114156ae9.
+
 Don't:
 
  - exit() within a <script> part.
index 680d7d68612b168a2642ab64e7bc6c15c316d5b4..9bee8bfd2e063c40bae2d76930370bd9e8ba8fa5 100755 (executable)
@@ -12,4 +12,17 @@ test_expect_success 'character classes (isspace, isalpha etc.)' '
        test-ctype
 '
 
+test_expect_success 'mktemp to nonexistent directory prints filename' '
+       test_must_fail test-mktemp doesnotexist/testXXXXXX 2>err &&
+       grep "doesnotexist/test" err
+'
+
+test_expect_success POSIXPERM 'mktemp to unwritable directory prints filename' '
+       mkdir cannotwrite &&
+       chmod -w cannotwrite &&
+       test_when_finished "chmod +w cannotwrite" &&
+       test_must_fail test-mktemp cannotwrite/testXXXXXX 2>err &&
+       grep "cannotwrite/test" err
+'
+
 test_done
index f072a8ed48ce87267c72635f417bc0b3ebe03f19..da6252b1179c47d39393c983d88c75d84a507cb7 100755 (executable)
@@ -343,7 +343,7 @@ test_expect_success 'make_relative_path handles double slashes in GIT_DIR' '
 test_expect_success 'relative $GIT_WORK_TREE and git subprocesses' '
        GIT_DIR=repo.git GIT_WORK_TREE=repo.git/work \
        test-subprocess --setup-work-tree rev-parse --show-toplevel >actual &&
-       echo "$TRASH_DIRECTORY/repo.git/work" >expected &&
+       echo "$(pwd)/repo.git/work" >expected &&
        test_cmp expected actual
 '
 
index c3798ce17917827c5a00bed09b2475d761fde32d..15101d5e032fbbef4a66039342d07afbc5203ee0 100755 (executable)
 #!/bin/sh
 
-test_description='Tests of cwd/prefix/worktree/gitdir setup in all cases'
+test_description="Tests of cwd/prefix/worktree/gitdir setup in all cases
 
-. ./test-lib.sh
-
-#
-# A few rules for repo setup:
-#
-# 1. GIT_DIR is relative to user's cwd. --git-dir is equivalent to
-#    GIT_DIR.
-#
-# 2. .git file is relative to parent directory. .git file is basically
-#    symlink in disguise. The directory where .git file points to will
-#    become new git_dir.
-#
-# 3. core.worktree is relative to git_dir.
-#
-# 4. GIT_WORK_TREE is relative to user's cwd. --work-tree is
-#    equivalent to GIT_WORK_TREE.
-#
-# 5. GIT_WORK_TREE/core.worktree is only effective if GIT_DIR is set
-#    Uneffective worktree settings should be warned.
-#
-# 6. Effective GIT_WORK_TREE overrides core.worktree and core.bare
-#
-# 7. Effective core.worktree conflicts with core.bare
-#
-# 8. If GIT_DIR is set but neither worktree nor bare setting is given,
-#    original cwd becomes worktree.
-#
-# 9. If .git discovery is done inside a repo, the repo becomes a bare
-#    repo. .git discovery is performed if GIT_DIR is not set.
-#
-# 10. If no worktree is available, cwd remains unchanged, prefix is
-#     NULL.
-#
-# 11. When user's cwd is outside worktree, cwd remains unchanged,
-#     prefix is NULL.
-#
-
-test_repo() {
-       (
-       cd "$1" &&
-       if test -n "$2"; then GIT_DIR="$2" && export GIT_DIR; fi &&
-       if test -n "$3"; then GIT_WORK_TREE="$3" && export GIT_WORK_TREE; fi &&
-       rm -f trace &&
-       GIT_TRACE="`pwd`/trace" git symbolic-ref HEAD >/dev/null &&
-       grep '^setup: ' trace >result &&
-       test_cmp expected result
-       )
-}
-
-# Bit 0 = GIT_WORK_TREE
-# Bit 1 = GIT_DIR
-# Bit 2 = core.worktree
-# Bit 3 = .git is a file
-# Bit 4 = bare repo
-# Case# = encoding of the above 5 bits
-
-#
-# Case #0
-#
-############################################################
-#
-# Input:
-#
-#  - GIT_WORK_TREE is not set
-#  - GIT_DIR is not set
-#  - core.worktree is not set
-#  - .git is a directory
-#  - core.bare is not set, cwd is outside .git
-#
-# Output:
-#
-#  - worktree is .git's parent directory
-#  - cwd is at worktree root dir
-#  - prefix is calculated
-#  - git_dir is set to ".git"
-#  - cwd can't be outside worktree
-
-test_expect_success '#0: setup' '
-       sane_unset GIT_DIR GIT_WORK_TREE &&
-       mkdir 0 0/sub &&
-       cd 0 && git init && cd ..
-'
-
-test_expect_success '#0: at root' '
-       cat >0/expected <<EOF &&
-setup: git_dir: .git
-setup: worktree: $TRASH_DIRECTORY/0
-setup: cwd: $TRASH_DIRECTORY/0
-setup: prefix: (null)
-EOF
-       test_repo 0
-'
-
-test_expect_success '#0: in subdir' '
-       cat >0/sub/expected <<EOF &&
-setup: git_dir: .git
-setup: worktree: $TRASH_DIRECTORY/0
-setup: cwd: $TRASH_DIRECTORY/0
-setup: prefix: sub/
-EOF
-       test_repo 0/sub
-'
-
-#
-# case #1
-#
-############################################################
-#
-# Input:
-#
-#  - GIT_WORK_TREE is set
-#  - GIT_DIR is not set
-#  - core.worktree is not set
-#  - .git is a directory
-#  - core.bare is not set, cwd is outside .git
-#
-# Output:
-#
-# GIT_WORK_TREE is ignored -> #0
-
-test_expect_success '#1: setup' '
-       sane_unset GIT_DIR GIT_WORK_TREE &&
-       mkdir 1 1/sub 1.wt 1.wt/sub 1/wt 1/wt/sub &&
-       cd 1 &&
-       git init &&
-       GIT_WORK_TREE=non-existent &&
-       export GIT_WORK_TREE &&
-       cd ..
-'
-
-test_expect_success '#1: at root' '
-       cat >1/expected <<EOF &&
-setup: git_dir: .git
-setup: worktree: $TRASH_DIRECTORY/1
-setup: cwd: $TRASH_DIRECTORY/1
-setup: prefix: (null)
-EOF
-       test_repo 1
-'
-
-test_expect_success '#1: in subdir' '
-       cat >1/sub/expected <<EOF &&
-setup: git_dir: .git
-setup: worktree: $TRASH_DIRECTORY/1
-setup: cwd: $TRASH_DIRECTORY/1
-setup: prefix: sub/
-EOF
-       test_repo 1/sub
-'
-
-#
-# case #2
-#
-############################################################
-#
-# Input:
-#
-#  - GIT_WORK_TREE is not set
-#  - GIT_DIR is set
-#  - core.worktree is not set
-#  - .git is a directory
-#  - core.bare is not set, cwd is outside .git
-#
-# Output:
-#
-#  - worktree is at original cwd
-#  - cwd is unchanged
-#  - prefix is NULL
-#  - git_dir is set to $GIT_DIR
-#  - cwd can't be outside worktree
-
-test_expect_success '#2: setup' '
-       sane_unset GIT_DIR GIT_WORK_TREE &&
-       mkdir 2 2/sub &&
-       cd 2 && git init && cd ..
-'
-
-test_expect_success '#2: at root' '
-       cat >2/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/2/.git
-setup: worktree: $TRASH_DIRECTORY/2
-setup: cwd: $TRASH_DIRECTORY/2
-setup: prefix: (null)
-EOF
-       test_repo 2 "$TRASH_DIRECTORY/2/.git"
-'
-
-test_expect_success '#2: in subdir' '
-       cat >2/sub/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/2/.git
-setup: worktree: $TRASH_DIRECTORY/2/sub
-setup: cwd: $TRASH_DIRECTORY/2/sub
-setup: prefix: (null)
-EOF
-       test_repo 2/sub "$TRASH_DIRECTORY/2/.git"
-'
-
-test_expect_success '#2: relative GIT_DIR at root' '
-       cat >2/expected <<EOF &&
-setup: git_dir: .git
-setup: worktree: $TRASH_DIRECTORY/2
-setup: cwd: $TRASH_DIRECTORY/2
-setup: prefix: (null)
-EOF
-       test_repo 2 .git
-'
-
-test_expect_success '#2: relative GIT_DIR in subdir' '
-       cat >2/sub/expected <<EOF &&
-setup: git_dir: ../.git
-setup: worktree: $TRASH_DIRECTORY/2/sub
-setup: cwd: $TRASH_DIRECTORY/2/sub
-setup: prefix: (null)
-EOF
-       test_repo 2/sub ../.git
-'
-
-#
-# case #3
-#
-############################################################
-#
-# Input:
-#
-#  - GIT_WORK_TREE is set
-#  - GIT_DIR is set
-#  - core.worktree is not set
-#  - .git is a directory
-#  - core.bare is not set, cwd is outside .git
-#
-# Output:
-#
-#  - worktree is set to $GIT_WORK_TREE
-#  - cwd is at worktree root
-#  - prefix is calculated
-#  - git_dir is set to $GIT_DIR
-#  - cwd can be outside worktree
-
-test_expect_success '#3: setup' '
-       sane_unset GIT_DIR GIT_WORK_TREE &&
-       mkdir 3 3/sub 3/sub/sub 3.wt 3.wt/sub 3/wt 3/wt/sub &&
-       cd 3 && git init && cd ..
-'
-
-test_expect_success '#3: GIT_DIR(rel), GIT_WORK_TREE=root at root' '
-       cat >3/expected <<EOF &&
-setup: git_dir: .git
-setup: worktree: $TRASH_DIRECTORY/3
-setup: cwd: $TRASH_DIRECTORY/3
-setup: prefix: (null)
-EOF
-       test_repo 3 .git "$TRASH_DIRECTORY/3"
-'
-
-test_expect_success '#3: GIT_DIR(rel), GIT_WORK_TREE=root(rel) at root' '
-       cat >3/expected <<EOF &&
-setup: git_dir: .git
-setup: worktree: $TRASH_DIRECTORY/3
-setup: cwd: $TRASH_DIRECTORY/3
-setup: prefix: (null)
-EOF
-       test_repo 3 .git .
-'
-
-test_expect_success '#3: GIT_DIR, GIT_WORK_TREE=root at root' '
-       cat >3/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/3/.git
-setup: worktree: $TRASH_DIRECTORY/3
-setup: cwd: $TRASH_DIRECTORY/3
-setup: prefix: (null)
-EOF
-       test_repo 3 "$TRASH_DIRECTORY/3/.git" "$TRASH_DIRECTORY/3"
-'
-
-test_expect_success '#3: GIT_DIR, GIT_WORK_TREE=root(rel) at root' '
-       cat >3/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/3/.git
-setup: worktree: $TRASH_DIRECTORY/3
-setup: cwd: $TRASH_DIRECTORY/3
-setup: prefix: (null)
-EOF
-       test_repo 3 "$TRASH_DIRECTORY/3/.git" .
-'
-
-test_expect_success '#3: GIT_DIR(rel), GIT_WORKTREE=root in subdir' '
-       cat >3/sub/sub/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/3/.git
-setup: worktree: $TRASH_DIRECTORY/3
-setup: cwd: $TRASH_DIRECTORY/3
-setup: prefix: sub/sub/
-EOF
-       test_repo 3/sub/sub ../../.git "$TRASH_DIRECTORY/3"
-'
-
-test_expect_success '#3: GIT_DIR(rel), GIT_WORKTREE=root(rel) in subdir' '
-       cat >3/sub/sub/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/3/.git
-setup: worktree: $TRASH_DIRECTORY/3
-setup: cwd: $TRASH_DIRECTORY/3
-setup: prefix: sub/sub/
-EOF
-       test_repo 3/sub/sub ../../.git ../..
-'
-
-test_expect_success '#3: GIT_DIR, GIT_WORKTREE=root in subdir' '
-       cat >3/sub/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/3/.git
-setup: worktree: $TRASH_DIRECTORY/3
-setup: cwd: $TRASH_DIRECTORY/3
-setup: prefix: sub/
-EOF
-       test_repo 3/sub "$TRASH_DIRECTORY/3/.git" "$TRASH_DIRECTORY/3"
-'
-
-test_expect_success '#3: GIT_DIR, GIT_WORKTREE=root(rel) in subdir' '
-       cat >3/sub/sub/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/3/.git
-setup: worktree: $TRASH_DIRECTORY/3
-setup: cwd: $TRASH_DIRECTORY/3
-setup: prefix: sub/sub/
-EOF
-       test_repo 3/sub/sub "$TRASH_DIRECTORY/3/.git" ../..
-'
-
-test_expect_success '#3: GIT_DIR(rel), GIT_WORK_TREE=wt at root' '
-       cat >3/expected <<EOF &&
-setup: git_dir: .git
-setup: worktree: $TRASH_DIRECTORY/3/wt
-setup: cwd: $TRASH_DIRECTORY/3
-setup: prefix: (null)
-EOF
-       test_repo 3 .git "$TRASH_DIRECTORY/3/wt"
-'
-
-test_expect_success '#3: GIT_DIR(rel), GIT_WORK_TREE=wt(rel) at root' '
-       cat >3/expected <<EOF &&
-setup: git_dir: .git
-setup: worktree: $TRASH_DIRECTORY/3/wt
-setup: cwd: $TRASH_DIRECTORY/3
-setup: prefix: (null)
-EOF
-       test_repo 3 .git wt
-'
-
-test_expect_success '#3: GIT_DIR, GIT_WORK_TREE=wt(rel) at root' '
-       cat >3/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/3/.git
-setup: worktree: $TRASH_DIRECTORY/3/wt
-setup: cwd: $TRASH_DIRECTORY/3
-setup: prefix: (null)
-EOF
-       test_repo 3 "$TRASH_DIRECTORY/3/.git" wt
-'
-
-test_expect_success '#3: GIT_DIR, GIT_WORK_TREE=wt at root' '
-       cat >3/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/3/.git
-setup: worktree: $TRASH_DIRECTORY/3/wt
-setup: cwd: $TRASH_DIRECTORY/3
-setup: prefix: (null)
-EOF
-       test_repo 3 "$TRASH_DIRECTORY/3/.git" "$TRASH_DIRECTORY/3/wt"
-'
-
-test_expect_success '#3: GIT_DIR(rel), GIT_WORK_TREE=wt in subdir' '
-       cat >3/sub/sub/expected <<EOF &&
-setup: git_dir: ../../.git
-setup: worktree: $TRASH_DIRECTORY/3/wt
-setup: cwd: $TRASH_DIRECTORY/3/sub/sub
-setup: prefix: (null)
-EOF
-       test_repo 3/sub/sub ../../.git "$TRASH_DIRECTORY/3/wt"
-'
-
-test_expect_success '#3: GIT_DIR(rel), GIT_WORK_TREE=wt(rel) in subdir' '
-       cat >3/sub/sub/expected <<EOF &&
-setup: git_dir: ../../.git
-setup: worktree: $TRASH_DIRECTORY/3/wt
-setup: cwd: $TRASH_DIRECTORY/3/sub/sub
-setup: prefix: (null)
-EOF
-       test_repo 3/sub/sub ../../.git ../../wt
-'
-
-test_expect_success '#3: GIT_DIR, GIT_WORK_TREE=wt(rel) in subdir' '
-       cat >3/sub/sub/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/3/.git
-setup: worktree: $TRASH_DIRECTORY/3/wt
-setup: cwd: $TRASH_DIRECTORY/3/sub/sub
-setup: prefix: (null)
-EOF
-       test_repo 3/sub/sub "$TRASH_DIRECTORY/3/.git" ../../wt
-'
-
-test_expect_success '#3: GIT_DIR, GIT_WORK_TREE=wt in subdir' '
-       cat >3/sub/sub/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/3/.git
-setup: worktree: $TRASH_DIRECTORY/3/wt
-setup: cwd: $TRASH_DIRECTORY/3/sub/sub
-setup: prefix: (null)
-EOF
-       test_repo 3/sub/sub "$TRASH_DIRECTORY/3/.git" "$TRASH_DIRECTORY/3/wt"
-'
-
-test_expect_success '#3: GIT_DIR(rel), GIT_WORK_TREE=.. at root' '
-       cat >3/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/3/.git
-setup: worktree: $TRASH_DIRECTORY
-setup: cwd: $TRASH_DIRECTORY
-setup: prefix: 3/
-EOF
-       test_repo 3 .git "$TRASH_DIRECTORY"
-'
-
-test_expect_success '#3: GIT_DIR(rel), GIT_WORK_TREE=..(rel) at root' '
-       cat >3/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/3/.git
-setup: worktree: $TRASH_DIRECTORY
-setup: cwd: $TRASH_DIRECTORY
-setup: prefix: 3/
-EOF
-       test_repo 3 .git ..
-'
-
-test_expect_success '#3: GIT_DIR, GIT_WORK_TREE=..(rel) at root' '
-       cat >3/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/3/.git
-setup: worktree: $TRASH_DIRECTORY
-setup: cwd: $TRASH_DIRECTORY
-setup: prefix: 3/
-EOF
-       test_repo 3 "$TRASH_DIRECTORY/3/.git" ..
-'
-
-test_expect_success '#3: GIT_DIR, GIT_WORK_TREE=.. at root' '
-       cat >3/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/3/.git
-setup: worktree: $TRASH_DIRECTORY
-setup: cwd: $TRASH_DIRECTORY
-setup: prefix: 3/
-EOF
-       test_repo 3 "$TRASH_DIRECTORY/3/.git" "$TRASH_DIRECTORY"
-'
-
-test_expect_success '#3: GIT_DIR(rel), GIT_WORK_TREE=.. in subdir' '
-       cat >3/sub/sub/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/3/.git
-setup: worktree: $TRASH_DIRECTORY
-setup: cwd: $TRASH_DIRECTORY
-setup: prefix: 3/sub/sub/
-EOF
-       test_repo 3/sub/sub ../../.git "$TRASH_DIRECTORY"
-'
-
-test_expect_success '#3: GIT_DIR(rel), GIT_WORK_TREE=..(rel) in subdir' '
-       cat >3/sub/sub/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/3/.git
-setup: worktree: $TRASH_DIRECTORY
-setup: cwd: $TRASH_DIRECTORY
-setup: prefix: 3/sub/sub/
-EOF
-       test_repo 3/sub/sub ../../.git ../../..
-'
-
-test_expect_success '#3: GIT_DIR, GIT_WORK_TREE=..(rel) in subdir' '
-       cat >3/sub/sub/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/3/.git
-setup: worktree: $TRASH_DIRECTORY
-setup: cwd: $TRASH_DIRECTORY
-setup: prefix: 3/sub/sub/
-EOF
-       test_repo 3/sub/sub "$TRASH_DIRECTORY/3/.git" ../../../
-'
-
-test_expect_success '#3: GIT_DIR, GIT_WORK_TREE=.. in subdir' '
-       cat >3/sub/sub/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/3/.git
-setup: worktree: $TRASH_DIRECTORY
-setup: cwd: $TRASH_DIRECTORY
-setup: prefix: 3/sub/sub/
-EOF
-       test_repo 3/sub/sub "$TRASH_DIRECTORY/3/.git" "$TRASH_DIRECTORY"
-'
-
-#
-# case #4
-#
-############################################################
-#
-# Input:
-#
-#  - GIT_WORK_TREE is not set
-#  - GIT_DIR is not set
-#  - core.worktree is set
-#  - .git is a directory
-#  - core.bare is not set, cwd is outside .git
-#
-# Output:
-#
-# core.worktree is ignored -> #0
-
-test_expect_success '#4: setup' '
-       sane_unset GIT_DIR GIT_WORK_TREE &&
-       mkdir 4 4/sub &&
-       cd 4 &&
-       git init &&
-       git config core.worktree non-existent &&
-       cd ..
-'
-
-test_expect_success '#4: at root' '
-       cat >4/expected <<EOF &&
-setup: git_dir: .git
-setup: worktree: $TRASH_DIRECTORY/4
-setup: cwd: $TRASH_DIRECTORY/4
-setup: prefix: (null)
-EOF
-       test_repo 4
-'
-
-test_expect_success '#4: in subdir' '
-       cat >4/sub/expected <<EOF &&
-setup: git_dir: .git
-setup: worktree: $TRASH_DIRECTORY/4
-setup: cwd: $TRASH_DIRECTORY/4
-setup: prefix: sub/
-EOF
-       test_repo 4/sub
-'
-
-#
-# case #5
-#
-############################################################
-#
-# Input:
-#
-#  - GIT_WORK_TREE is set
-#  - GIT_DIR is not set
-#  - core.worktree is set
-#  - .git is a directory
-#  - core.bare is not set, cwd is outside .git
-#
-# Output:
-#
-# GIT_WORK_TREE/core.worktree are ignored -> #0
-
-test_expect_success '#5: setup' '
-       sane_unset GIT_DIR GIT_WORK_TREE &&
-       mkdir 5 5/sub &&
-       cd 5 &&
-       git init &&
-       git config core.worktree non-existent &&
-       GIT_WORK_TREE=non-existent-too &&
-       export GIT_WORK_TREE &&
-       cd ..
-'
-
-test_expect_success '#5: at root' '
-       cat >5/expected <<EOF &&
-setup: git_dir: .git
-setup: worktree: $TRASH_DIRECTORY/5
-setup: cwd: $TRASH_DIRECTORY/5
-setup: prefix: (null)
-EOF
-       test_repo 5
-'
-
-test_expect_success '#5: in subdir' '
-       cat >5/sub/expected <<EOF &&
-setup: git_dir: .git
-setup: worktree: $TRASH_DIRECTORY/5
-setup: cwd: $TRASH_DIRECTORY/5
-setup: prefix: sub/
-EOF
-       test_repo 5/sub
-'
-
-#
-# case #6
-#
-############################################################
-#
-# Input:
-#
-#  - GIT_WORK_TREE is not set
-#  - GIT_DIR is set
-#  - core.worktree is set
-#  - .git is a directory
-#  - core.bare is not set, cwd is outside .git
-#
-# Output:
-#
-#  - worktree is at core.worktree
-#  - cwd is at worktree root
-#  - prefix is calculated
-#  - git_dir is at $GIT_DIR
-#  - cwd can be outside worktree
-
-test_expect_success '#6: setup' '
-       sane_unset GIT_DIR GIT_WORK_TREE &&
-       mkdir 6 6/sub 6/sub/sub 6.wt 6.wt/sub 6/wt 6/wt/sub &&
-       cd 6 && git init && cd ..
-'
-
-test_expect_success '#6: GIT_DIR(rel), core.worktree=.. at root' '
-       cat >6/expected <<EOF &&
-setup: git_dir: .git
-setup: worktree: $TRASH_DIRECTORY/6
-setup: cwd: $TRASH_DIRECTORY/6
-setup: prefix: (null)
-EOF
-       git config --file="$TRASH_DIRECTORY/6/.git/config" core.worktree "$TRASH_DIRECTORY/6" &&
-       test_repo 6 .git
-'
-
-test_expect_success '#6: GIT_DIR(rel), core.worktree=..(rel) at root' '
-       cat >6/expected <<EOF &&
-setup: git_dir: .git
-setup: worktree: $TRASH_DIRECTORY/6
-setup: cwd: $TRASH_DIRECTORY/6
-setup: prefix: (null)
-EOF
-       git config --file="$TRASH_DIRECTORY/6/.git/config" core.worktree .. &&
-       test_repo 6 .git
-'
-
-test_expect_success '#6: GIT_DIR, core.worktree=.. at root' '
-       cat >6/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/6/.git
-setup: worktree: $TRASH_DIRECTORY/6
-setup: cwd: $TRASH_DIRECTORY/6
-setup: prefix: (null)
-EOF
-       git config --file="$TRASH_DIRECTORY/6/.git/config" core.worktree "$TRASH_DIRECTORY/6" &&
-       test_repo 6 "$TRASH_DIRECTORY/6/.git"
-'
-
-test_expect_success '#6: GIT_DIR, core.worktree=..(rel) at root' '
-       cat >6/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/6/.git
-setup: worktree: $TRASH_DIRECTORY/6
-setup: cwd: $TRASH_DIRECTORY/6
-setup: prefix: (null)
-EOF
-       git config --file="$TRASH_DIRECTORY/6/.git/config" core.worktree .. &&
-       test_repo 6 "$TRASH_DIRECTORY/6/.git"
-'
-
-test_expect_success '#6: GIT_DIR(rel), core.worktree=.. in subdir' '
-       cat >6/sub/sub/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/6/.git
-setup: worktree: $TRASH_DIRECTORY/6
-setup: cwd: $TRASH_DIRECTORY/6
-setup: prefix: sub/sub/
-EOF
-       git config --file="$TRASH_DIRECTORY/6/.git/config" core.worktree "$TRASH_DIRECTORY/6" &&
-       test_repo 6/sub/sub ../../.git
-'
-
-test_expect_success '#6: GIT_DIR(rel), core.worktree=..(rel) in subdir' '
-       cat >6/sub/sub/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/6/.git
-setup: worktree: $TRASH_DIRECTORY/6
-setup: cwd: $TRASH_DIRECTORY/6
-setup: prefix: sub/sub/
-EOF
-       git config --file="$TRASH_DIRECTORY/6/.git/config" core.worktree .. &&
-       test_repo 6/sub/sub ../../.git
-'
-
-test_expect_success '#6: GIT_DIR, core.worktree=.. in subdir' '
-       cat >6/sub/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/6/.git
-setup: worktree: $TRASH_DIRECTORY/6
-setup: cwd: $TRASH_DIRECTORY/6
-setup: prefix: sub/
-EOF
-       git config --file="$TRASH_DIRECTORY/6/.git/config" core.worktree "$TRASH_DIRECTORY/6" &&
-       test_repo 6/sub "$TRASH_DIRECTORY/6/.git"
-'
-
-test_expect_success '#6: GIT_DIR, core.worktree=..(rel) in subdir' '
-       cat >6/sub/sub/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/6/.git
-setup: worktree: $TRASH_DIRECTORY/6
-setup: cwd: $TRASH_DIRECTORY/6
-setup: prefix: sub/sub/
-EOF
-       git config --file="$TRASH_DIRECTORY/6/.git/config" core.worktree .. &&
-       test_repo 6/sub/sub "$TRASH_DIRECTORY/6/.git"
-'
-
-test_expect_success '#6: GIT_DIR(rel), core.worktree=../wt at root' '
-       cat >6/expected <<EOF &&
-setup: git_dir: .git
-setup: worktree: $TRASH_DIRECTORY/6/wt
-setup: cwd: $TRASH_DIRECTORY/6
-setup: prefix: (null)
-EOF
-       git config --file="$TRASH_DIRECTORY/6/.git/config" core.worktree "$TRASH_DIRECTORY/6/wt" &&
-       test_repo 6 .git
-'
-
-test_expect_success '#6: GIT_DIR(rel), core.worktree=../wt(rel) at root' '
-       cat >6/expected <<EOF &&
-setup: git_dir: .git
-setup: worktree: $TRASH_DIRECTORY/6/wt
-setup: cwd: $TRASH_DIRECTORY/6
-setup: prefix: (null)
-EOF
-       git config --file="$TRASH_DIRECTORY/6/.git/config" core.worktree ../wt &&
-       test_repo 6 .git
-'
-
-test_expect_success '#6: GIT_DIR, core.worktree=../wt(rel) at root' '
-       cat >6/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/6/.git
-setup: worktree: $TRASH_DIRECTORY/6/wt
-setup: cwd: $TRASH_DIRECTORY/6
-setup: prefix: (null)
-EOF
-       git config --file="$TRASH_DIRECTORY/6/.git/config" core.worktree ../wt &&
-       test_repo 6 "$TRASH_DIRECTORY/6/.git"
-'
-
-test_expect_success '#6: GIT_DIR, core.worktree=../wt at root' '
-       cat >6/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/6/.git
-setup: worktree: $TRASH_DIRECTORY/6/wt
-setup: cwd: $TRASH_DIRECTORY/6
-setup: prefix: (null)
-EOF
-       git config --file="$TRASH_DIRECTORY/6/.git/config" core.worktree "$TRASH_DIRECTORY/6/wt" &&
-       test_repo 6 "$TRASH_DIRECTORY/6/.git"
-'
-
-test_expect_success '#6: GIT_DIR(rel), core.worktree=../wt in subdir' '
-       cat >6/sub/sub/expected <<EOF &&
-setup: git_dir: ../../.git
-setup: worktree: $TRASH_DIRECTORY/6/wt
-setup: cwd: $TRASH_DIRECTORY/6/sub/sub
-setup: prefix: (null)
-EOF
-       git config --file="$TRASH_DIRECTORY/6/.git/config" core.worktree "$TRASH_DIRECTORY/6/wt" &&
-       test_repo 6/sub/sub ../../.git
-'
-
-test_expect_success '#6: GIT_DIR(rel), core.worktree=../wt(rel) in subdir' '
-       cat >6/sub/sub/expected <<EOF &&
-setup: git_dir: ../../.git
-setup: worktree: $TRASH_DIRECTORY/6/wt
-setup: cwd: $TRASH_DIRECTORY/6/sub/sub
-setup: prefix: (null)
-EOF
-       git config --file="$TRASH_DIRECTORY/6/.git/config" core.worktree ../wt &&
-       test_repo 6/sub/sub ../../.git
-'
-
-test_expect_success '#6: GIT_DIR, core.worktree=../wt(rel) in subdir' '
-       cat >6/sub/sub/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/6/.git
-setup: worktree: $TRASH_DIRECTORY/6/wt
-setup: cwd: $TRASH_DIRECTORY/6/sub/sub
-setup: prefix: (null)
-EOF
-       git config --file="$TRASH_DIRECTORY/6/.git/config" core.worktree ../wt &&
-       test_repo 6/sub/sub "$TRASH_DIRECTORY/6/.git"
-'
-
-test_expect_success '#6: GIT_DIR, core.worktree=../wt in subdir' '
-       cat >6/sub/sub/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/6/.git
-setup: worktree: $TRASH_DIRECTORY/6/wt
-setup: cwd: $TRASH_DIRECTORY/6/sub/sub
-setup: prefix: (null)
-EOF
-       git config --file="$TRASH_DIRECTORY/6/.git/config" core.worktree "$TRASH_DIRECTORY/6/wt" &&
-       test_repo 6/sub/sub "$TRASH_DIRECTORY/6/.git"
-'
-
-test_expect_success '#6: GIT_DIR(rel), core.worktree=../.. at root' '
-       cat >6/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/6/.git
-setup: worktree: $TRASH_DIRECTORY
-setup: cwd: $TRASH_DIRECTORY
-setup: prefix: 6/
-EOF
-       git config --file="$TRASH_DIRECTORY/6/.git/config" core.worktree "$TRASH_DIRECTORY" &&
-       test_repo 6 .git
-'
-
-test_expect_success '#6: GIT_DIR(rel), core.worktree=../..(rel) at root' '
-       cat >6/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/6/.git
-setup: worktree: $TRASH_DIRECTORY
-setup: cwd: $TRASH_DIRECTORY
-setup: prefix: 6/
-EOF
-       git config --file="$TRASH_DIRECTORY/6/.git/config" core.worktree ../../ &&
-       test_repo 6 .git
-'
-
-test_expect_success '#6: GIT_DIR, core.worktree=../..(rel) at root' '
-       cat >6/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/6/.git
-setup: worktree: $TRASH_DIRECTORY
-setup: cwd: $TRASH_DIRECTORY
-setup: prefix: 6/
-EOF
-       git config --file="$TRASH_DIRECTORY/6/.git/config" core.worktree ../../ &&
-       test_repo 6 "$TRASH_DIRECTORY/6/.git"
-'
-
-test_expect_success '#6: GIT_DIR, core.worktree=../.. at root' '
-       cat >6/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/6/.git
-setup: worktree: $TRASH_DIRECTORY
-setup: cwd: $TRASH_DIRECTORY
-setup: prefix: 6/
-EOF
-       git config --file="$TRASH_DIRECTORY/6/.git/config" core.worktree "$TRASH_DIRECTORY" &&
-       test_repo 6 "$TRASH_DIRECTORY/6/.git"
-'
-
-test_expect_success '#6: GIT_DIR(rel), core.worktree=../.. in subdir' '
-       cat >6/sub/sub/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/6/.git
-setup: worktree: $TRASH_DIRECTORY
-setup: cwd: $TRASH_DIRECTORY
-setup: prefix: 6/sub/sub/
-EOF
-       git config --file="$TRASH_DIRECTORY/6/.git/config" core.worktree "$TRASH_DIRECTORY" &&
-       test_repo 6/sub/sub ../../.git
-'
-
-test_expect_success '#6: GIT_DIR(rel), core.worktree=../..(rel) in subdir' '
-       cat >6/sub/sub/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/6/.git
-setup: worktree: $TRASH_DIRECTORY
-setup: cwd: $TRASH_DIRECTORY
-setup: prefix: 6/sub/sub/
-EOF
-       git config --file="$TRASH_DIRECTORY/6/.git/config" core.worktree ../.. &&
-       test_repo 6/sub/sub ../../.git
-'
-
-test_expect_success '#6: GIT_DIR, core.worktree=../..(rel) in subdir' '
-       cat >6/sub/sub/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/6/.git
-setup: worktree: $TRASH_DIRECTORY
-setup: cwd: $TRASH_DIRECTORY
-setup: prefix: 6/sub/sub/
-EOF
-       git config --file="$TRASH_DIRECTORY/6/.git/config" core.worktree ../.. &&
-       test_repo 6/sub/sub "$TRASH_DIRECTORY/6/.git"
-'
-
-test_expect_success '#6: GIT_DIR, core.worktree=../.. in subdir' '
-       cat >6/sub/sub/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/6/.git
-setup: worktree: $TRASH_DIRECTORY
-setup: cwd: $TRASH_DIRECTORY
-setup: prefix: 6/sub/sub/
-EOF
-       git config --file="$TRASH_DIRECTORY/6/.git/config" core.worktree "$TRASH_DIRECTORY" &&
-       test_repo 6/sub/sub "$TRASH_DIRECTORY/6/.git"
-'
-
-#
-# case #7
-#
-############################################################
-#
-# Input:
-#
-#  - GIT_WORK_TREE is set
-#  - GIT_DIR is set
-#  - core.worktree is set
-#  - .git is a directory
-#  - core.bare is not set, cwd is outside .git
-#
-# Output:
-#
-# core.worktree is overridden by GIT_WORK_TREE -> #3
-
-test_expect_success '#7: setup' '
-       sane_unset GIT_DIR GIT_WORK_TREE &&
-       mkdir 7 7/sub 7/sub/sub 7.wt 7.wt/sub 7/wt 7/wt/sub &&
-       cd 7 &&
-       git init &&
-       git config core.worktree non-existent &&
-       cd ..
-'
-
-test_expect_success '#7: GIT_DIR(rel), GIT_WORK_TREE=root at root' '
-       cat >7/expected <<EOF &&
-setup: git_dir: .git
-setup: worktree: $TRASH_DIRECTORY/7
-setup: cwd: $TRASH_DIRECTORY/7
-setup: prefix: (null)
-EOF
-       test_repo 7 .git "$TRASH_DIRECTORY/7"
-'
-
-test_expect_success '#7: GIT_DIR(rel), GIT_WORK_TREE=root(rel) at root' '
-       cat >7/expected <<EOF &&
-setup: git_dir: .git
-setup: worktree: $TRASH_DIRECTORY/7
-setup: cwd: $TRASH_DIRECTORY/7
-setup: prefix: (null)
-EOF
-       test_repo 7 .git .
-'
-
-test_expect_success '#7: GIT_DIR, GIT_WORK_TREE=root at root' '
-       cat >7/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/7/.git
-setup: worktree: $TRASH_DIRECTORY/7
-setup: cwd: $TRASH_DIRECTORY/7
-setup: prefix: (null)
-EOF
-       test_repo 7 "$TRASH_DIRECTORY/7/.git" "$TRASH_DIRECTORY/7"
-'
-
-test_expect_success '#7: GIT_DIR, GIT_WORK_TREE=root(rel) at root' '
-       cat >7/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/7/.git
-setup: worktree: $TRASH_DIRECTORY/7
-setup: cwd: $TRASH_DIRECTORY/7
-setup: prefix: (null)
-EOF
-       test_repo 7 "$TRASH_DIRECTORY/7/.git" .
-'
-
-test_expect_success '#7: GIT_DIR(rel), GIT_WORKTREE=root in subdir' '
-       cat >7/sub/sub/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/7/.git
-setup: worktree: $TRASH_DIRECTORY/7
-setup: cwd: $TRASH_DIRECTORY/7
-setup: prefix: sub/sub/
-EOF
-       test_repo 7/sub/sub ../../.git "$TRASH_DIRECTORY/7"
-'
-
-test_expect_success '#7: GIT_DIR(rel), GIT_WORKTREE=root(rel) in subdir' '
-       cat >7/sub/sub/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/7/.git
-setup: worktree: $TRASH_DIRECTORY/7
-setup: cwd: $TRASH_DIRECTORY/7
-setup: prefix: sub/sub/
-EOF
-       test_repo 7/sub/sub ../../.git ../..
-'
-
-test_expect_success '#7: GIT_DIR, GIT_WORKTREE=root in subdir' '
-       cat >7/sub/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/7/.git
-setup: worktree: $TRASH_DIRECTORY/7
-setup: cwd: $TRASH_DIRECTORY/7
-setup: prefix: sub/
-EOF
-       test_repo 7/sub "$TRASH_DIRECTORY/7/.git" "$TRASH_DIRECTORY/7"
-'
-
-test_expect_success '#7: GIT_DIR, GIT_WORKTREE=root(rel) in subdir' '
-       cat >7/sub/sub/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/7/.git
-setup: worktree: $TRASH_DIRECTORY/7
-setup: cwd: $TRASH_DIRECTORY/7
-setup: prefix: sub/sub/
-EOF
-       test_repo 7/sub/sub "$TRASH_DIRECTORY/7/.git" ../..
-'
-
-test_expect_success '#7: GIT_DIR(rel), GIT_WORK_TREE=wt at root' '
-       cat >7/expected <<EOF &&
-setup: git_dir: .git
-setup: worktree: $TRASH_DIRECTORY/7/wt
-setup: cwd: $TRASH_DIRECTORY/7
-setup: prefix: (null)
-EOF
-       test_repo 7 .git "$TRASH_DIRECTORY/7/wt"
-'
-
-test_expect_success '#7: GIT_DIR(rel), GIT_WORK_TREE=wt(rel) at root' '
-       cat >7/expected <<EOF &&
-setup: git_dir: .git
-setup: worktree: $TRASH_DIRECTORY/7/wt
-setup: cwd: $TRASH_DIRECTORY/7
-setup: prefix: (null)
-EOF
-       test_repo 7 .git wt
-'
-
-test_expect_success '#7: GIT_DIR, GIT_WORK_TREE=wt(rel) at root' '
-       cat >7/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/7/.git
-setup: worktree: $TRASH_DIRECTORY/7/wt
-setup: cwd: $TRASH_DIRECTORY/7
-setup: prefix: (null)
-EOF
-       test_repo 7 "$TRASH_DIRECTORY/7/.git" wt
-'
-
-test_expect_success '#7: GIT_DIR, GIT_WORK_TREE=wt at root' '
-       cat >7/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/7/.git
-setup: worktree: $TRASH_DIRECTORY/7/wt
-setup: cwd: $TRASH_DIRECTORY/7
-setup: prefix: (null)
-EOF
-       test_repo 7 "$TRASH_DIRECTORY/7/.git" "$TRASH_DIRECTORY/7/wt"
-'
-
-test_expect_success '#7: GIT_DIR(rel), GIT_WORK_TREE=wt in subdir' '
-       cat >7/sub/sub/expected <<EOF &&
-setup: git_dir: ../../.git
-setup: worktree: $TRASH_DIRECTORY/7/wt
-setup: cwd: $TRASH_DIRECTORY/7/sub/sub
-setup: prefix: (null)
-EOF
-       test_repo 7/sub/sub ../../.git "$TRASH_DIRECTORY/7/wt"
-'
-
-test_expect_success '#7: GIT_DIR(rel), GIT_WORK_TREE=wt(rel) in subdir' '
-       cat >7/sub/sub/expected <<EOF &&
-setup: git_dir: ../../.git
-setup: worktree: $TRASH_DIRECTORY/7/wt
-setup: cwd: $TRASH_DIRECTORY/7/sub/sub
-setup: prefix: (null)
-EOF
-       test_repo 7/sub/sub ../../.git ../../wt
-'
-
-test_expect_success '#7: GIT_DIR, GIT_WORK_TREE=wt(rel) in subdir' '
-       cat >7/sub/sub/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/7/.git
-setup: worktree: $TRASH_DIRECTORY/7/wt
-setup: cwd: $TRASH_DIRECTORY/7/sub/sub
-setup: prefix: (null)
-EOF
-       test_repo 7/sub/sub "$TRASH_DIRECTORY/7/.git" ../../wt
-'
-
-test_expect_success '#7: GIT_DIR, GIT_WORK_TREE=wt in subdir' '
-       cat >7/sub/sub/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/7/.git
-setup: worktree: $TRASH_DIRECTORY/7/wt
-setup: cwd: $TRASH_DIRECTORY/7/sub/sub
-setup: prefix: (null)
-EOF
-       test_repo 7/sub/sub "$TRASH_DIRECTORY/7/.git" "$TRASH_DIRECTORY/7/wt"
-'
-
-test_expect_success '#7: GIT_DIR(rel), GIT_WORK_TREE=.. at root' '
-       cat >7/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/7/.git
-setup: worktree: $TRASH_DIRECTORY
-setup: cwd: $TRASH_DIRECTORY
-setup: prefix: 7/
-EOF
-       test_repo 7 .git "$TRASH_DIRECTORY"
-'
-
-test_expect_success '#7: GIT_DIR(rel), GIT_WORK_TREE=..(rel) at root' '
-       cat >7/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/7/.git
-setup: worktree: $TRASH_DIRECTORY
-setup: cwd: $TRASH_DIRECTORY
-setup: prefix: 7/
-EOF
-       test_repo 7 .git ..
-'
-
-test_expect_success '#7: GIT_DIR, GIT_WORK_TREE=..(rel) at root' '
-       cat >7/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/7/.git
-setup: worktree: $TRASH_DIRECTORY
-setup: cwd: $TRASH_DIRECTORY
-setup: prefix: 7/
-EOF
-       test_repo 7 "$TRASH_DIRECTORY/7/.git" ..
-'
-
-test_expect_success '#7: GIT_DIR, GIT_WORK_TREE=.. at root' '
-       cat >7/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/7/.git
-setup: worktree: $TRASH_DIRECTORY
-setup: cwd: $TRASH_DIRECTORY
-setup: prefix: 7/
-EOF
-       test_repo 7 "$TRASH_DIRECTORY/7/.git" "$TRASH_DIRECTORY"
-'
-
-test_expect_success '#7: GIT_DIR(rel), GIT_WORK_TREE=.. in subdir' '
-       cat >7/sub/sub/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/7/.git
-setup: worktree: $TRASH_DIRECTORY
-setup: cwd: $TRASH_DIRECTORY
-setup: prefix: 7/sub/sub/
-EOF
-       test_repo 7/sub/sub ../../.git "$TRASH_DIRECTORY"
-'
-
-test_expect_success '#7: GIT_DIR(rel), GIT_WORK_TREE=..(rel) in subdir' '
-       cat >7/sub/sub/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/7/.git
-setup: worktree: $TRASH_DIRECTORY
-setup: cwd: $TRASH_DIRECTORY
-setup: prefix: 7/sub/sub/
-EOF
-       test_repo 7/sub/sub ../../.git ../../..
-'
-
-test_expect_success '#7: GIT_DIR, GIT_WORK_TREE=..(rel) in subdir' '
-       cat >7/sub/sub/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/7/.git
-setup: worktree: $TRASH_DIRECTORY
-setup: cwd: $TRASH_DIRECTORY
-setup: prefix: 7/sub/sub/
-EOF
-       test_repo 7/sub/sub "$TRASH_DIRECTORY/7/.git" ../../../
-'
-
-test_expect_success '#7: GIT_DIR, GIT_WORK_TREE=.. in subdir' '
-       cat >7/sub/sub/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/7/.git
-setup: worktree: $TRASH_DIRECTORY
-setup: cwd: $TRASH_DIRECTORY
-setup: prefix: 7/sub/sub/
-EOF
-       test_repo 7/sub/sub "$TRASH_DIRECTORY/7/.git" "$TRASH_DIRECTORY"
-'
-
-#
-# case #8
-#
-############################################################
-#
-# Input:
-#
-#  - GIT_WORK_TREE is not set
-#  - GIT_DIR is not set
-#  - core.worktree is not set
-#  - .git is a file
-#  - core.bare is not set, cwd is outside .git
-#
-# Output:
-#
-# #0 except that git_dir is set by .git file
-
-test_expect_success '#8: setup' '
-       sane_unset GIT_DIR GIT_WORK_TREE &&
-       mkdir 8 8/sub &&
-       cd 8 &&
-       git init &&
-       mv .git ../8.git &&
-       echo gitdir: ../8.git >.git &&
-       cd ..
-'
-
-test_expect_success '#8: at root' '
-       cat >8/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/8.git
-setup: worktree: $TRASH_DIRECTORY/8
-setup: cwd: $TRASH_DIRECTORY/8
-setup: prefix: (null)
-EOF
-       test_repo 8
-'
-
-test_expect_success '#8: in subdir' '
-       cat >8/sub/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/8.git
-setup: worktree: $TRASH_DIRECTORY/8
-setup: cwd: $TRASH_DIRECTORY/8
-setup: prefix: sub/
-EOF
-       test_repo 8/sub
-'
-
-#
-# case #9
-#
-############################################################
-#
-# Input:
-#
-#  - GIT_WORK_TREE is set
-#  - GIT_DIR is not set
-#  - core.worktree is not set
-#  - .git is a file
-#  - core.bare is not set, cwd is outside .git
-#
-# Output:
-#
-# #1 except that git_dir is set by .git file
-
-test_expect_success '#9: setup' '
-       sane_unset GIT_DIR GIT_WORK_TREE &&
-       mkdir 9 9/sub 9.wt 9.wt/sub 9/wt 9/wt/sub &&
-       cd 9 &&
-       git init &&
-       mv .git ../9.git &&
-       echo gitdir: ../9.git >.git &&
-       GIT_WORK_TREE=non-existent &&
-       export GIT_WORK_TREE &&
-       cd ..
-'
-
-test_expect_success '#9: at root' '
-       cat >9/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/9.git
-setup: worktree: $TRASH_DIRECTORY/9
-setup: cwd: $TRASH_DIRECTORY/9
-setup: prefix: (null)
-EOF
-       test_repo 9
-'
-
-test_expect_success '#9: in subdir' '
-       cat >9/sub/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/9.git
-setup: worktree: $TRASH_DIRECTORY/9
-setup: cwd: $TRASH_DIRECTORY/9
-setup: prefix: sub/
-EOF
-       test_repo 9/sub
-'
-
-#
-# case #10
-#
-############################################################
-#
-# Input:
-#
-#  - GIT_WORK_TREE is not set
-#  - GIT_DIR is set
-#  - core.worktree is not set
-#  - .git is a file
-#  - core.bare is not set, cwd is outside .git
-#
-# Output:
-#
-# #2 except that git_dir is set by .git file
-
-test_expect_success '#10: setup' '
-       sane_unset GIT_DIR GIT_WORK_TREE &&
-       mkdir 10 10/sub &&
-       cd 10 &&
-       git init &&
-       mv .git ../10.git &&
-       echo gitdir: ../10.git >.git &&
-       cd ..
-'
-
-test_expect_success '#10: at root' '
-       cat >10/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/10.git
-setup: worktree: $TRASH_DIRECTORY/10
-setup: cwd: $TRASH_DIRECTORY/10
-setup: prefix: (null)
-EOF
-       test_repo 10 "$TRASH_DIRECTORY/10/.git"
-'
-
-test_expect_success '#10: in subdir' '
-       cat >10/sub/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/10.git
-setup: worktree: $TRASH_DIRECTORY/10/sub
-setup: cwd: $TRASH_DIRECTORY/10/sub
-setup: prefix: (null)
-EOF
-       test_repo 10/sub "$TRASH_DIRECTORY/10/.git"
-'
-
-test_expect_success '#10: relative GIT_DIR at root' '
-       cat >10/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/10.git
-setup: worktree: $TRASH_DIRECTORY/10
-setup: cwd: $TRASH_DIRECTORY/10
-setup: prefix: (null)
-EOF
-       test_repo 10 .git
-'
-
-test_expect_success '#10: relative GIT_DIR in subdir' '
-       cat >10/sub/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/10.git
-setup: worktree: $TRASH_DIRECTORY/10/sub
-setup: cwd: $TRASH_DIRECTORY/10/sub
-setup: prefix: (null)
-EOF
-       test_repo 10/sub ../.git
-'
-
-#
-# case #11
-#
-############################################################
-#
-# Input:
-#
-#  - GIT_WORK_TREE is set
-#  - GIT_DIR is set
-#  - core.worktree is not set
-#  - .git is a file
-#  - core.bare is not set, cwd is outside .git
-#
-# Output:
-#
-# #3 except that git_dir is set by .git file
-
-test_expect_success '#11: setup' '
-       sane_unset GIT_DIR GIT_WORK_TREE &&
-       mkdir 11 11/sub 11/sub/sub 11.wt 11.wt/sub 11/wt 11/wt/sub &&
-       cd 11 &&
-       git init &&
-       mv .git ../11.git &&
-       echo gitdir: ../11.git >.git &&
-       cd ..
-'
-
-test_expect_success '#11: GIT_DIR(rel), GIT_WORK_TREE=root at root' '
-       cat >11/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/11.git
-setup: worktree: $TRASH_DIRECTORY/11
-setup: cwd: $TRASH_DIRECTORY/11
-setup: prefix: (null)
-EOF
-       test_repo 11 .git "$TRASH_DIRECTORY/11"
-'
-
-test_expect_success '#11: GIT_DIR(rel), GIT_WORK_TREE=root(rel) at root' '
-       cat >11/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/11.git
-setup: worktree: $TRASH_DIRECTORY/11
-setup: cwd: $TRASH_DIRECTORY/11
-setup: prefix: (null)
-EOF
-       test_repo 11 .git .
-'
-
-test_expect_success '#11: GIT_DIR, GIT_WORK_TREE=root at root' '
-       cat >11/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/11.git
-setup: worktree: $TRASH_DIRECTORY/11
-setup: cwd: $TRASH_DIRECTORY/11
-setup: prefix: (null)
-EOF
-       test_repo 11 "$TRASH_DIRECTORY/11/.git" "$TRASH_DIRECTORY/11"
-'
-
-test_expect_success '#11: GIT_DIR, GIT_WORK_TREE=root(rel) at root' '
-       cat >11/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/11.git
-setup: worktree: $TRASH_DIRECTORY/11
-setup: cwd: $TRASH_DIRECTORY/11
-setup: prefix: (null)
-EOF
-       test_repo 11 "$TRASH_DIRECTORY/11/.git" .
-'
-
-test_expect_success '#11: GIT_DIR(rel), GIT_WORKTREE=root in subdir' '
-       cat >11/sub/sub/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/11.git
-setup: worktree: $TRASH_DIRECTORY/11
-setup: cwd: $TRASH_DIRECTORY/11
-setup: prefix: sub/sub/
-EOF
-       test_repo 11/sub/sub ../../.git "$TRASH_DIRECTORY/11"
-'
-
-test_expect_success '#11: GIT_DIR(rel), GIT_WORKTREE=root(rel) in subdir' '
-       cat >11/sub/sub/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/11.git
-setup: worktree: $TRASH_DIRECTORY/11
-setup: cwd: $TRASH_DIRECTORY/11
-setup: prefix: sub/sub/
-EOF
-       test_repo 11/sub/sub ../../.git ../..
-'
-
-test_expect_success '#11: GIT_DIR, GIT_WORKTREE=root in subdir' '
-       cat >11/sub/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/11.git
-setup: worktree: $TRASH_DIRECTORY/11
-setup: cwd: $TRASH_DIRECTORY/11
-setup: prefix: sub/
-EOF
-       test_repo 11/sub "$TRASH_DIRECTORY/11/.git" "$TRASH_DIRECTORY/11"
-'
-
-test_expect_success '#11: GIT_DIR, GIT_WORKTREE=root(rel) in subdir' '
-       cat >11/sub/sub/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/11.git
-setup: worktree: $TRASH_DIRECTORY/11
-setup: cwd: $TRASH_DIRECTORY/11
-setup: prefix: sub/sub/
-EOF
-       test_repo 11/sub/sub "$TRASH_DIRECTORY/11/.git" ../..
-'
-
-test_expect_success '#11: GIT_DIR(rel), GIT_WORK_TREE=wt at root' '
-       cat >11/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/11.git
-setup: worktree: $TRASH_DIRECTORY/11/wt
-setup: cwd: $TRASH_DIRECTORY/11
-setup: prefix: (null)
-EOF
-       test_repo 11 .git "$TRASH_DIRECTORY/11/wt"
-'
-
-test_expect_success '#11: GIT_DIR(rel), GIT_WORK_TREE=wt(rel) at root' '
-       cat >11/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/11.git
-setup: worktree: $TRASH_DIRECTORY/11/wt
-setup: cwd: $TRASH_DIRECTORY/11
-setup: prefix: (null)
-EOF
-       test_repo 11 .git wt
-'
-
-test_expect_success '#11: GIT_DIR, GIT_WORK_TREE=wt(rel) at root' '
-       cat >11/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/11.git
-setup: worktree: $TRASH_DIRECTORY/11/wt
-setup: cwd: $TRASH_DIRECTORY/11
-setup: prefix: (null)
-EOF
-       test_repo 11 "$TRASH_DIRECTORY/11/.git" wt
-'
-
-test_expect_success '#11: GIT_DIR, GIT_WORK_TREE=wt at root' '
-       cat >11/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/11.git
-setup: worktree: $TRASH_DIRECTORY/11/wt
-setup: cwd: $TRASH_DIRECTORY/11
-setup: prefix: (null)
-EOF
-       test_repo 11 "$TRASH_DIRECTORY/11/.git" "$TRASH_DIRECTORY/11/wt"
-'
-
-test_expect_success '#11: GIT_DIR(rel), GIT_WORK_TREE=wt in subdir' '
-       cat >11/sub/sub/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/11.git
-setup: worktree: $TRASH_DIRECTORY/11/wt
-setup: cwd: $TRASH_DIRECTORY/11/sub/sub
-setup: prefix: (null)
-EOF
-       test_repo 11/sub/sub ../../.git "$TRASH_DIRECTORY/11/wt"
-'
-
-test_expect_success '#11: GIT_DIR(rel), GIT_WORK_TREE=wt(rel) in subdir' '
-       cat >11/sub/sub/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/11.git
-setup: worktree: $TRASH_DIRECTORY/11/wt
-setup: cwd: $TRASH_DIRECTORY/11/sub/sub
-setup: prefix: (null)
-EOF
-       test_repo 11/sub/sub ../../.git ../../wt
-'
-
-test_expect_success '#11: GIT_DIR, GIT_WORK_TREE=wt(rel) in subdir' '
-       cat >11/sub/sub/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/11.git
-setup: worktree: $TRASH_DIRECTORY/11/wt
-setup: cwd: $TRASH_DIRECTORY/11/sub/sub
-setup: prefix: (null)
-EOF
-       test_repo 11/sub/sub "$TRASH_DIRECTORY/11/.git" ../../wt
-'
-
-test_expect_success '#11: GIT_DIR, GIT_WORK_TREE=wt in subdir' '
-       cat >11/sub/sub/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/11.git
-setup: worktree: $TRASH_DIRECTORY/11/wt
-setup: cwd: $TRASH_DIRECTORY/11/sub/sub
-setup: prefix: (null)
-EOF
-       test_repo 11/sub/sub "$TRASH_DIRECTORY/11/.git" "$TRASH_DIRECTORY/11/wt"
-'
-
-test_expect_success '#11: GIT_DIR(rel), GIT_WORK_TREE=.. at root' '
-       cat >11/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/11.git
-setup: worktree: $TRASH_DIRECTORY
-setup: cwd: $TRASH_DIRECTORY
-setup: prefix: 11/
-EOF
-       test_repo 11 .git "$TRASH_DIRECTORY"
-'
-
-test_expect_success '#11: GIT_DIR(rel), GIT_WORK_TREE=..(rel) at root' '
-       cat >11/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/11.git
-setup: worktree: $TRASH_DIRECTORY
-setup: cwd: $TRASH_DIRECTORY
-setup: prefix: 11/
-EOF
-       test_repo 11 .git ..
-'
-
-test_expect_success '#11: GIT_DIR, GIT_WORK_TREE=..(rel) at root' '
-       cat >11/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/11.git
-setup: worktree: $TRASH_DIRECTORY
-setup: cwd: $TRASH_DIRECTORY
-setup: prefix: 11/
-EOF
-       test_repo 11 "$TRASH_DIRECTORY/11/.git" ..
-'
-
-test_expect_success '#11: GIT_DIR, GIT_WORK_TREE=.. at root' '
-       cat >11/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/11.git
-setup: worktree: $TRASH_DIRECTORY
-setup: cwd: $TRASH_DIRECTORY
-setup: prefix: 11/
-EOF
-       test_repo 11 "$TRASH_DIRECTORY/11/.git" "$TRASH_DIRECTORY"
-'
-
-test_expect_success '#11: GIT_DIR(rel), GIT_WORK_TREE=.. in subdir' '
-       cat >11/sub/sub/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/11.git
-setup: worktree: $TRASH_DIRECTORY
-setup: cwd: $TRASH_DIRECTORY
-setup: prefix: 11/sub/sub/
-EOF
-       test_repo 11/sub/sub ../../.git "$TRASH_DIRECTORY"
-'
-
-test_expect_success '#11: GIT_DIR(rel), GIT_WORK_TREE=..(rel) in subdir' '
-       cat >11/sub/sub/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/11.git
-setup: worktree: $TRASH_DIRECTORY
-setup: cwd: $TRASH_DIRECTORY
-setup: prefix: 11/sub/sub/
-EOF
-       test_repo 11/sub/sub ../../.git ../../..
-'
-
-test_expect_success '#11: GIT_DIR, GIT_WORK_TREE=..(rel) in subdir' '
-       cat >11/sub/sub/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/11.git
-setup: worktree: $TRASH_DIRECTORY
-setup: cwd: $TRASH_DIRECTORY
-setup: prefix: 11/sub/sub/
-EOF
-       test_repo 11/sub/sub "$TRASH_DIRECTORY/11/.git" ../../../
-'
-
-test_expect_success '#11: GIT_DIR, GIT_WORK_TREE=.. in subdir' '
-       cat >11/sub/sub/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/11.git
-setup: worktree: $TRASH_DIRECTORY
-setup: cwd: $TRASH_DIRECTORY
-setup: prefix: 11/sub/sub/
-EOF
-       test_repo 11/sub/sub "$TRASH_DIRECTORY/11/.git" "$TRASH_DIRECTORY"
-'
-
-#
-# case #12
-#
-############################################################
-#
-# Input:
-#
-#  - GIT_WORK_TREE is not set
-#  - GIT_DIR is not set
-#  - core.worktree is set
-#  - .git is a file
-#  - core.bare is not set, cwd is outside .git
-#
-# Output:
-#
-# #4 except that git_dir is set by .git file
-
-
-test_expect_success '#12: setup' '
-       sane_unset GIT_DIR GIT_WORK_TREE &&
-       mkdir 12 12/sub 12/sub/sub 12.wt 12.wt/sub 12/wt 12/wt/sub &&
-       cd 12 &&
-       git init &&
-       git config core.worktree non-existent &&
-       mv .git ../12.git &&
-       echo gitdir: ../12.git >.git &&
-       cd ..
-'
-
-test_expect_success '#12: at root' '
-       cat >12/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/12.git
-setup: worktree: $TRASH_DIRECTORY/12
-setup: cwd: $TRASH_DIRECTORY/12
-setup: prefix: (null)
-EOF
-       test_repo 12
-'
-
-test_expect_success '#12: in subdir' '
-       cat >12/sub/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/12.git
-setup: worktree: $TRASH_DIRECTORY/12
-setup: cwd: $TRASH_DIRECTORY/12
-setup: prefix: sub/
-EOF
-       test_repo 12/sub
-'
-
-#
-# case #13
-#
-############################################################
-#
-# Input:
-#
-#  - GIT_WORK_TREE is set
-#  - GIT_DIR is not set
-#  - core.worktree is set
-#  - .git is a file
-#  - core.bare is not set, cwd is outside .git
-#
-# Output:
-#
-# #5 except that git_dir is set by .git file
-
-test_expect_success '#13: setup' '
-       sane_unset GIT_DIR GIT_WORK_TREE &&
-       mkdir 13 13/sub 13/sub/sub 13.wt 13.wt/sub 13/wt 13/wt/sub &&
-       cd 13 &&
-       git init &&
-       git config core.worktree non-existent &&
-       GIT_WORK_TREE=non-existent-too &&
-       export GIT_WORK_TREE &&
-       mv .git ../13.git &&
-       echo gitdir: ../13.git >.git &&
-       cd ..
-'
-
-test_expect_success '#13: at root' '
-       cat >13/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/13.git
-setup: worktree: $TRASH_DIRECTORY/13
-setup: cwd: $TRASH_DIRECTORY/13
-setup: prefix: (null)
-EOF
-       test_repo 13
-'
-
-test_expect_success '#13: in subdir' '
-       cat >13/sub/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/13.git
-setup: worktree: $TRASH_DIRECTORY/13
-setup: cwd: $TRASH_DIRECTORY/13
-setup: prefix: sub/
-EOF
-       test_repo 13/sub
-'
-
-#
-# case #14
-#
-############################################################
-#
-# Input:
-#
-#  - GIT_WORK_TREE is not set
-#  - GIT_DIR is set
-#  - core.worktree is set
-#  - .git is a file
-#  - core.bare is not set, cwd is outside .git
-#
-# Output:
-#
-# #6 except that git_dir is set by .git file
-
-test_expect_success '#14: setup' '
-       sane_unset GIT_DIR GIT_WORK_TREE &&
-       mkdir 14 14/sub 14/sub/sub 14.wt 14.wt/sub 14/wt 14/wt/sub &&
-       cd 14 &&
-       git init &&
-       mv .git ../14.git &&
-       echo gitdir: ../14.git >.git &&
-       cd ..
-'
-
-test_expect_success '#14: GIT_DIR(rel), core.worktree=../14 at root' '
-       cat >14/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/14.git
-setup: worktree: $TRASH_DIRECTORY/14
-setup: cwd: $TRASH_DIRECTORY/14
-setup: prefix: (null)
-EOF
-       git config --file="$TRASH_DIRECTORY/14.git/config" core.worktree "$TRASH_DIRECTORY/14" &&
-       test_repo 14 .git
-'
-
-test_expect_success '#14: GIT_DIR(rel), core.worktree=../14(rel) at root' '
-       cat >14/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/14.git
-setup: worktree: $TRASH_DIRECTORY/14
-setup: cwd: $TRASH_DIRECTORY/14
-setup: prefix: (null)
-EOF
-       git config --file="$TRASH_DIRECTORY/14.git/config" core.worktree ../14 &&
-       test_repo 14 .git
-'
-
-test_expect_success '#14: GIT_DIR, core.worktree=../14 at root' '
-       cat >14/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/14.git
-setup: worktree: $TRASH_DIRECTORY/14
-setup: cwd: $TRASH_DIRECTORY/14
-setup: prefix: (null)
-EOF
-       git config --file="$TRASH_DIRECTORY/14.git/config" core.worktree "$TRASH_DIRECTORY/14" &&
-       test_repo 14 "$TRASH_DIRECTORY/14/.git"
-'
-
-test_expect_success '#14: GIT_DIR, core.worktree=../14(rel) at root' '
-       cat >14/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/14.git
-setup: worktree: $TRASH_DIRECTORY/14
-setup: cwd: $TRASH_DIRECTORY/14
-setup: prefix: (null)
-EOF
-       git config --file="$TRASH_DIRECTORY/14.git/config" core.worktree ../14 &&
-       test_repo 14 "$TRASH_DIRECTORY/14/.git"
-'
-
-test_expect_success '#14: GIT_DIR(rel), core.worktree=../14 in subdir' '
-       cat >14/sub/sub/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/14.git
-setup: worktree: $TRASH_DIRECTORY/14
-setup: cwd: $TRASH_DIRECTORY/14
-setup: prefix: sub/sub/
-EOF
-       git config --file="$TRASH_DIRECTORY/14.git/config" core.worktree "$TRASH_DIRECTORY/14" &&
-       test_repo 14/sub/sub ../../.git
-'
-
-test_expect_success '#14: GIT_DIR(rel), core.worktree=../14(rel) in subdir' '
-       cat >14/sub/sub/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/14.git
-setup: worktree: $TRASH_DIRECTORY/14
-setup: cwd: $TRASH_DIRECTORY/14
-setup: prefix: sub/sub/
-EOF
-       git config --file="$TRASH_DIRECTORY/14.git/config" core.worktree ../14 &&
-       test_repo 14/sub/sub ../../.git
-'
-
-test_expect_success '#14: GIT_DIR, core.worktree=../14 in subdir' '
-       cat >14/sub/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/14.git
-setup: worktree: $TRASH_DIRECTORY/14
-setup: cwd: $TRASH_DIRECTORY/14
-setup: prefix: sub/
-EOF
-       git config --file="$TRASH_DIRECTORY/14.git/config" core.worktree "$TRASH_DIRECTORY/14" &&
-       test_repo 14/sub "$TRASH_DIRECTORY/14/.git"
-'
-
-test_expect_success '#14: GIT_DIR, core.worktree=../14(rel) in subdir' '
-       cat >14/sub/sub/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/14.git
-setup: worktree: $TRASH_DIRECTORY/14
-setup: cwd: $TRASH_DIRECTORY/14
-setup: prefix: sub/sub/
-EOF
-       git config --file="$TRASH_DIRECTORY/14.git/config" core.worktree ../14 &&
-       test_repo 14/sub/sub "$TRASH_DIRECTORY/14/.git"
-'
-
-test_expect_success '#14: GIT_DIR(rel), core.worktree=../14/wt at root' '
-       cat >14/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/14.git
-setup: worktree: $TRASH_DIRECTORY/14/wt
-setup: cwd: $TRASH_DIRECTORY/14
-setup: prefix: (null)
-EOF
-       git config --file="$TRASH_DIRECTORY/14.git/config" core.worktree "$TRASH_DIRECTORY/14/wt" &&
-       test_repo 14 .git
-'
-
-test_expect_success '#14: GIT_DIR(rel), core.worktree=../14/wt(rel) at root' '
-       cat >14/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/14.git
-setup: worktree: $TRASH_DIRECTORY/14/wt
-setup: cwd: $TRASH_DIRECTORY/14
-setup: prefix: (null)
-EOF
-       git config --file="$TRASH_DIRECTORY/14.git/config" core.worktree ../14/wt &&
-       test_repo 14 .git
-'
-
-test_expect_success '#14: GIT_DIR, core.worktree=../14/wt(rel) at root' '
-       cat >14/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/14.git
-setup: worktree: $TRASH_DIRECTORY/14/wt
-setup: cwd: $TRASH_DIRECTORY/14
-setup: prefix: (null)
-EOF
-       git config --file="$TRASH_DIRECTORY/14.git/config" core.worktree ../14/wt &&
-       test_repo 14 "$TRASH_DIRECTORY/14/.git"
-'
-
-test_expect_success '#14: GIT_DIR, core.worktree=../14/wt at root' '
-       cat >14/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/14.git
-setup: worktree: $TRASH_DIRECTORY/14/wt
-setup: cwd: $TRASH_DIRECTORY/14
-setup: prefix: (null)
-EOF
-       git config --file="$TRASH_DIRECTORY/14.git/config" core.worktree "$TRASH_DIRECTORY/14/wt" &&
-       test_repo 14 "$TRASH_DIRECTORY/14/.git"
-'
-
-test_expect_success '#14: GIT_DIR(rel), core.worktree=../14/wt in subdir' '
-       cat >14/sub/sub/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/14.git
-setup: worktree: $TRASH_DIRECTORY/14/wt
-setup: cwd: $TRASH_DIRECTORY/14/sub/sub
-setup: prefix: (null)
-EOF
-       git config --file="$TRASH_DIRECTORY/14.git/config" core.worktree "$TRASH_DIRECTORY/14/wt" &&
-       test_repo 14/sub/sub ../../.git
-'
-
-test_expect_success '#14: GIT_DIR(rel), core.worktree=../14/wt(rel) in subdir' '
-       cat >14/sub/sub/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/14.git
-setup: worktree: $TRASH_DIRECTORY/14/wt
-setup: cwd: $TRASH_DIRECTORY/14/sub/sub
-setup: prefix: (null)
-EOF
-       git config --file="$TRASH_DIRECTORY/14.git/config" core.worktree ../14/wt &&
-       test_repo 14/sub/sub ../../.git
-'
-
-test_expect_success '#14: GIT_DIR, core.worktree=../14/wt(rel) in subdir' '
-       cat >14/sub/sub/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/14.git
-setup: worktree: $TRASH_DIRECTORY/14/wt
-setup: cwd: $TRASH_DIRECTORY/14/sub/sub
-setup: prefix: (null)
-EOF
-       git config --file="$TRASH_DIRECTORY/14.git/config" core.worktree ../14/wt &&
-       test_repo 14/sub/sub "$TRASH_DIRECTORY/14/.git"
-'
-
-test_expect_success '#14: GIT_DIR, core.worktree=../14/wt in subdir' '
-       cat >14/sub/sub/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/14.git
-setup: worktree: $TRASH_DIRECTORY/14/wt
-setup: cwd: $TRASH_DIRECTORY/14/sub/sub
-setup: prefix: (null)
-EOF
-       git config --file="$TRASH_DIRECTORY/14.git/config" core.worktree "$TRASH_DIRECTORY/14/wt" &&
-       test_repo 14/sub/sub "$TRASH_DIRECTORY/14/.git"
-'
-
-test_expect_success '#14: GIT_DIR(rel), core.worktree=.. at root' '
-       cat >14/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/14.git
-setup: worktree: $TRASH_DIRECTORY
-setup: cwd: $TRASH_DIRECTORY
-setup: prefix: 14/
-EOF
-       git config --file="$TRASH_DIRECTORY/14.git/config" core.worktree "$TRASH_DIRECTORY" &&
-       test_repo 14 .git
-'
-
-test_expect_success '#14: GIT_DIR(rel), core.worktree=..(rel) at root' '
-       cat >14/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/14.git
-setup: worktree: $TRASH_DIRECTORY
-setup: cwd: $TRASH_DIRECTORY
-setup: prefix: 14/
-EOF
-       git config --file="$TRASH_DIRECTORY/14.git/config" core.worktree .. &&
-       test_repo 14 .git
-'
-
-test_expect_success '#14: GIT_DIR, core.worktree=..(rel) at root' '
-       cat >14/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/14.git
-setup: worktree: $TRASH_DIRECTORY
-setup: cwd: $TRASH_DIRECTORY
-setup: prefix: 14/
-EOF
-       git config --file="$TRASH_DIRECTORY/14.git/config" core.worktree .. &&
-       test_repo 14 "$TRASH_DIRECTORY/14/.git"
-'
-
-test_expect_success '#14: GIT_DIR, core.worktree=.. at root' '
-       cat >14/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/14.git
-setup: worktree: $TRASH_DIRECTORY
-setup: cwd: $TRASH_DIRECTORY
-setup: prefix: 14/
-EOF
-       git config --file="$TRASH_DIRECTORY/14.git/config" core.worktree "$TRASH_DIRECTORY" &&
-       test_repo 14 "$TRASH_DIRECTORY/14/.git"
-'
-
-test_expect_success '#14: GIT_DIR(rel), core.worktree=.. in subdir' '
-       cat >14/sub/sub/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/14.git
-setup: worktree: $TRASH_DIRECTORY
-setup: cwd: $TRASH_DIRECTORY
-setup: prefix: 14/sub/sub/
-EOF
-       git config --file="$TRASH_DIRECTORY/14.git/config" core.worktree "$TRASH_DIRECTORY" &&
-       test_repo 14/sub/sub ../../.git
-'
-
-test_expect_success '#14: GIT_DIR(rel), core.worktree=..(rel) in subdir' '
-       cat >14/sub/sub/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/14.git
-setup: worktree: $TRASH_DIRECTORY
-setup: cwd: $TRASH_DIRECTORY
-setup: prefix: 14/sub/sub/
-EOF
-       git config --file="$TRASH_DIRECTORY/14.git/config" core.worktree .. &&
-       test_repo 14/sub/sub ../../.git
-'
-
-test_expect_success '#14: GIT_DIR, core.worktree=..(rel) in subdir' '
-       cat >14/sub/sub/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/14.git
-setup: worktree: $TRASH_DIRECTORY
-setup: cwd: $TRASH_DIRECTORY
-setup: prefix: 14/sub/sub/
-EOF
-       git config --file="$TRASH_DIRECTORY/14.git/config" core.worktree .. &&
-       test_repo 14/sub/sub "$TRASH_DIRECTORY/14/.git"
-'
-
-test_expect_success '#14: GIT_DIR, core.worktree=.. in subdir' '
-       cat >14/sub/sub/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/14.git
-setup: worktree: $TRASH_DIRECTORY
-setup: cwd: $TRASH_DIRECTORY
-setup: prefix: 14/sub/sub/
-EOF
-       git config --file="$TRASH_DIRECTORY/14.git/config" core.worktree "$TRASH_DIRECTORY" &&
-       test_repo 14/sub/sub "$TRASH_DIRECTORY/14/.git"
-'
-
-#
-# case #15
-#
-############################################################
-#
-# Input:
-#
-#  - GIT_WORK_TREE is set
-#  - GIT_DIR is set
-#  - core.worktree is set
-#  - .git is a file
-#  - core.bare is not set, cwd is outside .git
-#
-# Output:
-#
-# #7 except that git_dir is set by .git file
-
-test_expect_success '#15: setup' '
-       sane_unset GIT_DIR GIT_WORK_TREE &&
-       mkdir 15 15/sub 15/sub/sub 15.wt 15.wt/sub 15/wt 15/wt/sub &&
-       cd 15 &&
-       git init &&
-       git config core.worktree non-existent &&
-       mv .git ../15.git &&
-       echo gitdir: ../15.git >.git &&
-       cd ..
-'
-
-test_expect_success '#15: GIT_DIR(rel), GIT_WORK_TREE=root at root' '
-       cat >15/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/15.git
-setup: worktree: $TRASH_DIRECTORY/15
-setup: cwd: $TRASH_DIRECTORY/15
-setup: prefix: (null)
-EOF
-       test_repo 15 .git "$TRASH_DIRECTORY/15"
-'
-
-test_expect_success '#15: GIT_DIR(rel), GIT_WORK_TREE=root(rel) at root' '
-       cat >15/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/15.git
-setup: worktree: $TRASH_DIRECTORY/15
-setup: cwd: $TRASH_DIRECTORY/15
-setup: prefix: (null)
-EOF
-       test_repo 15 .git .
-'
-
-test_expect_success '#15: GIT_DIR, GIT_WORK_TREE=root at root' '
-       cat >15/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/15.git
-setup: worktree: $TRASH_DIRECTORY/15
-setup: cwd: $TRASH_DIRECTORY/15
-setup: prefix: (null)
-EOF
-       test_repo 15 "$TRASH_DIRECTORY/15/.git" "$TRASH_DIRECTORY/15"
-'
-
-test_expect_success '#15: GIT_DIR, GIT_WORK_TREE=root(rel) at root' '
-       cat >15/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/15.git
-setup: worktree: $TRASH_DIRECTORY/15
-setup: cwd: $TRASH_DIRECTORY/15
-setup: prefix: (null)
-EOF
-       test_repo 15 "$TRASH_DIRECTORY/15/.git" .
-'
-
-test_expect_success '#15: GIT_DIR(rel), GIT_WORKTREE=root in subdir' '
-       cat >15/sub/sub/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/15.git
-setup: worktree: $TRASH_DIRECTORY/15
-setup: cwd: $TRASH_DIRECTORY/15
-setup: prefix: sub/sub/
-EOF
-       test_repo 15/sub/sub ../../.git "$TRASH_DIRECTORY/15"
-'
-
-test_expect_success '#15: GIT_DIR(rel), GIT_WORKTREE=root(rel) in subdir' '
-       cat >15/sub/sub/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/15.git
-setup: worktree: $TRASH_DIRECTORY/15
-setup: cwd: $TRASH_DIRECTORY/15
-setup: prefix: sub/sub/
-EOF
-       test_repo 15/sub/sub ../../.git ../..
-'
-
-test_expect_success '#15: GIT_DIR, GIT_WORKTREE=root in subdir' '
-       cat >15/sub/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/15.git
-setup: worktree: $TRASH_DIRECTORY/15
-setup: cwd: $TRASH_DIRECTORY/15
-setup: prefix: sub/
-EOF
-       test_repo 15/sub "$TRASH_DIRECTORY/15/.git" "$TRASH_DIRECTORY/15"
-'
-
-test_expect_success '#15: GIT_DIR, GIT_WORKTREE=root(rel) in subdir' '
-       cat >15/sub/sub/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/15.git
-setup: worktree: $TRASH_DIRECTORY/15
-setup: cwd: $TRASH_DIRECTORY/15
-setup: prefix: sub/sub/
-EOF
-       test_repo 15/sub/sub "$TRASH_DIRECTORY/15/.git" ../..
-'
-
-test_expect_success '#15: GIT_DIR(rel), GIT_WORK_TREE=wt at root' '
-       cat >15/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/15.git
-setup: worktree: $TRASH_DIRECTORY/15/wt
-setup: cwd: $TRASH_DIRECTORY/15
-setup: prefix: (null)
-EOF
-       test_repo 15 .git "$TRASH_DIRECTORY/15/wt"
-'
-
-test_expect_success '#15: GIT_DIR(rel), GIT_WORK_TREE=wt(rel) at root' '
-       cat >15/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/15.git
-setup: worktree: $TRASH_DIRECTORY/15/wt
-setup: cwd: $TRASH_DIRECTORY/15
-setup: prefix: (null)
-EOF
-       test_repo 15 .git wt
-'
-
-test_expect_success '#15: GIT_DIR, GIT_WORK_TREE=wt(rel) at root' '
-       cat >15/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/15.git
-setup: worktree: $TRASH_DIRECTORY/15/wt
-setup: cwd: $TRASH_DIRECTORY/15
-setup: prefix: (null)
-EOF
-       test_repo 15 "$TRASH_DIRECTORY/15/.git" wt
-'
-
-test_expect_success '#15: GIT_DIR, GIT_WORK_TREE=wt at root' '
-       cat >15/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/15.git
-setup: worktree: $TRASH_DIRECTORY/15/wt
-setup: cwd: $TRASH_DIRECTORY/15
-setup: prefix: (null)
-EOF
-       test_repo 15 "$TRASH_DIRECTORY/15/.git" "$TRASH_DIRECTORY/15/wt"
-'
-
-test_expect_success '#15: GIT_DIR(rel), GIT_WORK_TREE=wt in subdir' '
-       cat >15/sub/sub/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/15.git
-setup: worktree: $TRASH_DIRECTORY/15/wt
-setup: cwd: $TRASH_DIRECTORY/15/sub/sub
-setup: prefix: (null)
-EOF
-       test_repo 15/sub/sub ../../.git "$TRASH_DIRECTORY/15/wt"
-'
-
-test_expect_success '#15: GIT_DIR(rel), GIT_WORK_TREE=wt(rel) in subdir' '
-       cat >15/sub/sub/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/15.git
-setup: worktree: $TRASH_DIRECTORY/15/wt
-setup: cwd: $TRASH_DIRECTORY/15/sub/sub
-setup: prefix: (null)
-EOF
-       test_repo 15/sub/sub ../../.git ../../wt
-'
-
-test_expect_success '#15: GIT_DIR, GIT_WORK_TREE=wt(rel) in subdir' '
-       cat >15/sub/sub/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/15.git
-setup: worktree: $TRASH_DIRECTORY/15/wt
-setup: cwd: $TRASH_DIRECTORY/15/sub/sub
-setup: prefix: (null)
-EOF
-       test_repo 15/sub/sub "$TRASH_DIRECTORY/15/.git" ../../wt
-'
-
-test_expect_success '#15: GIT_DIR, GIT_WORK_TREE=wt in subdir' '
-       cat >15/sub/sub/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/15.git
-setup: worktree: $TRASH_DIRECTORY/15/wt
-setup: cwd: $TRASH_DIRECTORY/15/sub/sub
-setup: prefix: (null)
-EOF
-       test_repo 15/sub/sub "$TRASH_DIRECTORY/15/.git" "$TRASH_DIRECTORY/15/wt"
-'
-
-test_expect_success '#15: GIT_DIR(rel), GIT_WORK_TREE=.. at root' '
-       cat >15/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/15.git
-setup: worktree: $TRASH_DIRECTORY
-setup: cwd: $TRASH_DIRECTORY
-setup: prefix: 15/
-EOF
-       test_repo 15 .git "$TRASH_DIRECTORY"
-'
-
-test_expect_success '#15: GIT_DIR(rel), GIT_WORK_TREE=..(rel) at root' '
-       cat >15/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/15.git
-setup: worktree: $TRASH_DIRECTORY
-setup: cwd: $TRASH_DIRECTORY
-setup: prefix: 15/
-EOF
-       test_repo 15 .git ..
-'
-
-test_expect_success '#15: GIT_DIR, GIT_WORK_TREE=..(rel) at root' '
-       cat >15/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/15.git
-setup: worktree: $TRASH_DIRECTORY
-setup: cwd: $TRASH_DIRECTORY
-setup: prefix: 15/
-EOF
-       test_repo 15 "$TRASH_DIRECTORY/15/.git" ..
-'
-
-test_expect_success '#15: GIT_DIR, GIT_WORK_TREE=.. at root' '
-       cat >15/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/15.git
-setup: worktree: $TRASH_DIRECTORY
-setup: cwd: $TRASH_DIRECTORY
-setup: prefix: 15/
-EOF
-       test_repo 15 "$TRASH_DIRECTORY/15/.git" "$TRASH_DIRECTORY"
-'
-
-test_expect_success '#15: GIT_DIR(rel), GIT_WORK_TREE=.. in subdir' '
-       cat >15/sub/sub/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/15.git
-setup: worktree: $TRASH_DIRECTORY
-setup: cwd: $TRASH_DIRECTORY
-setup: prefix: 15/sub/sub/
-EOF
-       test_repo 15/sub/sub ../../.git "$TRASH_DIRECTORY"
-'
-
-test_expect_success '#15: GIT_DIR(rel), GIT_WORK_TREE=..(rel) in subdir' '
-       cat >15/sub/sub/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/15.git
-setup: worktree: $TRASH_DIRECTORY
-setup: cwd: $TRASH_DIRECTORY
-setup: prefix: 15/sub/sub/
-EOF
-       test_repo 15/sub/sub ../../.git ../../..
-'
-
-test_expect_success '#15: GIT_DIR, GIT_WORK_TREE=..(rel) in subdir' '
-       cat >15/sub/sub/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/15.git
-setup: worktree: $TRASH_DIRECTORY
-setup: cwd: $TRASH_DIRECTORY
-setup: prefix: 15/sub/sub/
-EOF
-       test_repo 15/sub/sub "$TRASH_DIRECTORY/15/.git" ../../../
-'
-
-test_expect_success '#15: GIT_DIR, GIT_WORK_TREE=.. in subdir' '
-       cat >15/sub/sub/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/15.git
-setup: worktree: $TRASH_DIRECTORY
-setup: cwd: $TRASH_DIRECTORY
-setup: prefix: 15/sub/sub/
-EOF
-       test_repo 15/sub/sub "$TRASH_DIRECTORY/15/.git" "$TRASH_DIRECTORY"
-'
-
-#
-# case #16.1
-#
-############################################################
-#
-# Input:
-#
-#  - GIT_WORK_TREE is not set
-#  - GIT_DIR is not set
-#  - core.worktree is not set
-#  - .git is a directory
-#  - cwd is inside .git
-#
-# Output:
-#
-#  - no worktree
-#  - cwd is unchanged
-#  - prefix is NULL
-#  - git_dir is set
-#  - cwd can't be outside worktree
-
-test_expect_success '#16.1: setup' '
-       sane_unset GIT_DIR GIT_WORK_TREE &&
-       mkdir 16 16/sub &&
-       cd 16 &&
-       git init &&
-       mkdir .git/wt .git/wt/sub &&
-       cd ..
-'
-
-test_expect_success '#16.1: at .git' '
-       cat >16/.git/expected <<EOF &&
-setup: git_dir: .
-setup: worktree: (null)
-setup: cwd: $TRASH_DIRECTORY/16/.git
-setup: prefix: (null)
-EOF
-       test_repo 16/.git
-'
-
-test_expect_success '#16.1: in .git/wt' '
-       cat >16/.git/wt/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/16/.git
-setup: worktree: (null)
-setup: cwd: $TRASH_DIRECTORY/16/.git/wt
-setup: prefix: (null)
-EOF
-       test_repo 16/.git/wt
-'
-
-test_expect_success '#16.1: in .git/wt/sub' '
-       cat >16/.git/wt/sub/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/16/.git
-setup: worktree: (null)
-setup: cwd: $TRASH_DIRECTORY/16/.git/wt/sub
-setup: prefix: (null)
-EOF
-       test_repo 16/.git/wt/sub
-'
-
-#
-# case #16.2
-#
-############################################################
-#
-# Input:
-#
-#  - GIT_WORK_TREE is not set
-#  - GIT_DIR is not set
-#  - core.worktree is not set
-#  - .git is a directory
-#  - core.bare is set
-#
-# Output:
-#
-#  - no worktree
-#  - cwd is unchanged
-#  - prefix is NULL
-#  - git_dir is set
-#  - cwd can't be outside worktree
-
-test_expect_success '#16.2: setup' '
-       git config --file="$TRASH_DIRECTORY/16/.git/config" core.bare true
-'
-
-test_expect_success '#16.2: at .git' '
-       cat >16/.git/expected <<EOF &&
-setup: git_dir: .
-setup: worktree: (null)
-setup: cwd: $TRASH_DIRECTORY/16/.git
-setup: prefix: (null)
-EOF
-       test_repo 16/.git
-'
-
-test_expect_success '#16.2: in .git/wt' '
-       cat >16/.git/wt/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/16/.git
-setup: worktree: (null)
-setup: cwd: $TRASH_DIRECTORY/16/.git/wt
-setup: prefix: (null)
-EOF
-       test_repo 16/.git/wt
-'
-
-test_expect_success '#16.2: in .git/wt/sub' '
-       cat >16/.git/wt/sub/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/16/.git
-setup: worktree: (null)
-setup: cwd: $TRASH_DIRECTORY/16/.git/wt/sub
-setup: prefix: (null)
-EOF
-       test_repo 16/.git/wt/sub
-'
-
-test_expect_success '#16.2: at root' '
-       cat >16/expected <<EOF &&
-setup: git_dir: .git
-setup: worktree: (null)
-setup: cwd: $TRASH_DIRECTORY/16
-setup: prefix: (null)
-EOF
-       test_repo 16
-'
-
-test_expect_success '#16.2: in subdir' '
-       cat >16/sub/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/16/.git
-setup: worktree: (null)
-setup: cwd: $TRASH_DIRECTORY/16/sub
-setup: prefix: (null)
-EOF
-       test_repo 16/sub
-'
-
-#
-# case #17.1
-#
-############################################################
-#
-# Input:
-#
-#  - GIT_WORK_TREE is set
-#  - GIT_DIR is not set
-#  - core.worktree is not set
-#  - .git is a directory
-#  - cwd is inside .git
-#
-# Output:
-#
-# GIT_WORK_TREE is ignored -> #16.1 (with warnings perhaps)
-
-test_expect_success '#17.1: setup' '
-       sane_unset GIT_DIR GIT_WORK_TREE &&
-       mkdir 17 17/sub &&
-       cd 17 &&
-       git init &&
-       mkdir .git/wt .git/wt/sub &&
-       GIT_WORK_TREE=non-existent &&
-       export GIT_WORK_TREE &&
-       cd ..
-'
-
-test_expect_success '#17.1: at .git' '
-       cat >17/.git/expected <<EOF &&
-setup: git_dir: .
-setup: worktree: (null)
-setup: cwd: $TRASH_DIRECTORY/17/.git
-setup: prefix: (null)
-EOF
-       test_repo 17/.git
-'
-
-test_expect_success '#17.1: in .git/wt' '
-       cat >17/.git/wt/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/17/.git
-setup: worktree: (null)
-setup: cwd: $TRASH_DIRECTORY/17/.git/wt
-setup: prefix: (null)
-EOF
-       test_repo 17/.git/wt
-'
-
-test_expect_success '#17.1: in .git/wt/sub' '
-       cat >17/.git/wt/sub/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/17/.git
-setup: worktree: (null)
-setup: cwd: $TRASH_DIRECTORY/17/.git/wt/sub
-setup: prefix: (null)
-EOF
-       test_repo 17/.git/wt/sub
-'
-
-#
-# case #17.2
-#
-############################################################
-#
-# Input:
-#
-#  - GIT_WORK_TREE is set
-#  - GIT_DIR is not set
-#  - core.worktree is not set
-#  - .git is a directory
-#  - core.bare is set
-#
-# Output:
-#
-# GIT_WORK_TREE is ignored -> #16.2 (with warnings perhaps)
-
-test_expect_success '#17.2: setup' '
-       git config --file="$TRASH_DIRECTORY/17/.git/config" core.bare true
-'
-
-test_expect_success '#17.2: at .git' '
-       cat >17/.git/expected <<EOF &&
-setup: git_dir: .
-setup: worktree: (null)
-setup: cwd: $TRASH_DIRECTORY/17/.git
-setup: prefix: (null)
-EOF
-       test_repo 17/.git
-'
-
-test_expect_success '#17.2: in .git/wt' '
-       cat >17/.git/wt/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/17/.git
-setup: worktree: (null)
-setup: cwd: $TRASH_DIRECTORY/17/.git/wt
-setup: prefix: (null)
-EOF
-       test_repo 17/.git/wt
-'
-
-test_expect_success '#17.2: in .git/wt/sub' '
-       cat >17/.git/wt/sub/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/17/.git
-setup: worktree: (null)
-setup: cwd: $TRASH_DIRECTORY/17/.git/wt/sub
-setup: prefix: (null)
-EOF
-       test_repo 17/.git/wt/sub
-'
-
-test_expect_success '#17.2: at root' '
-       cat >17/expected <<EOF &&
-setup: git_dir: .git
-setup: worktree: (null)
-setup: cwd: $TRASH_DIRECTORY/17
-setup: prefix: (null)
-EOF
-       test_repo 17
-'
-
-test_expect_success '#17.2: in subdir' '
-       cat >17/sub/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/17/.git
-setup: worktree: (null)
-setup: cwd: $TRASH_DIRECTORY/17/sub
-setup: prefix: (null)
-EOF
-       test_repo 17/sub
-'
-
-#
-# case #18
-#
-############################################################
-#
-# Input:
-#
-#  - GIT_WORK_TREE is not set
-#  - GIT_DIR is set
-#  - core.worktree is not set
-#  - .git is a directory
-#  - core.bare is set
-#
-# Output:
-#
-#  - no worktree (rule #8)
-#  - cwd is unchanged
-#  - prefix is NULL
-#  - git_dir is set to $GIT_DIR
-#  - cwd can't be outside worktree
-
-test_expect_success '#18: setup' '
-       sane_unset GIT_DIR GIT_WORK_TREE &&
-       mkdir 18 18/sub &&
-       cd 18 &&
-       git init &&
-       mkdir .git/wt .git/wt/sub &&
-       git config core.bare true &&
-       cd ..
-'
-
-test_expect_success '#18: (rel) at root' '
-       cat >18/expected <<EOF &&
-setup: git_dir: .git
-setup: worktree: (null)
-setup: cwd: $TRASH_DIRECTORY/18
-setup: prefix: (null)
-EOF
-        test_repo 18 .git
-'
-
-test_expect_success '#18: at root' '
-       cat >18/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/18/.git
-setup: worktree: (null)
-setup: cwd: $TRASH_DIRECTORY/18
-setup: prefix: (null)
-EOF
-        test_repo 18 "$TRASH_DIRECTORY/18/.git"
-'
-
-test_expect_success '#18: (rel) in subdir' '
-       cat >18/sub/expected <<EOF &&
-setup: git_dir: ../.git
-setup: worktree: (null)
-setup: cwd: $TRASH_DIRECTORY/18/sub
-setup: prefix: (null)
-EOF
-       test_repo 18/sub ../.git
-'
-
-test_expect_success '#18: in subdir' '
-       cat >18/sub/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/18/.git
-setup: worktree: (null)
-setup: cwd: $TRASH_DIRECTORY/18/sub
-setup: prefix: (null)
-EOF
-       test_repo 18/sub "$TRASH_DIRECTORY/18/.git"
-'
-
-#
-# case #19
-#
-############################################################
-#
-# Input:
-#
-#  - GIT_WORK_TREE is set
-#  - GIT_DIR is set
-#  - .git is a directory
-#  - core.worktree is not set
-#  - core.bare is set
-#
-# Output:
-#
-# bare repo is overridden by GIT_WORK_TREE -> #3
-
-test_expect_success '#19: setup' '
-       sane_unset GIT_DIR GIT_WORK_TREE &&
-       mkdir 19 19/sub 19/sub/sub 19.wt 19.wt/sub 19/wt 19/wt/sub &&
-       cd 19 &&
-       git init &&
-       git config core.bare true &&
-       cd ..
-'
-
-test_expect_success '#19: GIT_DIR(rel), GIT_WORK_TREE=root at root' '
-       cat >19/expected <<EOF &&
-setup: git_dir: .git
-setup: worktree: $TRASH_DIRECTORY/19
-setup: cwd: $TRASH_DIRECTORY/19
-setup: prefix: (null)
-EOF
-       test_repo 19 .git "$TRASH_DIRECTORY/19"
-'
-
-test_expect_success '#19: GIT_DIR(rel), GIT_WORK_TREE=root(rel) at root' '
-       cat >19/expected <<EOF &&
-setup: git_dir: .git
-setup: worktree: $TRASH_DIRECTORY/19
-setup: cwd: $TRASH_DIRECTORY/19
-setup: prefix: (null)
-EOF
-       test_repo 19 .git .
-'
-
-test_expect_success '#19: GIT_DIR, GIT_WORK_TREE=root at root' '
-       cat >19/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/19/.git
-setup: worktree: $TRASH_DIRECTORY/19
-setup: cwd: $TRASH_DIRECTORY/19
-setup: prefix: (null)
-EOF
-       test_repo 19 "$TRASH_DIRECTORY/19/.git" "$TRASH_DIRECTORY/19"
-'
-
-test_expect_success '#19: GIT_DIR, GIT_WORK_TREE=root(rel) at root' '
-       cat >19/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/19/.git
-setup: worktree: $TRASH_DIRECTORY/19
-setup: cwd: $TRASH_DIRECTORY/19
-setup: prefix: (null)
-EOF
-       test_repo 19 "$TRASH_DIRECTORY/19/.git" .
-'
-
-test_expect_success '#19: GIT_DIR(rel), GIT_WORKTREE=root in subdir' '
-       cat >19/sub/sub/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/19/.git
-setup: worktree: $TRASH_DIRECTORY/19
-setup: cwd: $TRASH_DIRECTORY/19
-setup: prefix: sub/sub/
-EOF
-       test_repo 19/sub/sub ../../.git "$TRASH_DIRECTORY/19"
-'
-
-test_expect_success '#19: GIT_DIR(rel), GIT_WORKTREE=root(rel) in subdir' '
-       cat >19/sub/sub/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/19/.git
-setup: worktree: $TRASH_DIRECTORY/19
-setup: cwd: $TRASH_DIRECTORY/19
-setup: prefix: sub/sub/
-EOF
-       test_repo 19/sub/sub ../../.git ../..
-'
-
-test_expect_success '#19: GIT_DIR, GIT_WORKTREE=root in subdir' '
-       cat >19/sub/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/19/.git
-setup: worktree: $TRASH_DIRECTORY/19
-setup: cwd: $TRASH_DIRECTORY/19
-setup: prefix: sub/
-EOF
-       test_repo 19/sub "$TRASH_DIRECTORY/19/.git" "$TRASH_DIRECTORY/19"
-'
-
-test_expect_success '#19: GIT_DIR, GIT_WORKTREE=root(rel) in subdir' '
-       cat >19/sub/sub/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/19/.git
-setup: worktree: $TRASH_DIRECTORY/19
-setup: cwd: $TRASH_DIRECTORY/19
-setup: prefix: sub/sub/
-EOF
-       test_repo 19/sub/sub "$TRASH_DIRECTORY/19/.git" ../..
-'
-
-test_expect_success '#19: GIT_DIR(rel), GIT_WORK_TREE=wt at root' '
-       cat >19/expected <<EOF &&
-setup: git_dir: .git
-setup: worktree: $TRASH_DIRECTORY/19/wt
-setup: cwd: $TRASH_DIRECTORY/19
-setup: prefix: (null)
-EOF
-       test_repo 19 .git "$TRASH_DIRECTORY/19/wt"
-'
-
-test_expect_success '#19: GIT_DIR(rel), GIT_WORK_TREE=wt(rel) at root' '
-       cat >19/expected <<EOF &&
-setup: git_dir: .git
-setup: worktree: $TRASH_DIRECTORY/19/wt
-setup: cwd: $TRASH_DIRECTORY/19
-setup: prefix: (null)
-EOF
-       test_repo 19 .git wt
-'
-
-test_expect_success '#19: GIT_DIR, GIT_WORK_TREE=wt(rel) at root' '
-       cat >19/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/19/.git
-setup: worktree: $TRASH_DIRECTORY/19/wt
-setup: cwd: $TRASH_DIRECTORY/19
-setup: prefix: (null)
-EOF
-       test_repo 19 "$TRASH_DIRECTORY/19/.git" wt
-'
-
-test_expect_success '#19: GIT_DIR, GIT_WORK_TREE=wt at root' '
-       cat >19/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/19/.git
-setup: worktree: $TRASH_DIRECTORY/19/wt
-setup: cwd: $TRASH_DIRECTORY/19
-setup: prefix: (null)
-EOF
-       test_repo 19 "$TRASH_DIRECTORY/19/.git" "$TRASH_DIRECTORY/19/wt"
-'
-
-test_expect_success '#19: GIT_DIR(rel), GIT_WORK_TREE=wt in subdir' '
-       cat >19/sub/sub/expected <<EOF &&
-setup: git_dir: ../../.git
-setup: worktree: $TRASH_DIRECTORY/19/wt
-setup: cwd: $TRASH_DIRECTORY/19/sub/sub
-setup: prefix: (null)
-EOF
-       test_repo 19/sub/sub ../../.git "$TRASH_DIRECTORY/19/wt"
-'
-
-test_expect_success '#19: GIT_DIR(rel), GIT_WORK_TREE=wt(rel) in subdir' '
-       cat >19/sub/sub/expected <<EOF &&
-setup: git_dir: ../../.git
-setup: worktree: $TRASH_DIRECTORY/19/wt
-setup: cwd: $TRASH_DIRECTORY/19/sub/sub
-setup: prefix: (null)
-EOF
-       test_repo 19/sub/sub ../../.git ../../wt
-'
-
-test_expect_success '#19: GIT_DIR, GIT_WORK_TREE=wt(rel) in subdir' '
-       cat >19/sub/sub/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/19/.git
-setup: worktree: $TRASH_DIRECTORY/19/wt
-setup: cwd: $TRASH_DIRECTORY/19/sub/sub
-setup: prefix: (null)
-EOF
-       test_repo 19/sub/sub "$TRASH_DIRECTORY/19/.git" ../../wt
-'
-
-test_expect_success '#19: GIT_DIR, GIT_WORK_TREE=wt in subdir' '
-       cat >19/sub/sub/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/19/.git
-setup: worktree: $TRASH_DIRECTORY/19/wt
-setup: cwd: $TRASH_DIRECTORY/19/sub/sub
-setup: prefix: (null)
-EOF
-       test_repo 19/sub/sub "$TRASH_DIRECTORY/19/.git" "$TRASH_DIRECTORY/19/wt"
-'
-
-test_expect_success '#19: GIT_DIR(rel), GIT_WORK_TREE=.. at root' '
-       cat >19/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/19/.git
-setup: worktree: $TRASH_DIRECTORY
-setup: cwd: $TRASH_DIRECTORY
-setup: prefix: 19/
-EOF
-       test_repo 19 .git "$TRASH_DIRECTORY"
-'
-
-test_expect_success '#19: GIT_DIR(rel), GIT_WORK_TREE=..(rel) at root' '
-       cat >19/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/19/.git
-setup: worktree: $TRASH_DIRECTORY
-setup: cwd: $TRASH_DIRECTORY
-setup: prefix: 19/
-EOF
-       test_repo 19 .git ..
-'
-
-test_expect_success '#19: GIT_DIR, GIT_WORK_TREE=..(rel) at root' '
-       cat >19/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/19/.git
-setup: worktree: $TRASH_DIRECTORY
-setup: cwd: $TRASH_DIRECTORY
-setup: prefix: 19/
-EOF
-       test_repo 19 "$TRASH_DIRECTORY/19/.git" ..
-'
-
-test_expect_success '#19: GIT_DIR, GIT_WORK_TREE=.. at root' '
-       cat >19/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/19/.git
-setup: worktree: $TRASH_DIRECTORY
-setup: cwd: $TRASH_DIRECTORY
-setup: prefix: 19/
-EOF
-       test_repo 19 "$TRASH_DIRECTORY/19/.git" "$TRASH_DIRECTORY"
-'
-
-test_expect_success '#19: GIT_DIR(rel), GIT_WORK_TREE=.. in subdir' '
-       cat >19/sub/sub/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/19/.git
-setup: worktree: $TRASH_DIRECTORY
-setup: cwd: $TRASH_DIRECTORY
-setup: prefix: 19/sub/sub/
-EOF
-       test_repo 19/sub/sub ../../.git "$TRASH_DIRECTORY"
-'
-
-test_expect_success '#19: GIT_DIR(rel), GIT_WORK_TREE=..(rel) in subdir' '
-       cat >19/sub/sub/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/19/.git
-setup: worktree: $TRASH_DIRECTORY
-setup: cwd: $TRASH_DIRECTORY
-setup: prefix: 19/sub/sub/
-EOF
-       test_repo 19/sub/sub ../../.git ../../..
-'
-
-test_expect_success '#19: GIT_DIR, GIT_WORK_TREE=..(rel) in subdir' '
-       cat >19/sub/sub/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/19/.git
-setup: worktree: $TRASH_DIRECTORY
-setup: cwd: $TRASH_DIRECTORY
-setup: prefix: 19/sub/sub/
-EOF
-       test_repo 19/sub/sub "$TRASH_DIRECTORY/19/.git" ../../../
-'
-
-test_expect_success '#19: GIT_DIR, GIT_WORK_TREE=.. in subdir' '
-       cat >19/sub/sub/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/19/.git
-setup: worktree: $TRASH_DIRECTORY
-setup: cwd: $TRASH_DIRECTORY
-setup: prefix: 19/sub/sub/
-EOF
-       test_repo 19/sub/sub "$TRASH_DIRECTORY/19/.git" "$TRASH_DIRECTORY"
-'
-
-#
-# case #20.1
-#
-############################################################
-#
-# Input:
-#
-#  - GIT_WORK_TREE is not set
-#  - GIT_DIR is not set
-#  - core.worktree is set
-#  - .git is a directory
-#  - cwd is inside .git
-#
-# Output:
-#
-# core.worktree is ignored -> #16.1
-
-test_expect_success '#20.1: setup' '
-       sane_unset GIT_DIR GIT_WORK_TREE &&
-       mkdir 20 20/sub &&
-       cd 20 &&
-       git init &&
-       git config core.worktree non-existent &&
-       mkdir .git/wt .git/wt/sub &&
-       cd ..
-'
-
-test_expect_success '#20.1: at .git' '
-       cat >20/.git/expected <<EOF &&
-setup: git_dir: .
-setup: worktree: (null)
-setup: cwd: $TRASH_DIRECTORY/20/.git
-setup: prefix: (null)
-EOF
-       test_repo 20/.git
-'
-
-test_expect_success '#20.1: in .git/wt' '
-       cat >20/.git/wt/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/20/.git
-setup: worktree: (null)
-setup: cwd: $TRASH_DIRECTORY/20/.git/wt
-setup: prefix: (null)
-EOF
-       test_repo 20/.git/wt
-'
-
-test_expect_success '#20.1: in .git/wt/sub' '
-       cat >20/.git/wt/sub/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/20/.git
-setup: worktree: (null)
-setup: cwd: $TRASH_DIRECTORY/20/.git/wt/sub
-setup: prefix: (null)
-EOF
-       test_repo 20/.git/wt/sub
-'
-
-#
-# case #20.2
-#
-############################################################
-#
-# Input:
-#
-#  - GIT_WORK_TREE is not set
-#  - GIT_DIR is not set
-#  - core.worktree is set
-#  - .git is a directory
-#  - core.bare is set
-#
-# Output:
-#
-# core.worktree is ignored -> #16.2
-
-test_expect_success '#20.2: setup' '
-       git config --file="$TRASH_DIRECTORY/20/.git/config" core.bare true
-'
-
-test_expect_success '#20.2: at .git' '
-       cat >20/.git/expected <<EOF &&
-setup: git_dir: .
-setup: worktree: (null)
-setup: cwd: $TRASH_DIRECTORY/20/.git
-setup: prefix: (null)
-EOF
-       test_repo 20/.git
-'
-
-test_expect_success '#20.2: in .git/wt' '
-       cat >20/.git/wt/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/20/.git
-setup: worktree: (null)
-setup: cwd: $TRASH_DIRECTORY/20/.git/wt
-setup: prefix: (null)
-EOF
-       test_repo 20/.git/wt
-'
-
-test_expect_success '#20.2: in .git/wt/sub' '
-       cat >20/.git/wt/sub/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/20/.git
-setup: worktree: (null)
-setup: cwd: $TRASH_DIRECTORY/20/.git/wt/sub
-setup: prefix: (null)
-EOF
-       test_repo 20/.git/wt/sub
-'
-
-test_expect_success '#20.2: at root' '
-       cat >20/expected <<EOF &&
-setup: git_dir: .git
-setup: worktree: (null)
-setup: cwd: $TRASH_DIRECTORY/20
-setup: prefix: (null)
-EOF
-       test_repo 20
-'
-
-test_expect_success '#20.2: in subdir' '
-       cat >20/sub/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/20/.git
-setup: worktree: (null)
-setup: cwd: $TRASH_DIRECTORY/20/sub
-setup: prefix: (null)
-EOF
-       test_repo 20/sub
-'
-
-#
-# case #21.1
-#
-############################################################
-#
-# Input:
-#
-#  - GIT_WORK_TREE is set
-#  - GIT_DIR is not set
-#  - core.worktree is set
-#  - .git is a directory
-#  - cwd is inside .git
-#
-# Output:
-#
-# GIT_WORK_TREE/core.worktree are ignored -> #20.1
-
-test_expect_success '#21.1: setup' '
-       sane_unset GIT_DIR GIT_WORK_TREE &&
-       mkdir 21 21/sub &&
-       cd 21 &&
-       git init &&
-       git config core.worktree non-existent &&
-       GIT_WORK_TREE=non-existent-too &&
-       export GIT_WORK_TREE &&
-       mkdir .git/wt .git/wt/sub &&
-       cd ..
-'
-
-test_expect_success '#21.1: at .git' '
-       cat >21/.git/expected <<EOF &&
-setup: git_dir: .
-setup: worktree: (null)
-setup: cwd: $TRASH_DIRECTORY/21/.git
-setup: prefix: (null)
-EOF
-       test_repo 21/.git
-'
-
-test_expect_success '#21.1: in .git/wt' '
-       cat >21/.git/wt/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/21/.git
-setup: worktree: (null)
-setup: cwd: $TRASH_DIRECTORY/21/.git/wt
-setup: prefix: (null)
-EOF
-       test_repo 21/.git/wt
-'
-
-test_expect_success '#21.1: in .git/wt/sub' '
-       cat >21/.git/wt/sub/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/21/.git
-setup: worktree: (null)
-setup: cwd: $TRASH_DIRECTORY/21/.git/wt/sub
-setup: prefix: (null)
-EOF
-       test_repo 21/.git/wt/sub
-'
-
-#
-# case #21.2
-#
-############################################################
-#
-# Input:
-#
-#  - GIT_WORK_TREE is set
-#  - GIT_DIR is not set
-#  - core.worktree is set
-#  - .git is a directory
-#  - core.bare is set
-#
-# Output:
-#
-# GIT_WORK_TREE/core.worktree are ignored -> #20.2
-
-test_expect_success '#21.2: setup' '
-       git config --file="$TRASH_DIRECTORY/21/.git/config" core.bare true
-'
-
-test_expect_success '#21.2: at .git' '
-       cat >21/.git/expected <<EOF &&
-setup: git_dir: .
-setup: worktree: (null)
-setup: cwd: $TRASH_DIRECTORY/21/.git
-setup: prefix: (null)
-EOF
-       test_repo 21/.git
-'
-
-test_expect_success '#21.2: in .git/wt' '
-       cat >21/.git/wt/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/21/.git
-setup: worktree: (null)
-setup: cwd: $TRASH_DIRECTORY/21/.git/wt
-setup: prefix: (null)
-EOF
-       test_repo 21/.git/wt
-'
-
-test_expect_success '#21.2: in .git/wt/sub' '
-       cat >21/.git/wt/sub/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/21/.git
-setup: worktree: (null)
-setup: cwd: $TRASH_DIRECTORY/21/.git/wt/sub
-setup: prefix: (null)
-EOF
-       test_repo 21/.git/wt/sub
-'
-
-test_expect_success '#21.2: at root' '
-       cat >21/expected <<EOF &&
-setup: git_dir: .git
-setup: worktree: (null)
-setup: cwd: $TRASH_DIRECTORY/21
-setup: prefix: (null)
-EOF
-       test_repo 21
-'
-
-test_expect_success '#21.2: in subdir' '
-       cat >21/sub/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/21/.git
-setup: worktree: (null)
-setup: cwd: $TRASH_DIRECTORY/21/sub
-setup: prefix: (null)
-EOF
-       test_repo 21/sub
-'
-
-#
-# case #22.1
-#
-############################################################
-#
-# Input:
-#
-#  - GIT_WORK_TREE is not set
-#  - GIT_DIR is set
-#  - core.worktree is set
-#  - .git is a directory
-#  - cwd is inside .git
-#
-# Output:
-#
-# bare attribute is ignored
-#
-#  - worktree is at core.worktree
-#  - cwd is at worktree root
-#  - prefix is calculated
-#  - git_dir is at $GIT_DIR
-#  - cwd can be outside worktree
-
-test_expect_success '#22.1: setup' '
-       sane_unset GIT_DIR GIT_WORK_TREE &&
-       mkdir 22 &&
-       cd 22 &&
-       git init &&
-       mkdir .git/sub .git/wt .git/wt/sub &&
-       cd ..
-'
-
-test_expect_success '#22.1: GIT_DIR(rel), core.worktree=. at .git' '
-       cat >22/.git/expected <<EOF &&
-setup: git_dir: .
-setup: worktree: $TRASH_DIRECTORY/22/.git
-setup: cwd: $TRASH_DIRECTORY/22/.git
-setup: prefix: (null)
-EOF
-       git config --file="$TRASH_DIRECTORY/22/.git/config" core.worktree "$TRASH_DIRECTORY/22/.git" &&
-       test_repo 22/.git .
-'
-
-test_expect_success '#22.1: GIT_DIR(rel), core.worktree=.(rel) at .git' '
-       cat >22/.git/expected <<EOF &&
-setup: git_dir: .
-setup: worktree: $TRASH_DIRECTORY/22/.git
-setup: cwd: $TRASH_DIRECTORY/22/.git
-setup: prefix: (null)
-EOF
-       git config --file="$TRASH_DIRECTORY/22/.git/config" core.worktree . &&
-       test_repo 22/.git .
-'
-
-test_expect_success '#22.1: GIT_DIR, core.worktree=. at .git' '
-       cat >22/.git/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/22/.git
-setup: worktree: $TRASH_DIRECTORY/22/.git
-setup: cwd: $TRASH_DIRECTORY/22/.git
-setup: prefix: (null)
-EOF
-       git config --file="$TRASH_DIRECTORY/22/.git/config" core.worktree "$TRASH_DIRECTORY/22/.git" &&
-       test_repo 22/.git "$TRASH_DIRECTORY/22/.git"
-'
-
-test_expect_success '#22.1: GIT_DIR, core.worktree=.(rel) at root' '
-       cat >22/.git/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/22/.git
-setup: worktree: $TRASH_DIRECTORY/22/.git
-setup: cwd: $TRASH_DIRECTORY/22/.git
-setup: prefix: (null)
-EOF
-       git config --file="$TRASH_DIRECTORY/22/.git/config" core.worktree . &&
-       test_repo 22/.git "$TRASH_DIRECTORY/22/.git"
-'
-
-test_expect_success '#22.1: GIT_DIR(rel), core.worktree=. in .git/sub' '
-       cat >22/.git/sub/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/22/.git
-setup: worktree: $TRASH_DIRECTORY/22/.git
-setup: cwd: $TRASH_DIRECTORY/22/.git
-setup: prefix: sub/
-EOF
-       git config --file="$TRASH_DIRECTORY/22/.git/config" core.worktree "$TRASH_DIRECTORY/22/.git" &&
-       test_repo 22/.git/sub ..
-'
-
-test_expect_success '#22.1: GIT_DIR(rel), core.worktree=.(rel) in .git/sub' '
-       cat >22/.git/sub/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/22/.git
-setup: worktree: $TRASH_DIRECTORY/22/.git
-setup: cwd: $TRASH_DIRECTORY/22/.git
-setup: prefix: sub/
-EOF
-       git config --file="$TRASH_DIRECTORY/22/.git/config" core.worktree . &&
-       test_repo 22/.git/sub/ ..
-'
-
-test_expect_success '#22.1: GIT_DIR, core.worktree=. in .git/sub' '
-       cat >22/.git/sub/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/22/.git
-setup: worktree: $TRASH_DIRECTORY/22/.git
-setup: cwd: $TRASH_DIRECTORY/22/.git
-setup: prefix: sub/
-EOF
-       git config --file="$TRASH_DIRECTORY/22/.git/config" core.worktree "$TRASH_DIRECTORY/22/.git" &&
-       test_repo 22/.git/sub "$TRASH_DIRECTORY/22/.git"
-'
-
-test_expect_success '#22.1: GIT_DIR, core.worktree=.(rel) in .git/sub' '
-       cat >22/.git/sub/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/22/.git
-setup: worktree: $TRASH_DIRECTORY/22/.git
-setup: cwd: $TRASH_DIRECTORY/22/.git
-setup: prefix: sub/
-EOF
-       git config --file="$TRASH_DIRECTORY/22/.git/config" core.worktree . &&
-       test_repo 22/.git/sub "$TRASH_DIRECTORY/22/.git"
-'
-
-test_expect_success '#22.1: GIT_DIR(rel), core.worktree=wt at .git' '
-       cat >22/.git/expected <<EOF &&
-setup: git_dir: .
-setup: worktree: $TRASH_DIRECTORY/22/.git/wt
-setup: cwd: $TRASH_DIRECTORY/22/.git
-setup: prefix: (null)
-EOF
-       git config --file="$TRASH_DIRECTORY/22/.git/config" core.worktree "$TRASH_DIRECTORY/22/.git/wt" &&
-       test_repo 22/.git .
-'
-
-test_expect_success '#22.1: GIT_DIR(rel), core.worktree=wt(rel) at .git' '
-       cat >22/.git/expected <<EOF &&
-setup: git_dir: .
-setup: worktree: $TRASH_DIRECTORY/22/.git/wt
-setup: cwd: $TRASH_DIRECTORY/22/.git
-setup: prefix: (null)
-EOF
-       git config --file="$TRASH_DIRECTORY/22/.git/config" core.worktree wt &&
-       test_repo 22/.git .
-'
-
-test_expect_success '#22.1: GIT_DIR, core.worktree=wt(rel) at .git' '
-       cat >22/.git/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/22/.git
-setup: worktree: $TRASH_DIRECTORY/22/.git/wt
-setup: cwd: $TRASH_DIRECTORY/22/.git
-setup: prefix: (null)
-EOF
-       git config --file="$TRASH_DIRECTORY/22/.git/config" core.worktree wt &&
-       test_repo 22/.git "$TRASH_DIRECTORY/22/.git"
-'
-
-test_expect_success '#22.1: GIT_DIR, core.worktree=wt at .git' '
-       cat >22/.git/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/22/.git
-setup: worktree: $TRASH_DIRECTORY/22/.git/wt
-setup: cwd: $TRASH_DIRECTORY/22/.git
-setup: prefix: (null)
-EOF
-       git config --file="$TRASH_DIRECTORY/22/.git/config" core.worktree "$TRASH_DIRECTORY/22/.git/wt" &&
-       test_repo 22/.git "$TRASH_DIRECTORY/22/.git"
-'
-
-test_expect_success '#22.1: GIT_DIR(rel), core.worktree=wt in .git/sub' '
-       cat >22/.git/sub/expected <<EOF &&
-setup: git_dir: ..
-setup: worktree: $TRASH_DIRECTORY/22/.git/wt
-setup: cwd: $TRASH_DIRECTORY/22/.git/sub
-setup: prefix: (null)
-EOF
-       git config --file="$TRASH_DIRECTORY/22/.git/config" core.worktree "$TRASH_DIRECTORY/22/.git/wt" &&
-       test_repo 22/.git/sub ..
-'
-
-test_expect_success '#22.1: GIT_DIR(rel), core.worktree=wt(rel) in .git/sub' '
-       cat >22/.git/sub/expected <<EOF &&
-setup: git_dir: ..
-setup: worktree: $TRASH_DIRECTORY/22/.git/wt
-setup: cwd: $TRASH_DIRECTORY/22/.git/sub
-setup: prefix: (null)
-EOF
-       git config --file="$TRASH_DIRECTORY/22/.git/config" core.worktree wt &&
-       test_repo 22/.git/sub ..
-'
-
-test_expect_success '#22.1: GIT_DIR, core.worktree=wt(rel) in .git/sub' '
-       cat >22/.git/sub/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/22/.git
-setup: worktree: $TRASH_DIRECTORY/22/.git/wt
-setup: cwd: $TRASH_DIRECTORY/22/.git/sub
-setup: prefix: (null)
-EOF
-       git config --file="$TRASH_DIRECTORY/22/.git/config" core.worktree wt &&
-       test_repo 22/.git/sub "$TRASH_DIRECTORY/22/.git"
-'
+A few rules for repo setup:
 
-test_expect_success '#22.1: GIT_DIR, core.worktree=wt in .git/sub' '
-       cat >22/.git/sub/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/22/.git
-setup: worktree: $TRASH_DIRECTORY/22/.git/wt
-setup: cwd: $TRASH_DIRECTORY/22/.git/sub
-setup: prefix: (null)
-EOF
-       git config --file="$TRASH_DIRECTORY/22/.git/config" core.worktree "$TRASH_DIRECTORY/22/.git/wt" &&
-       test_repo 22/.git/sub "$TRASH_DIRECTORY/22/.git"
-'
+1. GIT_DIR is relative to user's cwd. --git-dir is equivalent to
+   GIT_DIR.
 
-test_expect_success '#22.1: GIT_DIR(rel), core.worktree=.. at .git' '
-       cat >22/.git/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/22/.git
-setup: worktree: $TRASH_DIRECTORY/22
-setup: cwd: $TRASH_DIRECTORY/22
-setup: prefix: .git/
-EOF
-       git config --file="$TRASH_DIRECTORY/22/.git/config" core.worktree "$TRASH_DIRECTORY/22" &&
-       test_repo 22/.git .
-'
+2. .git file is relative to parent directory. .git file is basically
+   symlink in disguise. The directory where .git file points to will
+   become new git_dir.
 
-test_expect_success '#22.1: GIT_DIR(rel), core.worktree=..(rel) at .git' '
-       cat >22/.git/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/22/.git
-setup: worktree: $TRASH_DIRECTORY/22
-setup: cwd: $TRASH_DIRECTORY/22
-setup: prefix: .git/
-EOF
-       git config --file="$TRASH_DIRECTORY/22/.git/config" core.worktree .. &&
-       test_repo 22/.git .
-'
+3. core.worktree is relative to git_dir.
 
-test_expect_success '#22.1: GIT_DIR, core.worktree=..(rel) at .git' '
-       cat >22/.git/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/22/.git
-setup: worktree: $TRASH_DIRECTORY/22
-setup: cwd: $TRASH_DIRECTORY/22
-setup: prefix: .git/
-EOF
-       git config --file="$TRASH_DIRECTORY/22/.git/config" core.worktree .. &&
-       test_repo 22/.git "$TRASH_DIRECTORY/22/.git"
-'
+4. GIT_WORK_TREE is relative to user's cwd. --work-tree is
+   equivalent to GIT_WORK_TREE.
 
-test_expect_success '#22.1: GIT_DIR, core.worktree=.. at .git' '
-       cat >22/.git/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/22/.git
-setup: worktree: $TRASH_DIRECTORY/22
-setup: cwd: $TRASH_DIRECTORY/22
-setup: prefix: .git/
-EOF
-       git config --file="$TRASH_DIRECTORY/22/.git/config" core.worktree "$TRASH_DIRECTORY/22" &&
-       test_repo 22/.git "$TRASH_DIRECTORY/22/.git"
-'
+5. GIT_WORK_TREE/core.worktree was originally meant to work only if
+   GIT_DIR is set, but earlier git didn't enforce it, and some scripts
+   depend on the implementation that happened to first discover .git by
+   going up from the users $cwd and then using the specified working tree
+   that may or may not have any relation to where .git was found in.  This
+   historical behaviour must be kept.
 
-test_expect_success '#22.1: GIT_DIR(rel), core.worktree=.. in .git/sub' '
-       cat >22/.git/sub/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/22/.git
-setup: worktree: $TRASH_DIRECTORY/22
-setup: cwd: $TRASH_DIRECTORY/22
-setup: prefix: .git/sub/
-EOF
-       git config --file="$TRASH_DIRECTORY/22/.git/config" core.worktree "$TRASH_DIRECTORY/22" &&
-       test_repo 22/.git/sub ..
-'
+6. Effective GIT_WORK_TREE overrides core.worktree and core.bare
 
-test_expect_success '#22.1: GIT_DIR(rel), core.worktree=..(rel) in .git/sub' '
-       cat >22/.git/sub/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/22/.git
-setup: worktree: $TRASH_DIRECTORY/22
-setup: cwd: $TRASH_DIRECTORY/22
-setup: prefix: .git/sub/
-EOF
-       git config --file="$TRASH_DIRECTORY/22/.git/config" core.worktree .. &&
-       test_repo 22/.git/sub ..
-'
+7. Effective core.worktree conflicts with core.bare
 
-test_expect_success '#22.1: GIT_DIR, core.worktree=..(rel) in .git/sub' '
-       cat >22/.git/sub/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/22/.git
-setup: worktree: $TRASH_DIRECTORY/22
-setup: cwd: $TRASH_DIRECTORY/22
-setup: prefix: .git/sub/
-EOF
-       git config --file="$TRASH_DIRECTORY/22/.git/config" core.worktree .. &&
-       test_repo 22/.git/sub "$TRASH_DIRECTORY/22/.git"
-'
+8. If GIT_DIR is set but neither worktree nor bare setting is given,
+   original cwd becomes worktree.
 
-test_expect_success '#22.1: GIT_DIR, core.worktree=.. in .git/sub' '
-       cat >22/.git/sub/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/22/.git
-setup: worktree: $TRASH_DIRECTORY/22
-setup: cwd: $TRASH_DIRECTORY/22
-setup: prefix: .git/sub/
-EOF
-       git config --file="$TRASH_DIRECTORY/22/.git/config" core.worktree "$TRASH_DIRECTORY/22" &&
-       test_repo 22/.git/sub "$TRASH_DIRECTORY/22/.git"
-'
+9. If .git discovery is done inside a repo, the repo becomes a bare
+   repo. .git discovery is performed if GIT_DIR is not set.
 
-#
-# case #22.2
-#
-############################################################
-#
-# Input:
-#
-#  - GIT_WORK_TREE is not set
-#  - GIT_DIR is set
-#  - core.worktree is set
-#  - .git is a directory
-#  - core.bare is set
-#
-# Output:
-#
-# core.worktree and core.bare conflict, won't fly.
+10. If no worktree is available, cwd remains unchanged, prefix is
+    NULL.
 
-test_expect_success '#22.2: setup' '
-       git config --file="$TRASH_DIRECTORY/22/.git/config" core.bare true
-'
+11. When user's cwd is outside worktree, cwd remains unchanged,
+    prefix is NULL.
+"
+. ./test-lib.sh
 
-test_expect_success '#22.2: at .git' '
-       (
-       cd 22/.git &&
-       GIT_DIR=. &&
-       export GIT_DIR &&
-       test_must_fail git symbolic-ref HEAD 2>result &&
-       grep "core.bare and core.worktree do not make sense" result
-       )
-'
+here=$(pwd)
 
-test_expect_success '#22.2: at root' '
+test_repo () {
        (
-       cd 22 &&
-       GIT_DIR=.git &&
-       export GIT_DIR &&
-       test_must_fail git symbolic-ref HEAD 2>result &&
-       grep "core.bare and core.worktree do not make sense" result
+               cd "$1" &&
+               if test -n "$2"
+               then
+                       GIT_DIR="$2" &&
+                       export GIT_DIR
+               fi &&
+               if test -n "$3"
+               then
+                       GIT_WORK_TREE="$3" &&
+                       export GIT_WORK_TREE
+               fi &&
+               rm -f trace &&
+               GIT_TRACE="$(pwd)/trace" git symbolic-ref HEAD >/dev/null &&
+               grep '^setup: ' trace >result &&
+               test_cmp expected result
        )
-'
-
-#
-# case #23
-#
-############################################################
-#
-# Input:
-#
-#  - GIT_WORK_TREE is set
-#  - GIT_DIR is set
-#  - core.worktree is set
-#  - .git is a directory
-#  - core.bare is set
-#
-# Output:
-#
-# core.worktree is overridden by GIT_WORK_TREE -> #19
-
-test_expect_success '#23: setup' '
-       sane_unset GIT_DIR GIT_WORK_TREE &&
-       mkdir 23 23/sub 23/sub/sub 23.wt 23.wt/sub 23/wt 23/wt/sub &&
-       cd 23 &&
-       git init &&
-       git config core.bare true &&
-       git config core.worktree non-existent &&
-       cd ..
-'
-
-test_expect_success '#23: GIT_DIR(rel), GIT_WORK_TREE=root at root' '
-       cat >23/expected <<EOF &&
-setup: git_dir: .git
-setup: worktree: $TRASH_DIRECTORY/23
-setup: cwd: $TRASH_DIRECTORY/23
-setup: prefix: (null)
-EOF
-       test_repo 23 .git "$TRASH_DIRECTORY/23"
-'
-
-test_expect_success '#23: GIT_DIR(rel), GIT_WORK_TREE=root(rel) at root' '
-       cat >23/expected <<EOF &&
-setup: git_dir: .git
-setup: worktree: $TRASH_DIRECTORY/23
-setup: cwd: $TRASH_DIRECTORY/23
-setup: prefix: (null)
-EOF
-       test_repo 23 .git .
-'
-
-test_expect_success '#23: GIT_DIR, GIT_WORK_TREE=root at root' '
-       cat >23/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/23/.git
-setup: worktree: $TRASH_DIRECTORY/23
-setup: cwd: $TRASH_DIRECTORY/23
-setup: prefix: (null)
-EOF
-       test_repo 23 "$TRASH_DIRECTORY/23/.git" "$TRASH_DIRECTORY/23"
-'
-
-test_expect_success '#23: GIT_DIR, GIT_WORK_TREE=root(rel) at root' '
-       cat >23/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/23/.git
-setup: worktree: $TRASH_DIRECTORY/23
-setup: cwd: $TRASH_DIRECTORY/23
-setup: prefix: (null)
-EOF
-       test_repo 23 "$TRASH_DIRECTORY/23/.git" .
-'
-
-test_expect_success '#23: GIT_DIR(rel), GIT_WORKTREE=root in subdir' '
-       cat >23/sub/sub/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/23/.git
-setup: worktree: $TRASH_DIRECTORY/23
-setup: cwd: $TRASH_DIRECTORY/23
-setup: prefix: sub/sub/
-EOF
-       test_repo 23/sub/sub ../../.git "$TRASH_DIRECTORY/23"
-'
-
-test_expect_success '#23: GIT_DIR(rel), GIT_WORKTREE=root(rel) in subdir' '
-       cat >23/sub/sub/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/23/.git
-setup: worktree: $TRASH_DIRECTORY/23
-setup: cwd: $TRASH_DIRECTORY/23
-setup: prefix: sub/sub/
-EOF
-       test_repo 23/sub/sub ../../.git ../..
-'
-
-test_expect_success '#23: GIT_DIR, GIT_WORKTREE=root in subdir' '
-       cat >23/sub/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/23/.git
-setup: worktree: $TRASH_DIRECTORY/23
-setup: cwd: $TRASH_DIRECTORY/23
-setup: prefix: sub/
-EOF
-       test_repo 23/sub "$TRASH_DIRECTORY/23/.git" "$TRASH_DIRECTORY/23"
-'
-
-test_expect_success '#23: GIT_DIR, GIT_WORKTREE=root(rel) in subdir' '
-       cat >23/sub/sub/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/23/.git
-setup: worktree: $TRASH_DIRECTORY/23
-setup: cwd: $TRASH_DIRECTORY/23
-setup: prefix: sub/sub/
-EOF
-       test_repo 23/sub/sub "$TRASH_DIRECTORY/23/.git" ../..
-'
-
-test_expect_success '#23: GIT_DIR(rel), GIT_WORK_TREE=wt at root' '
-       cat >23/expected <<EOF &&
-setup: git_dir: .git
-setup: worktree: $TRASH_DIRECTORY/23/wt
-setup: cwd: $TRASH_DIRECTORY/23
-setup: prefix: (null)
-EOF
-       test_repo 23 .git "$TRASH_DIRECTORY/23/wt"
-'
-
-test_expect_success '#23: GIT_DIR(rel), GIT_WORK_TREE=wt(rel) at root' '
-       cat >23/expected <<EOF &&
-setup: git_dir: .git
-setup: worktree: $TRASH_DIRECTORY/23/wt
-setup: cwd: $TRASH_DIRECTORY/23
-setup: prefix: (null)
-EOF
-       test_repo 23 .git wt
-'
-
-test_expect_success '#23: GIT_DIR, GIT_WORK_TREE=wt(rel) at root' '
-       cat >23/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/23/.git
-setup: worktree: $TRASH_DIRECTORY/23/wt
-setup: cwd: $TRASH_DIRECTORY/23
-setup: prefix: (null)
-EOF
-       test_repo 23 "$TRASH_DIRECTORY/23/.git" wt
-'
-
-test_expect_success '#23: GIT_DIR, GIT_WORK_TREE=wt at root' '
-       cat >23/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/23/.git
-setup: worktree: $TRASH_DIRECTORY/23/wt
-setup: cwd: $TRASH_DIRECTORY/23
-setup: prefix: (null)
-EOF
-       test_repo 23 "$TRASH_DIRECTORY/23/.git" "$TRASH_DIRECTORY/23/wt"
-'
-
-test_expect_success '#23: GIT_DIR(rel), GIT_WORK_TREE=wt in subdir' '
-       cat >23/sub/sub/expected <<EOF &&
-setup: git_dir: ../../.git
-setup: worktree: $TRASH_DIRECTORY/23/wt
-setup: cwd: $TRASH_DIRECTORY/23/sub/sub
-setup: prefix: (null)
-EOF
-       test_repo 23/sub/sub ../../.git "$TRASH_DIRECTORY/23/wt"
-'
-
-test_expect_success '#23: GIT_DIR(rel), GIT_WORK_TREE=wt(rel) in subdir' '
-       cat >23/sub/sub/expected <<EOF &&
-setup: git_dir: ../../.git
-setup: worktree: $TRASH_DIRECTORY/23/wt
-setup: cwd: $TRASH_DIRECTORY/23/sub/sub
-setup: prefix: (null)
-EOF
-       test_repo 23/sub/sub ../../.git ../../wt
-'
-
-test_expect_success '#23: GIT_DIR, GIT_WORK_TREE=wt(rel) in subdir' '
-       cat >23/sub/sub/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/23/.git
-setup: worktree: $TRASH_DIRECTORY/23/wt
-setup: cwd: $TRASH_DIRECTORY/23/sub/sub
-setup: prefix: (null)
-EOF
-       test_repo 23/sub/sub "$TRASH_DIRECTORY/23/.git" ../../wt
-'
-
-test_expect_success '#23: GIT_DIR, GIT_WORK_TREE=wt in subdir' '
-       cat >23/sub/sub/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/23/.git
-setup: worktree: $TRASH_DIRECTORY/23/wt
-setup: cwd: $TRASH_DIRECTORY/23/sub/sub
-setup: prefix: (null)
-EOF
-       test_repo 23/sub/sub "$TRASH_DIRECTORY/23/.git" "$TRASH_DIRECTORY/23/wt"
-'
-
-test_expect_success '#23: GIT_DIR(rel), GIT_WORK_TREE=.. at root' '
-       cat >23/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/23/.git
-setup: worktree: $TRASH_DIRECTORY
-setup: cwd: $TRASH_DIRECTORY
-setup: prefix: 23/
-EOF
-       test_repo 23 .git "$TRASH_DIRECTORY"
-'
-
-test_expect_success '#23: GIT_DIR(rel), GIT_WORK_TREE=..(rel) at root' '
-       cat >23/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/23/.git
-setup: worktree: $TRASH_DIRECTORY
-setup: cwd: $TRASH_DIRECTORY
-setup: prefix: 23/
-EOF
-       test_repo 23 .git ..
-'
-
-test_expect_success '#23: GIT_DIR, GIT_WORK_TREE=..(rel) at root' '
-       cat >23/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/23/.git
-setup: worktree: $TRASH_DIRECTORY
-setup: cwd: $TRASH_DIRECTORY
-setup: prefix: 23/
-EOF
-       test_repo 23 "$TRASH_DIRECTORY/23/.git" ..
-'
-
-test_expect_success '#23: GIT_DIR, GIT_WORK_TREE=.. at root' '
-       cat >23/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/23/.git
-setup: worktree: $TRASH_DIRECTORY
-setup: cwd: $TRASH_DIRECTORY
-setup: prefix: 23/
-EOF
-       test_repo 23 "$TRASH_DIRECTORY/23/.git" "$TRASH_DIRECTORY"
-'
-
-test_expect_success '#23: GIT_DIR(rel), GIT_WORK_TREE=.. in subdir' '
-       cat >23/sub/sub/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/23/.git
-setup: worktree: $TRASH_DIRECTORY
-setup: cwd: $TRASH_DIRECTORY
-setup: prefix: 23/sub/sub/
-EOF
-       test_repo 23/sub/sub ../../.git "$TRASH_DIRECTORY"
-'
-
-test_expect_success '#23: GIT_DIR(rel), GIT_WORK_TREE=..(rel) in subdir' '
-       cat >23/sub/sub/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/23/.git
-setup: worktree: $TRASH_DIRECTORY
-setup: cwd: $TRASH_DIRECTORY
-setup: prefix: 23/sub/sub/
-EOF
-       test_repo 23/sub/sub ../../.git ../../..
-'
-
-test_expect_success '#23: GIT_DIR, GIT_WORK_TREE=..(rel) in subdir' '
-       cat >23/sub/sub/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/23/.git
-setup: worktree: $TRASH_DIRECTORY
-setup: cwd: $TRASH_DIRECTORY
-setup: prefix: 23/sub/sub/
-EOF
-       test_repo 23/sub/sub "$TRASH_DIRECTORY/23/.git" ../../../
-'
-
-test_expect_success '#23: GIT_DIR, GIT_WORK_TREE=.. in subdir' '
-       cat >23/sub/sub/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/23/.git
-setup: worktree: $TRASH_DIRECTORY
-setup: cwd: $TRASH_DIRECTORY
-setup: prefix: 23/sub/sub/
-EOF
-       test_repo 23/sub/sub "$TRASH_DIRECTORY/23/.git" "$TRASH_DIRECTORY"
-'
-
-#
-# case #24
-#
-############################################################
-#
-# Input:
-#
-#  - GIT_WORK_TREE is not set
-#  - GIT_DIR is not set
-#  - core.worktree is not set
-#  - .git is a file
-#  - core.bare is set
-#
-# Output:
-#
-# #16.2 except git_dir is set according to .git file
-
-test_expect_success '#24: setup' '
-       sane_unset GIT_DIR GIT_WORK_TREE &&
-       mkdir 24 24/sub &&
-       cd 24 &&
-       git init &&
-       git config core.bare true &&
-       mv .git ../24.git &&
-       echo gitdir: ../24.git >.git &&
-       cd ..
-'
-
-test_expect_success '#24: at root' '
-       cat >24/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/24.git
-setup: worktree: (null)
-setup: cwd: $TRASH_DIRECTORY/24
-setup: prefix: (null)
-EOF
-       test_repo 24
-'
-
-test_expect_success '#24: in subdir' '
-       cat >24/sub/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/24.git
-setup: worktree: (null)
-setup: cwd: $TRASH_DIRECTORY/24/sub
-setup: prefix: (null)
-EOF
-       test_repo 24/sub
-'
-
-#
-# case #25
-#
-############################################################
-#
-# Input:
-#
-#  - GIT_WORK_TREE is set
-#  - GIT_DIR is not set
-#  - core.worktree is not set
-#  - .git is a file
-#  - core.bare is set
-#
-# Output:
-#
-# #17.2 except git_dir is set according to .git file
-
-test_expect_success '#25: setup' '
-       sane_unset GIT_DIR GIT_WORK_TREE &&
-       mkdir 25 25/sub &&
-       cd 25 &&
-       git init &&
-       git config core.bare true &&
-       GIT_WORK_TREE=non-existent &&
-       export GIT_WORK_TREE &&
-       mv .git ../25.git &&
-       echo gitdir: ../25.git >.git &&
-       cd ..
-'
-
-test_expect_success '#25: at root' '
-       cat >25/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/25.git
-setup: worktree: (null)
-setup: cwd: $TRASH_DIRECTORY/25
-setup: prefix: (null)
-EOF
-       test_repo 25
-'
-
-test_expect_success '#25: in subdir' '
-       cat >25/sub/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/25.git
-setup: worktree: (null)
-setup: cwd: $TRASH_DIRECTORY/25/sub
-setup: prefix: (null)
-EOF
-       test_repo 25/sub
-'
+}
 
-#
-# case #26
-#
-############################################################
-#
-# Input:
-#
-#  - GIT_WORK_TREE is not set
-#  - GIT_DIR is set
-#  - core.worktree is not set
-#  - .git is a file
-#  - core.bare is set
-#
-# Output:
-#
-# #18 except git_dir is set according to .git file
+maybe_config () {
+       file=$1 var=$2 value=$3 &&
+       if test "$value" != unset
+       then
+               git config --file="$file" "$var" "$value"
+       fi
+}
 
-test_expect_success '#26: setup' '
+setup_repo () {
+       name=$1 worktreecfg=$2 gitfile=$3 barecfg=$4 &&
        sane_unset GIT_DIR GIT_WORK_TREE &&
-       mkdir 26 26/sub &&
-       cd 26 &&
-       git init &&
-       git config core.bare true &&
-       mv .git ../26.git &&
-       echo gitdir: ../26.git >.git &&
-       cd ..
-'
-
-test_expect_success '#26: (rel) at root' '
-       cat >26/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/26.git
-setup: worktree: (null)
-setup: cwd: $TRASH_DIRECTORY/26
-setup: prefix: (null)
-EOF
-        test_repo 26 .git
-'
 
-test_expect_success '#26: at root' '
-       cat >26/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/26.git
-setup: worktree: (null)
-setup: cwd: $TRASH_DIRECTORY/26
-setup: prefix: (null)
-EOF
-        test_repo 26 "$TRASH_DIRECTORY/26/.git"
-'
-
-test_expect_success '#26: (rel) in subdir' '
-       cat >26/sub/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/26.git
-setup: worktree: (null)
-setup: cwd: $TRASH_DIRECTORY/26/sub
-setup: prefix: (null)
-EOF
-       test_repo 26/sub ../.git
-'
+       git init "$name" &&
+       maybe_config "$name/.git/config" core.worktree "$worktreecfg" &&
+       maybe_config "$name/.git/config" core.bare "$barecfg" &&
+       mkdir -p "$name/sub/sub" &&
 
-test_expect_success '#26: in subdir' '
-       cat >26/sub/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/26.git
-setup: worktree: (null)
-setup: cwd: $TRASH_DIRECTORY/26/sub
-setup: prefix: (null)
-EOF
-       test_repo 26/sub "$TRASH_DIRECTORY/26/.git"
-'
+       if test "${gitfile:+set}"
+       then
+               mv "$name/.git" "$name.git" &&
+               echo "gitdir: ../$name.git" >"$name/.git"
+       fi
+}
 
-#
-# case #27
-#
-############################################################
-#
-# Input:
-#
-#  - GIT_WORK_TREE is set
-#  - GIT_DIR is set
-#  - .git is a file
-#  - core.worktree is not set
-#  - core.bare is set
-#
-# Output:
-#
-# #19 except git_dir is set according to .git file
+maybe_set () {
+       var=$1 value=$2 &&
+       if test "$value" != unset
+       then
+               eval "$var=\$value" &&
+               export $var
+       fi
+}
 
-test_expect_success '#27: setup' '
+setup_env () {
+       worktreenv=$1 gitdirenv=$2 &&
        sane_unset GIT_DIR GIT_WORK_TREE &&
-       mkdir 27 27/sub 27/sub/sub 27.wt 27.wt/sub 27/wt 27/wt/sub &&
-       cd 27 &&
-       git init &&
-       git config core.bare true &&
-       mv .git ../27.git &&
-       echo gitdir: ../27.git >.git &&
-       cd ..
-'
-
-test_expect_success '#27: GIT_DIR(rel), GIT_WORK_TREE=root at root' '
-       cat >27/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/27.git
-setup: worktree: $TRASH_DIRECTORY/27
-setup: cwd: $TRASH_DIRECTORY/27
-setup: prefix: (null)
-EOF
-       test_repo 27 .git "$TRASH_DIRECTORY/27"
-'
-
-test_expect_success '#27: GIT_DIR(rel), GIT_WORK_TREE=root(rel) at root' '
-       cat >27/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/27.git
-setup: worktree: $TRASH_DIRECTORY/27
-setup: cwd: $TRASH_DIRECTORY/27
-setup: prefix: (null)
-EOF
-       test_repo 27 .git .
-'
-
-test_expect_success '#27: GIT_DIR, GIT_WORK_TREE=root at root' '
-       cat >27/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/27.git
-setup: worktree: $TRASH_DIRECTORY/27
-setup: cwd: $TRASH_DIRECTORY/27
-setup: prefix: (null)
-EOF
-       test_repo 27 "$TRASH_DIRECTORY/27/.git" "$TRASH_DIRECTORY/27"
-'
-
-test_expect_success '#27: GIT_DIR, GIT_WORK_TREE=root(rel) at root' '
-       cat >27/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/27.git
-setup: worktree: $TRASH_DIRECTORY/27
-setup: cwd: $TRASH_DIRECTORY/27
-setup: prefix: (null)
-EOF
-       test_repo 27 "$TRASH_DIRECTORY/27/.git" .
-'
-
-test_expect_success '#27: GIT_DIR(rel), GIT_WORKTREE=root in subdir' '
-       cat >27/sub/sub/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/27.git
-setup: worktree: $TRASH_DIRECTORY/27
-setup: cwd: $TRASH_DIRECTORY/27
-setup: prefix: sub/sub/
-EOF
-       test_repo 27/sub/sub ../../.git "$TRASH_DIRECTORY/27"
-'
+       maybe_set GIT_DIR "$gitdirenv" &&
+       maybe_set GIT_WORK_TREE "$worktreeenv"
+}
 
-test_expect_success '#27: GIT_DIR(rel), GIT_WORKTREE=root(rel) in subdir' '
-       cat >27/sub/sub/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/27.git
-setup: worktree: $TRASH_DIRECTORY/27
-setup: cwd: $TRASH_DIRECTORY/27
-setup: prefix: sub/sub/
-EOF
-       test_repo 27/sub/sub ../../.git ../..
-'
+expect () {
+       cat >"$1/expected" <<-EOF
+       setup: git_dir: $2
+       setup: worktree: $3
+       setup: cwd: $4
+       setup: prefix: $5
+       EOF
+}
 
-test_expect_success '#27: GIT_DIR, GIT_WORKTREE=root in subdir' '
-       cat >27/sub/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/27.git
-setup: worktree: $TRASH_DIRECTORY/27
-setup: cwd: $TRASH_DIRECTORY/27
-setup: prefix: sub/
-EOF
-       test_repo 27/sub "$TRASH_DIRECTORY/27/.git" "$TRASH_DIRECTORY/27"
-'
+try_case () {
+       name=$1 worktreeenv=$2 gitdirenv=$3 &&
+       setup_env "$worktreeenv" "$gitdirenv" &&
+       expect "$name" "$4" "$5" "$6" "$7" &&
+       test_repo "$name"
+}
 
-test_expect_success '#27: GIT_DIR, GIT_WORKTREE=root(rel) in subdir' '
-       cat >27/sub/sub/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/27.git
-setup: worktree: $TRASH_DIRECTORY/27
-setup: cwd: $TRASH_DIRECTORY/27
-setup: prefix: sub/sub/
-EOF
-       test_repo 27/sub/sub "$TRASH_DIRECTORY/27/.git" ../..
-'
+run_wt_tests () {
+       N=$1 gitfile=$2
+
+       absgit="$here/$N/.git"
+       dotgit=.git
+       dotdotgit=../../.git
+
+       if test "$gitfile"
+       then
+               absgit="$here/$N.git"
+               dotgit=$absgit dotdotgit=$absgit
+       fi
+
+       test_expect_success "#$N: explicit GIT_WORK_TREE and GIT_DIR at toplevel" '
+               try_case $N "$here/$N" .git \
+                       "$dotgit" "$here/$N" "$here/$N" "(null)" &&
+               try_case $N . .git \
+                       "$dotgit" "$here/$N" "$here/$N" "(null)" &&
+               try_case $N "$here/$N" "$here/$N/.git" \
+                       "$absgit" "$here/$N" "$here/$N" "(null)" &&
+               try_case $N . "$here/$N/.git" \
+                       "$absgit" "$here/$N" "$here/$N" "(null)"
+       '
+
+       test_expect_success "#$N: explicit GIT_WORK_TREE and GIT_DIR in subdir" '
+               try_case $N/sub/sub "$here/$N" ../../.git \
+                       "$absgit" "$here/$N" "$here/$N" sub/sub/ &&
+               try_case $N/sub/sub ../.. ../../.git \
+                       "$absgit" "$here/$N" "$here/$N" sub/sub/ &&
+               try_case $N/sub/sub "$here/$N" "$here/$N/.git" \
+                       "$absgit" "$here/$N" "$here/$N" sub/sub/ &&
+               try_case $N/sub/sub ../.. "$here/$N/.git" \
+                       "$absgit" "$here/$N" "$here/$N" sub/sub/
+       '
+
+       test_expect_success "#$N: explicit GIT_WORK_TREE from parent of worktree" '
+               try_case $N "$here/$N/wt" .git \
+                       "$dotgit" "$here/$N/wt" "$here/$N" "(null)" &&
+               try_case $N wt .git \
+                       "$dotgit" "$here/$N/wt" "$here/$N" "(null)" &&
+               try_case $N wt "$here/$N/.git" \
+                       "$absgit" "$here/$N/wt" "$here/$N" "(null)" &&
+               try_case $N "$here/$N/wt" "$here/$N/.git" \
+                       "$absgit" "$here/$N/wt" "$here/$N" "(null)"
+       '
+
+       test_expect_success "#$N: explicit GIT_WORK_TREE from nephew of worktree" '
+               try_case $N/sub/sub "$here/$N/wt" ../../.git \
+                       "$dotdotgit" "$here/$N/wt" "$here/$N/sub/sub" "(null)" &&
+               try_case $N/sub/sub ../../wt ../../.git \
+                       "$dotdotgit" "$here/$N/wt" "$here/$N/sub/sub" "(null)" &&
+               try_case $N/sub/sub ../../wt "$here/$N/.git" \
+                       "$absgit" "$here/$N/wt" "$here/$N/sub/sub" "(null)" &&
+               try_case $N/sub/sub "$here/$N/wt" "$here/$N/.git" \
+                       "$absgit" "$here/$N/wt" "$here/$N/sub/sub" "(null)"
+       '
+
+       test_expect_success "#$N: chdir_to_toplevel uses worktree, not git dir" '
+               try_case $N "$here" .git \
+                       "$absgit" "$here" "$here" $N/ &&
+               try_case $N .. .git \
+                       "$absgit" "$here" "$here" $N/ &&
+               try_case $N .. "$here/$N/.git" \
+                       "$absgit" "$here" "$here" $N/ &&
+               try_case $N "$here" "$here/$N/.git" \
+                       "$absgit" "$here" "$here" $N/
+       '
+
+       test_expect_success "#$N: chdir_to_toplevel uses worktree (from subdir)" '
+               try_case $N/sub/sub "$here" ../../.git \
+                       "$absgit" "$here" "$here" $N/sub/sub/ &&
+               try_case $N/sub/sub ../../.. ../../.git \
+                       "$absgit" "$here" "$here" $N/sub/sub/ &&
+               try_case $N/sub/sub ../../../ "$here/$N/.git" \
+                       "$absgit" "$here" "$here" $N/sub/sub/ &&
+               try_case $N/sub/sub "$here" "$here/$N/.git" \
+                       "$absgit" "$here" "$here" $N/sub/sub/
+       '
+}
 
-test_expect_success '#27: GIT_DIR(rel), GIT_WORK_TREE=wt at root' '
-       cat >27/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/27.git
-setup: worktree: $TRASH_DIRECTORY/27/wt
-setup: cwd: $TRASH_DIRECTORY/27
-setup: prefix: (null)
-EOF
-       test_repo 27 .git "$TRASH_DIRECTORY/27/wt"
-'
+# try_repo #c GIT_WORK_TREE GIT_DIR core.worktree .gitfile? core.bare \
+#      (git dir) (work tree) (cwd) (prefix) \  <-- at toplevel
+#      (git dir) (work tree) (cwd) (prefix)    <-- from subdir
+try_repo () {
+       name=$1 worktreeenv=$2 gitdirenv=$3 &&
+       setup_repo "$name" "$4" "$5" "$6" &&
+       shift 6 &&
+       try_case "$name" "$worktreeenv" "$gitdirenv" \
+               "$1" "$2" "$3" "$4" &&
+       shift 4 &&
+       case "$gitdirenv" in
+       /* | ?:/* | unset) ;;
+       *)
+               gitdirenv=../$gitdirenv ;;
+       esac &&
+       try_case "$name/sub" "$worktreeenv" "$gitdirenv" \
+               "$1" "$2" "$3" "$4"
+}
 
-test_expect_success '#27: GIT_DIR(rel), GIT_WORK_TREE=wt(rel) at root' '
-       cat >27/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/27.git
-setup: worktree: $TRASH_DIRECTORY/27/wt
-setup: cwd: $TRASH_DIRECTORY/27
-setup: prefix: (null)
-EOF
-       test_repo 27 .git wt
-'
+# Bit 0 = GIT_WORK_TREE
+# Bit 1 = GIT_DIR
+# Bit 2 = core.worktree
+# Bit 3 = .git is a file
+# Bit 4 = bare repo
+# Case# = encoding of the above 5 bits
 
-test_expect_success '#27: GIT_DIR, GIT_WORK_TREE=wt(rel) at root' '
-       cat >27/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/27.git
-setup: worktree: $TRASH_DIRECTORY/27/wt
-setup: cwd: $TRASH_DIRECTORY/27
-setup: prefix: (null)
-EOF
-       test_repo 27 "$TRASH_DIRECTORY/27/.git" wt
+test_expect_success '#0: nonbare repo, no explicit configuration' '
+       try_repo 0 unset unset unset "" unset \
+               .git "$here/0" "$here/0" "(null)" \
+               .git "$here/0" "$here/0" sub/ 2>message &&
+       ! test -s message
 '
 
-test_expect_success '#27: GIT_DIR, GIT_WORK_TREE=wt at root' '
-       cat >27/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/27.git
-setup: worktree: $TRASH_DIRECTORY/27/wt
-setup: cwd: $TRASH_DIRECTORY/27
-setup: prefix: (null)
-EOF
-       test_repo 27 "$TRASH_DIRECTORY/27/.git" "$TRASH_DIRECTORY/27/wt"
+test_expect_success '#1: GIT_WORK_TREE without explicit GIT_DIR is accepted' '
+       mkdir -p wt &&
+       try_repo 1 "$here" unset unset "" unset \
+               "$here/1/.git" "$here" "$here" 1/ \
+               "$here/1/.git" "$here" "$here" 1/sub/ 2>message &&
+       ! test -s message
 '
 
-test_expect_success '#27: GIT_DIR(rel), GIT_WORK_TREE=wt in subdir' '
-       cat >27/sub/sub/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/27.git
-setup: worktree: $TRASH_DIRECTORY/27/wt
-setup: cwd: $TRASH_DIRECTORY/27/sub/sub
-setup: prefix: (null)
-EOF
-       test_repo 27/sub/sub ../../.git "$TRASH_DIRECTORY/27/wt"
+test_expect_success '#2: worktree defaults to cwd with explicit GIT_DIR' '
+       try_repo 2 unset "$here/2/.git" unset "" unset \
+               "$here/2/.git" "$here/2" "$here/2" "(null)" \
+               "$here/2/.git" "$here/2/sub" "$here/2/sub" "(null)"
 '
 
-test_expect_success '#27: GIT_DIR(rel), GIT_WORK_TREE=wt(rel) in subdir' '
-       cat >27/sub/sub/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/27.git
-setup: worktree: $TRASH_DIRECTORY/27/wt
-setup: cwd: $TRASH_DIRECTORY/27/sub/sub
-setup: prefix: (null)
-EOF
-       test_repo 27/sub/sub ../../.git ../../wt
+test_expect_success '#2b: relative GIT_DIR' '
+       try_repo 2b unset ".git" unset "" unset \
+               ".git" "$here/2b" "$here/2b" "(null)" \
+               "../.git" "$here/2b/sub" "$here/2b/sub" "(null)"
 '
 
-test_expect_success '#27: GIT_DIR, GIT_WORK_TREE=wt(rel) in subdir' '
-       cat >27/sub/sub/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/27.git
-setup: worktree: $TRASH_DIRECTORY/27/wt
-setup: cwd: $TRASH_DIRECTORY/27/sub/sub
-setup: prefix: (null)
-EOF
-       test_repo 27/sub/sub "$TRASH_DIRECTORY/27/.git" ../../wt
+test_expect_success '#3: setup' '
+       setup_repo 3 unset "" unset &&
+       mkdir -p 3/sub/sub 3/wt/sub
+'
+run_wt_tests 3
+
+test_expect_success '#4: core.worktree without GIT_DIR set is accepted' '
+       setup_repo 4 ../sub "" unset &&
+       mkdir -p 4/sub sub &&
+       try_case 4 unset unset \
+               .git "$here/4/sub" "$here/4" "(null)" \
+               "$here/4/.git" "$here/4/sub" "$here/4/sub" "(null)" 2>message &&
+       ! test -s message
+'
+
+test_expect_success '#5: core.worktree + GIT_WORK_TREE is accepted' '
+       # or: you cannot intimidate away the lack of GIT_DIR setting
+       try_repo 5 "$here" unset "$here/5" "" unset \
+               "$here/5/.git" "$here" "$here" 5/ \
+               "$here/5/.git" "$here" "$here" 5/sub/ 2>message &&
+       try_repo 5a .. unset "$here/5a" "" unset \
+               "$here/5a/.git" "$here" "$here" 5a/ \
+               "$here/5a/.git" "$here/5a" "$here/5a" sub/ &&
+       ! test -s message
+'
+
+test_expect_success '#6: setting GIT_DIR brings core.worktree to life' '
+       setup_repo 6 "$here/6" "" unset &&
+       try_case 6 unset .git \
+               .git "$here/6" "$here/6" "(null)" &&
+       try_case 6 unset "$here/6/.git" \
+               "$here/6/.git" "$here/6" "$here/6" "(null)" &&
+       try_case 6/sub/sub unset ../../.git \
+               "$here/6/.git" "$here/6" "$here/6" sub/sub/ &&
+       try_case 6/sub/sub unset "$here/6/.git" \
+               "$here/6/.git" "$here/6" "$here/6" sub/sub/
+'
+
+test_expect_success '#6b: GIT_DIR set, core.worktree relative' '
+       setup_repo 6b .. "" unset &&
+       try_case 6b unset .git \
+               .git "$here/6b" "$here/6b" "(null)" &&
+       try_case 6b unset "$here/6b/.git" \
+               "$here/6b/.git" "$here/6b" "$here/6b" "(null)" &&
+       try_case 6b/sub/sub unset ../../.git \
+               "$here/6b/.git" "$here/6b" "$here/6b" sub/sub/ &&
+       try_case 6b/sub/sub unset "$here/6b/.git" \
+               "$here/6b/.git" "$here/6b" "$here/6b" sub/sub/
+'
+
+test_expect_success '#6c: GIT_DIR set, core.worktree=../wt (absolute)' '
+       setup_repo 6c "$here/6c/wt" "" unset &&
+       mkdir -p 6c/wt/sub &&
+
+       try_case 6c unset .git \
+               .git "$here/6c/wt" "$here/6c" "(null)" &&
+       try_case 6c unset "$here/6c/.git" \
+               "$here/6c/.git" "$here/6c/wt" "$here/6c" "(null)" &&
+       try_case 6c/sub/sub unset ../../.git \
+               ../../.git "$here/6c/wt" "$here/6c/sub/sub" "(null)" &&
+       try_case 6c/sub/sub unset "$here/6c/.git" \
+               "$here/6c/.git" "$here/6c/wt" "$here/6c/sub/sub" "(null)"
+'
+
+test_expect_success '#6d: GIT_DIR set, core.worktree=../wt (relative)' '
+       setup_repo 6d "$here/6d/wt" "" unset &&
+       mkdir -p 6d/wt/sub &&
+
+       try_case 6d unset .git \
+               .git "$here/6d/wt" "$here/6d" "(null)" &&
+       try_case 6d unset "$here/6d/.git" \
+               "$here/6d/.git" "$here/6d/wt" "$here/6d" "(null)" &&
+       try_case 6d/sub/sub unset ../../.git \
+               ../../.git "$here/6d/wt" "$here/6d/sub/sub" "(null)" &&
+       try_case 6d/sub/sub unset "$here/6d/.git" \
+               "$here/6d/.git" "$here/6d/wt" "$here/6d/sub/sub" "(null)"
+'
+
+test_expect_success '#6e: GIT_DIR set, core.worktree=../.. (absolute)' '
+       setup_repo 6e "$here" "" unset &&
+       try_case 6e unset .git \
+               "$here/6e/.git" "$here" "$here" 6e/ &&
+       try_case 6e unset "$here/6e/.git" \
+               "$here/6e/.git" "$here" "$here" 6e/ &&
+       try_case 6e/sub/sub unset ../../.git \
+               "$here/6e/.git" "$here" "$here" 6e/sub/sub/ &&
+       try_case 6e/sub/sub unset "$here/6e/.git" \
+               "$here/6e/.git" "$here" "$here" 6e/sub/sub/
+'
+
+test_expect_success '#6f: GIT_DIR set, core.worktree=../.. (relative)' '
+       setup_repo 6f ../../ "" unset &&
+       try_case 6f unset .git \
+               "$here/6f/.git" "$here" "$here" 6f/ &&
+       try_case 6f unset "$here/6f/.git" \
+               "$here/6f/.git" "$here" "$here" 6f/ &&
+       try_case 6f/sub/sub unset ../../.git \
+               "$here/6f/.git" "$here" "$here" 6f/sub/sub/ &&
+       try_case 6f/sub/sub unset "$here/6f/.git" \
+               "$here/6f/.git" "$here" "$here" 6f/sub/sub/
+'
+
+# case #7: GIT_WORK_TREE overrides core.worktree.
+test_expect_success '#7: setup' '
+       setup_repo 7 non-existent "" unset &&
+       mkdir -p 7/sub/sub 7/wt/sub
 '
+run_wt_tests 7
 
-test_expect_success '#27: GIT_DIR, GIT_WORK_TREE=wt in subdir' '
-       cat >27/sub/sub/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/27.git
-setup: worktree: $TRASH_DIRECTORY/27/wt
-setup: cwd: $TRASH_DIRECTORY/27/sub/sub
-setup: prefix: (null)
-EOF
-       test_repo 27/sub/sub "$TRASH_DIRECTORY/27/.git" "$TRASH_DIRECTORY/27/wt"
+test_expect_success '#8: gitfile, easy case' '
+       try_repo 8 unset unset unset gitfile unset \
+               "$here/8.git" "$here/8" "$here/8" "(null)" \
+               "$here/8.git" "$here/8" "$here/8" sub/
 '
 
-test_expect_success '#27: GIT_DIR(rel), GIT_WORK_TREE=.. at root' '
-       cat >27/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/27.git
-setup: worktree: $TRASH_DIRECTORY
-setup: cwd: $TRASH_DIRECTORY
-setup: prefix: 27/
-EOF
-       test_repo 27 .git "$TRASH_DIRECTORY"
+test_expect_success '#9: GIT_WORK_TREE accepted with gitfile' '
+       mkdir -p 9/wt &&
+       try_repo 9 wt unset unset gitfile unset \
+               "$here/9.git" "$here/9/wt" "$here/9" "(null)" \
+               "$here/9.git" "$here/9/sub/wt" "$here/9/sub" "(null)" 2>message &&
+       ! test -s message
 '
 
-test_expect_success '#27: GIT_DIR(rel), GIT_WORK_TREE=..(rel) at root' '
-       cat >27/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/27.git
-setup: worktree: $TRASH_DIRECTORY
-setup: cwd: $TRASH_DIRECTORY
-setup: prefix: 27/
-EOF
-       test_repo 27 .git ..
+test_expect_success '#10: GIT_DIR can point to gitfile' '
+       try_repo 10 unset "$here/10/.git" unset gitfile unset \
+               "$here/10.git" "$here/10" "$here/10" "(null)" \
+               "$here/10.git" "$here/10/sub" "$here/10/sub" "(null)"
 '
 
-test_expect_success '#27: GIT_DIR, GIT_WORK_TREE=..(rel) at root' '
-       cat >27/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/27.git
-setup: worktree: $TRASH_DIRECTORY
-setup: cwd: $TRASH_DIRECTORY
-setup: prefix: 27/
-EOF
-       test_repo 27 "$TRASH_DIRECTORY/27/.git" ..
+test_expect_success '#10b: relative GIT_DIR can point to gitfile' '
+       try_repo 10b unset .git unset gitfile unset \
+               "$here/10b.git" "$here/10b" "$here/10b" "(null)" \
+               "$here/10b.git" "$here/10b/sub" "$here/10b/sub" "(null)"
 '
 
-test_expect_success '#27: GIT_DIR, GIT_WORK_TREE=.. at root' '
-       cat >27/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/27.git
-setup: worktree: $TRASH_DIRECTORY
-setup: cwd: $TRASH_DIRECTORY
-setup: prefix: 27/
-EOF
-       test_repo 27 "$TRASH_DIRECTORY/27/.git" "$TRASH_DIRECTORY"
+# case #11: GIT_WORK_TREE works, gitfile case.
+test_expect_success '#11: setup' '
+       setup_repo 11 unset gitfile unset &&
+       mkdir -p 11/sub/sub 11/wt/sub
+'
+run_wt_tests 11 gitfile
+
+test_expect_success '#12: core.worktree with gitfile is accepted' '
+       try_repo 12 unset unset "$here/12" gitfile unset \
+               "$here/12.git" "$here/12" "$here/12" "(null)" \
+               "$here/12.git" "$here/12" "$here/12" sub/ 2>message &&
+       ! test -s message
+'
+
+test_expect_success '#13: core.worktree+GIT_WORK_TREE accepted (with gitfile)' '
+       # or: you cannot intimidate away the lack of GIT_DIR setting
+       try_repo 13 non-existent-too unset non-existent gitfile unset \
+               "$here/13.git" "$here/13/non-existent-too" "$here/13" "(null)" \
+               "$here/13.git" "$here/13/sub/non-existent-too" "$here/13/sub" "(null)" 2>message &&
+       ! test -s message
+'
+
+# case #14.
+# If this were more table-driven, it could share code with case #6.
+
+test_expect_success '#14: core.worktree with GIT_DIR pointing to gitfile' '
+       setup_repo 14 "$here/14" gitfile unset &&
+       try_case 14 unset .git \
+               "$here/14.git" "$here/14" "$here/14" "(null)" &&
+       try_case 14 unset "$here/14/.git" \
+               "$here/14.git" "$here/14" "$here/14" "(null)" &&
+       try_case 14/sub/sub unset ../../.git \
+               "$here/14.git" "$here/14" "$here/14" sub/sub/ &&
+       try_case 14/sub/sub unset "$here/14/.git" \
+               "$here/14.git" "$here/14" "$here/14" sub/sub/ &&
+
+       setup_repo 14c "$here/14c/wt" gitfile unset &&
+       mkdir -p 14c/wt/sub &&
+
+       try_case 14c unset .git \
+               "$here/14c.git" "$here/14c/wt" "$here/14c" "(null)" &&
+       try_case 14c unset "$here/14c/.git" \
+               "$here/14c.git" "$here/14c/wt" "$here/14c" "(null)" &&
+       try_case 14c/sub/sub unset ../../.git \
+               "$here/14c.git" "$here/14c/wt" "$here/14c/sub/sub" "(null)" &&
+       try_case 14c/sub/sub unset "$here/14c/.git" \
+               "$here/14c.git" "$here/14c/wt" "$here/14c/sub/sub" "(null)" &&
+
+       setup_repo 14d "$here/14d/wt" gitfile unset &&
+       mkdir -p 14d/wt/sub &&
+
+       try_case 14d unset .git \
+               "$here/14d.git" "$here/14d/wt" "$here/14d" "(null)" &&
+       try_case 14d unset "$here/14d/.git" \
+               "$here/14d.git" "$here/14d/wt" "$here/14d" "(null)" &&
+       try_case 14d/sub/sub unset ../../.git \
+               "$here/14d.git" "$here/14d/wt" "$here/14d/sub/sub" "(null)" &&
+       try_case 14d/sub/sub unset "$here/14d/.git" \
+               "$here/14d.git" "$here/14d/wt" "$here/14d/sub/sub" "(null)" &&
+
+       setup_repo 14e "$here" gitfile unset &&
+       try_case 14e unset .git \
+               "$here/14e.git" "$here" "$here" 14e/ &&
+       try_case 14e unset "$here/14e/.git" \
+               "$here/14e.git" "$here" "$here" 14e/ &&
+       try_case 14e/sub/sub unset ../../.git \
+               "$here/14e.git" "$here" "$here" 14e/sub/sub/ &&
+       try_case 14e/sub/sub unset "$here/14e/.git" \
+               "$here/14e.git" "$here" "$here" 14e/sub/sub/
+'
+
+test_expect_success '#14b: core.worktree is relative to actual git dir' '
+       setup_repo 14b ../14b gitfile unset &&
+       try_case 14b unset .git \
+               "$here/14b.git" "$here/14b" "$here/14b" "(null)" &&
+       try_case 14b unset "$here/14b/.git" \
+               "$here/14b.git" "$here/14b" "$here/14b" "(null)" &&
+       try_case 14b/sub/sub unset ../../.git \
+               "$here/14b.git" "$here/14b" "$here/14b" sub/sub/ &&
+       try_case 14b/sub/sub unset "$here/14b/.git" \
+               "$here/14b.git" "$here/14b" "$here/14b" sub/sub/ &&
+
+       setup_repo 14f ../ gitfile unset &&
+       try_case 14f unset .git \
+               "$here/14f.git" "$here" "$here" 14f/ &&
+       try_case 14f unset "$here/14f/.git" \
+               "$here/14f.git" "$here" "$here" 14f/ &&
+       try_case 14f/sub/sub unset ../../.git \
+               "$here/14f.git" "$here" "$here" 14f/sub/sub/ &&
+       try_case 14f/sub/sub unset "$here/14f/.git" \
+               "$here/14f.git" "$here" "$here" 14f/sub/sub/
+'
+
+# case #15: GIT_WORK_TREE overrides core.worktree (gitfile case).
+test_expect_success '#15: setup' '
+       setup_repo 15 non-existent gitfile unset &&
+       mkdir -p 15/sub/sub 15/wt/sub
+'
+run_wt_tests 15 gitfile
+
+test_expect_success '#16a: implicitly bare repo (cwd inside .git dir)' '
+       setup_repo 16a unset "" unset &&
+       mkdir -p 16a/.git/wt/sub &&
+
+       try_case 16a/.git unset unset \
+               . "(null)" "$here/16a/.git" "(null)" &&
+       try_case 16a/.git/wt unset unset \
+               "$here/16a/.git" "(null)" "$here/16a/.git/wt" "(null)" &&
+       try_case 16a/.git/wt/sub unset unset \
+               "$here/16a/.git" "(null)" "$here/16a/.git/wt/sub" "(null)"
+'
+
+test_expect_success '#16b: bare .git (cwd inside .git dir)' '
+       setup_repo 16b unset "" true &&
+       mkdir -p 16b/.git/wt/sub &&
+
+       try_case 16b/.git unset unset \
+               . "(null)" "$here/16b/.git" "(null)" &&
+       try_case 16b/.git/wt unset unset \
+               "$here/16b/.git" "(null)" "$here/16b/.git/wt" "(null)" &&
+       try_case 16b/.git/wt/sub unset unset \
+               "$here/16b/.git" "(null)" "$here/16b/.git/wt/sub" "(null)"
+'
+
+test_expect_success '#16c: bare .git has no worktree' '
+       try_repo 16c unset unset unset "" true \
+               .git "(null)" "$here/16c" "(null)" \
+               "$here/16c/.git" "(null)" "$here/16c/sub" "(null)"
+'
+
+test_expect_success '#17: GIT_WORK_TREE without explicit GIT_DIR is accepted (bare case)' '
+       # Just like #16.
+       setup_repo 17a unset "" true &&
+       setup_repo 17b unset "" true &&
+       mkdir -p 17a/.git/wt/sub &&
+       mkdir -p 17b/.git/wt/sub &&
+
+       try_case 17a/.git "$here/17a" unset \
+               "$here/17a/.git" "$here/17a" "$here/17a" .git/ \
+               2>message &&
+       try_case 17a/.git/wt "$here/17a" unset \
+               "$here/17a/.git" "$here/17a" "$here/17a" .git/wt/ &&
+       try_case 17a/.git/wt/sub "$here/17a" unset \
+               "$here/17a/.git" "$here/17a" "$here/17a" .git/wt/sub/ &&
+
+       try_case 17b/.git "$here/17b" unset \
+               "$here/17b/.git" "$here/17b" "$here/17b" .git/ &&
+       try_case 17b/.git/wt "$here/17b" unset \
+               "$here/17b/.git" "$here/17b" "$here/17b" .git/wt/ &&
+       try_case 17b/.git/wt/sub "$here/17b" unset \
+               "$here/17b/.git" "$here/17b" "$here/17b" .git/wt/sub/ &&
+
+       try_repo 17c "$here/17c" unset unset "" true \
+               .git "$here/17c" "$here/17c" "(null)" \
+               "$here/17c/.git" "$here/17c" "$here/17c" sub/ 2>message &&
+       ! test -s message
+'
+
+test_expect_success '#18: bare .git named by GIT_DIR has no worktree' '
+       try_repo 18 unset .git unset "" true \
+               .git "(null)" "$here/18" "(null)" \
+               ../.git "(null)" "$here/18/sub" "(null)" &&
+       try_repo 18b unset "$here/18b/.git" unset "" true \
+               "$here/18b/.git" "(null)" "$here/18b" "(null)" \
+               "$here/18b/.git" "(null)" "$here/18b/sub" "(null)"
+'
+
+# Case #19: GIT_DIR + GIT_WORK_TREE suppresses bareness.
+test_expect_success '#19: setup' '
+       setup_repo 19 unset "" true &&
+       mkdir -p 19/sub/sub 19/wt/sub
+'
+run_wt_tests 19
+
+test_expect_success '#20a: core.worktree without GIT_DIR accepted (inside .git)' '
+       # Unlike case #16a.
+       setup_repo 20a "$here/20a" "" unset &&
+       mkdir -p 20a/.git/wt/sub &&
+       try_case 20a/.git unset unset \
+               "$here/20a/.git" "$here/20a" "$here/20a" .git/ 2>message &&
+       try_case 20a/.git/wt unset unset \
+               "$here/20a/.git" "$here/20a" "$here/20a" .git/wt/ &&
+       try_case 20a/.git/wt/sub unset unset \
+               "$here/20a/.git" "$here/20a" "$here/20a" .git/wt/sub/ &&
+       ! test -s message
+'
+
+test_expect_success '#20b/c: core.worktree and core.bare conflict' '
+       setup_repo 20b non-existent "" true &&
+       mkdir -p 20b/.git/wt/sub &&
+       (
+               cd 20b/.git &&
+               test_must_fail git symbolic-ref HEAD >/dev/null
+       ) 2>message &&
+       grep "core.bare and core.worktree" message
 '
 
-test_expect_success '#27: GIT_DIR(rel), GIT_WORK_TREE=.. in subdir' '
-       cat >27/sub/sub/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/27.git
-setup: worktree: $TRASH_DIRECTORY
-setup: cwd: $TRASH_DIRECTORY
-setup: prefix: 27/sub/sub/
-EOF
-       test_repo 27/sub/sub ../../.git "$TRASH_DIRECTORY"
+# Case #21: core.worktree/GIT_WORK_TREE overrides core.bare' '
+test_expect_success '#21: setup, core.worktree warns before overriding core.bare' '
+       setup_repo 21 non-existent "" unset &&
+       mkdir -p 21/.git/wt/sub &&
+       (
+               cd 21/.git &&
+               GIT_WORK_TREE="$here/21" &&
+               export GIT_WORK_TREE &&
+               git symbolic-ref HEAD >/dev/null
+       ) 2>message &&
+       ! test -s message
+
+'
+run_wt_tests 21
+
+test_expect_success '#22a: core.worktree = GIT_DIR = .git dir' '
+       # like case #6.
+
+       setup_repo 22a "$here/22a/.git" "" unset &&
+       setup_repo 22ab . "" unset
+       mkdir -p 22a/.git/sub 22a/sub &&
+       mkdir -p 22ab/.git/sub 22ab/sub &&
+       try_case 22a/.git unset . \
+               . "$here/22a/.git" "$here/22a/.git" "(null)" &&
+       try_case 22a/.git unset "$here/22a/.git" \
+               "$here/22a/.git" "$here/22a/.git" "$here/22a/.git" "(null)" &&
+       try_case 22a/.git/sub unset .. \
+               "$here/22a/.git" "$here/22a/.git" "$here/22a/.git" sub/ &&
+       try_case 22a/.git/sub unset "$here/22a/.git" \
+               "$here/22a/.git" "$here/22a/.git" "$here/22a/.git" sub/ &&
+
+       try_case 22ab/.git unset . \
+               . "$here/22ab/.git" "$here/22ab/.git" "(null)" &&
+       try_case 22ab/.git unset "$here/22ab/.git" \
+               "$here/22ab/.git" "$here/22ab/.git" "$here/22ab/.git" "(null)" &&
+       try_case 22ab/.git/sub unset .. \
+               "$here/22ab/.git" "$here/22ab/.git" "$here/22ab/.git" sub/ &&
+       try_case 22ab/.git unset "$here/22ab/.git" \
+               "$here/22ab/.git" "$here/22ab/.git" "$here/22ab/.git" "(null)"
+'
+
+test_expect_success '#22b: core.worktree child of .git, GIT_DIR=.git' '
+       setup_repo 22b "$here/22b/.git/wt" "" unset &&
+       setup_repo 22bb wt "" unset &&
+       mkdir -p 22b/.git/sub 22b/sub 22b/.git/wt/sub 22b/wt/sub &&
+       mkdir -p 22bb/.git/sub 22bb/sub 22bb/.git/wt 22bb/wt &&
+
+       try_case 22b/.git unset . \
+               . "$here/22b/.git/wt" "$here/22b/.git" "(null)" &&
+       try_case 22b/.git unset "$here/22b/.git" \
+               "$here/22b/.git" "$here/22b/.git/wt" "$here/22b/.git" "(null)" &&
+       try_case 22b/.git/sub unset .. \
+               .. "$here/22b/.git/wt" "$here/22b/.git/sub" "(null)" &&
+       try_case 22b/.git/sub unset "$here/22b/.git" \
+               "$here/22b/.git" "$here/22b/.git/wt" "$here/22b/.git/sub" "(null)" &&
+
+       try_case 22bb/.git unset . \
+               . "$here/22bb/.git/wt" "$here/22bb/.git" "(null)" &&
+       try_case 22bb/.git unset "$here/22bb/.git" \
+               "$here/22bb/.git" "$here/22bb/.git/wt" "$here/22bb/.git" "(null)" &&
+       try_case 22bb/.git/sub unset .. \
+               .. "$here/22bb/.git/wt" "$here/22bb/.git/sub" "(null)" &&
+       try_case 22bb/.git/sub unset "$here/22bb/.git" \
+               "$here/22bb/.git" "$here/22bb/.git/wt" "$here/22bb/.git/sub" "(null)"
+'
+
+test_expect_success '#22c: core.worktree = .git/.., GIT_DIR=.git' '
+       setup_repo 22c "$here/22c" "" unset &&
+       setup_repo 22cb .. "" unset &&
+       mkdir -p 22c/.git/sub 22c/sub &&
+       mkdir -p 22cb/.git/sub 22cb/sub &&
+
+       try_case 22c/.git unset . \
+               "$here/22c/.git" "$here/22c" "$here/22c" .git/ &&
+       try_case 22c/.git unset "$here/22c/.git" \
+               "$here/22c/.git" "$here/22c" "$here/22c" .git/ &&
+       try_case 22c/.git/sub unset .. \
+               "$here/22c/.git" "$here/22c" "$here/22c" .git/sub/ &&
+       try_case 22c/.git/sub unset "$here/22c/.git" \
+               "$here/22c/.git" "$here/22c" "$here/22c" .git/sub/ &&
+
+       try_case 22cb/.git unset . \
+               "$here/22cb/.git" "$here/22cb" "$here/22cb" .git/ &&
+       try_case 22cb/.git unset "$here/22cb/.git" \
+               "$here/22cb/.git" "$here/22cb" "$here/22cb" .git/ &&
+       try_case 22cb/.git/sub unset .. \
+               "$here/22cb/.git" "$here/22cb" "$here/22cb" .git/sub/ &&
+       try_case 22cb/.git/sub unset "$here/22cb/.git" \
+               "$here/22cb/.git" "$here/22cb" "$here/22cb" .git/sub/
+'
+
+test_expect_success '#22.2: core.worktree and core.bare conflict' '
+       setup_repo 22 "$here/22" "" true &&
+       (
+               cd 22/.git &&
+               GIT_DIR=. &&
+               export GIT_DIR &&
+               test_must_fail git symbolic-ref HEAD 2>result
+       ) &&
+       (
+               cd 22 &&
+               GIT_DIR=.git &&
+               export GIT_DIR &&
+               test_must_fail git symbolic-ref HEAD 2>result
+       ) &&
+       grep "core.bare and core.worktree" 22/.git/result &&
+       grep "core.bare and core.worktree" 22/result
 '
 
-test_expect_success '#27: GIT_DIR(rel), GIT_WORK_TREE=..(rel) in subdir' '
-       cat >27/sub/sub/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/27.git
-setup: worktree: $TRASH_DIRECTORY
-setup: cwd: $TRASH_DIRECTORY
-setup: prefix: 27/sub/sub/
-EOF
-       test_repo 27/sub/sub ../../.git ../../..
+# Case #23: GIT_DIR + GIT_WORK_TREE(+core.worktree) suppresses bareness.
+test_expect_success '#23: setup' '
+       setup_repo 23 non-existent "" true &&
+       mkdir -p 23/sub/sub 23/wt/sub
 '
+run_wt_tests 23
 
-test_expect_success '#27: GIT_DIR, GIT_WORK_TREE=..(rel) in subdir' '
-       cat >27/sub/sub/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/27.git
-setup: worktree: $TRASH_DIRECTORY
-setup: cwd: $TRASH_DIRECTORY
-setup: prefix: 27/sub/sub/
-EOF
-       test_repo 27/sub/sub "$TRASH_DIRECTORY/27/.git" ../../../
+test_expect_success '#24: bare repo has no worktree (gitfile case)' '
+       try_repo 24 unset unset unset gitfile true \
+               "$here/24.git" "(null)" "$here/24" "(null)" \
+               "$here/24.git" "(null)" "$here/24/sub" "(null)"
 '
 
-test_expect_success '#27: GIT_DIR, GIT_WORK_TREE=.. in subdir' '
-       cat >27/sub/sub/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/27.git
-setup: worktree: $TRASH_DIRECTORY
-setup: cwd: $TRASH_DIRECTORY
-setup: prefix: 27/sub/sub/
-EOF
-       test_repo 27/sub/sub "$TRASH_DIRECTORY/27/.git" "$TRASH_DIRECTORY"
+test_expect_success '#25: GIT_WORK_TREE accepted if GIT_DIR unset (bare gitfile case)' '
+       try_repo 25 "$here/25" unset unset gitfile true \
+               "$here/25.git" "$here/25" "$here/25" "(null)"  \
+               "$here/25.git" "$here/25" "$here/25" "sub/" 2>message &&
+       ! test -s message
 '
 
-#
-# case #28
-#
-############################################################
-#
-# Input:
-#
-#  - GIT_WORK_TREE is not set
-#  - GIT_DIR is not set
-#  - core.worktree is set
-#  - .git is a file
-#  - core.bare is set
-#
-# Output:
-#
-# core.worktree is ignored -> #24
-
-test_expect_success '#28: setup' '
-       sane_unset GIT_DIR GIT_WORK_TREE &&
-       mkdir 28 28/sub &&
-       cd 28 &&
-       git init &&
-       git config core.bare true &&
-       git config core.worktree non-existent &&
-       mv .git ../28.git &&
-       echo gitdir: ../28.git >.git &&
-       cd ..
+test_expect_success '#26: bare repo has no worktree (GIT_DIR -> gitfile case)' '
+       try_repo 26 unset "$here/26/.git" unset gitfile true \
+               "$here/26.git" "(null)" "$here/26" "(null)" \
+               "$here/26.git" "(null)" "$here/26/sub" "(null)" &&
+       try_repo 26b unset .git unset gitfile true \
+               "$here/26b.git" "(null)" "$here/26b" "(null)" \
+               "$here/26b.git" "(null)" "$here/26b/sub" "(null)"
 '
 
-test_expect_success '#28: at root' '
-       cat >28/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/28.git
-setup: worktree: (null)
-setup: cwd: $TRASH_DIRECTORY/28
-setup: prefix: (null)
-EOF
-       test_repo 28
+# Case #27: GIT_DIR + GIT_WORK_TREE suppresses bareness (with gitfile).
+test_expect_success '#27: setup' '
+       setup_repo 27 unset gitfile true &&
+       mkdir -p 27/sub/sub 27/wt/sub
 '
+run_wt_tests 27 gitfile
 
-test_expect_success '#28: in subdir' '
-       cat >28/sub/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/28.git
-setup: worktree: (null)
-setup: cwd: $TRASH_DIRECTORY/28/sub
-setup: prefix: (null)
-EOF
-       test_repo 28/sub
+test_expect_success '#28: core.worktree and core.bare conflict (gitfile case)' '
+       setup_repo 28 "$here/28" gitfile true &&
+       (
+               cd 28 &&
+               test_must_fail git symbolic-ref HEAD
+       ) 2>message &&
+       ! grep "^warning:" message &&
+       grep "core.bare and core.worktree" message
 '
 
-#
-# case #29
-#
-############################################################
-#
-# Input:
-#
-#  - GIT_WORK_TREE is set
-#  - GIT_DIR is not set
-#  - core.worktree is set
-#  - .git is a file
-#  - core.bare is set
-#
-# Output:
-#
-# GIT_WORK_TREE/core.worktree are ignored -> #28
-
+# Case #29: GIT_WORK_TREE(+core.worktree) overrides core.bare (gitfile case).
 test_expect_success '#29: setup' '
-       sane_unset GIT_DIR GIT_WORK_TREE &&
-       mkdir 29 29/sub &&
-       cd 29 &&
-       git init &&
-       git config core.bare true &&
-       GIT_WORK_TREE=non-existent &&
-       export GIT_WORK_TREE &&
-       mv .git ../29.git &&
-       echo gitdir: ../29.git >.git &&
-       cd ..
-'
-
-test_expect_success '#29: at root' '
-       cat >29/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/29.git
-setup: worktree: (null)
-setup: cwd: $TRASH_DIRECTORY/29
-setup: prefix: (null)
-EOF
-       test_repo 29
-'
-
-test_expect_success '#29: in subdir' '
-       cat >29/sub/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/29.git
-setup: worktree: (null)
-setup: cwd: $TRASH_DIRECTORY/29/sub
-setup: prefix: (null)
-EOF
-       test_repo 29/sub
-'
-
-#
-# case #30
-#
-############################################################
-#
-# Input:
-#
-#  - GIT_WORK_TREE is not set
-#  - GIT_DIR is set
-#  - core.worktree is set
-#  - .git is a file
-#  - core.bare is set
-#
-# Output:
-#
-# core.worktree and core.bare conflict, won't fly.
-
-test_expect_success '#30: setup' '
-       sane_unset GIT_DIR GIT_WORK_TREE &&
-       mkdir 30 &&
-       cd 30 &&
-       git init &&
-       git config core.bare true &&
-       git config core.worktree non-existent &&
-       mv .git ../30.git &&
-       echo gitdir: ../30.git >.git &&
-       cd ..
-'
-
-test_expect_success '#30: at root' '
+       setup_repo 29 non-existent gitfile true &&
+       mkdir -p 29/sub/sub 29/wt/sub
        (
-       cd 30 &&
-       GIT_DIR=.git &&
-       export GIT_DIR &&
-       test_must_fail git symbolic-ref HEAD 2>result &&
-       grep "core.bare and core.worktree do not make sense" result
-       )
+               cd 29 &&
+               GIT_WORK_TREE="$here/29" &&
+               export GIT_WORK_TREE &&
+               git symbolic-ref HEAD >/dev/null
+       ) 2>message &&
+       ! test -s message
+'
+run_wt_tests 29 gitfile
+
+test_expect_success '#30: core.worktree and core.bare conflict (gitfile version)' '
+       # Just like case #22.
+       setup_repo 30 "$here/30" gitfile true &&
+       (
+               cd 30 &&
+               GIT_DIR=.git &&
+               export GIT_DIR &&
+               test_must_fail git symbolic-ref HEAD 2>result
+       ) &&
+       grep "core.bare and core.worktree" 30/result
 '
 
-#
-# case #31
-#
-############################################################
-#
-# Input:
-#
-#  - GIT_WORK_TREE is set
-#  - GIT_DIR is set
-#  - core.worktree is set
-#  - .git is a file
-#  - core.bare is set
-#
-# Output:
-#
-# #23 except git_dir is set according to .git file
-
+# Case #31: GIT_DIR + GIT_WORK_TREE(+core.worktree) suppresses
+# bareness (gitfile version).
 test_expect_success '#31: setup' '
-       sane_unset GIT_DIR GIT_WORK_TREE &&
-       mkdir 31 31/sub 31/sub/sub 31.wt 31.wt/sub 31/wt 31/wt/sub &&
-       cd 31 &&
-       git init &&
-       git config core.bare true &&
-       git config core.worktree non-existent &&
-       mv .git ../31.git &&
-       echo gitdir: ../31.git >.git &&
-       cd ..
-'
-
-test_expect_success '#31: GIT_DIR(rel), GIT_WORK_TREE=root at root' '
-       cat >31/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/31.git
-setup: worktree: $TRASH_DIRECTORY/31
-setup: cwd: $TRASH_DIRECTORY/31
-setup: prefix: (null)
-EOF
-       test_repo 31 .git "$TRASH_DIRECTORY/31"
-'
-
-test_expect_success '#31: GIT_DIR(rel), GIT_WORK_TREE=root(rel) at root' '
-       cat >31/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/31.git
-setup: worktree: $TRASH_DIRECTORY/31
-setup: cwd: $TRASH_DIRECTORY/31
-setup: prefix: (null)
-EOF
-       test_repo 31 .git .
-'
-
-test_expect_success '#31: GIT_DIR, GIT_WORK_TREE=root at root' '
-       cat >31/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/31.git
-setup: worktree: $TRASH_DIRECTORY/31
-setup: cwd: $TRASH_DIRECTORY/31
-setup: prefix: (null)
-EOF
-       test_repo 31 "$TRASH_DIRECTORY/31/.git" "$TRASH_DIRECTORY/31"
-'
-
-test_expect_success '#31: GIT_DIR, GIT_WORK_TREE=root(rel) at root' '
-       cat >31/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/31.git
-setup: worktree: $TRASH_DIRECTORY/31
-setup: cwd: $TRASH_DIRECTORY/31
-setup: prefix: (null)
-EOF
-       test_repo 31 "$TRASH_DIRECTORY/31/.git" .
-'
-
-test_expect_success '#31: GIT_DIR(rel), GIT_WORKTREE=root in subdir' '
-       cat >31/sub/sub/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/31.git
-setup: worktree: $TRASH_DIRECTORY/31
-setup: cwd: $TRASH_DIRECTORY/31
-setup: prefix: sub/sub/
-EOF
-       test_repo 31/sub/sub ../../.git "$TRASH_DIRECTORY/31"
-'
-
-test_expect_success '#31: GIT_DIR(rel), GIT_WORKTREE=root(rel) in subdir' '
-       cat >31/sub/sub/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/31.git
-setup: worktree: $TRASH_DIRECTORY/31
-setup: cwd: $TRASH_DIRECTORY/31
-setup: prefix: sub/sub/
-EOF
-       test_repo 31/sub/sub ../../.git ../..
-'
-
-test_expect_success '#31: GIT_DIR, GIT_WORKTREE=root in subdir' '
-       cat >31/sub/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/31.git
-setup: worktree: $TRASH_DIRECTORY/31
-setup: cwd: $TRASH_DIRECTORY/31
-setup: prefix: sub/
-EOF
-       test_repo 31/sub "$TRASH_DIRECTORY/31/.git" "$TRASH_DIRECTORY/31"
-'
-
-test_expect_success '#31: GIT_DIR, GIT_WORKTREE=root(rel) in subdir' '
-       cat >31/sub/sub/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/31.git
-setup: worktree: $TRASH_DIRECTORY/31
-setup: cwd: $TRASH_DIRECTORY/31
-setup: prefix: sub/sub/
-EOF
-       test_repo 31/sub/sub "$TRASH_DIRECTORY/31/.git" ../..
-'
-
-test_expect_success '#31: GIT_DIR(rel), GIT_WORK_TREE=wt at root' '
-       cat >31/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/31.git
-setup: worktree: $TRASH_DIRECTORY/31/wt
-setup: cwd: $TRASH_DIRECTORY/31
-setup: prefix: (null)
-EOF
-       test_repo 31 .git "$TRASH_DIRECTORY/31/wt"
-'
-
-test_expect_success '#31: GIT_DIR(rel), GIT_WORK_TREE=wt(rel) at root' '
-       cat >31/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/31.git
-setup: worktree: $TRASH_DIRECTORY/31/wt
-setup: cwd: $TRASH_DIRECTORY/31
-setup: prefix: (null)
-EOF
-       test_repo 31 .git wt
-'
-
-test_expect_success '#31: GIT_DIR, GIT_WORK_TREE=wt(rel) at root' '
-       cat >31/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/31.git
-setup: worktree: $TRASH_DIRECTORY/31/wt
-setup: cwd: $TRASH_DIRECTORY/31
-setup: prefix: (null)
-EOF
-       test_repo 31 "$TRASH_DIRECTORY/31/.git" wt
-'
-
-test_expect_success '#31: GIT_DIR, GIT_WORK_TREE=wt at root' '
-       cat >31/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/31.git
-setup: worktree: $TRASH_DIRECTORY/31/wt
-setup: cwd: $TRASH_DIRECTORY/31
-setup: prefix: (null)
-EOF
-       test_repo 31 "$TRASH_DIRECTORY/31/.git" "$TRASH_DIRECTORY/31/wt"
-'
-
-test_expect_success '#31: GIT_DIR(rel), GIT_WORK_TREE=wt in subdir' '
-       cat >31/sub/sub/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/31.git
-setup: worktree: $TRASH_DIRECTORY/31/wt
-setup: cwd: $TRASH_DIRECTORY/31/sub/sub
-setup: prefix: (null)
-EOF
-       test_repo 31/sub/sub ../../.git "$TRASH_DIRECTORY/31/wt"
-'
-
-test_expect_success '#31: GIT_DIR(rel), GIT_WORK_TREE=wt(rel) in subdir' '
-       cat >31/sub/sub/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/31.git
-setup: worktree: $TRASH_DIRECTORY/31/wt
-setup: cwd: $TRASH_DIRECTORY/31/sub/sub
-setup: prefix: (null)
-EOF
-       test_repo 31/sub/sub ../../.git ../../wt
-'
-
-test_expect_success '#31: GIT_DIR, GIT_WORK_TREE=wt(rel) in subdir' '
-       cat >31/sub/sub/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/31.git
-setup: worktree: $TRASH_DIRECTORY/31/wt
-setup: cwd: $TRASH_DIRECTORY/31/sub/sub
-setup: prefix: (null)
-EOF
-       test_repo 31/sub/sub "$TRASH_DIRECTORY/31/.git" ../../wt
-'
-
-test_expect_success '#31: GIT_DIR, GIT_WORK_TREE=wt in subdir' '
-       cat >31/sub/sub/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/31.git
-setup: worktree: $TRASH_DIRECTORY/31/wt
-setup: cwd: $TRASH_DIRECTORY/31/sub/sub
-setup: prefix: (null)
-EOF
-       test_repo 31/sub/sub "$TRASH_DIRECTORY/31/.git" "$TRASH_DIRECTORY/31/wt"
-'
-
-test_expect_success '#31: GIT_DIR(rel), GIT_WORK_TREE=.. at root' '
-       cat >31/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/31.git
-setup: worktree: $TRASH_DIRECTORY
-setup: cwd: $TRASH_DIRECTORY
-setup: prefix: 31/
-EOF
-       test_repo 31 .git "$TRASH_DIRECTORY"
-'
-
-test_expect_success '#31: GIT_DIR(rel), GIT_WORK_TREE=..(rel) at root' '
-       cat >31/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/31.git
-setup: worktree: $TRASH_DIRECTORY
-setup: cwd: $TRASH_DIRECTORY
-setup: prefix: 31/
-EOF
-       test_repo 31 .git ..
-'
-
-test_expect_success '#31: GIT_DIR, GIT_WORK_TREE=..(rel) at root' '
-       cat >31/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/31.git
-setup: worktree: $TRASH_DIRECTORY
-setup: cwd: $TRASH_DIRECTORY
-setup: prefix: 31/
-EOF
-       test_repo 31 "$TRASH_DIRECTORY/31/.git" ..
-'
-
-test_expect_success '#31: GIT_DIR, GIT_WORK_TREE=.. at root' '
-       cat >31/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/31.git
-setup: worktree: $TRASH_DIRECTORY
-setup: cwd: $TRASH_DIRECTORY
-setup: prefix: 31/
-EOF
-       test_repo 31 "$TRASH_DIRECTORY/31/.git" "$TRASH_DIRECTORY"
-'
-
-test_expect_success '#31: GIT_DIR(rel), GIT_WORK_TREE=.. in subdir' '
-       cat >31/sub/sub/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/31.git
-setup: worktree: $TRASH_DIRECTORY
-setup: cwd: $TRASH_DIRECTORY
-setup: prefix: 31/sub/sub/
-EOF
-       test_repo 31/sub/sub ../../.git "$TRASH_DIRECTORY"
-'
-
-test_expect_success '#31: GIT_DIR(rel), GIT_WORK_TREE=..(rel) in subdir' '
-       cat >31/sub/sub/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/31.git
-setup: worktree: $TRASH_DIRECTORY
-setup: cwd: $TRASH_DIRECTORY
-setup: prefix: 31/sub/sub/
-EOF
-       test_repo 31/sub/sub ../../.git ../../..
-'
-
-test_expect_success '#31: GIT_DIR, GIT_WORK_TREE=..(rel) in subdir' '
-       cat >31/sub/sub/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/31.git
-setup: worktree: $TRASH_DIRECTORY
-setup: cwd: $TRASH_DIRECTORY
-setup: prefix: 31/sub/sub/
-EOF
-       test_repo 31/sub/sub "$TRASH_DIRECTORY/31/.git" ../../../
-'
-
-test_expect_success '#31: GIT_DIR, GIT_WORK_TREE=.. in subdir' '
-       cat >31/sub/sub/expected <<EOF &&
-setup: git_dir: $TRASH_DIRECTORY/31.git
-setup: worktree: $TRASH_DIRECTORY
-setup: cwd: $TRASH_DIRECTORY
-setup: prefix: 31/sub/sub/
-EOF
-       test_repo 31/sub/sub "$TRASH_DIRECTORY/31/.git" "$TRASH_DIRECTORY"
+       setup_repo 31 non-existent gitfile true &&
+       mkdir -p 31/sub/sub 31/wt/sub
 '
+run_wt_tests 31 gitfile
 
 test_done
index 44f5421be45579b10c5556a958404ad2daa02002..2b17311cb0870ea210d9b5cbe167363d13641d67 100755 (executable)
@@ -110,6 +110,20 @@ test_expect_success '--ignore-space-change makes merge succeed' '
        git merge-recursive --ignore-space-change HEAD^ -- HEAD remote
 '
 
+test_expect_success 'naive cherry-pick fails' '
+       git read-tree --reset -u HEAD &&
+       test_must_fail git cherry-pick --no-commit remote &&
+       git read-tree --reset -u HEAD &&
+       test_must_fail git cherry-pick remote &&
+       test_must_fail git update-index --refresh &&
+       grep "<<<<<<" text.txt
+'
+
+test_expect_success '-Xignore-space-change makes cherry-pick succeed' '
+       git read-tree --reset -u HEAD &&
+       git cherry-pick --no-commit -Xignore-space-change remote
+'
+
 test_expect_success '--ignore-space-change: our w/s-only change wins' '
        q_to_cr <<-\EOF >expected &&
            justice and holiness and is the nurse of his age and theQ
index 948ca1bce66cab317bf74984b22384f2625418c1..df921d1f33df34dd2b2631580f8d53b18270662a 100755 (executable)
@@ -3,12 +3,14 @@
 test_description='Test cherry-pick with directory/file conflicts'
 . ./test-lib.sh
 
-test_expect_success SYMLINKS 'Setup rename across paths each below D/F conflicts' '
+test_expect_success 'Initialize repository' '
        mkdir a &&
        >a/f &&
        git add a &&
-       git commit -m a &&
+       git commit -m a
+'
 
+test_expect_success SYMLINKS 'Setup rename across paths each below D/F conflicts' '
        mkdir b &&
        ln -s ../a b/a &&
        git add b &&
index 9a665205884fcdb1c5888558d6edf960e335e013..b8f81d07c33d3596fef5f5a361f4774d5e357fca 100755 (executable)
@@ -290,4 +290,15 @@ test_expect_success 'log -S requires an argument' '
        test_must_fail git log -S
 '
 
+test_expect_success 'diff --cached on unborn branch' '
+       echo ref: refs/heads/unborn >.git/HEAD &&
+       git diff --cached >result &&
+       test_cmp "$TEST_DIRECTORY/t4013/diff.diff_--cached" result
+'
+
+test_expect_success 'diff --cached -- file on unborn branch' '
+       git diff --cached -- file0 >result &&
+       test_cmp "$TEST_DIRECTORY/t4013/diff.diff_--cached_--_file0" result
+'
+
 test_done
diff --git a/t/t4013/diff.diff_--cached b/t/t4013/diff.diff_--cached
new file mode 100644 (file)
index 0000000..ff16e83
--- /dev/null
@@ -0,0 +1,38 @@
+diff --git a/dir/sub b/dir/sub
+new file mode 100644
+index 0000000..992913c
+--- /dev/null
++++ b/dir/sub
+@@ -0,0 +1,8 @@
++A
++B
++C
++D
++E
++F
++1
++2
+diff --git a/file0 b/file0
+new file mode 100644
+index 0000000..10a8a9f
+--- /dev/null
++++ b/file0
+@@ -0,0 +1,9 @@
++1
++2
++3
++4
++5
++6
++A
++B
++C
+diff --git a/file1 b/file1
+new file mode 100644
+index 0000000..b1e6722
+--- /dev/null
++++ b/file1
+@@ -0,0 +1,3 @@
++A
++B
++C
diff --git a/t/t4013/diff.diff_--cached_--_file0 b/t/t4013/diff.diff_--cached_--_file0
new file mode 100644 (file)
index 0000000..b9bb858
--- /dev/null
@@ -0,0 +1,15 @@
+diff --git a/file0 b/file0
+new file mode 100644
+index 0000000..10a8a9f
+--- /dev/null
++++ b/file0
+@@ -0,0 +1,9 @@
++1
++2
++3
++4
++5
++6
++A
++B
++C
index 579c9e61054521301464bfc31351040d45966836..a33d510bf6b27a6bb2c640cfc9d11f462cbdf7a6 100755 (executable)
@@ -6,6 +6,7 @@
 test_description='git apply -p handling.'
 
 . ./test-lib.sh
+. "$TEST_DIRECTORY"/lib-prereq-FILEMODE.sh
 
 test_expect_success setup '
        mkdir sub &&
@@ -62,8 +63,12 @@ test_expect_success 'apply (-p2) diff, mode change only' '
        old mode 100644
        new mode 100755
        EOF
-       chmod 644 file1 &&
-       git apply -p2 patch.chmod &&
+       test_chmod -x file1 &&
+       git apply --index -p2 patch.chmod &&
+       case $(git ls-files -s file1) in 100755*) : good;; *) false;; esac
+'
+
+test_expect_success FILEMODE 'file mode was changed' '
        test -x file1
 '
 
index 884a5e567c308e976ce50036dc93c3932b717603..a5f458533fd071c13550a72bf251e2e10c109637 100755 (executable)
@@ -124,7 +124,7 @@ test_expect_success "--recurse-submodules overrides fetchRecurseSubmodules setti
        (
                cd downstream &&
                git fetch --recurse-submodules >../actual.out 2>../actual.err &&
-               git config -f --unset .gitmodules submodule.submodule.fetchRecurseSubmodules true &&
+               git config --unset -f .gitmodules submodule.submodule.fetchRecurseSubmodules &&
                git config --unset submodule.submodule.fetchRecurseSubmodules
        ) &&
        test_cmp expect.out actual.out &&
index d8ad25036f325ecdcc71257614e19b5e6ab2cdc5..e5be13c271c92ce7c51601ee1eaf966d849d8ae4 100755 (executable)
@@ -238,6 +238,10 @@ test_expect_success 'ensure "status --cached --recursive" preserves the --cached
                ) &&
                git submodule status --cached --recursive -- nested1 > ../actual
        ) &&
+       if test_have_prereq MINGW
+       then
+               dos2unix actual
+       fi &&
        test_cmp expect actual
 '
 
index 222d1059ef99879d3db387be798f973fb093f53e..52ac0e56dce12016ab03155bd16b2b66b062fca3 100755 (executable)
@@ -919,6 +919,48 @@ test_expect_success \
         git diff-tree -C --find-copies-harder -r N4 N6 >actual &&
         compare_diff_raw expect actual'
 
+test_expect_success \
+       'N: delete directory by copying' \
+       'cat >expect <<-\EOF &&
+       OBJID
+       :100644 000000 OBJID OBJID D    foo/bar/qux
+       OBJID
+       :000000 100644 OBJID OBJID A    foo/bar/baz
+       :000000 100644 OBJID OBJID A    foo/bar/qux
+       EOF
+        empty_tree=$(git mktree </dev/null) &&
+        cat >input <<-INPUT_END &&
+       commit refs/heads/N-delete
+       committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+       data <<COMMIT
+       collect data to be deleted
+       COMMIT
+
+       deleteall
+       M 100644 inline foo/bar/baz
+       data <<DATA_END
+       hello
+       DATA_END
+       C "foo/bar/baz" "foo/bar/qux"
+       C "foo/bar/baz" "foo/bar/quux/1"
+       C "foo/bar/baz" "foo/bar/quuux"
+       M 040000 $empty_tree foo/bar/quux
+       M 040000 $empty_tree foo/bar/quuux
+
+       commit refs/heads/N-delete
+       committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+       data <<COMMIT
+       delete subdirectory
+       COMMIT
+
+       M 040000 $empty_tree foo/bar/qux
+       INPUT_END
+        git fast-import <input &&
+        git rev-list N-delete |
+               git diff-tree -r --stdin --root --always |
+               sed -e "s/$_x40/OBJID/g" >actual &&
+        test_cmp expect actual'
+
 test_expect_success \
        'N: modify copied tree' \
        'cat >expect <<-\EOF &&
@@ -1706,6 +1748,61 @@ test_expect_success \
     'cat input | git fast-import --export-marks=other.marks &&
     grep :1 other.marks'
 
+test_expect_success 'R: catch typo in marks file name' '
+       test_must_fail git fast-import --import-marks=nonexistent.marks </dev/null &&
+       echo "feature import-marks=nonexistent.marks" |
+       test_must_fail git fast-import
+'
+
+test_expect_success 'R: import and output marks can be the same file' '
+       rm -f io.marks &&
+       blob=$(echo hi | git hash-object --stdin) &&
+       cat >expect <<-EOF &&
+       :1 $blob
+       :2 $blob
+       EOF
+       git fast-import --export-marks=io.marks <<-\EOF &&
+       blob
+       mark :1
+       data 3
+       hi
+
+       EOF
+       git fast-import --import-marks=io.marks --export-marks=io.marks <<-\EOF &&
+       blob
+       mark :2
+       data 3
+       hi
+
+       EOF
+       test_cmp expect io.marks
+'
+
+test_expect_success 'R: --import-marks=foo --output-marks=foo to create foo fails' '
+       rm -f io.marks &&
+       test_must_fail git fast-import --import-marks=io.marks --export-marks=io.marks <<-\EOF
+       blob
+       mark :1
+       data 3
+       hi
+
+       EOF
+'
+
+test_expect_success 'R: --import-marks-if-exists' '
+       rm -f io.marks &&
+       blob=$(echo hi | git hash-object --stdin) &&
+       echo ":1 $blob" >expect &&
+       git fast-import --import-marks-if-exists=io.marks --export-marks=io.marks <<-\EOF &&
+       blob
+       mark :1
+       data 3
+       hi
+
+       EOF
+       test_cmp expect io.marks
+'
+
 cat >input << EOF
 feature import-marks=marks.out
 feature export-marks=marks.new
index 7cf8cd8a2fed2191b31082c92a95598a3e06513d..463254c72734beaf74948b6c424367ef4fea9d1a 100755 (executable)
@@ -120,6 +120,7 @@ test_expect_success 'add notes with simple M command' '
 
 test_tick
 cat >input <<INPUT_END
+feature notes
 commit refs/notes/test
 committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
 data <<COMMIT
index 42f2f144969a0671b3431f21f659beaff2c53b3d..0fdc541a7cd7d6b694c4f4a3fd06b6cf21dc7380 100644 (file)
@@ -70,6 +70,9 @@ unset GIT_NOTES_REF
 unset GIT_NOTES_DISPLAY_REF
 unset GIT_NOTES_REWRITE_REF
 unset GIT_NOTES_REWRITE_MODE
+unset GIT_REFLOG_ACTION
+unset GIT_CHERRY_PICK_HELP
+unset GIT_QUIET
 GIT_MERGE_VERBOSITY=5
 export GIT_MERGE_VERBOSITY
 export GIT_AUTHOR_EMAIL GIT_AUTHOR_NAME
diff --git a/tag.c b/tag.c
index f789744ccaf5d5fb6f63ba0911a869492affc162..ecf7c1e9ce889514e04765695298ef11f28edab6 100644 (file)
--- a/tag.c
+++ b/tag.c
@@ -56,7 +56,7 @@ static unsigned long parse_tag_date(const char *buf, const char *tail)
        return strtoul(dateptr, NULL, 10);
 }
 
-int parse_tag_buffer(struct tag *item, void *data, unsigned long size)
+int parse_tag_buffer(struct tag *item, const void *data, unsigned long size)
 {
        unsigned char sha1[20];
        char type[20];
diff --git a/tag.h b/tag.h
index 85223700396f5ddb00c046a1a9fdb63c92aae40e..5ee88e6550cafa78b7e4acaa1285d5805974a037 100644 (file)
--- a/tag.h
+++ b/tag.h
@@ -13,7 +13,7 @@ struct tag {
 };
 
 extern struct tag *lookup_tag(const unsigned char *sha1);
-extern int parse_tag_buffer(struct tag *item, void *data, unsigned long size);
+extern int parse_tag_buffer(struct tag *item, const void *data, unsigned long size);
 extern int parse_tag(struct tag *item);
 extern struct object *deref_tag(struct object *, const char *, int);
 extern size_t parse_signature(const char *buf, unsigned long size);
diff --git a/test-mktemp.c b/test-mktemp.c
new file mode 100644 (file)
index 0000000..c8c5421
--- /dev/null
@@ -0,0 +1,14 @@
+/*
+ * test-mktemp.c: code to exercise the creation of temporary files
+ */
+#include "git-compat-util.h"
+
+int main(int argc, char *argv[])
+{
+       if (argc != 2)
+               usage("Expected 1 parameter defining the temporary file template");
+
+       xmkstemp(xstrdup(argv[1]));
+
+       return 0;
+}
index 1ca41b1a6986559a7c5ddc3983d751d75a0d23ff..bf204b921040f411a22d0f17592e940517672c66 100644 (file)
@@ -1374,16 +1374,22 @@ static int verify_absent_1(struct cache_entry *ce,
                char path[PATH_MAX + 1];
                memcpy(path, ce->name, len);
                path[len] = 0;
-               lstat(path, &st);
+               if (lstat(path, &st))
+                       return error("cannot stat '%s': %s", path,
+                                       strerror(errno));
 
                return check_ok_to_remove(path, len, DT_UNKNOWN, NULL, &st,
                                error_type, o);
-       } else if (!lstat(ce->name, &st))
+       } else if (lstat(ce->name, &st)) {
+               if (errno != ENOENT)
+                       return error("cannot stat '%s': %s", ce->name,
+                                    strerror(errno));
+               return 0;
+       } else {
                return check_ok_to_remove(ce->name, ce_namelen(ce),
-                               ce_to_dtype(ce), ce, &st,
-                               error_type, o);
-
-       return 0;
+                                         ce_to_dtype(ce), ce, &st,
+                                         error_type, o);
+       }
 }
 
 static int verify_absent(struct cache_entry *ce,
index 3a1c392bbd76b167847f7a3b164f0135eb66740e..1ff47977d549992ada8c1236187d4516b648ee7d 100644 (file)
@@ -51,7 +51,7 @@ PATTERNS("objc",
         "|[-+0-9.e]+[fFlL]?|0[xXbB]?[0-9a-fA-F]+[lL]?"
         "|[-+*/<>%&^|=!]=|--|\\+\\+|<<=?|>>=?|&&|\\|\\||::|->"),
 PATTERNS("pascal",
-        "^((procedure|function|constructor|destructor|interface|"
+        "^(((class[ \t]+)?(procedure|function)|constructor|destructor|interface|"
                "implementation|initialization|finalization)[ \t]*.*)$"
         "\n"
         "^(.*=[ \t]*(class|record).*)$",
index fa580e62de05f832e7d7474cc1a457cd7379cef2..2ad2c307dd6e8f4bddf5cbd9c588973a085bf870 100644 (file)
@@ -211,7 +211,7 @@ void svndump_read(const char *url)
                if (key == keys.svn_fs_dump_format_version) {
                        dump_ctx.version = atoi(val);
                        if (dump_ctx.version > 2)
-                               die("expected svn dump format version <= 2, found %d",
+                               die("expected svn dump format version <= 2, found %"PRIu32,
                                    dump_ctx.version);
                } else if (key == keys.uuid) {
                        dump_ctx.uuid = pool_intern(val);
index 8d7dd31c4ba5439652d11e5ada06e0d52bc04e4f..55b074ec46b0a222b03f8bea42f4d5cdd9811293 100644 (file)
--- a/wrapper.c
+++ b/wrapper.c
@@ -198,10 +198,22 @@ FILE *xfdopen(int fd, const char *mode)
 int xmkstemp(char *template)
 {
        int fd;
+       char origtemplate[PATH_MAX];
+       strlcpy(origtemplate, template, sizeof(origtemplate));
 
        fd = mkstemp(template);
-       if (fd < 0)
-               die_errno("Unable to create temporary file");
+       if (fd < 0) {
+               int saved_errno = errno;
+               const char *nonrelative_template;
+
+               if (!template[0])
+                       template = origtemplate;
+
+               nonrelative_template = make_nonrelative_path(template);
+               errno = saved_errno;
+               die_errno("Unable to create temporary file '%s'",
+                       nonrelative_template);
+       }
        return fd;
 }
 
@@ -321,10 +333,22 @@ int gitmkstemps(char *pattern, int suffix_len)
 int xmkstemp_mode(char *template, int mode)
 {
        int fd;
+       char origtemplate[PATH_MAX];
+       strlcpy(origtemplate, template, sizeof(origtemplate));
 
        fd = git_mkstemp_mode(template, mode);
-       if (fd < 0)
-               die_errno("Unable to create temporary file");
+       if (fd < 0) {
+               int saved_errno = errno;
+               const char *nonrelative_template;
+
+               if (!template[0])
+                       template = origtemplate;
+
+               nonrelative_template = make_nonrelative_path(template);
+               errno = saved_errno;
+               die_errno("Unable to create temporary file '%s'",
+                       nonrelative_template);
+       }
        return fd;
 }