如何在合并分支时重命名更改的文件并保留旧版本?

How to rename changed files while merging branches and keep old versions?

假设我的主分支上有以下文件

$ git checkout master
$ cat truth.txt
The Earth is flat

及其在某些分支上的更新版本(基于 master

$ git checkout magellan-dev
$ cat truth.txt
The Earth is a globe

我现在想将分支 magellan-dev 合并到 master,但将所有文件更改为具有不同名称的新文件。它可能看起来像

$ git checkout master
$ git merge megellan-dev --some-magic-flag
$ ls
truth.txt truth.txt.magellan-dev

我找到的针对单个文件的解决方案是手动重命名该文件并检查之前的文件

$ git checkout master
$ git merge magellan-dev
$ mv truth.txt truth.txt.magellan-dev
$ git checkout HEAD^ truth.txt
$ git add truth.txt truth.txt.magellan-dev 

但这对大量文件的泛化效果很差。我怎样才能做到这一点?

Git 没有内置任何东西来执行此操作。

您可以通过使用 git read-tree 在索引中进行合并来处理 一些 情况,而无需解决任何冲突的更改。但请注意 even git read-tree's 3-way merge 在某些情况下只会选择某个文件的两个端点版本之一:如果某个文件的合并基本版本(树 #1 插入索引中的插槽 #1)F 匹配其他两个(暂存槽 2 或 3)之一,并且 匹配 F 中的版本other 两个暂存槽中的 git read-tree 会将三个版本折叠到一个 stage-zero 槽中,并采用修改后的文件。

换句话说,给定您的示例 truth.txt 有两个不同的内容,我们首先需要知道:合并基础版本说什么? 如果合并truth.txt 的基本版本与两个 branch-tip 版本中的一个完全匹配,然后 all Git 合并操作将自动采用另一个版本。只有当这三个都不同时,Git 才会将所有三个都保留在索引中,这样您就可以使用 Git 的 built-in 助手中的一些来实现您想要的结果。

如果这不符合您的需求,您将不得不构建自己的程序来处理各种树木。请注意,您可以创建自己的临时索引并使用 git read-tree 来填充它,然后在您使用的许多临时索引文件上使用 git ls-files --stage,当然还有真正的索引文件,以比较实体。这为您提供了一种快速的方法来确定读入任何两个索引文件的任何两棵树中 truth.txt 是相同还是不同。

(当然,您可以在不使用 Git 的任何内部结构的情况下完成所有这些:只需在单独的 work-trees 中检查有问题的提交,然后比较 work-tree文件。)