Stories

Detail Return Return

Git 提交時神秘的 create mode 100644 到底是什麼?一文告訴你答案! - Stories Detail

簡介

上下文:它出現在哪裏?

常見於以下命令輸出中:

$ git show

輸出示例:

diff --git a/src/test.txt b/src/test.txt
new file mode 100644
index 0000000..7f3e5a4
--- /dev/null
+++ b/src/test.txt
@@ -0,0 +1,2 @@
hello
world
$ git commit -m "Add new files"
[main 1a2b3c4] Add new files
 2 files changed, 15 insertions(+)
 create mode 100644 README.md
 create mode 100755 script.sh
 create mode 120000 symlink.txt

這些都表示此提交中新增了一個文件,且該文件的“mode(模式)”為 100644。

Git 的文件模式(mode)是什麼?

Git 在內部保存每個文件的三類信息(在 indextree 對象中):

信息 含義
mode 文件類型 + 權限
SHA-1/Hash 文件內容對應的 blob 對象
文件名 文件路徑名

所以,Git 實際上並不直接保存整個文件,而是保存 “文件內容(blob)+ mode + 文件名” 三元組。

100644 的含義分解

100644 是一個 文件模式(mode),用八進制表示。

文件類型部分(前兩位)

模式前綴 文件類型
100 普通文件(regular file)
120 符號鏈接(symbolic link)
160 Git 子模塊(gitlink)

權限部分(後三位)

模式 含義
644 普通文件(可讀寫、不可執行)
755 可執行文件(腳本、二進制等)

實際權限解析(Linux 風格):

6 = rw- (所有者可讀寫)
4 = r-- (組可讀)
4 = r-- (其他用户可讀)

rw-r--r--

常見幾種模式對照表

Git 模式(八進制) 類型 含義 示例
100644 普通文件 普通非執行文件(rw-r--r--) 源代碼、配置文件
100755 普通文件 可執行文件(rwxr-xr-x) 腳本、二進制文件
120000 符號鏈接 保存符號鏈接路徑 Linux 下的 symlink
160000 gitlink 子模塊 .gitmodules 指向的 repo
040000 目錄(tree 對象) 存儲 tree 引用 非實際文件

查看文件在 Git 中的 mode

可以用以下命令查看工作區、索引和歷史中對應文件的 mode

查看 index(暫存區):

git ls-files -s

示例輸出:

100644 4d1f48a5e9e6b032d212d24ec8594f98639b6f08 0       README.md
100755 05a43e2a77fdab64d45c601944bcdbba05cf8cb1 0       build.sh

第一列即是文件模式。

查看 tree(提交快照):

git ls-tree HEAD

輸出:

100644 blob 4d1f48a5e9e6b032d212d24ec8594f98639b6f08    README.md
100755 blob 05a43e2a77fdab64d45c601944bcdbba05cf8cb1    build.sh

Git 為什麼只保存兩種權限(644 與 755)

  • Git 主要在 跨平台 環境使用。
  • Windows 文件系統不支持 POSIX 權限位(如執行權限)。
  • 為了避免混亂,Git 簡化為兩種狀態:

    • 普通文件(非執行)
    • 可執行文件(執行位)
也就是説,Git 只關心文件是否“可執行”,其餘權限位不影響版本內容。

如何修改可執行標誌

修改本地文件執行權限:

chmod +x script.sh

再次提交:

git add script.sh
git commit -m "make script executable"

提交後再次查看

mode change 100644 => 100755 script.sh

子模塊(160000)與符號鏈接(120000)

模式 類型 存儲內容 備註
160000 子模塊 存儲子倉庫的 commit ID 不保存實際文件
120000 符號鏈接 存儲符號鏈接目標路徑 不保存實際文件內容

示例(符號鏈接):

ln -s ../config.yml link.yml
git add link.yml
git commit -m "add symlink"
# 顯示 create mode 120000 link.yml

Git 是如何在內部保存這些信息的?

Git 提交由多個對象組成:

Commit → Tree → Blob

舉例:

commit對象
  ↓
tree對象(保存 mode + 文件名 + blob 引用)
  ├── 100644 README.md → blob(內容)
  ├── 100755 build.sh  → blob(內容)
  └── 040000 src/ → tree(子目錄)

也就是説,100644 這一信息實際上存在 tree 對象 中,是提交快照(snapshot)的一部分。

實際操作示例

場景 1:添加普通文件

# 創建普通文本文件
echo "Hello World" > hello.txt

# 查看權限
ls -l hello.txt
# -rw-r--r-- 1 user group 12 Jan 1 10:00 hello.txt

# 添加到 Git 並提交
git add hello.txt
git commit -m "Add hello"
# create mode 100644 hello.txt

場景 2:創建可執行腳本

# 創建腳本並設為可執行
echo '#!/bin/bash\necho "Hello"' > run.sh
chmod +x run.sh

# 查看權限
ls -l run.sh
# -rwxr-xr-x 1 user group 22 Jan 1 10:00 run.sh

# 添加到 Git 並提交
git add run.sh
git commit -m "Add script"
# create mode 100755 run.sh

場景 3:創建符號鏈接

# 創建符號鏈接
ln -s target.txt link.txt

# 查看文件類型
ls -l link.txt
# lrwxrwxrwx 1 user group 10 Jan 1 10:00 link.txt -> target.txt

# 添加到 Git 並提交
git add link.txt
git commit -m "Add symlink"
# create mode 120000 link.txt

文件模式的管理

查看 Git 中的文件模式

# 查看 Git 數據庫中文件的模式
git ls-tree HEAD
# 100644 blob 89abcde    README.md
# 100755 blob 2345678    script.sh
# 120000 blob 3456789    link.txt
# 040000 tree 4567890    src

# 查看特定提交的文件模式
git ls-tree 1a2b3c4

修改文件模式

# 如果文件模式不正確,可以修改文件權限後重新添加
chmod +x my-script.py
git add my-script.py
git commit -m "Fix file permissions"

# 或者使用 Git 命令更新索引中的文件模式
git update-index --chmod=+x my-script.py

忽略文件權限變化

# 告訴 Git 忽略文件權限變化(在跨平台協作時有用)
git config core.filemode false

# 檢查當前配置
git config core.filemode

跨平台注意:

  • Linux/MacGit 尊重文件權限。

    • Windows:權限支持有限,默認 core.fileMode = false,模式變化不會被跟蹤。
user avatar skyselang Avatar jiedianxiaobao Avatar CH3CH2OH-Blog Avatar junxiudetuoba Avatar
Favorites 4 users favorite the story!
Favorites

Add a new Comments

Some HTML is okay.