1. 典故
忒修斯之船是一个非常著名的悖论,是一种统一性的悖论。它主要的研究问题是:假定某物体的构成要素被置换后,但它依旧是原来的物体吗?
其问题的具体形式是:
它描述的是一艘可以在海上航行几百年的船,归功于不间断的维修和替换部件。只要一块木板腐烂了,它就会被替换掉,以此类推,直到所有的功能部件都不是最开始的那些了。问题是,最终产生的这艘船是否还是原来的那艘特修斯之船,还是一艘完全不同的船?如果不是原来的船,那么在什么时候它不再是原来的船了?哲学家Thomas Hobbes后来对此进行了延伸,如果用特修斯之船上取下来的老部件来重新建造一艘新的船,那么两艘船中哪艘才是真正的特修斯之船?
这是一个非常有趣的思想实验,在git里同样会遇到这样的问题,当你修改了一个文件时,那么这个文件到底还是不是原来那个文件,修改到什么程度了,才不是原来的文件,什么时候该跟踪,根据什么跟踪?文件名么?文件名更改后,是不是就认为是2个文件了?还是根据内容?内容变化了,是不是就是2个文件了?
在传统的解读里,也就是3种情况,一种就是,只要发生变化,就认为是不同的东西。第二种认为,无论它怎么变化,它还是它自己。因为它就是这个船。第三种就是,如果它替换的东西达到了一半了,那么就认为是新的东西,否则的话,还是原来的那个。
这三种想法都是非常朴素的,因此也非常容易实现,在历史上的各中版本控制工具中,也是有这样的做法的。
2. 在不同的版本控制系统中的做法
CVS系统:当你移动文件的时候,历史就会被破坏,它认为这是一个完全不同的东西,你不能在移动过程中追踪文件的历史。
SVN 企业版的控制工具(每个文件都有标识,文件可以分支,追踪文件的移动是很简单的事情,因为数据库记录这个东西。)
Git的处理方式:默认,只要有100%相似它就被判定为同一个东西。你可以上下调整这个参数:
$ git log --stat -1 -M
$ git log -M99 -1 --stat
例如我们修改了file2.txt文件,重命名为file2new.txt。那么提交后,Git会给我们一个这样的结果:
$ git commit -m "重命名了file2new.txt 文件"
[master 08d8664] 重命名了file2new.txt 文件
1 file changed, 0 insertions(+), 0 deletions(-)
rename file2.txt => file2new.txt (100%)
可以看到在最后一行我们看到了一个100%的相似度。
使用-M在开关log命令中,当我们的相似度管的改变的时候,Git不存储Move内部的持久化数据结构,Move是时候的说明,关于日志的命令或者合并的命令,在仓库中发生,在持久化数据结构这个level,他只是存储一个删除和添加的操作,代码在以后能够读到那个数据,然后能够定义它是什么意义。
3. 小结
事实上,以上三种实现方法都是非常朴素的,它们只考虑了这个物体本身的特性,并没有加上时空和性质等更加复杂的因素在内。