某些git
命令(例如git add ...
)会修改.git/index
文件的状态,但我认为某些此类操作可能被视为一系列较小的操作。例如,
git add foo bar
可以分解为
git add foo
git add bar
事实上,可能(据我所知)上面的命令可能被分解为“更细粒度”(但仍然是“.git/index
- 修改”)git
命令。 / p>
我的问题是,使用.git/index
命令可以在git
文件上执行哪些最细粒度的修改? IOW,.git/index
上的“原子”命令行操作是什么?
我想所有这些命令都是管道命令。此外,如果我不得不猜测,我认为gid add <file>
和git rm --cached <file>
将近似于其中两个操作。另一方面,git mv <old> <new>
可能是“原子”删除,然后是“原子”添加的复合......
编辑:这个问题的动机如下。
我发现最令人困惑的git
行为的方面是导致修改.git/index
文件的行为。 git
那些对检查更加开放的其他所有内容。但是,.git/index
文件非常不透明。
出于这个原因,我想更好地了解.git/index
文件的修改方式。
答案 0 :(得分:2)
主索引由多个索引条目组成,条目集合表示下一次提交的内容。当您git add
文件时,它会添加(或更新)给定文件名的索引条目。
索引条目本身包含几个与分阶段更改(对象ID和模式)相关的字段,以及与工作目录中的内容(时间戳,文件大小等)相关的字段。您可以使用git ls-files
命令查看这两个命令:
C:\Temp\TestRepo>git add file.txt
C:\Temp\TestRepo>git ls-files --stage
100644 9b72baa6b025e0eb1dd8f1fd23bf5d5515012cd6 0 file.txt
C:\Temp\TestRepo>git ls-files --debug
file.txt
ctime: 1391645170:0
mtime: 1391645172:0
dev: 0 ino: 0
uid: 0 gid: 0
size: 7 flags: 0
一般来说,只需使用git add
和git rm
命令添加,更新和删除主索引中的条目。但是,某些命令只会更新部分索引条目。例如,git checkout
和git status
将写入索引条目的工作目录缓存内容。例如:
C:\Temp\TestRepo>touch file.txt
C:\Temp\TestRepo>git status
# On branch master
nothing to commit, working directory clean
C:\Temp\TestRepo>git ls-files --debug
file.txt
ctime: 1391645170:0
mtime: 1391645458:0
dev: 0 ino: 0
uid: 0 gid: 0
size: 7 flags: 0
(请注意索引条目中更新的mtime
(修改时间)字段。
您可以在单个命令中对索引进行的最小单个更改是翻转文件中假设未更改的位:
C:\Temp\TestRepo>git update-index --assume-unchanged file.txt
C:\Temp\TestRepo>git ls-files --debug
file.txt
ctime: 1391645170:0
mtime: 1391645458:0
dev: 0 ino: 0
uid: 0 gid: 0
size: 7 flags: 8000
(注意flags
字段从0x0000到0x8000的更改,翻转一位。)
答案 1 :(得分:0)
一般来说,git只不过是一个复杂的键值存储,它实际上有一些存储在树中的对象blob。
您可能希望阅读有关Git Objects的内容,这些内容取自官方Git Internals文档,以确切了解它们是如何组合在一起的。
具体来说,关于你的问题:
...当您运行
git add
和git commit
命令时Git会执行什么操作 - 它为已更改的文件存储blob,更新索引,写出树,并写入引用的提交对象顶级树和紧接着它们的提交。