phd对这一行的评论:
edit-unmerged = !"f() { git ls-files --unmerged | cut -f2 | sort -u ; }; `git var GIT_EDITOR` `f`"
是对您想要做的事情的直接回答,但值得指出的是,它的git status
作用远不止git ls-files
于此。Git 是围绕“工具哲学”构建的,有些工具级别较低,有些工具级别较高;git status
是相对较高级别的,并且包含了必须通过多次调用多个较低级别工具来完成的事情:
如果有当前分支并且它有上游,它将计算当前分支在其上游之前和/或之后的提交次数。这需要使用git symbolic-ref
或类似的方法来查找当前分支,git rev-parse
或类似的方法来查找其上游,并git rev-list --count --left-right
进行计数。
它将检查是否某些文件未合并,如果是,则更改其策略。该git ls-files
命令可以执行此操作,但不会因此更改策略:需要一次调用git ls-files
来发现这一点,然后根据策略进行一次或多次单独的调用。
它将比较HEAD
(当前提交)与索引:git ls-files
可以做到这一点,但它需要多次调用git ls-files
.
它将比较索引与暂存区域:git ls-files
也可以这样做,但同样需要多次调用。
这里要了解的主要内容git ls-files
是面向检查 Git 的索引。索引本身是一个复杂的野兽,但它的主要内容是 <file name, staging number, hash ID, cache data> 元组的列表:
- 文件名是文件的名称,如果您现在提交,它将出现在下一次提交中;
- 分段编号是介于 0 和 3 之间的数值;
- 哈希 ID 是文件的内部 blob 哈希,或者对于意图添加条目全为零;
- 缓存数据包括
lstat
数据和标志,例如假设不变和跳过工作树:旨在使 Git 运行得更快和/或更有用的东西。
如果所有这些条目的暂存编号为零,则没有未合并的文件。任何具有非零暂存编号的条目都表示一个未合并的文件,暂存编号告诉我们它的来源:
- 1 = 出现在合并库中的文件;
- 2 = 出现在 中的文件
--ours
,即HEAD
提交;
- 3 = 中出现的文件
--theirs
,即另一个提交。
这些最多三个非零阶段条目中的每个条目中的文件名称通常对于所有三个都相同,但是当文件被重命名时,Git 的索引条目在这里变得有点松散。(理论上,可能有超过三个条目,尽管只有三个阶段编号:Junio Hamano 在邮件列表中提到,其目的是在复杂的多重合并库和/或章鱼中允许多个阶段 1 条目例如,合并。但实际上这不会发生。我认为当前索引格式存在一些额外的问题,需要扩展或新的索引格式。但无论如何,它们在实践中都极为罕见。)在任何情况下,任何存在非零阶段数意味着索引不能写入树:git write-tree
将失败。一些 Git 脚本使用它作为“是否存在未合并的索引条目”的快捷测试:
unmerged=false
t=$(git write-tree 2>/dev/null) || unmerged=true
if $unmerged; then ...; fi # test for unmerged entries
尽管从技术上讲git write-tree
可能会因其他原因而失败(.git/index
例如,由于文件系统完整、超出配额状态和/或权限问题而无法写入)。
在任何情况下,如果所有索引条目都处于零阶段,则没有未合并的文件,并且可以将索引转换为新的提交。这个提议的提交中的文件内容可能与提交中的内容匹配,也可能HEAD
不匹配;它们可能与工作树中的匹配,也可能不匹配;索引的文件集独立于这两者。