簡介
上下文:它出現在哪裏?
常見於以下命令輸出中:
$ 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 在內部保存每個文件的三類信息(在 index 和 tree 對象中):
| 信息 | 含義 |
|---|---|
| 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/Mac:Git尊重文件權限。Windows:權限支持有限,默認core.fileMode = false,模式變化不會被跟蹤。