{"thread":{"id":"14816","subject":"git-pull sets write bit, git-push does not","startedAt":"2008-08-02T22:32:41Z","lastAt":"2008-08-03T01:15:53Z","messageCount":3,"participants":["Alexander E Genaud","Matt Pearson"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"86026","messageId":"ee521d6f0808021532k66bc5b24ma2eeb51021fb5f36@mail.gmail.com","threadId":"14816","inReplyTo":null,"subject":"git-pull sets write bit, git-push does not","fromName":"Alexander E Genaud","fromEmail":"alex@genaud.net","sentAt":"2008-08-02T22:32:41Z","receivedAt":"2008-08-02T22:32:41Z","isPatch":false,"sender":{"key":"alex@genaud.net","avatar":"https://gravatar.com/avatar/046079bd0c4a3c04a9d0cdca66980d593471a7c3b13bed8c57e2c5b0aa56844b?d=mp&s=160"},"body":"git-pull sets write bit, git-push does not\n\nHello,\n\nBackground: I am using Git locally with ClearCase upstream. I\ninitialized a Git repository on top of a ClearCase snapshot view,\nwhile my work branches are in a clone. As ClearCase is particular\nabout the write bit, I have come to depend on an undocumented feature\nof Git. Namely, that git-push preserves read only permissions, while\ngit-pull sets modified files writable.\n\nCan git-push be relied upon to preserve the write bit (readonly)? Why\nis git-pull different? Is it a side effect of the plumbing?\n\nThanks,\nAlex\n\nhttp://genaud.net/2008/08/clearcase-globally-git-locally/\n\n\nSimplified case:\n\necho --\necho create a repo r1 with files A and B committed\necho --\nmkdir r1\ncd r1\necho A > A\necho B > B\ngit init\ngit add .\ngit commit -m init\n\necho --\necho create an identical repo r2 whose files are readonly\necho --\ncp -r ../r1 ../r2\nchmod u-w ../r2/[AB]\n\necho --\necho push a modification of A from r1 to r2\necho --\necho AA > A\ngit commit -a -m modA\ngit push ../r2\n\necho --\necho pull a modification of B from r1 to r2\necho --\necho BB > B\ngit commit -a -m modB\ncd ../r2\ngit pull ../r1\n\necho --\necho notice that pushed A remains readonly\necho while pulled B has become writable\necho --\nls -l\n\n\n-- \n[ alex@genaud.net ][ http://genaud.net ]\n[ B068 ED90 F47B 0965 2953 9FC3 EE9C C4D5 3E51 A207 ]\n"},{"id":"86027","messageId":"706b4240808021618y5604b7c9h915237c30d87dace@mail.gmail.com","threadId":"14816","inReplyTo":"ee521d6f0808021532k66bc5b24ma2eeb51021fb5f36@mail.gmail.com","subject":"Re: git-pull sets write bit, git-push does not","fromName":"Matt Pearson","fromEmail":"404emailnotfound@gmail.com","sentAt":"2008-08-02T23:18:15Z","receivedAt":"2008-08-02T23:18:15Z","isPatch":false,"sender":{"key":"404emailnotfound@gmail.com","avatar":null},"body":"On Sat, Aug 2, 2008 at 6:32 PM, Alexander E Genaud <alex@genaud.net> wrote:\n> git-pull sets write bit, git-push does not\n>\n> Hello,\n>\n> Background: I am using Git locally with ClearCase upstream. I\n> initialized a Git repository on top of a ClearCase snapshot view,\n> while my work branches are in a clone. As ClearCase is particular\n> about the write bit, I have come to depend on an undocumented feature\n> of Git. Namely, that git-push preserves read only permissions, while\n> git-pull sets modified files writable.\n>\n> Can git-push be relied upon to preserve the write bit (readonly)? Why\n> is git-pull different? Is it a side effect of the plumbing?\n\nPush and pull are not opposite operations: the opposite of push is\nfetch. This is because pull updates the working copy, while push does\nnot (like fetch, it only modifies the ref).\n\n>\n> Thanks,\n> Alex\n>\n> http://genaud.net/2008/08/clearcase-globally-git-locally/\n>\n>\n> Simplified case:\n>\n> echo --\n> echo create a repo r1 with files A and B committed\n> echo --\n> mkdir r1\n> cd r1\n> echo A > A\n> echo B > B\n> git init\n> git add .\n> git commit -m init\n>\n> echo --\n> echo create an identical repo r2 whose files are readonly\n> echo --\n> cp -r ../r1 ../r2\n> chmod u-w ../r2/[AB]\n>\n> echo --\n> echo push a modification of A from r1 to r2\n> echo --\n> echo AA > A\n> git commit -a -m modA\n> git push ../r2\n>\n> echo --\n> echo pull a modification of B from r1 to r2\n> echo --\n> echo BB > B\n> git commit -a -m modB\n> cd ../r2\n> git pull ../r1\n>\n> echo --\n> echo notice that pushed A remains readonly\n> echo while pulled B has become writable\n> echo --\n> ls -l\n>\nAfter running this:\n$ cat A\nA\n$ cat ../r1/A\nAA\n\nThe working copy in r2 was not updated with the changes you pushed to\nit (both the content and the mode change).\n"},{"id":"86028","messageId":"706b4240808021815h68db2179y7ceb35501f7f4f66@mail.gmail.com","threadId":"14816","inReplyTo":"706b4240808021618y5604b7c9h915237c30d87dace@mail.gmail.com","subject":"Re: git-pull sets write bit, git-push does not","fromName":"Matt Pearson","fromEmail":"404emailnotfound@gmail.com","sentAt":"2008-08-03T01:15:53Z","receivedAt":"2008-08-03T01:15:53Z","isPatch":false,"sender":{"key":"404emailnotfound@gmail.com","avatar":null},"body":"On Sat, Aug 2, 2008 at 7:18 PM, Matt Pearson <404emailnotfound@gmail.com> wrote:\n> The working copy in r2 was not updated with the changes you pushed to\n> it (both the content and the mode change).\n\nHm, your test case is more complicated than I originally thought. I\nget that result with the git from Ubuntu Hardy, but current master\ndies on the pull complaining B is not uptodate (has local changes). I\nguess this was a bug that was fixed, but there's no way I'm going to\nbisect or look at release notes over half a year (or more) of changes\n:)\n\nWhat it mainly comes down to is that git has only two possible file\nmodes: 644 and 755. These are the only ones that will ever be stored\nin the object database. It seems like older git would ignore\npermission changes to the working copy, and reset the permissions to\nthe \"normalized\" version when updating a file that was modified by the\npull.\n\nHere's a blow-by-blow explanation. I'll use numbers to refer to the\ncommits, where 1 is the initial commit, 2 is the commit you pushed,\nand 3 is the one you pulled. After the cp -r, both repos have a clean\nworking tree; the chmod dirties the working tree of r2.\n\nThe push causes both repos to have 2 be the HEAD commit, but r2 keeps\nthe dirty working tree changes, including (what now appears to be,\nfrom git's POV) a change in the content of A from 'AA' to the 'A' in\nthe initial commit. (The content change will appear as a staged change\nwhen running status in r2, because the index isn't updated either)\n\nWhen pulling 3, git thinks that these changes were made on top of 2,\nand you want to keep them. So it doesn't modify the contents of A\nbecause A was not changed in commit 3---if it was, you'd get a \"not\nuptodate\" message.\n\nB, however, *was* changed in 3, so it tries to apply those changes.\nWith the older version, it seems to ignore the permissions change and\nsimply fast-forward to the state B was in after commit 3 (content\n'BB', mode 644). With the newer version, it does see that the mode has\nbeen changed, and aborts due to a conflict. In fact, it doesn't seem\nto like any mode change---it still dies with a conflict if I change\nthe chmod to 'a+x'.\n\nHope that clears it up better---figuring this out helped me learn some\nstuff about git. Now I'll wait for someone more knowledgeable than I\nto tell me I'm wrong. :)\n\nMatt\n"}]}