{"thread":{"id":"15859","subject":"[PATCH] Introduce core.keepHardLinks","startedAt":"2008-10-11T11:45:13Z","lastAt":"2008-10-15T09:07:32Z","messageCount":14,"participants":["Johannes Schindelin","Shawn O. Pearce","Junio C Hamano","Stephan Beyer"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"92793","messageId":"alpine.DEB.1.00.0810111344241.22125@pacific.mpi-cbg.de.mpi-cbg.de","threadId":"15859","inReplyTo":null,"subject":"[PATCH] Introduce core.keepHardLinks","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2008-10-11T11:45:13Z","receivedAt":"2008-10-11T11:45:13Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"\nWhen a tracked file was hard linked, we used to break the hard link\nwhenever Git writes to that file.  Make that optional.\n\nTo keep the implementation simple, mode changes will still break the\nhard links.\n\nSigned-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>\n---\n\n\tWith the current revision of the patch, I can set\n\tkeep_hard_links = 1 and the test suite still passes.\n\n\tI briefly tried to fix the \"mode changes\" issue, but replacing\n\tthe \"st.st_mode != ce->ce_mode\" with \"S_ISREG(ce->ce_mode)\"\n\t(and consequently also adding\n\t \"|| (keep_hard_links && chmod(path, mode)\" to create_file()),\n\tmade at least t3400 fail, and then I ran out of my Git time budget.\n\n Documentation/config.txt |    4 +++\n cache.h                  |    1 +\n config.c                 |    5 ++++\n entry.c                  |    7 ++++-\n environment.c            |    1 +\n t/t0056-hardlinked.sh    |   58 ++++++++++++++++++++++++++++++++++++++++++++++\n 6 files changed, 74 insertions(+), 2 deletions(-)\n create mode 100644 t/t0056-hardlinked.sh\n\ndiff --git a/Documentation/config.txt b/Documentation/config.txt\nindex 173386e..7bfe431 100644\n--- a/Documentation/config.txt\n+++ b/Documentation/config.txt\n@@ -207,6 +207,10 @@ core.symlinks::\n \tfile. Useful on filesystems like FAT that do not support\n \tsymbolic links. True by default.\n \n+core.keepHardLinks::\n+\tIf true, do not break hard links by deleting and recreating the\n+\tfiles.  Off by default.\n+\n core.gitProxy::\n \tA \"proxy command\" to execute (as 'command host port') instead\n \tof establishing direct connection to the remote server when\ndiff --git a/cache.h b/cache.h\nindex c89f2c6..c4bdece 100644\n--- a/cache.h\n+++ b/cache.h\n@@ -479,6 +479,7 @@ enum rebase_setup_type {\n \n extern enum branch_track git_branch_track;\n extern enum rebase_setup_type autorebase;\n+extern int keep_hard_links;\n \n #define GIT_REPO_VERSION 0\n extern int repository_format_version;\ndiff --git a/config.c b/config.c\nindex 18d305c..35ffdef 100644\n--- a/config.c\n+++ b/config.c\n@@ -490,6 +490,11 @@ static int git_default_core_config(const char *var, const char *value)\n \t\treturn 0;\n \t}\n \n+\tif (!strcmp(var, \"core.keephardlinks\")) {\n+\t\tkeep_hard_links = git_config_bool(var, value);\n+\t\treturn 0;\n+\t}\n+\n \t/* Add other config variables here and to Documentation/config.txt. */\n \treturn 0;\n }\ndiff --git a/entry.c b/entry.c\nindex aa2ee46..dfddf83 100644\n--- a/entry.c\n+++ b/entry.c\n@@ -82,7 +82,8 @@ static void remove_subtree(const char *path)\n static int create_file(const char *path, unsigned int mode)\n {\n \tmode = (mode & 0100) ? 0777 : 0666;\n-\treturn open(path, O_WRONLY | O_CREAT | O_EXCL, mode);\n+\treturn open(path, O_WRONLY | O_CREAT |\n+\t\t\t(keep_hard_links ? O_TRUNC : O_EXCL), mode);\n }\n \n static void *read_blob_entry(struct cache_entry *ce, const char *path, unsigned long *size)\n@@ -225,7 +226,9 @@ int checkout_entry(struct cache_entry *ce, const struct checkout *state, char *t\n \t\t\tif (!state->force)\n \t\t\t\treturn error(\"%s is a directory\", path);\n \t\t\tremove_subtree(path);\n-\t\t} else if (unlink(path))\n+\t\t} else if ((!keep_hard_links || !S_ISREG(st.st_mode) ||\n+\t\t\t\t\tst.st_mode != ce->ce_mode) &&\n+\t\t\t\tunlink(path))\n \t\t\treturn error(\"unable to unlink old '%s' (%s)\", path, strerror(errno));\n \t} else if (state->not_new)\n \t\treturn 0;\ndiff --git a/environment.c b/environment.c\nindex 0693cd9..ef721e0 100644\n--- a/environment.c\n+++ b/environment.c\n@@ -42,6 +42,7 @@ enum safe_crlf safe_crlf = SAFE_CRLF_WARN;\n unsigned whitespace_rule_cfg = WS_DEFAULT_RULE;\n enum branch_track git_branch_track = BRANCH_TRACK_REMOTE;\n enum rebase_setup_type autorebase = AUTOREBASE_NEVER;\n+int keep_hard_links = 0;\n \n /* This is set by setup_git_dir_gently() and/or git_default_config() */\n char *git_work_tree_cfg;\ndiff --git a/t/t0056-hardlinked.sh b/t/t0056-hardlinked.sh\nnew file mode 100644\nindex 0000000..934c2bc\n--- /dev/null\n+++ b/t/t0056-hardlinked.sh\n@@ -0,0 +1,58 @@\n+#!/bin/sh\n+\n+test_description='read-tree and checkout respect hardlinked files'\n+\n+. ./test-lib.sh\n+\n+cat > file << EOF\n+1. Nf3 Nf6 2. c4 g6 3. Nc3 Bg7 4. d4 O-O 5. Bf4 d5 6. Qb3 dxc4 7. Qxc4 c6\n+8. e4 Nbd7 9. Rd1 Nb6 10. Qc5 Bg4 11. Bg5 Na4 12. Qa3 Nxc3 13. bxc3 Nxe4\n+14. Bxe7 Qb6 15. Bc4 Nxc3 16. Bc5 Rfe8+ 17. Kf1 Be6 18. Bxb6 Bxc4+ 19. Kg1 Ne2+\n+20. Kf1 Nxd4+ 21. Kg1 Ne2+ 22. Kf1 Nc3+ 23. Kg1 axb6 24. Qb4 Ra4 25. Qxb6 Nxd1\n+26. h3 Rxa2 27. Kh2 Nxf2 28. Re1 Rxe1 29. Qd8+ Bf8 30. Nxe1 Bd5 31. Nf3 Ne4\n+32. Qb8 b5 33. h4 h5 34. Ne5 Kg7 35. Kg1 Bc5+ 36. Kf1 Ng3+ 37. Ke1 Bb4+\n+38. Kd1 Bb3+ 39. Kc1 Ne2+ 40. Kb1 Nc3+\n+EOF\n+\n+ln file link || {\n+\tsay \"Could not hard link; skipping test\"\n+\ttest_done\n+\texit\n+}\n+\n+test_expect_success setup '\n+\n+\tgit config core.keepHardLinks true &&\n+\ttest_cmp file link &&\n+\tcp file old &&\n+\tgit add file &&\n+\ttest_tick &&\n+\tgit commit -m initial &&\n+\techo \"41. Kc1 Rc2#\" >> file &&\n+\tgit add file &&\n+\ttest_tick &&\n+\tgit commit -m 2nd &&\n+\ttest_cmp file link &&\n+\t! test_cmp file old\n+\n+'\n+\n+test_expect_success 'checking a file out does not break the hard link' '\n+\n+\tgit checkout HEAD^ -- file &&\n+\ttest_cmp file link &&\n+\ttest_cmp file old\n+\n+'\n+\n+test_expect_success 'read-tree -u -m does not break the hard link' '\n+\n+\tgit reset --hard &&\n+\ttest_cmp file link &&\n+\tgit read-tree -u -m HEAD^ &&\n+\ttest_cmp file link &&\n+\ttest_cmp file old\n+\n+'\n+\n+test_done\n-- \n1.6.0.2.749.g0cc32\n"},{"id":"92864","messageId":"20081012183855.GA5255@spearce.org","threadId":"15859","inReplyTo":"alpine.DEB.1.00.0810111344241.22125@pacific.mpi-cbg.de.mpi-cbg.de","subject":"Re: [PATCH] Introduce core.keepHardLinks","fromName":"Shawn O. Pearce","fromEmail":"spearce@spearce.org","sentAt":"2008-10-12T18:38:55Z","receivedAt":"2008-10-12T18:38:55Z","isPatch":true,"sender":{"key":"spearce@spearce.org","avatar":"https://avatars.githubusercontent.com/u/34844?v=4"},"body":"Johannes Schindelin <Johannes.Schindelin@gmx.de> wrote:\n> \n> When a tracked file was hard linked, we used to break the hard link\n> whenever Git writes to that file.  Make that optional.\n\nWhy would anyone want to do this?\n\nI cannot fathom why a user wants this much rope to hang themselves\nwith...\n\n \n> diff --git a/Documentation/config.txt b/Documentation/config.txt\n> index 173386e..7bfe431 100644\n> --- a/Documentation/config.txt\n> +++ b/Documentation/config.txt\n> @@ -207,6 +207,10 @@ core.symlinks::\n>  \tfile. Useful on filesystems like FAT that do not support\n>  \tsymbolic links. True by default.\n>  \n> +core.keepHardLinks::\n> +\tIf true, do not break hard links by deleting and recreating the\n> +\tfiles.  Off by default.\n> +\n>  core.gitProxy::\n>  \tA \"proxy command\" to execute (as 'command host port') instead\n>  \tof establishing direct connection to the remote server when\n\n-- \nShawn.\n"},{"id":"92904","messageId":"7vskr1c976.fsf@gitster.siamese.dyndns.org","threadId":"15859","inReplyTo":"alpine.DEB.1.00.0810111344241.22125@pacific.mpi-cbg.de.mpi-cbg.de","subject":"Re: [PATCH] Introduce core.keepHardLinks","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2008-10-13T06:15:09Z","receivedAt":"2008-10-13T06:15:09Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Shawn had this queued in pu, but it appears to even fail its own tests on\nmy machine, when applied on top of 'master'.\n\nI tentatively dropped this from pu.\n"},{"id":"92915","messageId":"alpine.DEB.1.00.0810131057150.22125@pacific.mpi-cbg.de.mpi-cbg.de","threadId":"15859","inReplyTo":"20081012183855.GA5255@spearce.org","subject":"Re: [PATCH] Introduce core.keepHardLinks","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2008-10-13T08:58:01Z","receivedAt":"2008-10-13T08:58:01Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Sun, 12 Oct 2008, Shawn O. Pearce wrote:\n\n> Johannes Schindelin <Johannes.Schindelin@gmx.de> wrote:\n> > \n> > When a tracked file was hard linked, we used to break the hard link\n> > whenever Git writes to that file.  Make that optional.\n> \n> Why would anyone want to do this?\n> \n> I cannot fathom why a user wants this much rope to hang themselves \n> with...\n\nThe question is not so much why anyone want to do this, but _if_.\n\nAnd the answer is: yes.\n\nCiao,\nDscho\n"},{"id":"92916","messageId":"alpine.DEB.1.00.0810131058110.22125@pacific.mpi-cbg.de.mpi-cbg.de","threadId":"15859","inReplyTo":"7vskr1c976.fsf@gitster.siamese.dyndns.org","subject":"Re: [PATCH] Introduce core.keepHardLinks","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2008-10-13T09:03:38Z","receivedAt":"2008-10-13T09:03:38Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Sun, 12 Oct 2008, Junio C Hamano wrote:\n\n> Shawn had this queued in pu, but it appears to even fail its own tests \n> on my machine, when applied on top of 'master'.\n\nSorry, I cannot reproduce at all.\n\nI tested this on two machines, i686 and x86_64 (of course, on top of my \npatches to 'next', but now repeated the test with the commit \ncherry-picked to your 5c283eb(Merge branch 'maint')).\n\nIt passes.\n\nCiao,\nDscho\n\nP.S.: I even made \"make clean && make -j50 test\", just in case  we have \nsome dependency issue in the Makefile (happened before).  Still passes.\n\nP.P.S.: It would be nice if you could run the test with -i -v (and maybe \nwith sh -x) and post the output.  Thank you very much.\n\nP.P.P.S.: Just for reference: this is what the cherry-picked commit \nformat-patches to:\n\n-- snipsnap --\n[PATCH] Introduce core.keepHardLinks\n\nWhen a tracked file was hard linked, we used to break the hard link\nwhenever Git writes to that file.  Make that optional.\n\nTo keep the implementation simple, mode changes will still break the\nhard links.\n\nSigned-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>\n---\n Documentation/config.txt |    4 +++\n cache.h                  |    1 +\n config.c                 |    5 ++++\n entry.c                  |    7 ++++-\n environment.c            |    1 +\n t/t0056-hardlinked.sh    |   58 ++++++++++++++++++++++++++++++++++++++++++++++\n 6 files changed, 74 insertions(+), 2 deletions(-)\n create mode 100644 t/t0056-hardlinked.sh\n\ndiff --git a/Documentation/config.txt b/Documentation/config.txt\nindex da18a54..aacaeae 100644\n--- a/Documentation/config.txt\n+++ b/Documentation/config.txt\n@@ -207,6 +207,10 @@ core.symlinks::\n \tfile. Useful on filesystems like FAT that do not support\n \tsymbolic links. True by default.\n \n+core.keepHardLinks::\n+\tIf true, do not break hard links by deleting and recreating the\n+\tfiles.  Off by default.\n+\n core.gitProxy::\n \tA \"proxy command\" to execute (as 'command host port') instead\n \tof establishing direct connection to the remote server when\ndiff --git a/cache.h b/cache.h\nindex 991544c..d6348a1 100644\n--- a/cache.h\n+++ b/cache.h\n@@ -478,6 +478,7 @@ enum rebase_setup_type {\n \n extern enum branch_track git_branch_track;\n extern enum rebase_setup_type autorebase;\n+extern int keep_hard_links;\n \n #define GIT_REPO_VERSION 0\n extern int repository_format_version;\ndiff --git a/config.c b/config.c\nindex b8d289d..944e18e 100644\n--- a/config.c\n+++ b/config.c\n@@ -490,6 +490,11 @@ static int git_default_core_config(const char *var, const char *value)\n \t\treturn 0;\n \t}\n \n+\tif (!strcmp(var, \"core.keephardlinks\")) {\n+\t\tkeep_hard_links = git_config_bool(var, value);\n+\t\treturn 0;\n+\t}\n+\n \t/* Add other config variables here and to Documentation/config.txt. */\n \treturn 0;\n }\ndiff --git a/entry.c b/entry.c\nindex aa2ee46..dfddf83 100644\n--- a/entry.c\n+++ b/entry.c\n@@ -82,7 +82,8 @@ static void remove_subtree(const char *path)\n static int create_file(const char *path, unsigned int mode)\n {\n \tmode = (mode & 0100) ? 0777 : 0666;\n-\treturn open(path, O_WRONLY | O_CREAT | O_EXCL, mode);\n+\treturn open(path, O_WRONLY | O_CREAT |\n+\t\t\t(keep_hard_links ? O_TRUNC : O_EXCL), mode);\n }\n \n static void *read_blob_entry(struct cache_entry *ce, const char *path, unsigned long *size)\n@@ -225,7 +226,9 @@ int checkout_entry(struct cache_entry *ce, const struct checkout *state, char *t\n \t\t\tif (!state->force)\n \t\t\t\treturn error(\"%s is a directory\", path);\n \t\t\tremove_subtree(path);\n-\t\t} else if (unlink(path))\n+\t\t} else if ((!keep_hard_links || !S_ISREG(st.st_mode) ||\n+\t\t\t\t\tst.st_mode != ce->ce_mode) &&\n+\t\t\t\tunlink(path))\n \t\t\treturn error(\"unable to unlink old '%s' (%s)\", path, strerror(errno));\n \t} else if (state->not_new)\n \t\treturn 0;\ndiff --git a/environment.c b/environment.c\nindex 0693cd9..ef721e0 100644\n--- a/environment.c\n+++ b/environment.c\n@@ -42,6 +42,7 @@ enum safe_crlf safe_crlf = SAFE_CRLF_WARN;\n unsigned whitespace_rule_cfg = WS_DEFAULT_RULE;\n enum branch_track git_branch_track = BRANCH_TRACK_REMOTE;\n enum rebase_setup_type autorebase = AUTOREBASE_NEVER;\n+int keep_hard_links = 0;\n \n /* This is set by setup_git_dir_gently() and/or git_default_config() */\n char *git_work_tree_cfg;\ndiff --git a/t/t0056-hardlinked.sh b/t/t0056-hardlinked.sh\nnew file mode 100644\nindex 0000000..934c2bc\n--- /dev/null\n+++ b/t/t0056-hardlinked.sh\n@@ -0,0 +1,58 @@\n+#!/bin/sh\n+\n+test_description='read-tree and checkout respect hardlinked files'\n+\n+. ./test-lib.sh\n+\n+cat > file << EOF\n+1. Nf3 Nf6 2. c4 g6 3. Nc3 Bg7 4. d4 O-O 5. Bf4 d5 6. Qb3 dxc4 7. Qxc4 c6\n+8. e4 Nbd7 9. Rd1 Nb6 10. Qc5 Bg4 11. Bg5 Na4 12. Qa3 Nxc3 13. bxc3 Nxe4\n+14. Bxe7 Qb6 15. Bc4 Nxc3 16. Bc5 Rfe8+ 17. Kf1 Be6 18. Bxb6 Bxc4+ 19. Kg1 Ne2+\n+20. Kf1 Nxd4+ 21. Kg1 Ne2+ 22. Kf1 Nc3+ 23. Kg1 axb6 24. Qb4 Ra4 25. Qxb6 Nxd1\n+26. h3 Rxa2 27. Kh2 Nxf2 28. Re1 Rxe1 29. Qd8+ Bf8 30. Nxe1 Bd5 31. Nf3 Ne4\n+32. Qb8 b5 33. h4 h5 34. Ne5 Kg7 35. Kg1 Bc5+ 36. Kf1 Ng3+ 37. Ke1 Bb4+\n+38. Kd1 Bb3+ 39. Kc1 Ne2+ 40. Kb1 Nc3+\n+EOF\n+\n+ln file link || {\n+\tsay \"Could not hard link; skipping test\"\n+\ttest_done\n+\texit\n+}\n+\n+test_expect_success setup '\n+\n+\tgit config core.keepHardLinks true &&\n+\ttest_cmp file link &&\n+\tcp file old &&\n+\tgit add file &&\n+\ttest_tick &&\n+\tgit commit -m initial &&\n+\techo \"41. Kc1 Rc2#\" >> file &&\n+\tgit add file &&\n+\ttest_tick &&\n+\tgit commit -m 2nd &&\n+\ttest_cmp file link &&\n+\t! test_cmp file old\n+\n+'\n+\n+test_expect_success 'checking a file out does not break the hard link' '\n+\n+\tgit checkout HEAD^ -- file &&\n+\ttest_cmp file link &&\n+\ttest_cmp file old\n+\n+'\n+\n+test_expect_success 'read-tree -u -m does not break the hard link' '\n+\n+\tgit reset --hard &&\n+\ttest_cmp file link &&\n+\tgit read-tree -u -m HEAD^ &&\n+\ttest_cmp file link &&\n+\ttest_cmp file old\n+\n+'\n+\n+test_done\n-- \n1.6.0.2.749.g0cc32\n"},{"id":"92931","messageId":"7vskr0bnlk.fsf@gitster.siamese.dyndns.org","threadId":"15859","inReplyTo":"alpine.DEB.1.00.0810131057150.22125@pacific.mpi-cbg.de.mpi-cbg.de","subject":"Re: [PATCH] Introduce core.keepHardLinks","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2008-10-13T14:01:43Z","receivedAt":"2008-10-13T14:01:43Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:\n\n>> I cannot fathom why a user wants this much rope to hang themselves \n>> with...\n>\n> The question is not so much why anyone want to do this, but _if_.\n\nSorry, I think the question should be _why_.\n\nYou can gain a sympathetic \"Ah, that is sensible, and 'this much rope to\nhang themselves with' comment was unwarranted\" only by answering that\nquestion.\n"},{"id":"92938","messageId":"alpine.DEB.1.00.0810131611470.22125@pacific.mpi-cbg.de.mpi-cbg.de","threadId":"15859","inReplyTo":"7vskr0bnlk.fsf@gitster.siamese.dyndns.org","subject":"Re: [PATCH] Introduce core.keepHardLinks","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2008-10-13T16:09:21Z","receivedAt":"2008-10-13T16:09:21Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Mon, 13 Oct 2008, Junio C Hamano wrote:\n\n> Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:\n> \n> >> I cannot fathom why a user wants this much rope to hang themselves \n> >> with...\n> >\n> > The question is not so much why anyone want to do this, but _if_.\n> \n> Sorry, I think the question should be _why_.\n> \n> You can gain a sympathetic \"Ah, that is sensible, and 'this much rope to \n> hang themselves with' comment was unwarranted\" only by answering that \n> question.\n\nOkay, here are a couple of reasons:\n\n- all the editors that this guy tested keep the hard links, so it was \n  kinda hard to understand why Git insists on behaving differently,\n\n- if the user asked for hard links, it is not Git's place to question that \n  decision,\n\n- and in that user's scenario a certain file has to be shared between \n  different projects that are all version-controlled with Git, but in \n  different teams and with different servers they connect to.  So no, you \n  cannot even make a submodule of it, because the guys involved do not \n  share any repository/server access.  Besides, submodules are not \n  user-friendly enough yet.\n\nOh, and come to think of it, this could solve the old issue of \"I want to \ntrack only a few files in my $HOME/\".\n\nAnyway, I think that breaking hard links is not a nice habit of Git (after \nall, from the user's point of view the file is not created, but \nmodified!), and I would have expected others to need a lot less arguments \nto see it that way, too.\n\nCiao,\nDscho\n"},{"id":"92939","messageId":"20081013162132.GB20371@leksak.fem-net","threadId":"15859","inReplyTo":"alpine.DEB.1.00.0810131611470.22125@pacific.mpi-cbg.de.mpi-cbg.de","subject":"Re: [PATCH] Introduce core.keepHardLinks","fromName":"Stephan Beyer","fromEmail":"s-beyer@gmx.net","sentAt":"2008-10-13T16:21:32Z","receivedAt":"2008-10-13T16:21:32Z","isPatch":true,"sender":{"key":"s-beyer@gmx.net","avatar":"https://avatars.githubusercontent.com/u/143889?v=4"},"body":"Hi,\n\nJohannes Schindelin wrote:\n> and I would have expected others to need a lot less arguments \n> to see it that way, too.\n\nDespite the fact that I've never used hardlinks in a git repository, I\nwould have expected git to keep them.  So I'm one of the \"others\" who\nthinks this config option is just sane (and should perhaps even be\nenabled by default, if it does not break stuff on file systems that do\nnot have a hardlink feature... but ok)\n\nRegards,\n  Stephan\n\n-- \nStephan Beyer <s-beyer@gmx.net>, PGP 0x6EDDD207FCC5040F\n"},{"id":"92940","messageId":"20081013162351.GQ4856@spearce.org","threadId":"15859","inReplyTo":"20081013162132.GB20371@leksak.fem-net","subject":"Re: [PATCH] Introduce core.keepHardLinks","fromName":"Shawn O. Pearce","fromEmail":"spearce@spearce.org","sentAt":"2008-10-13T16:23:51Z","receivedAt":"2008-10-13T16:23:51Z","isPatch":true,"sender":{"key":"spearce@spearce.org","avatar":"https://avatars.githubusercontent.com/u/34844?v=4"},"body":"Stephan Beyer <s-beyer@gmx.net> wrote:\n> Johannes Schindelin wrote:\n> > and I would have expected others to need a lot less arguments \n> > to see it that way, too.\n> \n> Despite the fact that I've never used hardlinks in a git repository, I\n> would have expected git to keep them.  So I'm one of the \"others\" who\n> thinks this config option is just sane (and should perhaps even be\n> enabled by default, if it does not break stuff on file systems that do\n> not have a hardlink feature... but ok)\n\nMy problem is many users do \"cp -rl a b\" to clone a->b and hardlink\nthe working directory.  They expect \"cd b && git checkout foo\" to\nthen only unlink the paths that differ.  Updating the original inode\nwould break repository a.\n\nIts a change in behavior, to some of our oldest users.  So it can't\nreally be on by default.\n\n-- \nShawn.\n"},{"id":"92947","messageId":"7vhc7g9z7s.fsf@gitster.siamese.dyndns.org","threadId":"15859","inReplyTo":"alpine.DEB.1.00.0810131611470.22125@pacific.mpi-cbg.de.mpi-cbg.de","subject":"Re: [PATCH] Introduce core.keepHardLinks","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2008-10-13T17:33:43Z","receivedAt":"2008-10-13T17:33:43Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:\n\n> - all the editors that this guy tested keep the hard links, so it was \n>   kinda hard to understand why Git insists on behaving differently,\n>\n> - if the user asked for hard links, it is not Git's place to question that \n>   decision,\n\nThese are non-arguments, when you are asked to give rationale for adding\ncapability to \"ask for hard links\" to begin with.\n\nIOW, the question was why git should support tracked contents being\nhardlinked to something else.\n\n[jc: Sorry for dropping Shawn from CC: list.  pobox.com seems to complain\non his address for some reason.  Here are msmtp log for an identical\nmessage with and without him on the recipient list.\n\nOct 13 10:23:57 host=sasl.smtp.pobox.com tls=on auth=on user=junio@pobox.com from=junio@pobox.com recipients=Johannes.Schindelin@gmx.de,barkalow@iabervon.org,git@vger.kernel.org,spearce@spearce.org,gitster@pobox.com smtpstatus=451 smtpmsg='451 4.3.5 Server configuration problem' errormsg='recipient address spearce@spearce.org not accepted by the server' exitcode=EX_DATAERR\nOct 13 10:31:26 host=sasl.smtp.pobox.com tls=on auth=on user=junio@pobox.com from=junio@pobox.com recipients=Johannes.Schindelin@gmx.de,barkalow@iabervon.org,git@vger.kernel.org,gitster@pobox.com mailsize=2283 exitcode=EX_OK\n]\n"},{"id":"92950","messageId":"alpine.DEB.1.00.0810131950140.22125@pacific.mpi-cbg.de.mpi-cbg.de","threadId":"15859","inReplyTo":"7vhc7g9z7s.fsf@gitster.siamese.dyndns.org","subject":"Re: [PATCH] Introduce core.keepHardLinks","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2008-10-13T17:54:02Z","receivedAt":"2008-10-13T17:54:02Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Mon, 13 Oct 2008, Junio C Hamano wrote:\n\n> Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:\n> \n> > - all the editors that this guy tested keep the hard links, so it was \n> >   kinda hard to understand why Git insists on behaving differently,\n> >\n> > - if the user asked for hard links, it is not Git's place to question \n> >   that decision,\n> \n> These are non-arguments,\n\nActually, they are arguments.\n\nThe thing is: these editors do what they do for a reason.  Which is \nexactly the second reason.\n\nWhen a user makes hard links, it is not just for fun and bullocks.  It is \nnot for copy-on-write either, that's not what hard links are supposed to \ndo.  It is for cases when you need the _same_ information in two places.\n\nI am not that big a user of hard links myself, but when I do, I know \nexactly what I am doing.  And with my patch and that config variable set \nto true, Git will not interfer with that.\n\nCiao,\nDscho\n"},{"id":"92951","messageId":"alpine.DEB.1.00.0810131954180.22125@pacific.mpi-cbg.de.mpi-cbg.de","threadId":"15859","inReplyTo":"20081013162351.GQ4856@spearce.org","subject":"Re: [PATCH] Introduce core.keepHardLinks","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2008-10-13T17:55:47Z","receivedAt":"2008-10-13T17:55:47Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Mon, 13 Oct 2008, Shawn O. Pearce wrote:\n\n> Stephan Beyer <s-beyer@gmx.net> wrote:\n> > Johannes Schindelin wrote:\n> > > and I would have expected others to need a lot less arguments \n> > > to see it that way, too.\n> > \n> > Despite the fact that I've never used hardlinks in a git repository, I \n> > would have expected git to keep them.  So I'm one of the \"others\" who \n> > thinks this config option is just sane (and should perhaps even be \n> > enabled by default, if it does not break stuff on file systems that do \n> > not have a hardlink feature... but ok)\n> \n> My problem is many users do \"cp -rl a b\" to clone a->b and hardlink the \n> working directory.  They expect \"cd b && git checkout foo\" to then only \n> unlink the paths that differ.  Updating the original inode would break \n> repository a.\n> \n> Its a change in behavior, to some of our oldest users.  So it can't \n> really be on by default.\n\nWhich is the reason why my commit is not titled \"Make Git respect hard \nlinks by default\", but \"Introduce core.keepHardLinks\".  I also hate people \nwho try to break my setup.\n\nWhich scenario (breaking someone's setup) was exactly what triggered this \npatch.\n\nCiao,\nDscho\n"},{"id":"92955","messageId":"7v63nw9xor.fsf@gitster.siamese.dyndns.org","threadId":"15859","inReplyTo":"alpine.DEB.1.00.0810131950140.22125@pacific.mpi-cbg.de.mpi-cbg.de","subject":"Re: [PATCH] Introduce core.keepHardLinks","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2008-10-13T18:06:44Z","receivedAt":"2008-10-13T18:06:44Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:\n\n> On Mon, 13 Oct 2008, Junio C Hamano wrote:\n>\n>> Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:\n>> \n>> > - all the editors that this guy tested keep the hard links, so it was \n>> >   kinda hard to understand why Git insists on behaving differently,\n>> >\n>> > - if the user asked for hard links, it is not Git's place to question \n>> >   that decision,\n>> \n>> These are non-arguments,\n>\n> Actually, they are arguments.\n>\n> The thing is: these editors do what they do for a reason.  Which is \n> exactly the second reason.\n>\n> When a user makes hard links, it is not just for fun and bullocks.  It is \n> not for copy-on-write either, that's not what hard links are supposed to \n> do.  It is for cases when you need the _same_ information in two places.\n>\n> I am not that big a user of hard links myself, but when I do, I know \n> exactly what I am doing.  And with my patch and that config variable set \n> to true, Git will not interfer with that.\n\nOk, such a possible benefit should be described and defended better then.\nI only thought of the scenario Shawn has brought up, which is a downside\nof using this option without any conceivable upside, when I read your\npatch and your rationale you repeated in a few messages that followed.\n\nYou could have said something like \"The users may want to have a checkout,\nand keep the same contents always appear elsewhere i.e. 'installing by\nhardlinking'.  In such a setup, editing the source with an editor\nconfigured not to break hardlinks would still work fine, but git-checkout\nwill unconditionally break such links, which is undesirable.  Such a setup\nwould want a configuration variable like this.\"\n\n\"It is not for fun and bullocks\" is not a description any clearer than\nwhat you kept repeating, but if you stated it like the above, then I would\nnot have had trouble understanding what you wanted to say.\n\nThe documentation update needs to warn about the Shawn's scenario.  I also\ndo not know what this should do when you have two tracked paths with\nidentical contents hardlinked to each other.  Because we do not track\nhardlinks, I _think_ breaking links would be the right thing to do for\nsuch paths regardless of this configuration variable.\n\nIt also raises another question.  Don't you want this to be an attribute\nfor paths, not all-or-nothing configuration per repository?\n"},{"id":"93080","messageId":"alpine.DEB.1.00.0810151104400.22125@pacific.mpi-cbg.de.mpi-cbg.de","threadId":"15859","inReplyTo":"7v63nw9xor.fsf@gitster.siamese.dyndns.org","subject":"Re: [PATCH] Introduce core.keepHardLinks","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2008-10-15T09:07:32Z","receivedAt":"2008-10-15T09:07:32Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Mon, 13 Oct 2008, Junio C Hamano wrote:\n\n> You could have said something like \"The users may want to have a \n> checkout, and keep the same contents always appear elsewhere i.e. \n> 'installing by hardlinking'.  In such a setup, editing the source with \n> an editor configured not to break hardlinks would still work fine, but \n> git-checkout will unconditionally break such links, which is \n> undesirable.  Such a setup would want a configuration variable like \n> this.\"\n\nSounds very nice.  Sorry for being grumpy, and not being able to come up \nwith such a beautiful description.\n\n> The documentation update needs to warn about the Shawn's scenario.  I also\n> do not know what this should do when you have two tracked paths with\n> identical contents hardlinked to each other.\n\nWhen the user does that, it's the user's wish.  I'd not let Git play cute \ngames with that.\n\n> It also raises another question.  Don't you want this to be an attribute \n> for paths, not all-or-nothing configuration per repository?\n\nI'd rather not have it as an attribute, because it is not so much about \nfile types that should show this behavior.  It is more like an option that \nI fully expect to be set in $HOME/.gitconfig.\n\nCiao,\nDscho\n"}]}