655

I use Git in Windows, and want to push the executable shell script into git repo by one commit.

Usually I need to do two steps (git commit).

$ vi install.sh
$ git add install.sh  
$ git commit -am "add new file for installation" # first commit
[master f2e92da] add support for install.sh
 1 files changed, 18 insertions(+), 3 deletions(-)
 create mode 100644 install.sh
$ git update-index --chmod=+x install.sh
$ git commit -am "update file permission"        # second commit
[master 317ba0c] update file permission
  0 files changed
  mode change 100644 => 100755 install.sh

How can I combine these two steps into one step? git configuration? windows command?

Reference: see question in Git file permissions on Windows for second commit

2
  • 38
    With git 2.9.x/2.10 (Q3 2016), git add --chmod=+x is actually possible. See my answer below, credit to Edward Thomson.
    – VonC
    Jul 9, 2016 at 19:18
  • 9
    It would be worth updating the selected answer to the git add --chmod=+x version Sep 17, 2018 at 10:54

7 Answers 7

954

There's no need to do this in two commits, you can add the file and mark it executable in a single commit:

C:\Temp\TestRepo>touch foo.sh

C:\Temp\TestRepo>git add foo.sh

C:\Temp\TestRepo>git ls-files --stage
100644 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 0       foo.sh

As you note, after adding, the mode is 0644 (ie, not executable). However, we can mark it as executable before committing:

C:\Temp\TestRepo>git update-index --chmod=+x foo.sh

C:\Temp\TestRepo>git ls-files --stage
100755 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 0       foo.sh

And now the file is mode 0755 (executable).

C:\Temp\TestRepo>git commit -m"Executable!"
[master (root-commit) 1f7a57a] Executable!
 1 file changed, 0 insertions(+), 0 deletions(-)
 create mode 100755 foo.sh

And now we have a single commit with a single executable file.

2
  • 4
    Note that as per stackoverflow.com/a/38285462/1852005, since 2016, marking it executable locally through chmod +x <filename> will result in the committed file to also be executable.
    – stwr667
    Dec 16, 2022 at 5:46
  • 2
    Helpful for commits in WSL.
    – Weekend
    Apr 24, 2023 at 8:49
305

Indeed, it would be nice if git-add had a --mode flag

git 2.9.x/2.10 (Q3 2016) actually will allow that (thanks to Edward Thomson):

git add --chmod=+x -- afile
git commit -m"Executable!"

That makes the all process quicker, and works even if core.filemode is set to false.

See commit 4e55ed3 (31 May 2016) by Edward Thomson (ethomson).
Helped-by: Johannes Schindelin (dscho).
(Merged by Junio C Hamano -- gitster -- in commit c8b080a, 06 Jul 2016)

add: add --chmod=+x / --chmod=-x options

The executable bit will not be detected (and therefore will not be set) for paths in a repository with core.filemode set to false, though the users may still wish to add files as executable for compatibility with other users who do have core.filemode functionality.
For example, Windows users adding shell scripts may wish to add them as executable for compatibility with users on non-Windows.

Although this can be done with a plumbing command (git update-index --add --chmod=+x foo), teaching the git-add command allows users to set a file executable with a command that they're already familiar with.

2
  • 3
    Make sure to NOT use GitHub Desktop to commit it, it would not recognize the change and so wouldn't commit
    – Akaisteph7
    Aug 1, 2022 at 13:22
  • @Akaisteph7 Good point. I always use the command-line myself anyway.
    – VonC
    Aug 1, 2022 at 14:25
79

If the files already have the +x flag set, git update-index --chmod=+x does nothing and git thinks there's nothing to commit, even though the flag isn't being saved into the repo.

You must first remove the flag, run the git command, then put the flag back:

chmod -x <file>
git update-index --chmod=+x <file>
chmod +x <file>

then git sees a change and will allow you to commit the change.


Required git config for the committer (credit: Nabi’s answer):

git config core.filemode false

Required git config for the cloner:

git config --global core.autocrlf input
7
  • 3
    ... terrible! is that still the case
    – MrR
    May 27, 2021 at 22:08
  • @MrR Yes, still the case. I believe this is the fastest way (least git fu) to fix it.
    – Bohemian
    May 27, 2021 at 22:10
  • I did that, git sees the change, I did commit and push to repo, and when I use the file elsewhere, permission denied...any idea what can be wrong? I download the file from repo and check permissions and it doesnt have executable...
    – mrRobot
    Jan 9, 2022 at 1:46
  • @mrRobot check git config: core.filemode should be false. If not, git config core.filemode false (credit Nabi’s answer)
    – Bohemian
    Jan 9, 2022 at 5:14
  • 1
    @Bohemian maybe this helped me: git config --global core.autocrlf input
    – mrRobot
    Jan 9, 2022 at 15:20
29

I have no touch and chmod command in my cmd.exe and git update-index --chmod=+x foo.sh doesn't work for me.

I finally resolve it by setting skip-worktree bit:

git update-index --skip-worktree --chmod=+x foo.sh
1
27

The note is firstly you must sure about filemode set to false in config git file, or use this command:

git config core.filemode false

and then you can set 0777 permission with this command:

git update-index --chmod=+x foo.sh
0
14

What I had to do to get this working for me was:

  1. To NOT use GitHub Desktop to commit it, it would not recognize the change and so wouldn't commit
  2. Instead, in a terminal, I ran git add --chmod=+x foo.sh
  3. Then git commit -m"Executable!"
1

Based upon the other answers here, you might find these aliases useful to add to your .gitconfig file.

…
[alias]
  …
  stage = add
  stagex = add --chmod=+x
  unstage = restore --staged
  setmodx = update-index --chmod=+x

stagex adds the file with the executable permission bit turned on. setmodx turns on the executable permission for a file already staged or committed. The other aliases are given to show how these two fit in.

1
  • Technically this is not an answer but "additional useful information to the existing answers", but Stack Overflow doesn't allow multiline code snippets in comments, unfortunately. Mar 12, 2023 at 15:57

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.