I want to git commit a .sh file, but want it to be executable when I checkout that same file in another server.
Is there a way to do so without manually chmod u+x that file in the servers that checkout the file?
This question is related to
According to official documentation, you can set or remove the "executable" flag on any tracked file using
To set the flag, use following command:
git update-index --chmod=+x path/to/file
To remove it, use:
git update-index --chmod=-x path/to/file
Under the hood
While this looks like the regular unix files permission system, actually it is not. Git maintains a special "mode" for each file in its internal storage:
100644for regular files
100755for executable ones
You can visualize it using
ls-file subcommand, with
$ git ls-files --stage 100644 aee89ef43dc3b0ec6a7c6228f742377692b50484 0 .gitignore 100755 0ac339497485f7cc80d988561807906b2fd56172 0 my_executable_script.sh
By default, when you add a file to a repository, Git will try to honor its filesystem attributes and set the correct filemode accordingly. You can disable this by setting
core.fileMode option to false:
git config core.fileMode false
If at some point the Git filemode is not set but the file has correct filesystem flag, try to remove mode and set it again:
git update-index --chmod=-x path/to/file git update-index --chmod=+x path/to/file
Starting with Git 2.9, you can stage a file AND set the flag in one command:
git add --chmod=+x path/to/file
Antwane's answer is correct, and this should be a comment but comments don't have enough space and do not allow formatting. :-) I just want to add that in Git, file permissions are recorded only1 as either
755 (spelled (
100 part means "regular file"):
diff --git a/path b/path new file mode 100644
The former—644—means that the file should not be executable, and the latter means that it should be executable. How that turns into actual file modes within your file system is somewhat OS-dependent. On Unix-like systems, the bits are passed through your
umask setting, which would normally be
022 to remove write permission from "group" and "other", or
002 to remove write permission only from "other". It might also be
077 if you are especially concerned about privacy and wish to remove read, write, and execute permission from both "group" and "other".
1Extremely-early versions of Git saved group permissions, so that some repositories have tree entries with mode
664 in them. Modern Git does not, but since no part of any object can ever be changed, those old permissions bits still persist in old tree objects.
The change to store only 0644 or 0755 was in commit e44794706eeb57f2, which is before Git v0.99 and dated 16 April 2005.