1

I have a repository where some files should have 600 permissions. That is chmod 600 <file>, and even though umask 022, if I edit that file again and write it (e.g. via Emacs), the 600 permissions are preserved and not reset according to umask. That's correct behavior in my opinion or at least desired from my side.

Now, when I decide that those changes are bad and I want to discard them, I can issue git checkout -- <file>. However, in this case, Git somehow forces umask 022 on this file and permissions become 644. Why?

How can I get rid of this intrusive behavior? Is this editor (e.g. Emacs) being smart on preserving permissions or Git forcing umask 022 on me? git config --add core.sharedrepository 0077 also had no effect so far.

Drew
  • 29,895
  • 7
  • 74
  • 104
Alexander Shukaev
  • 16,674
  • 8
  • 70
  • 85
  • Git tracks a file with either 644(non executable) or 755(executable). – ElpieKay Jun 30 '21 at 13:24
  • Reasonable question, but sadly, the current answer is "you can't". If you came up with a way to have Git stat the existing file and attempt to preserve the equivalent umask, you could send that to the mailing list. The easiest way to handle this today though is to run `umask 0700 && git ...` for such Git commands (or start whatever it is that runs Git commands with the right umask). – torek Jul 02 '21 at 09:39
  • @torek, I personally think this is a good case for feature pull request. It could easily be a Git configuration setting (both per-repo and per-user) to use file truncate/rewrite mode instead as text editors do. Otherwise, continuously tampering with permissions behind user's back is both disruptive and security-unfriendly. – Alexander Shukaev Jul 02 '21 at 13:25
  • The Git mailing list doesn't use GitHub-style pull requests. You must write your implementation of your new feature, and then convert it to `git format-patch` style output. There is a nice way to do this with GitHub and [`GitGitGadget`](https://github.com/gitgitgadget/gitgitgadget), though. – torek Jul 02 '21 at 13:28

1 Answers1

2

When Git writes a file into the working tree, it always deletes the file and replaces it. This is unlike the way that many editors work, where they truncate and rewrite the file from the beginning, but has the benefit that it's much easier to detect failure cases like out-of-disk conditions without corrupting the working tree.

When Git does this, it always uses the umask setting, so there's no way to control this setting. That's what the operating system does by default anyway, so you'd have this problem any time the file is rewritten. Note that core.sharedrepository only controls files in the .git directory, not the working tree.

You can try using a post-checkout hook to set the permissions of the file, but note that you'll probably also want to run git update-index since Git will think those files are potentially dirty otherwise and re-read them the next time you run git status.

bk2204
  • 64,793
  • 6
  • 84
  • 100