Cha*_*ers 66 git git-diff git-log
有几次,我遇到过这样的说法:如果你将一个函数从一个文件移动到另一个文件,Git可以跟踪它.例如,这个条目说,"Linus说,如果你将一个函数从一个文件移动到另一个文件,Git会告诉你整个移动过程中单个函数的历史."
但我对Git的一些引擎盖设计有一点了解,我不知道这是怎么回事.所以我想知道......这是正确的陈述吗?如果是这样,这怎么可能?
我的理解是Git将每个文件的内容存储为Blob,每个Blob都有一个全局唯一的标识,该标识来自其内容和大小的SHA哈希.然后Git将文件夹表示为树.任何文件名信息都属于Tree,而不属于Blob,因此文件重命名例如显示为对Tree的更改,而不是Blob.
因此,如果我有一个名为"foo"的文件,其中包含20个函数,以及一个名为"bar"的文件,其中包含5个函数,我将其中一个函数从foo移动到bar(分别生成19和6), Git如何检测到我将该函数从一个文件移动到另一个文件?
根据我的理解,这将导致2个新的blob存在(一个用于修改的foo,一个用于修改的条).我意识到可以计算diff以显示函数从一个文件移动到另一个文件.但是我没有看到关于函数的历史如何可能与bar而不是foo相关联(反正不是自动的).
如果Git的是真正看里面单个的文件,并计算每个函数BLOB(这将是疯狂的/不可行的,因为你必须知道如何解析任何可能的语言),那么我可以看到这是可能的.
所以...声明是否正确?如果它是正确的,那么我理解中缺少什么?
小智 28
此功能通过git blame -C提供
-C选项驱动git尝试查找正在审阅的文件中添加或删除文本块与在相同更改集中修改的文件之间的匹配.附加-CC或-CCC扩展搜索范围.输入git help blame作为手册页.
尝试使用git blame -C进行测试回购,你会看到你刚刚移动的代码块来自它所属的原始文件.
vas*_*vas 14
从Git 2.15开始,git diff现在支持使用该--color-moved选项检测移动的行.它适用于跨文件移动.
显然,它适用于彩色终端输出.据我所知,没有选项以纯文本补丁格式指示移动,但这是有道理的.
对于默认行为,请尝试
git diff --color-moved
该命令还需要选择,目前是no,default,plain,zebra和dimmed_zebra(使用git help diff以获得最新的选项及其说明).例如:
git diff --color-moved=zebra
至于如何完成,您可以通过该功能的作者从该电子邮件交换中收集一些理解.
git实际上根本不跟踪重命名。重命名只是删除和添加,仅此而已。任何显示重命名的工具都会根据此历史信息重建它们。
因此,跟踪函数重命名是一个简单的事情,只需在事后分析每次提交中所有文件的差异即可。这没有什么特别不可能的。现有的重命名跟踪已经可以处理“模糊”重命名,其中对文件进行一些更改以及重命名;这需要查看文件的内容。查找函数重命名也是一个简单的扩展。
我不知道基本的 git 工具是否真的做到了这一点——它们试图保持语言中立,而函数识别在很大程度上不是语言中立的。
这个功能有点像git gui blame(+ filename).它显示文件行的注释,每个注释表示文件的创建时间和最后更改时间.对于跨文件的代码移动,它显示原始文件的提交作为创建,以及将其作为最后一次更改添加到当前文件的提交.试试吧.
我真正想要的是git log作为一些参数给出文件路径之外的行号范围,然后它将显示该代码块的历史.如果文件是正确的,那就没有这样的选择.是的,根据Linus的陈述,我也认为这样的命令应该随时可用.