【问题标题】:Is there a clean way to handle two original git repositories that started with the same content?有没有一种干净的方法来处理两个以相同内容开头的原始 git 存储库?
【发布时间】:2008-12-27 04:11:23
【问题描述】:

假设我有两个从相同初始内容创建的存储库。例如,如果我使用 git 来管理 /etc/apache2 中的 apache 配置文件,并且我在 machine-a 和 machine-b 上分别运行 git init

我已经对 machine-b 进行了一些配置更改,我想将这些更改应用于 machine-a 上的配置,而不会覆盖不常见的东西,例如主机名等。

如果我这样做:

machine-a% remote add machine-b ssh://...
machine-a% git fetch machine-b

我得到了 machine-b 上的所有提交,而 GitX 显示了一组完全断开的提交,正如我所期望的那样。

但是,如果我尝试合并 machine-b 的任何更改,我会在所有修改的行上遇到冲突。

就我的目的而言,这已经足够了,但我想知道,有没有更清洁的解决方案?

【问题讨论】:

    标签: git


    【解决方案1】:

    你可能想看看 git 移植。此处提供了一些信息:http://git-scm.com/docs/git-filter-branch

    基本上,你想做的就是伪造祖先。

    您在两台机器上都进行了初始提交——我们称它们为“baseA”和“baseB”。然后,您在两侧创建了第二次提交——“secondA”和“secondB”。你想要做的是告诉 git 'secondB' 没有 'baseB' 作为祖先,而是有 'baseA' 作为父级。

    您可以通过使用移植物来做到这一点。例如,把它放在你的 .git/info/grafts 文件中:

    secondB baseA
    

    (但随后使用真正的 SHA)。现在,如果你查看 GitX,你会看到历史是相互关联的。要使更改永久生效,您需要运行 git filter-branch。

    从 cmets 更新

    我不确定您所做的是否“正确”,尽管它会起作用。如果你做什么 你做了,你会得到历史:

     BaseA --- SecondA -- .. - ..  - Merge
       \ BaseB --- SecondB ... - .. /
    

    哪个会起作用(并且合并将成功而不会出现问题)。然而,什么 这个更好一点:

     BaseA --- SecondA -- .. - ..  - Merge
       \ SecondB ... - .. /
    

    它基本上将“BaseA”作为提交并将“BaseA”设置为父级 第二B。使用我告诉你的嫁接规则应该可以做到这一点。

    为了证明这一点,我创建了一个小型存储库,您可以下载here

    如果你查看 GitX 中的历史(“gitx master second_master”),你会 看到历史是断开的。如果你将 .git/info/_grafts 文件移动到 .git/info/grafts,你会得到第二个,好看的历史记录。

    我还添加了一个 .git/info/wrong_grafts 文件。如果您使用那个,您将获得您创建的历史记录。

    如果你查看 grafts 文件中的 SHA,你会发现 _grafts 文件基本上有这个:

    SecondB BaseA
    

    而 wrong_grafts 文件有这个:

    BaseB BaseA
    

    【讨论】:

    • 我认为这真的很接近,但目前对我不起作用。在我编辑 .git/info/grafts 和 git-filter-branch 后,GitX 没有显示更新,并且 git-filter-branch 给了我“错误:错误的移植数据:”我现在正在尝试移植中的各种提交组合。
    • 好的,我得到了这个工作。如果你能更新我会接受答案。 .git/info/grafts 是 baseB baseA 然后我运行: git filter-branch baseB..HEAD 同样使用正确的移植文件 gitx 在运行 filter-branch 之前正确显示了历史记录。
    • 我更新了我的答案,回复了您的 cmets,因为它太大而无法放入 cmets 部分。
    • 你的对我有用,现在由于某种原因我的测试回购工作。我不确定我在移植文件中搞砸了什么,但从我读到的内容来看,它可能就像空格一样简单。谢谢。无论如何,如果新的 repo 还没有任何新的提交,我认为我可能不得不这样做。
    【解决方案2】:

    这是 Git 的一个有趣用途;我本可以用它来处理几个基于相同 wiki 代码库但配置却大不相同的网站。

    使用您的初始内容设置一个 Git 存储库,并为每台保存其当前配置的机器创建单独的分支。克隆到另一台机器并将每台机器设置为另一台机器的远程。

    现在您可以在一台机器上进行更改,并在您提交时将它们推送到另一台机器上的分支。

    如果将公共元素与非公共元素分开提交,则可以

    $ git checkout [localmachine bracnch]
    $ git cherry-pick [SHA1 of common commit1]
    $ git cherry-pick [SHA1 of common commit2]
    

    而且,如果您在一台机器上提交之前不知道要重用什么,您可以使用git add --patch 从一个分支中提取单个差异并将它们分阶段提交到另一个分支。

    对于两个以上的机器/站点,您可以将常见的更改合并到 MASTER 并将 MASTER 的更改合并到每个分支上。

    【讨论】:

    • 如果我有先见之明来克隆配置仓库,那将是可行的。在这种情况下,我通常在编辑一些配置文件之前执行 git init,后来我意识到我想将我在另一台机器上做的一些东西打补丁到这台机器的配置中。不过,将根据机器的想法调查分支。
    • 是的,外卖的想法是每台机器都有一个分支。您可以使用移植或创建一个新的存储库,该存储库从每台机器通用的文件内容开始,并将每台机器的历史记录重新设置为一个单独的分支。彼得对移植物给出了很好的解释。
    【解决方案3】:

    Git 如何区分什么是“配置更改”和什么是“不常见的事情”?您是否只想在两者之间共享某些文件,例如 mime 类型的文件?

    如何将共享部分分解为单独的文件并使用 Apache 的 Include 指令并将您想要忽略的任何文件添加到 .gitignore 中?

    【讨论】:

    • Apache 只是我想使用这种东西的情况之一。将其视为使用 git 作为补丁分发机制。我经常对同一库存配置文件中的多台服务器进行相同的配置更改。
    猜你喜欢
    • 1970-01-01
    • 2013-07-16
    • 2022-08-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-14
    • 2011-06-12
    • 2012-10-14
    相关资源
    最近更新 更多