{"thread":{"id":"47964","subject":"[PATCH 0/3] git worktree prune improvements","startedAt":"2018-03-03T03:39:32Z","lastAt":"2018-03-18T23:02:06Z","messageCount":15,"participants":["Nguyễn Thái Ngọc Duy","Eric Sunshine","Randall S. Becker","Duy Nguyen"],"isPatch":true,"patchVersion":1,"patchTotal":3},"messages":[{"id":"340859","messageId":"20180303033918.15751-1-pclouds@gmail.com","threadId":"47964","inReplyTo":null,"subject":"[PATCH 0/3] git worktree prune improvements","fromName":"Nguyễn Thái Ngọc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2018-03-03T03:39:15Z","receivedAt":"2018-03-03T03:39:32Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"This is something we could do to improve the situation when a user\nmanually moves a worktree and not follow the update process (we have\nhad the first reported case [1]). Plus a bit cleanup in gc.\n\nI think this is something we should do until we somehow make the user\naware that the worktree is broken as soon as they move a worktree\nmanually. But there's some more work to get there.\n\n[1] http://public-inbox.org/git/%3Caa98f187-4b1a-176d-2a1b-826c995776cd@aegee.org%3E\n\nNguyễn Thái Ngọc Duy (3):\n  gc.txt: more details about what gc does\n  worktree: delete dead code\n  worktree prune: improve prune logic when worktree is moved\n\n Documentation/git-gc.txt               | 12 ++++++++++--\n Documentation/gitrepository-layout.txt |  5 -----\n builtin/worktree.c                     | 11 +++--------\n 3 files changed, 13 insertions(+), 15 deletions(-)\n\n-- \n2.16.1.435.g8f24da2e1a\n\n"},{"id":"340860","messageId":"20180303033918.15751-2-pclouds@gmail.com","threadId":"47964","inReplyTo":"20180303033918.15751-1-pclouds@gmail.com","subject":"[PATCH 1/3] gc.txt: more details about what gc does","fromName":"Nguyễn Thái Ngọc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2018-03-03T03:39:16Z","receivedAt":"2018-03-03T03:39:34Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n---\n Documentation/git-gc.txt | 12 ++++++++++--\n 1 file changed, 10 insertions(+), 2 deletions(-)\n\ndiff --git a/Documentation/git-gc.txt b/Documentation/git-gc.txt\nindex 571b5a7e3c..862c931104 100644\n--- a/Documentation/git-gc.txt\n+++ b/Documentation/git-gc.txt\n@@ -15,8 +15,9 @@ DESCRIPTION\n -----------\n Runs a number of housekeeping tasks within the current repository,\n such as compressing file revisions (to reduce disk space and increase\n-performance) and removing unreachable objects which may have been\n-created from prior invocations of 'git add'.\n+performance), removing unreachable objects which may have been\n+created from prior invocations of 'git add', packing refs, pruning\n+reflog, rerere or stale working trees.\n \n Users are encouraged to run this task on a regular basis within\n each repository to maintain good disk space utilization and good\n@@ -59,6 +60,10 @@ then existing packs (except those marked with a `.keep` file)\n are consolidated into a single pack by using the `-A` option of\n 'git repack'. Setting `gc.autoPackLimit` to 0 disables\n automatic consolidation of packs.\n++\n+If `git gc --auto` goes ahead because of either too loose objects or\n+packs, all other housekeeping tasks (e.g. rerere, working trees,\n+reflog...) will also be be performed.\n \n --prune=<date>::\n \tPrune loose objects older than date (default is 2 weeks ago,\n@@ -133,6 +138,9 @@ The optional configuration variable `gc.pruneExpire` controls how old\n the unreferenced loose objects have to be before they are pruned.  The\n default is \"2 weeks ago\".\n \n+The optional gc.worktreePruneExpire controls how old a stale working\n+tree before `git worktree prune` deletes it. The default is \"3 months\n+ago\".\n \n Notes\n -----\n-- \n2.16.1.435.g8f24da2e1a\n\n"},{"id":"340861","messageId":"20180303033918.15751-3-pclouds@gmail.com","threadId":"47964","inReplyTo":"20180303033918.15751-1-pclouds@gmail.com","subject":"[PATCH 2/3] worktree: delete dead code","fromName":"Nguyễn Thái Ngọc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2018-03-03T03:39:17Z","receivedAt":"2018-03-03T03:39:39Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"This \"link\" was a feature in early iterations of multiple worktree\nfunctionality but for some reason it was dropped. Since nobody creates\nthis \"link\", there's no need to check it.\n\nThis is mostly used to let the user moves a worktree manually [1]. If\nyou move a worktree within the same file system, this hard link count\nlets us know the worktree is still there even if we don't know where it\nis.\n\nWe're having proper worktree move support now and don't need this\nanymore.\n\n[1] 23af91d102 (prune: strategies for linked checkouts - 2014-11-30)\n\nSigned-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n---\n Documentation/gitrepository-layout.txt | 5 -----\n builtin/worktree.c                     | 8 --------\n 2 files changed, 13 deletions(-)\n\ndiff --git a/Documentation/gitrepository-layout.txt b/Documentation/gitrepository-layout.txt\nindex c60bcad44a..e85148f05e 100644\n--- a/Documentation/gitrepository-layout.txt\n+++ b/Documentation/gitrepository-layout.txt\n@@ -275,11 +275,6 @@ worktrees/<id>/locked::\n \tor manually by `git worktree prune`. The file may contain a string\n \texplaining why the repository is locked.\n \n-worktrees/<id>/link::\n-\tIf this file exists, it is a hard link to the linked .git\n-\tfile. It is used to detect if the linked repository is\n-\tmanually removed.\n-\n SEE ALSO\n --------\n linkgit:git-init[1],\ndiff --git a/builtin/worktree.c b/builtin/worktree.c\nindex 4e7c98758f..60440c4106 100644\n--- a/builtin/worktree.c\n+++ b/builtin/worktree.c\n@@ -99,15 +99,7 @@ static int prune_worktree(const char *id, struct strbuf *reason)\n \t}\n \tpath[len] = '\\0';\n \tif (!file_exists(path)) {\n-\t\tstruct stat st_link;\n \t\tfree(path);\n-\t\t/*\n-\t\t * the repo is moved manually and has not been\n-\t\t * accessed since?\n-\t\t */\n-\t\tif (!stat(git_path(\"worktrees/%s/link\", id), &st_link) &&\n-\t\t    st_link.st_nlink > 1)\n-\t\t\treturn 0;\n \t\tif (st.st_mtime <= expire) {\n \t\t\tstrbuf_addf(reason, _(\"Removing worktrees/%s: gitdir file points to non-existent location\"), id);\n \t\t\treturn 1;\n-- \n2.16.1.435.g8f24da2e1a\n\n"},{"id":"340862","messageId":"20180303033918.15751-4-pclouds@gmail.com","threadId":"47964","inReplyTo":"20180303033918.15751-1-pclouds@gmail.com","subject":"[PATCH 3/3] worktree prune: improve prune logic when worktree is moved","fromName":"Nguyễn Thái Ngọc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2018-03-03T03:39:18Z","receivedAt":"2018-03-03T03:39:43Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"Worktree manual move support is actually gone in 618244e160 (worktree:\nstop supporting moving worktrees manually - 2016-01-22). Before that,\nthis gitdir could be updated often when the worktree is accessed. That\nkeeps the worktree from being pruned by this logic.\n\n\"git worktree move\" is coming so we don't really need this, but since\nit's easy to do, perhaps we could keep supporting manual worktree move a\nbit longer. Notice that when a worktree is active, the \"index\" file\nshould be updated pretty often in common case. The logic is updated to\ncheck for index mtime to see if the worktree is alive.\n\nSigned-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n---\n builtin/worktree.c | 3 +++\n 1 file changed, 3 insertions(+)\n\ndiff --git a/builtin/worktree.c b/builtin/worktree.c\nindex 60440c4106..4d4404e97f 100644\n--- a/builtin/worktree.c\n+++ b/builtin/worktree.c\n@@ -101,6 +101,9 @@ static int prune_worktree(const char *id, struct strbuf *reason)\n \tif (!file_exists(path)) {\n \t\tfree(path);\n \t\tif (st.st_mtime <= expire) {\n+\t\t\tif (!stat(git_path(\"worktrees/%s/index\", id), &st) &&\n+\t\t\t    st.st_mtime > expire)\n+\t\t\t\treturn 0;\n \t\t\tstrbuf_addf(reason, _(\"Removing worktrees/%s: gitdir file points to non-existent location\"), id);\n \t\t\treturn 1;\n \t\t} else {\n-- \n2.16.1.435.g8f24da2e1a\n\n"},{"id":"340881","messageId":"CAPig+cSo_n7y3-qDT92+NYspTB+yF+NUL19MLvfztLJ_qZhXnw@mail.gmail.com","threadId":"47964","inReplyTo":"20180303033918.15751-2-pclouds@gmail.com","subject":"Re: [PATCH 1/3] gc.txt: more details about what gc does","fromName":"Eric Sunshine","fromEmail":"sunshine@sunshineco.com","sentAt":"2018-03-03T09:14:16Z","receivedAt":"2018-03-03T09:14:22Z","isPatch":true,"sender":{"key":"sunshine@sunshineco.com","avatar":"https://avatars.githubusercontent.com/u/163641?v=4"},"body":"On Fri, Mar 2, 2018 at 10:39 PM, Nguyễn Thái Ngọc Duy <pclouds@gmail.com> wrote:\n> Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n> ---\n> diff --git a/Documentation/git-gc.txt b/Documentation/git-gc.txt\n> @@ -15,8 +15,9 @@ DESCRIPTION\n>  -----------\n>  Runs a number of housekeeping tasks within the current repository,\n>  such as compressing file revisions (to reduce disk space and increase\n> -performance) and removing unreachable objects which may have been\n> -created from prior invocations of 'git add'.\n> +performance), removing unreachable objects which may have been\n> +created from prior invocations of 'git add', packing refs, pruning\n> +reflog, rerere or stale working trees.\n\ns/rerere/& metadata/\n\n>  Users are encouraged to run this task on a regular basis within\n>  each repository to maintain good disk space utilization and good\n> @@ -59,6 +60,10 @@ then existing packs (except those marked with a `.keep` file)\n>  are consolidated into a single pack by using the `-A` option of\n>  'git repack'. Setting `gc.autoPackLimit` to 0 disables\n>  automatic consolidation of packs.\n> ++\n> +If `git gc --auto` goes ahead because of either too loose objects or\n> +packs, all other housekeeping tasks (e.g. rerere, working trees,\n> +reflog...) will also be be performed.\n\ns/be be/be/\n\nPerhaps this new paragraph should be moved up by one paragraph; the\nresult feels a bit more cohesive.\n\nMinor rewrite:\n\n    If `git gc --auto` finds that housekeeping is required due to too\n    many loose objects or packs, all other housekeeping tasks (e.g.\n    rerere, working trees, reflog...) will be performed, as well.\n\n> @@ -133,6 +138,9 @@ The optional configuration variable `gc.pruneExpire` controls how old\n>  the unreferenced loose objects have to be before they are pruned.  The\n>  default is \"2 weeks ago\".\n>\n> +The optional gc.worktreePruneExpire controls how old a stale working\n> +tree before `git worktree prune` deletes it. The default is \"3 months\n> +ago\".\n>\n>  Notes\n>  -----\n\nMissing backticks around \"gc.worktreePruneExpire\".\n\ns/tree before/tree should be before/\n\nYou lost a blank line before the \"Notes\" section.\n\nWith minor fixes:\n\n    Optional configuration variable `gc.worktreePruneExpire` controls\n    how old a stale working tree should be before `git worktree prune`\n    deletes it. Default is \"3 months ago\".\n"},{"id":"340885","messageId":"CAPig+cQG8yEqunNUjoEAPY-W9+TtzWADhgjdL6udnyrG0YEOVg@mail.gmail.com","threadId":"47964","inReplyTo":"20180303033918.15751-4-pclouds@gmail.com","subject":"Re: [PATCH 3/3] worktree prune: improve prune logic when worktree is moved","fromName":"Eric Sunshine","fromEmail":"sunshine@sunshineco.com","sentAt":"2018-03-03T09:30:01Z","receivedAt":"2018-03-03T09:30:09Z","isPatch":true,"sender":{"key":"sunshine@sunshineco.com","avatar":"https://avatars.githubusercontent.com/u/163641?v=4"},"body":"On Fri, Mar 2, 2018 at 10:39 PM, Nguyễn Thái Ngọc Duy <pclouds@gmail.com> wrote:\n> Worktree manual move support is actually gone in 618244e160 (worktree:\n> stop supporting moving worktrees manually - 2016-01-22). Before that,\n> this gitdir could be updated often when the worktree is accessed. That\n> keeps the worktree from being pruned by this logic.\n\nI had a bit of trouble digesting this paragraph. Possible rewrite:\n\n    Automatic detection of worktree relocation by a user (via 'mv',\n    for instance) was removed by 618244e160 (worktree: stop supporting\n    moving worktrees manually - 2016-01-22). Prior to that,\n    .git/worktrees/<tag>/gitdir was updated whenever the worktree was\n    accessed in order to let the pruning logic know that the worktree\n    was \"active\" even if it disappeared for a while (due to being\n    located on removable media, for instance).\n\n> \"git worktree move\" is coming so we don't really need this, but since\n> it's easy to do, perhaps we could keep supporting manual worktree move a\n> bit longer. Notice that when a worktree is active, the \"index\" file\n> should be updated pretty often in common case. The logic is updated to\n> check for index mtime to see if the worktree is alive.\n\nSeems like a reasonable approximation of the pre-618244e160 way things worked.\n\n> Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n> ---\n> diff --git a/builtin/worktree.c b/builtin/worktree.c\n> @@ -101,6 +101,9 @@ static int prune_worktree(const char *id, struct strbuf *reason)\n>         if (!file_exists(path)) {\n>                 free(path);\n>                 if (st.st_mtime <= expire) {\n\nThis st.st_mtime is that of 'gitdir'...\n\n> +                       if (!stat(git_path(\"worktrees/%s/index\", id), &st) &&\n> +                           st.st_mtime > expire)\n\n...and this st.st_mtime is of 'index'.\n\nI wonder if it the 'gitdir' mtime check is really that useful anymore\nconsidering that 'index' mtime will almost certainly be more recent.\n\n> +                               return 0;\n>                         strbuf_addf(reason, _(\"Removing worktrees/%s: gitdir file points to non-existent location\"), id);\n>                         return 1;\n"},{"id":"340940","messageId":"002601d3b2fa$ff6df240$fe49d6c0$@nexbridge.com","threadId":"47964","inReplyTo":"20180303033918.15751-1-pclouds@gmail.com","subject":"RE: [PATCH 0/3] git worktree prune improvements","fromName":"Randall S. Becker","fromEmail":"rsbecker@nexbridge.com","sentAt":"2018-03-03T14:21:56Z","receivedAt":"2018-03-03T14:22:16Z","isPatch":true,"sender":{"key":"randall.becker@nexbridge.ca","avatar":"https://avatars.githubusercontent.com/u/28956764?v=4"},"body":"On March 2, 2018 10:39 PM, Nguy?n Thái Ng?c Duy wrote:\n> This is something we could do to improve the situation when a user manually\n> moves a worktree and not follow the update process (we have had the first\n> reported case [1]). Plus a bit cleanup in gc.\n> \n> I think this is something we should do until we somehow make the user\n> aware that the worktree is broken as soon as they move a worktree\n> manually. But there's some more work to get there.\n> \n> [1] http://public-inbox.org/git/%3Caa98f187-4b1a-176d-2a1b-\n> 826c995776cd@aegee.org%3E\n\nI wonder whether the OT thread discussion about branch annotation may have some value here. For some repositories I manage, I have received questions about whether there was some way to know that a branch in the clone was associated with a worktree \"at any point in the past\", which, once the worktree has been pruned, is not derivable in a formal computational sense - there may be specific conditions where it is. Perhaps, if that line of development moves forward, that we should considering annotating the worktree-created branch to help with our pruning process and to identify where the branch originated.\n\nJust a thought.\n\nCheers,\nRandall\n\n-- Brief whoami:\n  NonStop developer since approximately NonStop(211288444200000000)\n  UNIX developer since approximately 421664400\n-- In my real life, I talk too much.\n\n\n\n"},{"id":"341015","messageId":"CACsJy8BvJPpR9hNcBoTze2fDhgWJ4Ya3u9YG5uNY8nu4_qRsVw@mail.gmail.com","threadId":"47964","inReplyTo":"002601d3b2fa$ff6df240$fe49d6c0$@nexbridge.com","subject":"Re: [PATCH 0/3] git worktree prune improvements","fromName":"Duy Nguyen","fromEmail":"pclouds@gmail.com","sentAt":"2018-03-05T12:16:02Z","receivedAt":"2018-03-05T12:16:38Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"On Sat, Mar 3, 2018 at 9:21 PM, Randall S. Becker\n<rsbecker@nexbridge.com> wrote:\n> On March 2, 2018 10:39 PM, Nguy?n Thái Ng?c Duy wrote:\n>> This is something we could do to improve the situation when a user manually\n>> moves a worktree and not follow the update process (we have had the first\n>> reported case [1]). Plus a bit cleanup in gc.\n>>\n>> I think this is something we should do until we somehow make the user\n>> aware that the worktree is broken as soon as they move a worktree\n>> manually. But there's some more work to get there.\n>>\n>> [1] http://public-inbox.org/git/%3Caa98f187-4b1a-176d-2a1b-\n>> 826c995776cd@aegee.org%3E\n>\n> I wonder whether the OT thread discussion about branch annotation may have some value here. For some repositories I manage, I have received questions about whether there was some way to know that a branch in the clone was associated with a worktree \"at any point in the past\", which, once the worktree has been pruned, is not derivable in a formal computational sense - there may be specific conditions where it is. Perhaps, if that line of development moves forward, that we should considering annotating the worktree-created branch to help with our pruning process and to identify where the branch originated.\n>\n\nI think for pruning, we already have that information. If a branch is\nassociated to a worktree, its HEAD must say so and we must not prune\nanything reachable from _any_ HEAD. I made that mistake actually.\nStill in process of fixing it (and fsck).\n-- \nDuy\n"},{"id":"341759","messageId":"20180315164412.14697-1-pclouds@gmail.com","threadId":"47964","inReplyTo":"20180303033918.15751-1-pclouds@gmail.com","subject":"[PATCH v2 0/3] git worktree prune improvements","fromName":"Nguyễn Thái Ngọc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2018-03-15T16:44:09Z","receivedAt":"2018-03-15T16:44:45Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"v2 fixes comments from Eric and rebases on 'master' since 'worktree\nmove' has been merged. Commit messages are updated to reflect this.\n\nThere's one thing I didn't do is moving the new paragraph up [1]. I\nstill feel this it's not right to put it there since it starts with\n'gc --auto' introduction, then goes to loose objects and packs.\nInserting a note between the loose objects paragraph and the packs one\ndoes not make much sense.\n\nInterdiff\n\n-- 8< --\ndiff --git a/Documentation/git-gc.txt b/Documentation/git-gc.txt\nindex 862c931104..3126e0dd00 100644\n--- a/Documentation/git-gc.txt\n+++ b/Documentation/git-gc.txt\n@@ -17,7 +17,7 @@ Runs a number of housekeeping tasks within the current repository,\n such as compressing file revisions (to reduce disk space and increase\n performance), removing unreachable objects which may have been\n created from prior invocations of 'git add', packing refs, pruning\n-reflog, rerere or stale working trees.\n+reflog, rerere metadata or stale working trees.\n \n Users are encouraged to run this task on a regular basis within\n each repository to maintain good disk space utilization and good\n@@ -46,14 +46,14 @@ OPTIONS\n \tWith this option, 'git gc' checks whether any housekeeping is\n \trequired; if not, it exits without performing any work.\n \tSome git commands run `git gc --auto` after performing\n-\toperations that could create many loose objects.\n+\toperations that could create many loose objects. Housekeeping\n+\tis required if there are too many loose objects or too many\n+\tpacks in the repository.\n +\n-Housekeeping is required if there are too many loose objects or\n-too many packs in the repository. If the number of loose objects\n-exceeds the value of the `gc.auto` configuration variable, then\n-all loose objects are combined into a single pack using\n-`git repack -d -l`.  Setting the value of `gc.auto` to 0\n-disables automatic packing of loose objects.\n+If the number of loose objects exceeds the value of the `gc.auto`\n+configuration variable, then all loose objects are combined into a\n+single pack using `git repack -d -l`.  Setting the value of `gc.auto`\n+to 0 disables automatic packing of loose objects.\n +\n If the number of packs exceeds the value of `gc.autoPackLimit`,\n then existing packs (except those marked with a `.keep` file)\n@@ -61,9 +61,10 @@ are consolidated into a single pack by using the `-A` option of\n 'git repack'. Setting `gc.autoPackLimit` to 0 disables\n automatic consolidation of packs.\n +\n-If `git gc --auto` goes ahead because of either too loose objects or\n-packs, all other housekeeping tasks (e.g. rerere, working trees,\n-reflog...) will also be be performed.\n+If houskeeping is required due to many loose objects or packs, all\n+other housekeeping tasks (e.g. rerere, working trees, reflog...) will\n+be performed as well.\n+\n \n --prune=<date>::\n \tPrune loose objects older than date (default is 2 weeks ago,\n@@ -138,9 +139,10 @@ The optional configuration variable `gc.pruneExpire` controls how old\n the unreferenced loose objects have to be before they are pruned.  The\n default is \"2 weeks ago\".\n \n-The optional gc.worktreePruneExpire controls how old a stale working\n-tree before `git worktree prune` deletes it. The default is \"3 months\n-ago\".\n+Optional configuration variable `gc.worktreePruneExpire` controls how\n+old a stale working tree should be before `git worktree prune` deletes\n+it. Default is \"3 months ago\".\n+\n \n Notes\n -----\ndiff --git a/builtin/worktree.c b/builtin/worktree.c\nindex 4d4404e97f..b1e8f0534c 100644\n--- a/builtin/worktree.c\n+++ b/builtin/worktree.c\n@@ -100,10 +100,8 @@ static int prune_worktree(const char *id, struct strbuf *reason)\n \tpath[len] = '\\0';\n \tif (!file_exists(path)) {\n \t\tfree(path);\n-\t\tif (st.st_mtime <= expire) {\n-\t\t\tif (!stat(git_path(\"worktrees/%s/index\", id), &st) &&\n-\t\t\t    st.st_mtime > expire)\n-\t\t\t\treturn 0;\n+\t\tif (stat(git_path(\"worktrees/%s/index\", id), &st) ||\n+\t\t    st.st_mtime <= expire) {\n \t\t\tstrbuf_addf(reason, _(\"Removing worktrees/%s: gitdir file points to non-existent location\"), id);\n \t\t\treturn 1;\n \t\t} else {\ndiff --git a/t/t2026-worktree-prune.sh b/t/t2026-worktree-prune.sh\nindex a0f1e3bb80..b7d6d5d45a 100755\n--- a/t/t2026-worktree-prune.sh\n+++ b/t/t2026-worktree-prune.sh\n@@ -78,10 +78,9 @@ test_expect_success 'not prune locked checkout' '\n \n test_expect_success 'not prune recent checkouts' '\n \ttest_when_finished rm -r .git/worktrees &&\n-\tmkdir zz &&\n-\tmkdir -p .git/worktrees/jlm &&\n-\techo \"$(pwd)\"/zz >.git/worktrees/jlm/gitdir &&\n-\trmdir zz &&\n+\tgit worktree add jlm HEAD &&\n+\ttest -d .git/worktrees/jlm &&\n+\trm -rf jlm &&\n \tgit worktree prune --verbose --expire=2.days.ago &&\n \ttest -d .git/worktrees/jlm\n '\n-- 8< --\n\n\n[1] https://public-inbox.org/git/CAPig+cSo_n7y3-qDT92+NYspTB+yF+NUL19MLvfztLJ_qZhXnw@mail.gmail.com/\n\nNguyễn Thái Ngọc Duy (3):\n  gc.txt: more details about what gc does\n  worktree: delete dead code\n  worktree prune: improve prune logic when worktree is moved\n\n Documentation/git-gc.txt               | 28 +++++++++++++++++---------\n Documentation/gitrepository-layout.txt |  5 -----\n builtin/worktree.c                     | 11 ++--------\n t/t2026-worktree-prune.sh              |  7 +++----\n 4 files changed, 24 insertions(+), 27 deletions(-)\n\n-- \n2.16.2.903.gd04caf5039\n\n"},{"id":"341760","messageId":"20180315164412.14697-2-pclouds@gmail.com","threadId":"47964","inReplyTo":"20180315164412.14697-1-pclouds@gmail.com","subject":"[PATCH v2 1/3] gc.txt: more details about what gc does","fromName":"Nguyễn Thái Ngọc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2018-03-15T16:44:10Z","receivedAt":"2018-03-15T16:44:48Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n---\n Documentation/git-gc.txt | 28 +++++++++++++++++++---------\n 1 file changed, 19 insertions(+), 9 deletions(-)\n\ndiff --git a/Documentation/git-gc.txt b/Documentation/git-gc.txt\nindex 571b5a7e3c..3126e0dd00 100644\n--- a/Documentation/git-gc.txt\n+++ b/Documentation/git-gc.txt\n@@ -15,8 +15,9 @@ DESCRIPTION\n -----------\n Runs a number of housekeeping tasks within the current repository,\n such as compressing file revisions (to reduce disk space and increase\n-performance) and removing unreachable objects which may have been\n-created from prior invocations of 'git add'.\n+performance), removing unreachable objects which may have been\n+created from prior invocations of 'git add', packing refs, pruning\n+reflog, rerere metadata or stale working trees.\n \n Users are encouraged to run this task on a regular basis within\n each repository to maintain good disk space utilization and good\n@@ -45,20 +46,25 @@ OPTIONS\n \tWith this option, 'git gc' checks whether any housekeeping is\n \trequired; if not, it exits without performing any work.\n \tSome git commands run `git gc --auto` after performing\n-\toperations that could create many loose objects.\n+\toperations that could create many loose objects. Housekeeping\n+\tis required if there are too many loose objects or too many\n+\tpacks in the repository.\n +\n-Housekeeping is required if there are too many loose objects or\n-too many packs in the repository. If the number of loose objects\n-exceeds the value of the `gc.auto` configuration variable, then\n-all loose objects are combined into a single pack using\n-`git repack -d -l`.  Setting the value of `gc.auto` to 0\n-disables automatic packing of loose objects.\n+If the number of loose objects exceeds the value of the `gc.auto`\n+configuration variable, then all loose objects are combined into a\n+single pack using `git repack -d -l`.  Setting the value of `gc.auto`\n+to 0 disables automatic packing of loose objects.\n +\n If the number of packs exceeds the value of `gc.autoPackLimit`,\n then existing packs (except those marked with a `.keep` file)\n are consolidated into a single pack by using the `-A` option of\n 'git repack'. Setting `gc.autoPackLimit` to 0 disables\n automatic consolidation of packs.\n++\n+If houskeeping is required due to many loose objects or packs, all\n+other housekeeping tasks (e.g. rerere, working trees, reflog...) will\n+be performed as well.\n+\n \n --prune=<date>::\n \tPrune loose objects older than date (default is 2 weeks ago,\n@@ -133,6 +139,10 @@ The optional configuration variable `gc.pruneExpire` controls how old\n the unreferenced loose objects have to be before they are pruned.  The\n default is \"2 weeks ago\".\n \n+Optional configuration variable `gc.worktreePruneExpire` controls how\n+old a stale working tree should be before `git worktree prune` deletes\n+it. Default is \"3 months ago\".\n+\n \n Notes\n -----\n-- \n2.16.2.903.gd04caf5039\n\n"},{"id":"341761","messageId":"20180315164412.14697-3-pclouds@gmail.com","threadId":"47964","inReplyTo":"20180315164412.14697-1-pclouds@gmail.com","subject":"[PATCH v2 2/3] worktree: delete dead code","fromName":"Nguyễn Thái Ngọc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2018-03-15T16:44:11Z","receivedAt":"2018-03-15T16:44:50Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"This \"link\" was a feature in early iterations of multiple worktree\nfunctionality for some reason it was dropped [1]. Since nobody creates\nthis \"link\", there's no need to check it.\n\nThis is mostly used to let the user moves a worktree manually [2]. If\nyou move a worktree within the same file system, this hard link count\nlets us know the worktree is still there even if we don't know where it\nis.\n\nWe support 'worktree move' now and don't need this anymore.\n\n[1] last appearance in v4 message-id:\n    1393675983-3232-25-git-send-email-pclouds@gmail.com\n    and the reason in v5 was \"revisit later\", message-id:\n    1394246900-31535-1-git-send-email-pclouds@gmail.com\n[2] 23af91d102 (prune: strategies for linked checkouts - 2014-11-30)\n\nSigned-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n---\n Documentation/gitrepository-layout.txt | 5 -----\n builtin/worktree.c                     | 8 --------\n 2 files changed, 13 deletions(-)\n\ndiff --git a/Documentation/gitrepository-layout.txt b/Documentation/gitrepository-layout.txt\nindex c60bcad44a..e85148f05e 100644\n--- a/Documentation/gitrepository-layout.txt\n+++ b/Documentation/gitrepository-layout.txt\n@@ -275,11 +275,6 @@ worktrees/<id>/locked::\n \tor manually by `git worktree prune`. The file may contain a string\n \texplaining why the repository is locked.\n \n-worktrees/<id>/link::\n-\tIf this file exists, it is a hard link to the linked .git\n-\tfile. It is used to detect if the linked repository is\n-\tmanually removed.\n-\n SEE ALSO\n --------\n linkgit:git-init[1],\ndiff --git a/builtin/worktree.c b/builtin/worktree.c\nindex 670555dedd..e55edf2aa5 100644\n--- a/builtin/worktree.c\n+++ b/builtin/worktree.c\n@@ -101,15 +101,7 @@ static int prune_worktree(const char *id, struct strbuf *reason)\n \t}\n \tpath[len] = '\\0';\n \tif (!file_exists(path)) {\n-\t\tstruct stat st_link;\n \t\tfree(path);\n-\t\t/*\n-\t\t * the repo is moved manually and has not been\n-\t\t * accessed since?\n-\t\t */\n-\t\tif (!stat(git_path(\"worktrees/%s/link\", id), &st_link) &&\n-\t\t    st_link.st_nlink > 1)\n-\t\t\treturn 0;\n \t\tif (st.st_mtime <= expire) {\n \t\t\tstrbuf_addf(reason, _(\"Removing worktrees/%s: gitdir file points to non-existent location\"), id);\n \t\t\treturn 1;\n-- \n2.16.2.903.gd04caf5039\n\n"},{"id":"341762","messageId":"20180315164412.14697-4-pclouds@gmail.com","threadId":"47964","inReplyTo":"20180315164412.14697-1-pclouds@gmail.com","subject":"[PATCH v2 3/3] worktree prune: improve prune logic when worktree is moved","fromName":"Nguyễn Thái Ngọc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2018-03-15T16:44:12Z","receivedAt":"2018-03-15T16:44:54Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"Automatic detection of worktree relocation by a user (via 'mv', for\ninstance) was removed by 618244e160 (worktree: stop supporting moving\nworktrees manually - 2016-01-22). Prior to that,\n.git/worktrees/<tag>/gitdir was updated whenever the worktree was\naccessed in order to let the pruning logic know that the worktree was\n\"active\" even if it disappeared for a while (due to being located on\nremovable media, for instance).\n\n\"git worktree move\" has come so we don't really need this, but since\nit's easy to do, perhaps we could keep supporting manual worktree move\na bit longer. Notice that when a worktree is active, the \"index\" file\nshould be updated pretty often in common case. The logic is updated to\ncheck for index mtime to see if the worktree is alive.\n\nThe old logic of checking gitdir's mtime is dropped because nobody\nupdates it anyway. The new corner case is, if the index file does not\nexist, we immediately remove the stale worktree. But if the \"index\"\nfile does not exist, you may have a bigger problem.\n\nSigned-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n---\n builtin/worktree.c        | 3 ++-\n t/t2026-worktree-prune.sh | 7 +++----\n 2 files changed, 5 insertions(+), 5 deletions(-)\n\ndiff --git a/builtin/worktree.c b/builtin/worktree.c\nindex e55edf2aa5..594ace7c2b 100644\n--- a/builtin/worktree.c\n+++ b/builtin/worktree.c\n@@ -102,7 +102,8 @@ static int prune_worktree(const char *id, struct strbuf *reason)\n \tpath[len] = '\\0';\n \tif (!file_exists(path)) {\n \t\tfree(path);\n-\t\tif (st.st_mtime <= expire) {\n+\t\tif (stat(git_path(\"worktrees/%s/index\", id), &st) ||\n+\t\t    st.st_mtime <= expire) {\n \t\t\tstrbuf_addf(reason, _(\"Removing worktrees/%s: gitdir file points to non-existent location\"), id);\n \t\t\treturn 1;\n \t\t} else {\ndiff --git a/t/t2026-worktree-prune.sh b/t/t2026-worktree-prune.sh\nindex a0f1e3bb80..b7d6d5d45a 100755\n--- a/t/t2026-worktree-prune.sh\n+++ b/t/t2026-worktree-prune.sh\n@@ -78,10 +78,9 @@ test_expect_success 'not prune locked checkout' '\n \n test_expect_success 'not prune recent checkouts' '\n \ttest_when_finished rm -r .git/worktrees &&\n-\tmkdir zz &&\n-\tmkdir -p .git/worktrees/jlm &&\n-\techo \"$(pwd)\"/zz >.git/worktrees/jlm/gitdir &&\n-\trmdir zz &&\n+\tgit worktree add jlm HEAD &&\n+\ttest -d .git/worktrees/jlm &&\n+\trm -rf jlm &&\n \tgit worktree prune --verbose --expire=2.days.ago &&\n \ttest -d .git/worktrees/jlm\n '\n-- \n2.16.2.903.gd04caf5039\n\n"},{"id":"342117","messageId":"CAPig+cSrsc4MhFf_h4b0Rc=hsxux4p=pkQkYVfs_zTR3u7sH-A@mail.gmail.com","threadId":"47964","inReplyTo":"20180315164412.14697-3-pclouds@gmail.com","subject":"Re: [PATCH v2 2/3] worktree: delete dead code","fromName":"Eric Sunshine","fromEmail":"sunshine@sunshineco.com","sentAt":"2018-03-18T22:51:11Z","receivedAt":"2018-03-18T22:51:17Z","isPatch":true,"sender":{"key":"sunshine@sunshineco.com","avatar":"https://avatars.githubusercontent.com/u/163641?v=4"},"body":"On Thu, Mar 15, 2018 at 12:44 PM, Nguyễn Thái Ngọc Duy\n<pclouds@gmail.com> wrote:\n> This \"link\" was a feature in early iterations of multiple worktree\n> functionality for some reason it was dropped [1]. Since nobody creates\n> this \"link\", there's no need to check it.\n>\n> This is mostly used to let the user moves a worktree manually [2]. If\n\ns/moves/move/\n\n(Not worth a re-roll; perhaps Junio can tweak this when queuing.)\n\n> you move a worktree within the same file system, this hard link count\n> lets us know the worktree is still there even if we don't know where it\n> is.\n>\n> We support 'worktree move' now and don't need this anymore.\n>\n> [1] last appearance in v4 message-id:\n>     1393675983-3232-25-git-send-email-pclouds@gmail.com\n>     and the reason in v5 was \"revisit later\", message-id:\n>     1394246900-31535-1-git-send-email-pclouds@gmail.com\n> [2] 23af91d102 (prune: strategies for linked checkouts - 2014-11-30)\n>\n> Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n"},{"id":"342118","messageId":"CAPig+cTwFCtNNJomC-8RHNYErkbZ821hm3mWGBXATedEcy44Jg@mail.gmail.com","threadId":"47964","inReplyTo":"20180315164412.14697-4-pclouds@gmail.com","subject":"Re: [PATCH v2 3/3] worktree prune: improve prune logic when worktree is moved","fromName":"Eric Sunshine","fromEmail":"sunshine@sunshineco.com","sentAt":"2018-03-18T22:59:28Z","receivedAt":"2018-03-18T22:59:38Z","isPatch":true,"sender":{"key":"sunshine@sunshineco.com","avatar":"https://avatars.githubusercontent.com/u/163641?v=4"},"body":"On Thu, Mar 15, 2018 at 12:44 PM, Nguyễn Thái Ngọc Duy\n<pclouds@gmail.com> wrote:\n> Automatic detection of worktree relocation by a user (via 'mv', for\n> instance) was removed by 618244e160 (worktree: stop supporting moving\n> worktrees manually - 2016-01-22). Prior to that,\n> .git/worktrees/<tag>/gitdir was updated whenever the worktree was\n> accessed in order to let the pruning logic know that the worktree was\n> \"active\" even if it disappeared for a while (due to being located on\n> removable media, for instance).\n\nThis is my fault since I suggested this rewrite[1], but other\ndocumentation calls this <id>, not <tag>, so: s/tag/id/\n\n(Again, not worth a re-roll; perhaps Junio can tweak it when queuing.)\n\n> \"git worktree move\" has come so we don't really need this, but since\n> it's easy to do, perhaps we could keep supporting manual worktree move\n> a bit longer. Notice that when a worktree is active, the \"index\" file\n> should be updated pretty often in common case. The logic is updated to\n> check for index mtime to see if the worktree is alive.\n>\n> The old logic of checking gitdir's mtime is dropped because nobody\n> updates it anyway. The new corner case is, if the index file does not\n> exist, we immediately remove the stale worktree. But if the \"index\"\n> file does not exist, you may have a bigger problem.\n\nMakes sense.\n\n> Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>\n\n[1]: https://public-inbox.org/git/CAPig+cQG8yEqunNUjoEAPY-W9+TtzWADhgjdL6udnyrG0YEOVg@mail.gmail.com/\n"},{"id":"342119","messageId":"CAPig+cSgmpXdSiEGLGTZaSDKFXsWoH76OCJnf9xu3XWZJxUfRA@mail.gmail.com","threadId":"47964","inReplyTo":"20180315164412.14697-1-pclouds@gmail.com","subject":"Re: [PATCH v2 0/3] git worktree prune improvements","fromName":"Eric Sunshine","fromEmail":"sunshine@sunshineco.com","sentAt":"2018-03-18T23:02:00Z","receivedAt":"2018-03-18T23:02:06Z","isPatch":true,"sender":{"key":"sunshine@sunshineco.com","avatar":"https://avatars.githubusercontent.com/u/163641?v=4"},"body":"On Thu, Mar 15, 2018 at 12:44 PM, Nguyễn Thái Ngọc Duy\n<pclouds@gmail.com> wrote:\n> v2 fixes comments from Eric and rebases on 'master' since 'worktree\n> move' has been merged. Commit messages are updated to reflect this.\n\nThanks. Aside from a couple minor commit message tweaks (not worth a\nre-roll), I didn't find anything else on which to comment on this\nversion.\n\n> There's one thing I didn't do is moving the new paragraph up [1]. I\n> still feel this it's not right to put it there since it starts with\n> 'gc --auto' introduction, then goes to loose objects and packs.\n> Inserting a note between the loose objects paragraph and the packs one\n> does not make much sense.\n\nFair enough.\n"}]}