{"thread":{"id":"36757","subject":"[PATCH v4] Add an explicit GIT_DIR to the list of excludes","startedAt":"2014-05-27T03:56:47Z","lastAt":"2014-06-04T13:52:28Z","messageCount":6,"participants":["Pasha Bolokhov","Duy Nguyen"],"isPatch":true,"patchVersion":4,"patchTotal":null},"messages":[{"id":"242716","messageId":"1401163007-5808-1-git-send-email-pasha.bolokhov@gmail.com","threadId":"36757","inReplyTo":null,"subject":"[PATCH v4] Add an explicit GIT_DIR to the list of excludes","fromName":"Pasha Bolokhov","fromEmail":"pasha.bolokhov@gmail.com","sentAt":"2014-05-27T03:56:47Z","receivedAt":"2014-05-27T03:56:47Z","isPatch":true,"sender":{"key":"pasha.bolokhov@gmail.com","avatar":null},"body":"When an explicit '--git-dir' option points to a directory inside\nthe work tree, git treats it as if it were any other directory.\nIn particular, 'git status' lists it as untracked, while 'git add -A'\nstages the metadata directory entirely\n\nAdd GIT_DIR to the list of excludes in setup_standard_excludes(),\nwhile checking that GIT_DIR is not just '.git', in which case it\nwould be ignored by default, and that GIT_DIR is inside GIT_WORK_TREE\n\nAlthough an analogous comparison of any given path against '.git'\nis done in treat_path(), this does not seem to be the right place\nto compare against GIT_DIR. Instead, the excludes provide an\neffective mechanism of ignoring a file/directory, and adding GIT_DIR\nas an exclude is equivalent of putting it into '.gitignore'. Function\nsetup_standard_excludes() was chosen because that is the place where\nthe excludes are initialized by the commands that are concerned about\nexcludes\n\nSigned-off-by: Pasha Bolokhov <pasha.bolokhov@gmail.com>\n---\nImprove test tree structure.\nAdd a check for work_tree==NULL in dir.c:setup_standard_excludes\nWhen work_tree is NULL, there is no concept of whether the\nrepo is within work tree or not, but we still default to ignoring\nGIT_DIR\n\n Documentation/technical/api-directory-listing.txt |   4 +-\n dir.c                                             |  32 +++++\n t/t2205-add-gitdir.sh                             | 163 ++++++++++++++++++++++\n 3 files changed, 197 insertions(+), 2 deletions(-)\n create mode 100755 t/t2205-add-gitdir.sh\n\ndiff --git a/Documentation/technical/api-directory-listing.txt b/Documentation/technical/api-directory-listing.txt\nindex 7f8e78d..fd4a178 100644\n--- a/Documentation/technical/api-directory-listing.txt\n+++ b/Documentation/technical/api-directory-listing.txt\n@@ -90,8 +90,8 @@ marked. If you to exclude files, make sure you have loaded index first.\n   `add_exclude()`.\n \n * To add patterns from a file (e.g. `.git/info/exclude`), call\n-  `add_excludes_from_file()` , and/or set `dir.exclude_per_dir`.  A\n-  short-hand function `setup_standard_excludes()` can be used to set\n+  `add_excludes_from_file()` , and/or set `dir.exclude_per_dir`.  The\n+  short-hand function `setup_standard_excludes()` must be used to set\n   up the standard set of exclude settings.\n \n * Set options described in the Data Structure section above.\ndiff --git a/dir.c b/dir.c\nindex 98bb50f..dd76da1 100644\n--- a/dir.c\n+++ b/dir.c\n@@ -1588,6 +1588,38 @@ void setup_standard_excludes(struct dir_struct *dir)\n {\n \tconst char *path;\n \tchar *xdg_path;\n+\tconst char *r_git, *gitdir = get_git_dir();\n+\tchar *n_git, *basename;\n+\tint len, i;\n+\n+\t/*\n+\t * Add git directory to the ignores; do this only if\n+\t * GIT_DIR does not end with \"/.git\"\n+\t */\n+\tr_git = real_path(absolute_path(gitdir));\n+\tn_git = xmalloc(strlen(r_git) + 1 + 1);\n+\tnormalize_path_copy(n_git, r_git);\n+\n+\tlen = strlen(n_git); /* real_path() has stripped trailing slash */\n+\tfor (i = len - 1; i > 0 && !is_dir_sep(n_git[i]); i--) ;\n+\tbasename = n_git + i;\n+\tif (is_dir_sep(*basename))\n+\t\tbasename++;\n+\tif (strcmp(basename, \".git\")) {\n+\t\tconst char *worktree = get_git_work_tree();\n+\n+\t\tif (worktree == NULL ||\n+\t\t    dir_inside_of(n_git, get_git_work_tree()) >= 0) {\n+\t\t\tstruct exclude_list *el = add_exclude_list(dir, EXC_CMDL,\n+\t\t\t\t\t\t\t\"GIT_DIR setup\");\n+\n+\t\t\t/* append a trailing slash to exclude directories */\n+\t\t\tn_git[len] = '/';\n+\t\t\tn_git[len + 1] = '\\0';\n+\t\t\tadd_exclude(basename, \"\", 0, el, 0);\n+\t\t}\n+\t}\n+\tfree(n_git);\n \n \tdir->exclude_per_dir = \".gitignore\";\n \tpath = git_path(\"info/exclude\");\ndiff --git a/t/t2205-add-gitdir.sh b/t/t2205-add-gitdir.sh\nnew file mode 100755\nindex 0000000..4cc26af\n--- /dev/null\n+++ b/t/t2205-add-gitdir.sh\n@@ -0,0 +1,163 @@\n+#!/bin/sh\n+#\n+# Copyright (c) 2014 Pasha Bolokhov\n+#\n+\n+test_description='alternative repository path specified by --git-dir is ignored by add and status'\n+\n+. ./test-lib.sh\n+\n+#\n+# Create a tree:\n+#\n+#\trepo-inside/  repo-outside/\n+#\n+#\n+# repo-inside:\n+# \ta  b  c  d  subdir/ [meta/]\n+#\n+# repo-inside/subdir:\n+# \te  f  g  h  meta/  ssubdir/\n+#\n+# repo-inside/subdir/meta:\n+# \taa\n+#\n+# repo-inside/subdir/ssubdir:\n+# \tmeta/\n+#\n+# repo-inside/subdir/ssubdir/meta:\n+# \taaa\n+#\n+#\n+#\n+# repo-outside:\n+#\texternal/  tree/\n+#\n+# repo-outside/external:\n+#\t[meta/]\n+#\n+# repo-outside/tree:\n+#\tn  o  p  q  meta/  sub/\n+#\n+# repo-outside/tree/meta:\n+#\tbb\n+#\n+# repo-outside/tree/sub:\n+#\tmeta/\n+#\n+# repo-outside/tree/sub/meta:\n+#\tbbb\n+#\n+#\n+# (both of the above [meta/] denote the actual repositories)\n+#\n+\n+#\n+# First set of tests (in \"repo-inside/\"):\n+# ---------------------------------------\n+#\n+# Name the repository \"meta\" and see whether or not \"git status\" includes or\n+# ignores directories named \"meta\". Directory \"meta\" at the top level of\n+# \"repo-inside/\"is the repository and appears upon the first \"git init\"\n+#\n+#\n+# Second set of tests (in \"repo-outside/\"):\n+# -----------------------------------------\n+#\n+# Put the work tree into \"tree/\" and repository into \"external/meta\"\n+# (the latter directory appears upon the corresponding \"git init\").\n+# The work tree again contains directories named \"meta\", but those ones are\n+# tested not to be ignored now\n+#\n+\n+test_expect_success \"setup\" '\n+\tmkdir repo-inside/ &&\n+\t(\n+\t\tcd repo-inside/ &&\n+\t\tfor f in a b c d\n+\t\tdo\n+\t\t\techo \"DATA\" >\"$f\" || exit 1\n+\t\tdone &&\n+\t\tmkdir subdir subdir/meta &&\n+\t\tmkdir subdir/ssubdir subdir/ssubdir/meta &&\n+\t\tfor f in e f g h\n+\t\tdo\n+\t\t\techo \"MORE DATA\" >\"subdir/$f\" || exit 1\n+\t\tdone &&\n+\t\techo \"EVEN more Data\" >subdir/meta/aa &&\n+\t\techo \"Data and BAIT\" >subdir/ssubdir/meta/aaa &&\n+\t\tgit --git-dir=meta init\n+\t) &&\n+\tmkdir repo-outside/ repo-outside/external repo-outside/tree &&\n+\t(\n+\t\tcd repo-outside/tree &&\n+\t\tfor f in n o p q\n+\t\tdo\n+\t\t\techo \"Literal Data\" >\"$f\" || exit 1\n+\t\tdone &&\n+\t\tmkdir meta sub sub/meta &&\n+\t\techo \"Sample data\" >meta/bb &&\n+\t\techo \"Stream of data and BAIT\" >sub/meta/bbb &&\n+\t\tgit --git-dir=../external/meta init\n+\t)\n+'\n+\n+\n+#\n+# The first set of tests (the repository is inside the work tree)\n+#\n+test_expect_success \"'git status' ignores the repository directory\" '\n+\t(\n+\t\tcd repo-inside &&\n+\t\tgit --git-dir=meta --work-tree=. status --porcelain >status.out &&\n+\t\ttest_might_fail grep meta status.out >out &&\n+\t\t! test -s out\n+\t)\n+'\n+\n+test_expect_success \"'git add -A' ignores the repository directory\" '\n+\t(\n+\t\tcd repo-inside &&\n+\t\tgit --git-dir=meta --work-tree=. add -A &&\n+\t\tgit --git-dir=meta --work-tree=. status --porcelain >status1.out &&\n+\t\ttest_might_fail grep meta status1.out >out1 &&\n+\t\t! test -s out1\n+\t)\n+'\n+\n+test_expect_success \"'git grep --exclude-standard' ignores the repository directory\" '\n+\t(\n+\t\tcd repo-inside &&\n+\t\ttest_might_fail git --git-dir=meta \\\n+\t\t\tgrep --no-index --exclude-standard BAIT >out2 &&\n+\t\t! test -s out2\n+\t)\n+'\n+\n+\n+#\n+# The second set of tests (the repository is outside of the work tree)\n+#\n+test_expect_success \"'git status' acknowledges directories 'meta' \\\n+if repo is not within work tree\" '\n+\ttest_might_fail rm -rf meta/ &&\n+\t(\n+\t\tcd repo-outside/tree &&\n+\t\tgit --git-dir=../external/meta init &&\n+\t\tgit --git-dir=../external/meta --work-tree=. status --porcelain >status3.out &&\n+\t\ttest_might_fail grep meta status3.out >out3 &&\n+\t\ttest -s out3\n+\t)\n+'\n+\n+test_expect_success \"'git add -A' adds 'meta' if the repo is outside the work tree\" '\n+\t(\n+\t\tcd repo-outside/tree &&\n+\t\tgit --git-dir=../external/meta --work-tree=. add -A &&\n+\t\tgit --git-dir=../external/meta --work-tree=. status --porcelain >status4.out &&\n+\t\ttest_might_fail grep meta status4.out >out4 &&\n+\t\ttest -s out4\n+\t)\n+'\n+\n+test_done\n-- \n1.9.1\n"},{"id":"242854","messageId":"CACsJy8By-58wBoV8BydWbpDkpUG6jJhM16aO+Ed8J2ucq66VcQ@mail.gmail.com","threadId":"36757","inReplyTo":"1401163007-5808-1-git-send-email-pasha.bolokhov@gmail.com","subject":"Re: [PATCH v4] Add an explicit GIT_DIR to the list of excludes","fromName":"Duy Nguyen","fromEmail":"pclouds@gmail.com","sentAt":"2014-05-28T12:36:27Z","receivedAt":"2014-05-28T12:36:27Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"On Tue, May 27, 2014 at 10:56 AM, Pasha Bolokhov\n<pasha.bolokhov@gmail.com> wrote:\n> @@ -1588,6 +1588,38 @@ void setup_standard_excludes(struct dir_struct *dir)\n>  {\n>         const char *path;\n>         char *xdg_path;\n> +       const char *r_git, *gitdir = get_git_dir();\n> +       char *n_git, *basename;\n> +       int len, i;\n> +\n> +       /*\n> +        * Add git directory to the ignores; do this only if\n> +        * GIT_DIR does not end with \"/.git\"\n> +        */\n> +       r_git = real_path(absolute_path(gitdir));\n> +       n_git = xmalloc(strlen(r_git) + 1 + 1);\n> +       normalize_path_copy(n_git, r_git);\n> +\n> +       len = strlen(n_git); /* real_path() has stripped trailing slash */\n> +       for (i = len - 1; i > 0 && !is_dir_sep(n_git[i]); i--) ;\n> +       basename = n_git + i;\n> +       if (is_dir_sep(*basename))\n> +               basename++;\n> +       if (strcmp(basename, \".git\")) {\n\nI think normalize_path_copy makes sure that dir sep is '/', so this\ncode may be simplified to \"if (strcmp(n_git, .git\") && (len == 4 ||\nstrcmp(n_git + len - 5, \"/.git\")))\"?\n\n> +               const char *worktree = get_git_work_tree();\n> +\n> +               if (worktree == NULL ||\n> +                   dir_inside_of(n_git, get_git_work_tree()) >= 0) {\n> +                       struct exclude_list *el = add_exclude_list(dir, EXC_CMDL,\n> +                                                       \"GIT_DIR setup\");\n> +\n> +                       /* append a trailing slash to exclude directories */\n> +                       n_git[len] = '/';\n> +                       n_git[len + 1] = '\\0';\n> +                       add_exclude(basename, \"\", 0, el, 0);\n> +               }\n> +       }\n> +       free(n_git);\n\nAll this add-only code makes me think it may be nice to make it a\nseparate function. A good function name could replace the comment near\nthe beginning of the block.\n-- \nDuy\n"},{"id":"242912","messageId":"CAKpPgvfvrdBr7oxyKg2G1XDHwS=Dzs9=K9MmQLtLzUx-Zi+1dA@mail.gmail.com","threadId":"36757","inReplyTo":"CACsJy8By-58wBoV8BydWbpDkpUG6jJhM16aO+Ed8J2ucq66VcQ@mail.gmail.com","subject":"Re: [PATCH v4] Add an explicit GIT_DIR to the list of excludes","fromName":"Pasha Bolokhov","fromEmail":"pasha.bolokhov@gmail.com","sentAt":"2014-05-28T22:11:05Z","receivedAt":"2014-05-28T22:11:05Z","isPatch":true,"sender":{"key":"pasha.bolokhov@gmail.com","avatar":null},"body":"On Wed, May 28, 2014 at 5:36 AM, Duy Nguyen <pclouds@gmail.com> wrote:\n> On Tue, May 27, 2014 at 10:56 AM, Pasha Bolokhov\n> <pasha.bolokhov@gmail.com> wrote:\n>> @@ -1588,6 +1588,38 @@ void setup_standard_excludes(struct dir_struct *dir)\n>>  {\n>>         const char *path;\n>>         char *xdg_path;\n>> +       const char *r_git, *gitdir = get_git_dir();\n>> +       char *n_git, *basename;\n>> +       int len, i;\n>> +\n>> +       /*\n>> +        * Add git directory to the ignores; do this only if\n>> +        * GIT_DIR does not end with \"/.git\"\n>> +        */\n>> +       r_git = real_path(absolute_path(gitdir));\n>> +       n_git = xmalloc(strlen(r_git) + 1 + 1);\n>> +       normalize_path_copy(n_git, r_git);\n>> +\n>> +       len = strlen(n_git); /* real_path() has stripped trailing slash */\n>> +       for (i = len - 1; i > 0 && !is_dir_sep(n_git[i]); i--) ;\n>> +       basename = n_git + i;\n>> +       if (is_dir_sep(*basename))\n>> +               basename++;\n>> +       if (strcmp(basename, \".git\")) {\n>\n> I think normalize_path_copy makes sure that dir sep is '/', so this\n> code may be simplified to \"if (strcmp(n_git, .git\") && (len == 4 ||\n> strcmp(n_git + len - 5, \"/.git\")))\"?\n\nThen if \"n_git\" is \"/ab\"  =>  coredump. But I agree there is logic to\nthis (if we check len >= 4 first). However, we still need the\nbasename. So I've just shortened it a bit, what do you think: (notice\nthe condition \"i >= 0\" btw)\n\n        for (i = len - 1; i >= 0 && n_git[i] != '/'; i--) ;\n        basename = n_git + i + 1;\n        if (strcmp(basename, \".git)) {\n\n>\n>> +               const char *worktree = get_git_work_tree();\n>> +\n>> +               if (worktree == NULL ||\n>> +                   dir_inside_of(n_git, get_git_work_tree()) >= 0) {\n>> +                       struct exclude_list *el = add_exclude_list(dir, EXC_CMDL,\n>> +                                                       \"GIT_DIR setup\");\n>> +\n>> +                       /* append a trailing slash to exclude directories */\n>> +                       n_git[len] = '/';\n>> +                       n_git[len + 1] = '\\0';\n>> +                       add_exclude(basename, \"\", 0, el, 0);\n>> +               }\n>> +       }\n>> +       free(n_git);\n>\n> All this add-only code makes me think it may be nice to make it a\n> separate function. A good function name could replace the comment near\n> the beginning of the block.\n\nReasonable\nI'll send the all-updated patch including doc when ready\n\n> --\n> Duy\n"},{"id":"242936","messageId":"CACsJy8Dy2quFrXynH7g5DzNMikwkOiyJZGMoSqLyjxzzvRreYQ@mail.gmail.com","threadId":"36757","inReplyTo":"CAKpPgvfvrdBr7oxyKg2G1XDHwS=Dzs9=K9MmQLtLzUx-Zi+1dA@mail.gmail.com","subject":"Re: [PATCH v4] Add an explicit GIT_DIR to the list of excludes","fromName":"Duy Nguyen","fromEmail":"pclouds@gmail.com","sentAt":"2014-05-29T11:42:49Z","receivedAt":"2014-05-29T11:42:49Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"On Thu, May 29, 2014 at 5:11 AM, Pasha Bolokhov\n<pasha.bolokhov@gmail.com> wrote:\n>>> +       len = strlen(n_git); /* real_path() has stripped trailing slash */\n>>> +       for (i = len - 1; i > 0 && !is_dir_sep(n_git[i]); i--) ;\n>>> +       basename = n_git + i;\n>>> +       if (is_dir_sep(*basename))\n>>> +               basename++;\n>>> +       if (strcmp(basename, \".git\")) {\n>>\n>> I think normalize_path_copy makes sure that dir sep is '/', so this\n>> code may be simplified to \"if (strcmp(n_git, .git\") && (len == 4 ||\n>> strcmp(n_git + len - 5, \"/.git\")))\"?\n>\n> Then if \"n_git\" is \"/ab\"  =>  coredump. But I agree there is logic to\n> this (if we check len >= 4 first). However, we still need the\n> basename.\n\nAh I missed this at add_exclude()\n\n> So I've just shortened it a bit, what do you think: (notice\n> the condition \"i >= 0\" btw)\n>\n>         for (i = len - 1; i >= 0 && n_git[i] != '/'; i--) ;\n\nThere's basename() that does this for you. A compat version is\nprovided for Windows port so no portability worries.\n\n>         basename = n_git + i + 1;\n>         if (strcmp(basename, \".git)) {\n>\n>>\n>>> +               const char *worktree = get_git_work_tree();\n>>> +\n>>> +               if (worktree == NULL ||\n>>> +                   dir_inside_of(n_git, get_git_work_tree()) >= 0) {\n>>> +                       struct exclude_list *el = add_exclude_list(dir, EXC_CMDL,\n>>> +                                                       \"GIT_DIR setup\");\n>>> +\n>>> +                       /* append a trailing slash to exclude directories */\n>>> +                       n_git[len] = '/';\n>>> +                       n_git[len + 1] = '\\0';\n>>> +                       add_exclude(basename, \"\", 0, el, 0);\n\nHmm.. I overlooked this bit before. So if  $GIT_DIR is /something/foo,\nwe set to ignore \"foo/\". Because we know n_git must be part of\n(normalized) get_git_work_tree() at this point, could we path n_git +\nstrlen(get_git_work_tree()) to add_exclude() instead of basename? Full\npath makes sure we don't accidentally exclude too much.\n\nThe case when $GIT_DIR points to a _file_ seems uncovered.\nsetup_git_directory() will transform the file to the directory\ninternally and we never know the .git file's path (so we can't exclude\nit). So people could accidentally add the .git file in, then remove it\nfrom from work tree and suddenly the work tree becomes repo-less. It's\nnot as bad as .git _directory_ because we don't lose valuable data. I\ndon't know if you want to cover this too.\n-- \nDuy\n"},{"id":"243207","messageId":"CAKpPgvcv10-DNM4xetfmcckG6ancfEn_y7i8EJ3mWQLaELDdUQ@mail.gmail.com","threadId":"36757","inReplyTo":"CACsJy8Dy2quFrXynH7g5DzNMikwkOiyJZGMoSqLyjxzzvRreYQ@mail.gmail.com","subject":"Re: [PATCH v4] Add an explicit GIT_DIR to the list of excludes","fromName":"Pasha Bolokhov","fromEmail":"pasha.bolokhov@gmail.com","sentAt":"2014-06-03T20:55:25Z","receivedAt":"2014-06-03T20:55:25Z","isPatch":true,"sender":{"key":"pasha.bolokhov@gmail.com","avatar":null},"body":"On Thu, May 29, 2014 at 4:42 AM, Duy Nguyen <pclouds@gmail.com> wrote:\n>>>> +               const char *worktree = get_git_work_tree();\n>>>> +\n>>>> +               if (worktree == NULL ||\n>>>> +                   dir_inside_of(n_git, get_git_work_tree()) >= 0) {\n>>>> +                       struct exclude_list *el = add_exclude_list(dir, EXC_CMDL,\n>>>> +                                                       \"GIT_DIR setup\");\n>>>> +\n>>>> +                       /* append a trailing slash to exclude directories */\n>>>> +                       n_git[len] = '/';\n>>>> +                       n_git[len + 1] = '\\0';\n>>>> +                       add_exclude(basename, \"\", 0, el, 0);\n>\n> Hmm.. I overlooked this bit before. So if  $GIT_DIR is /something/foo,\n> we set to ignore \"foo/\". Because we know n_git must be part of\n> (normalized) get_git_work_tree() at this point, could we path n_git +\n> strlen(get_git_work_tree()) to add_exclude() instead of basename? Full\n> path makes sure we don't accidentally exclude too much.\n\nI guess so. In fact, dir_inside_of() already returns the relative\nposition, can reuse that (however, that function doesn't include the\nleading path, making it a relative path; but it's not difficult to\nwork around). The only uncovered situation is when GIT_DIR=WORK_TREE.\nBut that's user's fault and I don't think we need to guarantee that\nGIT_DIR will be excluded then\n\n>\n> The case when $GIT_DIR points to a _file_ seems uncovered.\n> setup_git_directory() will transform the file to the directory\n> internally and we never know the .git file's path (so we can't exclude\n> it). So people could accidentally add the .git file in, then remove it\n> from from work tree and suddenly the work tree becomes repo-less. It's\n> not as bad as .git _directory_ because we don't lose valuable data. I\n> don't know if you want to cover this too.\n\nThat's right, there is no way of knowing what the original .git file\nwas. I guess the only way to work around this problem is to modify\n\"read_gitfile()\" so it saves the name of the original file. Then we\ncan add both that .git-file and GIT_DIR to the exclude list. Not a big\nproblem with me, but need to see what you guys think\n"},{"id":"243289","messageId":"CACsJy8A_CtC_05mja3L-udM_CYwGA46UoN122Xp6kxaUGkFYSw@mail.gmail.com","threadId":"36757","inReplyTo":"CAKpPgvcv10-DNM4xetfmcckG6ancfEn_y7i8EJ3mWQLaELDdUQ@mail.gmail.com","subject":"Re: [PATCH v4] Add an explicit GIT_DIR to the list of excludes","fromName":"Duy Nguyen","fromEmail":"pclouds@gmail.com","sentAt":"2014-06-04T13:52:28Z","receivedAt":"2014-06-04T13:52:28Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"On Wed, Jun 4, 2014 at 3:55 AM, Pasha Bolokhov <pasha.bolokhov@gmail.com> wrote:\n>> The case when $GIT_DIR points to a _file_ seems uncovered.\n>> setup_git_directory() will transform the file to the directory\n>> internally and we never know the .git file's path (so we can't exclude\n>> it). So people could accidentally add the .git file in, then remove it\n>> from from work tree and suddenly the work tree becomes repo-less. It's\n>> not as bad as .git _directory_ because we don't lose valuable data. I\n>> don't know if you want to cover this too.\n>\n> That's right, there is no way of knowing what the original .git file\n> was. I guess the only way to work around this problem is to modify\n> \"read_gitfile()\" so it saves the name of the original file. Then we\n> can add both that .git-file and GIT_DIR to the exclude list. Not a big\n> problem with me, but need to see what you guys think\n\nMy view is this non-standard $(basename $GIT_DIR) is a corner case.\nUnless people who care about it (e.g. you) do something that affects\nthe common \".git\" case, or really mess up the code, I don't think it's\na problem if you decide to ignore some smaller cases.\n-- \nDuy\n"}]}