How to add chmod permissions to file in Git?

Git

Git Problem Overview


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?

Git Solutions


Solution 1 - Git

According to official documentation, you can set or remove the "executable" flag on any tracked file using update-index sub-command.

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:

  • 100644 for regular files
  • 100755 for executable ones

You can visualize it using ls-file subcommand, with --stage option:

$ 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

Troubleshooting

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

Bonus

Starting with Git 2.9, you can stage a file AND set the flag in one command:

git add --chmod=+x path/to/file

Solution 2 - Git

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 644 or 755 (spelled (100644 and 100755; the 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.

Solution 3 - Git

To set the executeable flag to all files in the repository:

git ls-files --stage |grep 100644 | cut -f2 | xargs -d '\n' git update-index --chmod=+x

To unset the executeable flag to all files do the reverse

git ls-files --stage | grep 100755 | cut -f2 | xargs -d '\n' git update-index --chmod=-x

... and to set all the .sh-scripts executable, maybe this is your way:

git ls-files --stage | grep  ".sh$" | cut -f2 | xargs -d '\n' git update-index --chmod=+x

Solution 4 - Git

On linux, do not forget to

set sudo chmod +x /path/to/file

locally beside doing the git update otherwise the git will always bring the index back to 644 which set by default on the local machine !

In Windows Powershell, you can use

icacls .\path\to\file /grant Everyone:F

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionHenleyView Question on Stackoverflow
Solution 1 - GitAntwaneView Answer on Stackoverflow
Solution 2 - GittorekView Answer on Stackoverflow
Solution 3 - GitMaxView Answer on Stackoverflow
Solution 4 - GitKashkashioView Answer on Stackoverflow