假设我有两个从相同的初始内容创建的存储库.例如,如果我使用git来管理/ etc/apache2中的apache配置文件,我会分别git init
在machine-a和machine-b上运行.
我已经对machine-b进行了一些配置更改,我希望将其应用于机器上的配置,而不会覆盖诸如主机名之类的非常见内容.
如果我这样做:
machine-a% remote add machine-b ssh://...
machine-a% git fetch machine-b
Run Code Online (Sandbox Code Playgroud)
我得到了机器b上的所有提交,而GitX显示了一组完全断开的提交,正如我所料.
但是,如果我尝试合并任何机器b的更改,我会在所有修改的行上出现冲突.
就我的目的而言,这已经足够了,但我想知道,有更清洁的解决方案吗?
你可能想看看 git 移植。一些信息可以在这里找到:http://git-scm.com/docs/git-filter-branch
基本上,你想做的就是伪造祖先。
您在两台机器上进行了初始提交——我们将它们称为“baseA”和“baseB”。然后,您在两侧的基础上创建了第二个提交——“secondA”和“secondB”。你想要做的是告诉 git 'secondB' 没有 'baseB' 作为祖先,而是以 'baseA' 作为父代。
您可以通过使用移植物来实现这一点。例如,将其放入您的 .git/info/grafts 文件中:
secondB baseA
Run Code Online (Sandbox Code Playgroud)
(但随后使用真正的 SHA)。现在,如果您查看 GitX,您会发现历史记录是相互关联的。要使更改永久生效,您需要运行 git filter-branch。
我不确定你所做的是否“正确”,尽管它会起作用。如果你做了你所做的事情,你将得到历史:
BaseA --- SecondA -- .. - .. - Merge
\ BaseB --- SecondB ... - .. /
Run Code Online (Sandbox Code Playgroud)
这将起作用(并且合并将成功而不会出现问题)。然而,更好一点的是:
BaseA --- SecondA -- .. - .. - Merge
\ SecondB ... - .. /
Run Code Online (Sandbox Code Playgroud)
这基本上会删除“BaseA”作为提交并将“BaseA”设置为 SecondB 的父级。使用我告诉过你的嫁接规则这应该是可能的。
为了演示这一点,我创建了一个小型存储库,您可以在此处下载。
如果您查看 GitX 中的历史记录(“gitx master secondary_master”),您会发现历史记录已断开连接。如果将 .git/info/_grafts 文件移动到 .git/info/grafts,您将获得第二个漂亮的历史记录。
我还添加了一个 .git/info/wrong_grafts 文件。如果您使用它,您将获得您创建的历史记录。
如果您查看移植文件中的 SHA,您会发现 _grafts 文件基本上包含以下内容:
SecondB BaseA
Run Code Online (Sandbox Code Playgroud)
错误的_grafts 文件有这样的内容:
BaseB BaseA
Run Code Online (Sandbox Code Playgroud)