我需要将两个文件合并为一个。人们可以简单地复制和粘贴。
但是我想知道git是否提供了任何机制,以便合并的文件将保留两个文件的行历史记录?因此,当git blame
您仍然可以看到两个文件的历史记录时。
答案 0 :(得分:2)
简短的回答是:“尝试git blame -C -C -C
。如果还没有完成这项工作,那就不行。”
答案很长,如果你修改git blame
本身,你可以追溯性地进行这项工作,即即使对于已经发生这种情况的代码,它也会起作用。但是,这需要一些非常聪明的工作。
git blame
和git log --follow
处理文件重命名的方式与git diff
处理重命名和复制的方式相同,也就是说,通过heuristic。使用git diff
,您可以使用一些控制旋钮来设置参数:-B
,-M
,-C
,--find-copies-harder
和-l
。这些允许您增加并限制git diff
在查找复制和移动代码方面的工作量。
使用git blame
,您只能获得-C
选项,您可以重复此选项。 (你也得到-M
,但它与git diff
中的含义不同 - 差异化的重命名检测功能就像通过默认的-M
选项一样开启。)
什么git diff
- 因此git blame
,因为它使用相同的内部差异机制,所以将每个提交视为完整的快照。
也就是说,假设您在开发中的当前位置(例如)总共有三个文件,f1
,f2
和f3
。现在这三个都存在,您可以更改一个(f1
),添加更改并提交。新提交仍然具有相同的三个文件:与之前的提交相比,它只有f1
的修改版本。
如果您随后删除文件(例如f3
)并提交,则新提交有两个文件f1
和f2
。如果您没有修改和git add
这两个文件,则它们在此新提交中与先前提交中的相同。如果你做了修改和add
- 例如,如果你将所有f3
的内容都包含在f2
中 - 那么新提交的剩余文件就不同了以前的提交。
git diff
以及git blame
可以做的是注意到在“之前的提交”中有三个文件,f1
,f2
和{ {1}},在“下一次提交”(或“当前提交”)中,只有两个文件。因此,它可以查看f3
或f3
中是否显示f1
的任何行。
如果您执行相反的操作,例如,如果您从f2
到f1
的任何文件中获取一些代码并将其移动到新文件f3
中,然后添加并提交这些更改 - 然后f4
可以看到git diff
之前和之前都不存在,因此它可以查看是否已从其中一个现有文件重命名或复制f4
。< / p>
在所有情况下,重命名和复制检测都需要花费大量的工作。 1 因此在f4
的情况下,重命名和复制检测通常完全关闭,除非你将git diff
配置为diff.renames
, 2 或true
或copies
;或者如果在命令行中指定copy
和/或-M
参数。 (Git的差异也提供-C
来限制看起来有多难。 3 )
使用-l
,重命名检测更容易,因为它一次只能处理一个文件(使用有效的git blame
自动重命名)。仅在检测复制线时出现困难。在这里,-M50%
- 给出一次 - 告诉-C
查看修改了正在检查的文件的相同提交中已修改(包括删除)的文件。给定两次,git blame
将查看在创建文件时在同一提交中修改的文件。给定三次,git blame
将查看每次提交中的所有文件。也就是说,即使git blame
在您要求f1
查看文件git blame
的更改的提交中未更改,它也会查找来自f3
的副本,但只有你已经给过f1
三次。
1 由于git的设计,有一种重命名/复制检测很容易。 与其他文件完全相同的文件在git的存储库中具有相同的“内部名称”,因为存储库对象的“名称”实际上只是对象数据的加密校验和。 Git假设没有两个不同的文件将校验和到相同的值。
理论上可能会出错。机会由"Birthday problem"给出。由于SHA-1是160位散列,因此任意两个文件随机冲突的可能性为2个 159 中的1个,或730个中的1个750 818 665 451 459 101 842 416 358 141 509 827 966 271 488(“短程”系统中约730个quindecillion中的1个。这不是一个大问题;我们更有可能被一个错误的小行星消灭。 : - )
2 确实设置为任何有效的布尔值“true”。请参阅git config
的文档。
3 这可以配置为-C
。设置为diff.renameLimit
表示“无限制”。多年来,默认情况发生了变化;它是100,然后是200,目前设置为400.我认为现有限制对0
没有实际影响。
答案 1 :(得分:0)
是的,您可以这样做!假设您有两个文件foo
和bar
希望合并到foobar
:
my_branch
。my_branch
,将foo
重命名为foobar
,然后提交。master
,将bar
重命名为foobar
,然后提交。my_branch
合并为master。您会遇到大冲突。解决它并提交。我现在需要执行此操作,效果很好!
(请注意,@ bperson已经在上面提出了这一建议)