git将两个文件合并成一个历史记录保存 [英] git combining two files into one with history preserved

查看:354
本文介绍了git将两个文件合并成一个历史记录保存的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设你在git仓库中有两个文件,比如 A.txt B.txt



是否可以将这两个文件连接成第三个文件 A + B.txt ,将原始的 A.txt B.txt 并提交,所以历史记录仍然保留?



也就是说,如果我询问 git log --follow A + B.txt 我就会知道内容来源于 A.txt B.txt 文件?



我尝试将这些文件分成两个不同的分支,然后将它们合并为一个新文件(同时删除旧文件),但无济于事。

解决方案

简短的答案是否(甚至可能是 Mu )。



在Git中,历史记录是 提交集。没有文件历史这样的事情:你有一个提交,或者你没有,并且该提交有一个或多个父母,或者它没有。这意味着文件历史记录不存在 - 但是,存在 git log --follow 。这是自相矛盾的:如果文件历史不存在, git log --follow 如何生成文件历史记录?



答案是 git log --follow 作弊。它没有真正找到文件历史记录。它通过历史查看并通过更改正在查找的文件的(单个)名称构建子历史。它逐个查看每个提交,并针对其父项运行提交(加速,有限)的 git diff - 查找 - 重命名。 > 1 如果diff在父文件中将文件 X.txt 重命名为 A.txt 在孩子里,你正在运行 git log --follow A.txt ,现在 git log 中的代码开始寻找 X.txt



由于没有代码可以一次查找多个文件,你无法得到这个特定的作弊来适应你想要的情况,这是从寻找一个特定的文件到多个文件。 (实际上这里有两个问题,一个是由于内部实现相当有限,所以只能看一下 2 git log --follow 一次一个文件;另一个是重命名检测不包括联合检测:有一种分裂检测的形式,其中Git将执行复制查找,使用 - 查找-copies - find-copies-harder 。后者是非常计算密集型的,两者都在错误的方向上工作,尽管)




1 这意味着, - follow 根本不会查看合并比较,至少默认情况下是这样。另请参阅`git log --follow --graph`跳过提交



2 又名cheesy hack

Imagine the you have two files in a git repository, say A.txt and B.txt.

Is it possible to concat the two files into a third one A+B.txt, removing the original A.txt and B.txt and committing it all, so the history is still preserved?

That is, if I asked git log --follow A+B.txt I would know that the content originated from the A.txt and B.txt files?

I've tried to separate the files into two different branches and then merging them into a new file (while removing the old ones), but to no avail.

解决方案

The short answer is "no" (or perhaps even Mu).

History, in Git, is the set of commits. There is no such thing as "file history": you either have a commit, or you don't, and that commit has one or more parents, or it doesn't. This means that "file history" as a thing doesn't exist—and yet, git log --follow exists. This is self-contradictory: How can git log --follow produce a file history, if file history doesn't exist?

The answer is that git log --follow cheats. It doesn't really find file history. It looks through history and constructs a sub-history by changing the (single) name of the file it is looking for. It looks at each commit, one at a time, and runs a (sped-up, limited) git diff --find-renames of that commit against its parent.1 If the diff says that file X.txt in the parent was renamed to A.txt in the child, and you're running git log --follow A.txt, the code in git log now starts looking for X.txt.

Since there's no code to start looking for more than one file at a time, you can't get this particular cheat to accommodate your desired situation, which is to go from looking for one particular file to more-than-one file. (There are actually two problems here. One is that, due to the rather limited internal implementation,2 git log --follow can only look at one file at a time. The other is that rename detection does not include "combine detection": there is a form of "split detection", in which Git will do copy-finding, enabled with --find-copies and --find-copies-harder. The latter is very compute-intensive, and both are working in the wrong direction here, although it could be made to do the right thing simply by reversing the order of the diff.)


1As this implies, --follow doesn't look at merge diffs at all, at least by default. See also `git log --follow --graph` skips commits.

2aka "cheesy hack"

这篇关于git将两个文件合并成一个历史记录保存的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆