顺便说一句,跟踪“内容”是导致不跟踪空目录的原因。
这就是为什么,如果你git rm文件夹的最后一个文件,文件夹本身会被删除。
但情况并非总是如此,只有Git 1.4(2006年5月)在commit 443f833中强制执行了“跟踪内容”策略:
Git状态:跳过空目录,并添加-u显示所有未跟踪的文件
默认情况下,我们使用——others——directory来显示无趣的目录(以引起用户的注意),而不显示其内容(以整理输出)。
显示空目录没有意义,因此在执行此操作时传递——no-empty-directory。
给出-u(或——untracked)将禁用这种整理
用户获取所有未跟踪的文件。
这在几年后的2011年1月Git v1.7.4的commit 8fe533中得到了回应:
这与一般的UI理念是一致的:git跟踪内容,而不是空目录。
同时,在Git 1.4.3(2006年9月)中,Git开始将未跟踪的内容限制在非空文件夹中,commit 2074cb0:
它不应该列出完全未跟踪的目录的内容,而只列出该目录的名称(加上末尾的'/')。
跟踪内容是git在早期(git 1.4.4, 2006年10月,commit cee7f24)性能更好的原因:
更重要的是,它的内部结构被设计为通过允许从同一个提交中获得多个路径来更容易地支持内容移动(即剪切和粘贴)。
这(跟踪内容)也是git在git 1.5.0中添加的内容(2006年12月,commit 366bfcb)
make 'git add' a first class user friendly interface to the index
This brings the power of the index up front using a proper mental model without talking about the index at all.
See for example how all the technical discussion has been evacuated from the git-add man page.
Any content to be committed must be added together.
Whether that content comes from new files or modified files doesn't matter.
You just need to "add" it, either with git-add, or by providing git-commit with -a (for already known files only of course).
这就是为什么git在1.5.0版本中添加了交互功能(commit 5cde71d)
在做出选择之后,用空行回答,以显示索引中所选路径的工作树文件的内容。
这也是为什么,要递归地从目录中删除所有内容,你需要传递-r选项,而不仅仅是目录名<path>(仍然是Git 1.5.0, commit 9f95069)。
看到文件内容而不是文件本身是允许合并场景的原因,就像commit 1de70db中描述的那样(Git v2.18.0-rc0, 2018年4月)
考虑下面带有重命名/添加冲突的合并:
边A:修改foo,添加不相关栏
边B:重命名foo->bar(但不修改模式或内容)
在这种情况下,原始foo、A的foo和B的bar的三向合并将导致bar的期望路径名具有与A的foo相同的模式/内容。
这样,A就有了文件的正确模式和内容,并且有了正确的路径名(即bar)。
提交37b65ce, Git v2.21.0-rc0, 2018年12月,最近改进了碰撞冲突解决方案。
通过改进rename/rename(2to1)冲突的处理,commit bbafc9c进一步说明了考虑文件内容的重要性:
Instead of storing files at collide_path~HEAD and collide_path~MERGE, the files are two-way merged and recorded at collide_path.
Instead of recording the version of the renamed file that existed on the renamed side in the index (thus ignoring any changes that were made to the file on the side of history without the rename), we do a three-way content merge on the renamed path, then store that at either stage 2 or stage 3.
Note that since the content merge for each rename may have conflicts, and then we have to merge the two renamed files, we can end up with nested conflict markers.