{"thread":{"id":"27030","subject":"[RFH] eol=lf on existing mixed line-ending files","startedAt":"2011-04-07T23:15:57Z","lastAt":"2011-04-12T13:57:16Z","messageCount":7,"participants":["Jeff King","Michael J Gruber","Dmitry Potapov","Jay Soffian"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"165387","messageId":"20110407231556.GA10868@sigill.intra.peff.net","threadId":"27030","inReplyTo":null,"subject":"[RFH] eol=lf on existing mixed line-ending files","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2011-04-07T23:15:57Z","receivedAt":"2011-04-07T23:15:57Z","isPatch":false,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"I investigated some odd git behavior with the EOL gitattributes today,\nand I'm curious to hear what others on the list think of what git does.\nIn particular, index raciness means git produces non-deterministic\nresults in this case.\n\nThe repo in question has a gitattributes file with \"* crlf=input\" (which\nwe would spell \"eol=lf\" these days, but the results are the same), but\nstill contains some files with mixed line endings. Which you can\nreproduce with:\n\n  git init repo &&\n  cd repo &&\n  {\n    printf 'one\\n' &&\n    printf 'two\\r\\n'\n  } >mixed &&\n  git add mixed &&\n  git commit -m one &&\n  echo '* eol=lf' >.gitattributes\n\nNow if we run \"git status\" or \"git diff\", it will let us know that\n\"mixed\" is modified, insofar as adding and committing it would perform\nthe LF conversion.\n\nNow we come to the first confusing behavior. Generally one would expect\nthe working directory to be clean after a \"git reset --hard\". But not\nhere:\n\n  git reset --hard &&\n  git status\n\nwill still show \"mixed\" as modified. Because of course we are checking\nout the version from HEAD into the index and working tree, which has the\nmixed line endings. So we rewrite the identical file.\n\nSo that kind of makes sense. But it isn't all that helpful, if I just\nwant to reset my working tree to something sane without making a new\ncommit (more on this later).\n\nBut here's an extra helping of confusion on top. Every once in a while,\ndoing the reset _won't_ keep \"mixed\" as modified. I can trigger it\nreliably by inserting an extra sleep into git:\n\ndiff --git a/unpack-trees.c b/unpack-trees.c\nindex 500ebcf..735b13e 100644\n--- a/unpack-trees.c\n+++ b/unpack-trees.c\n@@ -223,6 +223,7 @@ static int check_updates(struct unpack_trees_options *o)\n \t\t}\n \t}\n \tstop_progress(&progress);\n+\tsleep(1);\n \tif (o->update)\n \t\tgit_attr_set_direction(GIT_ATTR_CHECKIN, NULL);\n \treturn errs != 0;\n\nThat puts a delay between when reset writes the \"mixed\" file, and when\nwe write out the refreshed index. So next time we look at the index\n(e.g., in \"status\"), we will see that the \"mixed\" entry has up-to-date\nstat information and not look at its actual contents.\n\nBut in the original case (without the sleep), that doesn't happen.\nThere, we usually end up writing the file and the index in the same\nsecond. So when status looks at the index, the \"mixed\" entry is racily\nclean, and we actually check it again.\n\nSo we get two different outcomes, depending on the index raciness. Which\none is right, or is it right for it to be non-deterministic?\n\nAnd one final question. Let's say I don't immediately convert this mixed\nfile to the correct line-endings. Instead, it persists over a large\nnumber of commits, some of them even changing the \"mixed\" file but not\nfixing the line endings[1]. We can simulate that with:\n\n  mv .gitattributes tmp\n  echo three >>mixed &&\n  git commit -a -m three &&\n  mv tmp .gitattributes\n\nNow imagine I am somebody who has cloned this repo; the clone will tend\nto end the race condition in the \"clean\" state, since it will often take\nmore than 1 second to write out all of the files (at least for a\nnormal-sized project). We can simulate using our sleep-patched reset:\n\n  git reset --hard\n\nto get a \"clean\" repo. Now let's say I want to explore old history, so I\ngo to a detached HEAD, but using normal git, not the sleep-patched one:\n\n  git checkout HEAD^\n\nAnd, of course, now we think \"mixed\" is modified. After I'm done\nexploring, I want to go back to \"master\", but I can't:\n\n  $ git checkout master\n  error: Your local changes to the following files would be overwritten by checkout:\n          mixed\n\nWhat is the best way out of this situation? You can't use \"reset --hard\"\nto fix the working tree. I guess \"git checkout -f\" is the best option.\n\nHopefully my example made sense and was reproducible. The real repo\nwhich triggered this puzzle was jquery. You can try:\n\n  git clone git://github.com/jquery/jquery.git &&\n  cd jquery &&\n  git checkout 1.4.2 &&\n  git checkout master\n\nwhich will fail (but may succeed racily on a slow enough machine).\nObviously they need to fix the mixed line-ending files in their repo.\nBut that fix would be on HEAD, and \"git checkout 1.4.2\" will be forever\nbroken. Is there a way to fix that?\n\n-Peff\n\n[1] The one thing still puzzling me about the jquery repo is how they\nmanaged to make so many commits (including ones to mixed line ending\nfiles) without seeing the dirty working tree state and committing it. Is\nthere some combination of config that makes this not happen?\n"},{"id":"165413","messageId":"4D9ED714.80307@drmicha.warpmail.net","threadId":"27030","inReplyTo":"20110407231556.GA10868@sigill.intra.peff.net","subject":"Re: [RFH] eol=lf on existing mixed line-ending files","fromName":"Michael J Gruber","fromEmail":"git@drmicha.warpmail.net","sentAt":"2011-04-08T09:36:20Z","receivedAt":"2011-04-08T09:36:20Z","isPatch":false,"sender":{"key":"git@grubix.eu","avatar":"https://avatars.githubusercontent.com/u/233215?v=4"},"body":"Jeff King venit, vidit, dixit 08.04.2011 01:15:\n> I investigated some odd git behavior with the EOL gitattributes today,\n> and I'm curious to hear what others on the list think of what git does.\n> In particular, index raciness means git produces non-deterministic\n> results in this case.\n> \n> The repo in question has a gitattributes file with \"* crlf=input\" (which\n> we would spell \"eol=lf\" these days, but the results are the same), but\n> still contains some files with mixed line endings. Which you can\n> reproduce with:\n> \n>   git init repo &&\n>   cd repo &&\n>   {\n>     printf 'one\\n' &&\n>     printf 'two\\r\\n'\n>   } >mixed &&\n>   git add mixed &&\n>   git commit -m one &&\n>   echo '* eol=lf' >.gitattributes\n> \n> Now if we run \"git status\" or \"git diff\", it will let us know that\n> \"mixed\" is modified, insofar as adding and committing it would perform\n> the LF conversion.\n> \n> Now we come to the first confusing behavior. Generally one would expect\n> the working directory to be clean after a \"git reset --hard\". But not\n> here:\n> \n>   git reset --hard &&\n>   git status\n> \n> will still show \"mixed\" as modified. Because of course we are checking\n> out the version from HEAD into the index and working tree, which has the\n> mixed line endings. So we rewrite the identical file.\n> \n> So that kind of makes sense. But it isn't all that helpful, if I just\n> want to reset my working tree to something sane without making a new\n> commit (more on this later).\n> \n> But here's an extra helping of confusion on top. Every once in a while,\n> doing the reset _won't_ keep \"mixed\" as modified. I can trigger it\n> reliably by inserting an extra sleep into git:\n> \n> diff --git a/unpack-trees.c b/unpack-trees.c\n> index 500ebcf..735b13e 100644\n> --- a/unpack-trees.c\n> +++ b/unpack-trees.c\n> @@ -223,6 +223,7 @@ static int check_updates(struct unpack_trees_options *o)\n>  \t\t}\n>  \t}\n>  \tstop_progress(&progress);\n> +\tsleep(1);\n>  \tif (o->update)\n>  \t\tgit_attr_set_direction(GIT_ATTR_CHECKIN, NULL);\n>  \treturn errs != 0;\n> \n> That puts a delay between when reset writes the \"mixed\" file, and when\n> we write out the refreshed index. So next time we look at the index\n> (e.g., in \"status\"), we will see that the \"mixed\" entry has up-to-date\n> stat information and not look at its actual contents.\n> \n> But in the original case (without the sleep), that doesn't happen.\n> There, we usually end up writing the file and the index in the same\n> second. So when status looks at the index, the \"mixed\" entry is racily\n> clean, and we actually check it again.\n> \n> So we get two different outcomes, depending on the index raciness. Which\n> one is right, or is it right for it to be non-deterministic?\n> \n> And one final question. Let's say I don't immediately convert this mixed\n> file to the correct line-endings. Instead, it persists over a large\n> number of commits, some of them even changing the \"mixed\" file but not\n> fixing the line endings[1]. We can simulate that with:\n> \n>   mv .gitattributes tmp\n>   echo three >>mixed &&\n>   git commit -a -m three &&\n>   mv tmp .gitattributes\n> \n> Now imagine I am somebody who has cloned this repo; the clone will tend\n> to end the race condition in the \"clean\" state, since it will often take\n> more than 1 second to write out all of the files (at least for a\n> normal-sized project). We can simulate using our sleep-patched reset:\n> \n>   git reset --hard\n> \n> to get a \"clean\" repo. Now let's say I want to explore old history, so I\n> go to a detached HEAD, but using normal git, not the sleep-patched one:\n> \n>   git checkout HEAD^\n> \n> And, of course, now we think \"mixed\" is modified. After I'm done\n> exploring, I want to go back to \"master\", but I can't:\n> \n>   $ git checkout master\n>   error: Your local changes to the following files would be overwritten by checkout:\n>           mixed\n> \n> What is the best way out of this situation? You can't use \"reset --hard\"\n> to fix the working tree. I guess \"git checkout -f\" is the best option.\n> \n> Hopefully my example made sense and was reproducible. The real repo\n> which triggered this puzzle was jquery. You can try:\n> \n>   git clone git://github.com/jquery/jquery.git &&\n>   cd jquery &&\n>   git checkout 1.4.2 &&\n>   git checkout master\n> \n> which will fail (but may succeed racily on a slow enough machine).\n> Obviously they need to fix the mixed line-ending files in their repo.\n> But that fix would be on HEAD, and \"git checkout 1.4.2\" will be forever\n> broken. Is there a way to fix that?\n> \n> -Peff\n> \n> [1] The one thing still puzzling me about the jquery repo is how they\n> managed to make so many commits (including ones to mixed line ending\n> files) without seeing the dirty working tree state and committing it. Is\n> there some combination of config that makes this not happen?\n\nWhen did they introduce the .gitattributes file?\nAlso, maybe they're jgit users.\n\nMichael\n"},{"id":"165427","messageId":"20110408160616.GA32709@sigill.intra.peff.net","threadId":"27030","inReplyTo":"4D9ED714.80307@drmicha.warpmail.net","subject":"Re: [RFH] eol=lf on existing mixed line-ending files","fromName":"Jeff King","fromEmail":"peff@github.com","sentAt":"2011-04-08T16:06:16Z","receivedAt":"2011-04-08T16:06:16Z","isPatch":false,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Fri, Apr 08, 2011 at 11:36:20AM +0200, Michael J Gruber wrote:\n\n> > [1] The one thing still puzzling me about the jquery repo is how they\n> > managed to make so many commits (including ones to mixed line ending\n> > files) without seeing the dirty working tree state and committing it. Is\n> > there some combination of config that makes this not happen?\n> \n> When did they introduce the .gitattributes file?\n> Also, maybe they're jgit users.\n\nThe gitattributes file was introduced in 2009, and there are several\ncommits to mixed line-ending files between then and now. So it seems\nunlikely that they just won the race condition over and over.\n\nI don't know whether they could be using jgit.\n\n-Peff\n"},{"id":"165495","messageId":"BANLkTimBewshVRYBibXJ7nDNoX0S0iDaUQ@mail.gmail.com","threadId":"27030","inReplyTo":"20110407231556.GA10868@sigill.intra.peff.net","subject":"Re: [RFH] eol=lf on existing mixed line-ending files","fromName":"Dmitry Potapov","fromEmail":"dpotapov@gmail.com","sentAt":"2011-04-09T18:58:59Z","receivedAt":"2011-04-09T18:58:59Z","isPatch":false,"sender":{"key":"dpotapov@gmail.com","avatar":"https://avatars.githubusercontent.com/u/6568595?v=4"},"body":"On Fri, Apr 8, 2011 at 3:15 AM, Jeff King <peff@peff.net> wrote:\n>\n>  git init repo &&\n>  cd repo &&\n>  {\n>    printf 'one\\n' &&\n>    printf 'two\\r\\n'\n>  } >mixed &&\n>  git add mixed &&\n>  git commit -m one &&\n>  echo '* eol=lf' >.gitattributes\n>\n> Now if we run \"git status\" or \"git diff\", it will let us know that\n> \"mixed\" is modified, insofar as adding and committing it would perform\n> the LF conversion.\n\nWell, git _may_ report that file is modified, but usually when you\nchange .gitattributes, git does not notice changes to file endings\nuntil you touch those files. You can force git to notice changes in\nall files by doing:\n\n $ touch -d 2000-1-1 .git/index\n\nso it will re-read all files, but I guess it should be do that\nautomatically, otherwise many people end up with having inconsistent\nfile endings in their repository as result of editing .gitattributes\n(or by just pulling a new version from the upstream).\n\n>\n> Now we come to the first confusing behavior. Generally one would expect\n> the working directory to be clean after a \"git reset --hard\". But not\n> here:\n>\n>  git reset --hard &&\n>  git status\n>\n> will still show \"mixed\" as modified.\n\nIt is because you discard all changes except to .gitattributes.  If\n.gitattributes were tracked, \"reset\" would discard them too, and you\nwould get clean original state.\n\n> So that kind of makes sense. But it isn't all that helpful, if I just\n> want to reset my working tree to something sane without making a new\n> commit (more on this later).\n\nIf we do not discard changes to .gitattributes then the question is\nwhat a sane state is? It is really difficult to define what is sane\nwhen conversion to the work tree and back gives a different result.\n\n> But here's an extra helping of confusion on top. Every once in a while,\n> doing the reset _won't_ keep \"mixed\" as modified. I can trigger it\n> reliably by inserting an extra sleep into git:\n\nyou can have the same effect by doing:\n\ngit reset --hard HEAD && sleep 1 && git touch .git/index\n\nIronically, that the race that you observed is result of fixing another\nrace in git when files are changed too fast, so they may have the same\ntimestamp. To prevent this race, git checks timestamp of .git/index\nand a trcking file. If .git/index timestamp is older or same as that file,\nthis file is considered dirty. So, it is re-read from the disk to check\nif there are any changes. This works well but only if conversion to the\nwork tree and back produces the same result.\n\n> So we get two different outcomes, depending on the index raciness. Which\n> one is right, or is it right for it to be non-deterministic?\n\nI like everything being deterministic, but in this case I do not see\nhow it is possible without making the normal case much slower.\n\n> And one final question. Let's say I don't immediately convert this mixed\n> file to the correct line-endings.\n\nIMHO, adding .gitattributes that specifies line endings while not\nfixing actual line endings of existing files is really a bad idea.\n\nAs with any other filter, the rule is that conversion from git to\nthe working tree and back should give the same result for any file\nin the repository, otherwise you will have a lot of troubles later.\n\n> Hopefully my example made sense and was reproducible. The real repo\n> which triggered this puzzle was jquery. You can try:\n>\n>  git clone git://github.com/jquery/jquery.git &&\n>  cd jquery &&\n>  git checkout 1.4.2 &&\n>  git checkout master\n>\n> which will fail (but may succeed racily on a slow enough machine).\n> Obviously they need to fix the mixed line-ending files in their repo.\n> But that fix would be on HEAD, and \"git checkout 1.4.2\" will be forever\n> broken. Is there a way to fix that?\n\nYou cannot change the past history. Well, you can overwrite that\nsetting using .git/info/attributes. It does not make sense to do\nthat in general, but it may be useful if you do git bisect.\n\nBTW, nowadays, we have much better alternative than using\n\n* crlf=input\n\nInstead of it, you probably want to use:\n\n* text=auto\n\nwhich will automatically detect text files, so you won't have problems\nwith binary files. All text files are put into the repository with LF,\nbut users may have different endings in their working tree if they like.\n\n\nDmitry\n"},{"id":"165498","messageId":"20110409192941.GB31579@sigill.intra.peff.net","threadId":"27030","inReplyTo":"BANLkTimBewshVRYBibXJ7nDNoX0S0iDaUQ@mail.gmail.com","subject":"Re: [RFH] eol=lf on existing mixed line-ending files","fromName":"Jeff King","fromEmail":"peff@github.com","sentAt":"2011-04-09T19:32:39Z","receivedAt":"2011-04-09T19:32:39Z","isPatch":false,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Sat, Apr 09, 2011 at 10:58:59PM +0400, Dmitry Potapov wrote:\n\n> > Now we come to the first confusing behavior. Generally one would expect\n> > the working directory to be clean after a \"git reset --hard\". But not\n> > here:\n> >\n> >  git reset --hard &&\n> >  git status\n> >\n> > will still show \"mixed\" as modified.\n> \n> It is because you discard all changes except to .gitattributes.  If\n> .gitattributes were tracked, \"reset\" would discard them too, and you\n> would get clean original state.\n\nYeah, in this case. But gitattributes could easily be in the repository\nalready, and reset still wouldn't change it (as it is in the jquery\nexample).\n\n> > So that kind of makes sense. But it isn't all that helpful, if I just\n> > want to reset my working tree to something sane without making a new\n> > commit (more on this later).\n> \n> If we do not discard changes to .gitattributes then the question is\n> what a sane state is? It is really difficult to define what is sane\n> when conversion to the work tree and back gives a different result.\n\nAgreed. The problem is the disconnect between what is in the repository,\nand what _would_ be in the repository if we committed the file. So\nobviously what the user is giving to git in this case is slightly\ninsane.\n\nI just wonder if git can do better. But the only options I could think\nof are:\n\n  1. Set the working tree file to have just LF's. But that doesn't help,\n     since it is the conversion _to_ linefeeds that make it look like\n     the file is changed. So we'd still see unstaged changes.\n\n  2. Set the index file to have just LF's. That would make the working\n     tree look clean, but it would look like changes are staged, which\n     is even worse.\n\n> > But here's an extra helping of confusion on top. Every once in a while,\n> > doing the reset _won't_ keep \"mixed\" as modified. I can trigger it\n> > reliably by inserting an extra sleep into git:\n> \n> you can have the same effect by doing:\n> \n> git reset --hard HEAD && sleep 1 && git touch .git/index\n\nYeah, that has the same effect. I wanted to show the sleep inside git to\ndemonstrate that it really is an inside-git race condition.\n\n> Ironically, that the race that you observed is result of fixing another\n> race in git when files are changed too fast, so they may have the same\n> timestamp. To prevent this race, git checks timestamp of .git/index\n> and a trcking file. If .git/index timestamp is older or same as that file,\n> this file is considered dirty. So, it is re-read from the disk to check\n> if there are any changes. This works well but only if conversion to the\n> work tree and back produces the same result.\n\nYeah, that's my analysis, too.\n\n> > So we get two different outcomes, depending on the index raciness. Which\n> > one is right, or is it right for it to be non-deterministic?\n> \n> I like everything being deterministic, but in this case I do not see\n> how it is possible without making the normal case much slower.\n\nI think if you took my (1) suggestion above, it would be deterministic.\nI don't know how much that would help. It would at least force people to\nalways see the change and hopefully spur them to commit the fixed\nline-endings.\n\n> > And one final question. Let's say I don't immediately convert this mixed\n> > file to the correct line-endings.\n> \n> IMHO, adding .gitattributes that specifies line endings while not\n> fixing actual line endings of existing files is really a bad idea.\n\nI absolutely agree, and my first advice upon seeing this jquery repo was\nto fix those line endings. But they went for over a year with the broken\nsetup, so clearly it wasn't bothering them. I wonder what git could do\nbetter to provoke them to fix it sooner.\n\n> As with any other filter, the rule is that conversion from git to\n> the working tree and back should give the same result for any file\n> in the repository, otherwise you will have a lot of troubles later.\n\nI think that's a good rule in general, but doesn't crlf=input (and now\neol=lf, and by extension, the text attribute) encourage exactly that if\nyou have mixed line-ending files?\n\nI think the moral of the story may simply be that mixed line-ending text\nfiles are an abomination which should be rooted out and destroyed.\n\n> >  git clone git://github.com/jquery/jquery.git &&\n> >  cd jquery &&\n> >  git checkout 1.4.2 &&\n> >  git checkout master\n> >\n> > which will fail (but may succeed racily on a slow enough machine).\n> > Obviously they need to fix the mixed line-ending files in their repo.\n> > But that fix would be on HEAD, and \"git checkout 1.4.2\" will be forever\n> > broken. Is there a way to fix that?\n> \n> You cannot change the past history. Well, you can overwrite that\n> setting using .git/info/attributes. It does not make sense to do\n> that in general, but it may be useful if you do git bisect.\n\nThe problem with that is that for recent commits you want one set of\nattributes (where the files have been fixed), and for going back to\nolder commits, you want a different set of attributes (where you say\n\"don't care about line endings in these files\").\n\nOne solution would be to have a git-notes ref with per-commit\nattributes, so you could selectively override attributes as you explore\nhistory.\n\n> BTW, nowadays, we have much better alternative than using\n> \n> * crlf=input\n> \n> Instead of it, you probably want to use:\n> \n> * text=auto\n\nAgreed, and I already recommended that to jquery people (actually, one\nof the problem files you will see in the example above is a binary file,\nthough later on they ended up fixing its attributes by specifically\nmarking its extension as binary).\n\n-Peff\n"},{"id":"165500","messageId":"BANLkTi=qBeT=09YFng1gyt+SuN2v0g+kDg@mail.gmail.com","threadId":"27030","inReplyTo":"20110409192941.GB31579@sigill.intra.peff.net","subject":"Re: [RFH] eol=lf on existing mixed line-ending files","fromName":"Dmitry Potapov","fromEmail":"dpotapov@gmail.com","sentAt":"2011-04-09T20:09:38Z","receivedAt":"2011-04-09T20:09:38Z","isPatch":false,"sender":{"key":"dpotapov@gmail.com","avatar":"https://avatars.githubusercontent.com/u/6568595?v=4"},"body":"On Sat, Apr 9, 2011 at 11:32 PM, Jeff King <peff@github.com> wrote:\n>\n> I just wonder if git can do better. But the only options I could think\n> of are:\n>\n>  1. Set the working tree file to have just LF's. But that doesn't help,\n>     since it is the conversion _to_ linefeeds that make it look like\n>     the file is changed. So we'd still see unstaged changes.\n\nWell, eol=crlf _does_ set the working tree file to have only CRLF, but\nyou still have the same race as before. Just because git converts file,\nit does not think about it as \"dirty\". It becomes \"dirty\" when git\ntries to convert it back and gets a different result, and whether it\ntries or not depend on timestamp. So, you still have the same race.\n\n>> > So we get two different outcomes, depending on the index raciness. Which\n>> > one is right, or is it right for it to be non-deterministic?\n>>\n>> I like everything being deterministic, but in this case I do not see\n>> how it is possible without making the normal case much slower.\n>\n> I think if you took my (1) suggestion above, it would be deterministic.\n\nReplace \"eol=lf\" with \"eol=crlf\" in your script, and you will see that\nit does not help with the race.\n\n>\n> I absolutely agree, and my first advice upon seeing this jquery repo was\n> to fix those line endings. But they went for over a year with the broken\n> setup, so clearly it wasn't bothering them. I wonder what git could do\n> better to provoke them to fix it sooner.\n\nI believe git should consider all files as \"dirty\" if .gitattributes is\nchanged. So, you cannot accidentally commit changes to .gitattributes\nwithout fixing line endings. Currently, you can provoke git to consider\nall files as dirty by doing:\n\n  touch -d 2000-1-1 .git/index\n\nbut we should not expect users to do that after editing .gitattributes.\n\n\nDmitry\n"},{"id":"165686","messageId":"BANLkTik9oKJSx-=dt0o28oqQ67p-OTX_qg@mail.gmail.com","threadId":"27030","inReplyTo":"20110407231556.GA10868@sigill.intra.peff.net","subject":"Re: [RFH] eol=lf on existing mixed line-ending files","fromName":"Jay Soffian","fromEmail":"jaysoffian@gmail.com","sentAt":"2011-04-12T13:57:16Z","receivedAt":"2011-04-12T13:57:16Z","isPatch":false,"sender":{"key":"jaysoffian@gmail.com","avatar":"https://avatars.githubusercontent.com/u/155970?v=4"},"body":"On Thu, Apr 7, 2011 at 7:15 PM, Jeff King <peff@peff.net> wrote:\n> I investigated some odd git behavior with the EOL gitattributes today,\n> and I'm curious to hear what others on the list think of what git does.\n> In particular, index raciness means git produces non-deterministic\n> results in this case.\n\nRelatedly, http://article.gmane.org/gmane.comp.version-control.git/169476\n\nj.\n"}]}