Git tracks one permission distinction: whether a file is executable. An executable file gets mode 100755 instead of 100644, and that mode is part of the tree hash. Today you detect it when staging.
Record mode 100755 for an executable working file and 100644 otherwise.
Git deliberately tracks almost nothing about file permissions: not the group or
world bits, not ownership, not timestamps. The single exception is whether a file
is executable. A regular file is mode 100644 and an executable one is
100755. These are the only two blob modes you will ever see in a tree (the third
mode, 40000, is for subdirectories).
This matters because the mode is part of the tree entry, and therefore part of the
tree’s hash. Flip a file’s executable bit and re-commit, and the tree id changes
even though the file’s content, and so its blob id, is identical. Detect the
owner-execute bit when staging and record the right mode; everything downstream,
write-tree included, just uses whatever the index says.
// check the owner-execute bit of the file's permissionsinfo, _ := os.Stat(full)mode := "100644"if info.Mode().Perm()&0o100 != 0 {mode = "100755"}