57

I performed a git commit command and it gave me the following reply:

7 files changed, 93 insertions(+), 15 deletions(-)
mode change 100644 => 100755 assets/internal/fonts/icomoon.svg
mode change 100644 => 100755 assets/internal/fonts/icomoon.ttf
mode change 100644 => 100755 assets/internal/fonts/icomoon.woff

I know files can have user / group / other rwx permissions and those can be expressed as three octal digits, like "644" or "755". But why is git showing six digits here?

I've read the following articles but didn't find an answer:

ilkkachu
  • 138,973

2 Answers2

74

The values shown are the 16-bit file modes as stored by Git, following the layout of POSIX types and modes:

  32-bit mode, split into (high to low bits)
4-bit object type
  valid values in binary are 1000 (regular file), 1010 (symbolic link)
  and 1110 (gitlink)

3-bit unused

9-bit unix permission. Only 0755 and 0644 are valid for regular files.
Symbolic links and gitlinks have value 0 in this field.

That file doesn’t mention directories; they are represented using object type 0100. Gitlinks are used for submodules.

Each digit in the six-digit value is in octal, representing three bits; 16 bits thus need six digits, the first of which only represents one bit:

Type|---|Perm bits

1000 000 111101101 1 0 0 7 5 5

1000 000 110100100 1 0 0 6 4 4

Git doesn’t store arbitrary modes, only a subset of the values are allowed, from the usual POSIX types and modes (in octal, 12 for a symbolic link, 10 for a regular file, 04 for a directory) to which git adds 16 for Git links. The mode is appended, using four octal digits. For files, you’ll only ever see 100755 or 100644 (although 100664 is also technically possible); directories are 040000 (permissions are ignored), symbolic links 120000. The set-user-ID, set-group-ID and sticky bits aren’t supported at all (they would be stored in the unused bits).

See also this related answer.

Stephen Kitt
  • 434,908
  • in this answer https://stackoverflow.com/a/16581096/3990767 it says 160 instead of 111 – SOFe Apr 15 '20 at 07:05
  • 2
    1600 is the commit object at the tip of the submodule (you can compare the hashes to verify, and git ls-tree itself lists this as a commit). The submodule itself is stored as a gitlink with mode 1110. – Stephen Kitt Apr 15 '20 at 07:49
  • 2
    For the lazy, 0755 is basically restricting writes to user, and leaving all other perms open. 0644 is basically the same, except without any execute perms for anyone. – ijoseph Jan 18 '21 at 23:57
  • Why is it that they allocate 32 bits but only use 16 bits for the mode? When I go into my own .git/index and check I see that they use the lower bits to store them (for 100644 it's 0000 0000 0000 0000 1000 0001 1010 0100) – RexYuan Jun 26 '21 at 21:41
  • 1
    @RexYuan probably because mode_t, the type used to store this information in stat’s results, is 32 bits in size as well. – Stephen Kitt Jun 27 '21 at 18:54
  • If you want to change 100644 to 100755, you need to run chmod 755 my_file. – questionto42 Apr 25 '22 at 13:59
9

Traditionally, Unix file systems used 16 bits to hold the type in 4 bits (e.g. regular file, directory, character special device... ) 9 bits of user/group/other permissions, the sticky bit, the SUID bit and the SGID bit.

You are seeing this in octal, so the rightmost 5 digits can have the values 0 - 7 (representing 3 bits for a total of 15) and the left digit is 0 or 1 for the last bit.

On a Linux system man -s 7 inode (i.e. inode(7)) should tell you about this in the file type and mode section.

icarus
  • 17,920