git将两个文件合并成一个历史记录保存 [英] git combining two files into one with history preserved
问题描述
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屋!