6

我现在每天都在使用 git,这一次我遇到了一个可以这样描述的问题。

我有一个包含整个网站结构的存储库,并且 Web 根目录位于存储库的根目录中。一切都很好,直到那是单个站点的存储库。但是,同一个 repo 现在用于多个站点 - 基本上是同一个站点,使用不同的语言,小的模板调整,不同的图形等。这些东西自然是版本化的。

有一个 master 分支,它保存该站点的原始源代码,我希望 master(或其他一些分支)保存所有站点通用的代码,因为最终会有太多的更改站点-具体包括在回购的通用部分。

接下来,每个使用此源代码的站点都有一个分支。所有这些分支(例如site1site2site3)都是从 master 分支创建的,并且每个站点都克隆正确的分支。

好吧,这似乎是个好主意,直​​到我开始到处进行更改。

如果我在 site1 分支上进行了更改,并且需要将该更改复制到 site2 分支,我会从一个分支选择提交到另一个分支。在那里合并是不可能的,因为 site1 分支上还有其他不属于 site2 分支的更改。对于这种情况,是否还有其他更优雅的解决方案,或者挑选樱桃正是为了这个目的?

现在,对我来说真正的“问题”是当我更改 master 时,然后我想将所有这些更改复制到所有分支。自然地,考虑到所有分支都是 master 的后代,并且我确实希望在所有 site* 分支中进行这些更改,我切换到每个分支并合并 master。

这为所有分支创造了一个看起来很糟糕的历史。每一轮合并都会使图变得相当复杂,这使我得出两个结论:

  1. 只要我注意自己的步骤并且不做任何愚蠢的事情,并且不试图从所有分支历史图表中获得任何意义,这种分层分支的方式就可以工作。或者..
  2. 必须有一些更好,更合适的方法来做到这一点。

为了说明我的“问题”,我将给出创建这些分支后得到的图形图像,添加一些特定于分支的提交,挑选其中的几个,添加并合并从 master 到所有分支的提交,提交或两个到特定的分支,然后再进行一个 master-to-all 合并。

一种不那么简单的历史图

我不知道,我喜欢简单,也许我不习惯看到像这样难以理解的图表(恐怕每次合并都会变得更加复杂)。

我想我可以一直进行挑选,并拥有整洁的历史图表,但这听起来也不对,因为我可能会连续进行几次提交,然后忘记选择其中一个到所有其他分支。 ..

所以... 有什么想法、经验和建议,您不介意分享吗?

更新:我选择了我对已接受答案的评论中描述的解决方案。感谢所有贡献的人!

更新 2:尽管它与这个问题并没有密切相关,但最近我偶然发现了这种似乎适用于几乎任何有组织的开发周期的分支模型,其中 GIT 作为底层 DVCS。这真是一本好书。受到推崇的。

4

2 回答 2

4

替代答案:

您可以将抽象从分支级别移动到存储库级别。创建一个带有 master 分支的主仓库。为每个站点克隆此存储库。在主分支上进行更改时,将这些更改拉入每个站点存储库。这样,每个 repo 只需要一个 master 分支。


原答案:

当主分支发生变化时,您可以将其他分支重新定位到更新的主分支上。让我们假设您有 pl_site 基于对 master 的一些提交,并且该 master 已更改:

 o---o---o---o---o  master
         \
          o---o---o---o---o  pl_site

重新设置 pl_site 的基础后,它将如下所示:

 o---o---o---o---o  master
                  \
                   o'---o'---o'---o'---o'  pl_site

请注意,对 pl_site 的 rebase 版本的提交是新的。pl_site 现在包含对 master 所做的更改。

命令:

$ git checkout pl_site
$ git rebase master
于 2011-05-12T12:17:37.000 回答
1

我没有给你一个好的答案,因为你的问题很复杂,并且有复杂的解决方案。

选项 1:重构

您说不同的站点“基本上是同一站点”。因此,将它们移动到不同的项目中,并将它们单独保存main_site在一个项目中。然后,其他站点将main_site作为子项目包含在内。

所以,对于横幅...

en_site/
en_site/images/banner.jpg
en_site/master/
en_site/master/images/banner.jpg

您的网站代码、配置脚本、部署脚本或任何能确保images/banner.jpg选择master/images/banner.jpg. 也许当您部署站点master/images时先复制然后再images复制它,也许您会做一些更复杂的事情。

这可能是很多工作。但是,当您查看历史记录时,您会得到如下信息:

en_site: A -> B -> C -> D
de_site: E -> F -> G -> H -> I
main_site: J -> K -> L -> M -> N -> O

选项 2:使用 Darcs

在 Darcs 中,您可以将补丁从一个分支移动到另一个分支。一些商业 VCS 可能也可以做到这一点。所以你的分支看起来像这样:

master: patch1 patch2 patch3 patch4
en_site: patch1 patch2 patch3 patch4 en1 en2 en3
de_site: patch1 patch2 patch3 patch4 de1 de2 de3

假设您要将补丁移植en2到德国站点。

de_site: patch1 patch2 patch3 patch4 de1 de2 de3 en2

瞧。然而,这并不像看起来那么干净。Darcs 爱好者会指出,这个补丁模型与我们的“将补丁移动到另一个分支”的概念模型相匹配,但是,这掩盖了一个事实,即您仍然需要测试以确保en2补丁不会破坏所有内容你穿上它de_site

例如,如果en2对代码的同一部分进行更改de1怎么办?然后怎样呢?无论您使用什么 VCS,您都必须手动合并。对于像这样的每一个明显的情况,还有另一种情况是 VCS 无法检测到的,您必须自己检查。

我的经验

当我第一次开始使用git时,它似乎git merge很神奇。但是,再多的 VCS 诡计都无法掩盖您的站点具有一些非常复杂的相互依赖关系的事实。您可以重构您的站点以消除相互依赖关系,或者希望您的 VCS 历史不会变得如此复杂以至于您无法再理解它。

新分支、新项目和重构库之间的权衡是一个微妙的权衡。维护大量补丁集比维护大量使用公共库的项目集合要多得多,重构所需的(大量)工作可能会很快得到回报。或者它可能不会。

于 2011-05-12T12:25:42.870 回答