GIT分支/合并策略(主干中没有垃圾)

时间:2015-10-29 23:39:33

标签: git svn version-control merge bitbucket

我目前正在调查如何将subversion repo移动到git(bitbucket)。对我来说最大的阻碍是理解如何将我们当前基于SVN的分支/合并策略转换为git。

我们练习的东西类似于"后备箱里没有垃圾。"具体来说,我们有两个分支(一个用于主动开发,一个用于分段/ QA)和主干(生产):

dev ______________
         \  \ \  (selective merges)
staging ___________
             \  \  (selective merges)
trunk ________________________________

实际上说:

  1. 每个开发人员都在使用新的开发功能,将他们的更改提交给开发分支
  2. 当该功能准备好进行测试时,与该功能相关的开发修订将合并到暂存
  3. 功能准备好推出后,相关的暂存修订将合并到主干
  4. 从颠覆的优势来看,它看起来像这样:

    1. 致力于发展
      • svn checkout .../branches/dev(即:在开发部门工作)
      • svn commit -m "re ticket #1234"(可以进行多次提交,在示例中它们是修订版100,102和105)
    2. 将功能合并到暂存
      • svn checkout .../branches/staging(即:在分期分支工作)
      • svn merge .../branches/dev -c 100,102,105
      • svn commit -m "re #1234 revs 100,102,105"(这可以创建修订版110)
    3. 将功能合并到生产中
      • svn checkout .../trunk(即:在主干中工作)
      • svn merge .../branches/staging -c 110(假设在暂存期间此功能只有一个版本......可能会有更多版本)
      • svn commit -m "re #1234 revs 110"
    4. 这种结构使我们能够实现以下目标:

      • 开发工作的安全空间孤立发生
      • 仅包含来自开发的现成工作的集成测试环境
      • 仅包含质量保证批准代码的现成工作的生产环境
      • 特别强调:我们努力避免全部或全部"合并策略,以及将其移至其他代码行的樱桃挑选修订

      对于所有关于git分支/合并策略的Google搜索,我见过的最佳解决方案涉及主题/功能分支,然后将其合并到主代码行中。这似乎涉及合并全部或全部过程。

      在大多数情况下,我并不关心这个过程在功能上是否与git相同,但该策略的功能具有可比性。

      git newbie的任何指针?

      谢谢,

      麦克

      PS - 经过更多的挖掘,我遇到了skullcandy工作流outlined here似乎最接近我想做的事情。我最好的猜测是它会通过git(有大量的bitbucket pull请求)来完成(假设有两个现有的分支 - 主和分段):

      • git checkout master
      • git branch feature-001
      • (进行更改)
      • git commit -a
      • git push -u origin feature-001
      • 在bitbucket中创建pull-request for feature-001 to staging
      • 在拉取请求批准后,通过bitbucket合并到staging
      • 功能在分段中传递QA后,在bitbucket功能-001中进行新的拉取请求以掌握
      • 批准了pull请求后,通过bitbucket合并为master,删除feature-001分支

      这似乎是一个很好的过程。最佳实践?我不知道。

      这个过程完成后,会出现一个副作用"我不明白bitbucket是否报告了升级分支正在受到惊吓并领先于主人?

1 个答案:

答案 0 :(得分:1)

您在帖子末尾概述的工作流程是基本的Github工作流程,但它有一个缺陷。您的功能分支不在master范围内,但会合并到stagingmaster。这是第一次双重合并后的结果。

          - - - - - 5 [staging]
         /         /
        | Z - Y - X
        |/         \
1 - 2 - 3 - - - - - 4 [master]

请注意,虽然stagingmaster具有相同的内容,但它们具有不同的提交ID和历史记录。这会使事情变得复杂。您不仅要解决任何合并冲突两次(并且可能不同),而且它会杀死Git的一个主要特性:相同的提交具有相同的ID。

等等,情况变得更糟。由于您在QA之后立即合并到staging,然后QA合并到master,因此可以将要素合并到masterstaging 以不同的顺序。这不仅会产生重要的历史,它还会产生不同分辨率的不同合并冲突。现在,您确实不知道masterstaging是否相同。您可以查看git diff master staging,但很难找出差异泄露的位置以及原因。

            - - - - - 5 - - - - 6 - 7 [staging]
           /         /         /  /
          /         / E - F - G -+-
         /         / /          /  \
        | Z - Y - X /  J - K - L    \
        |/         \|/          \    \
1 - 2 - 3 - - - - - 4 - - - - - - 8 - 9 [master]

在此示例中,EFGJKL都来自master上的同一提交。在EFG之前,JKL已合并到暂存,但JKL首先完成QA并在master之前合并回EFGmasterstaging现在可能不同了。您的历史图表也很粗糙,很难理解。

我猜你是否正在使用this Skullcandy workflow?我从未在实践中看到过这样的工作流程,你习惯性地合并到两个分支。看起来过于复杂。你是Git的新手,保持简单。只需从master分支并合并回master。这会生成一个带有所需"特征气泡的图表。

          Z - Y - X   J - K - L
         /         \ /         \
1 - 2 - 3 - - - - - 4 - - - - - 8 - 9 [master]
                     \             /
                      E - F - G - -

现在只有一个合并功能的订单。

此工作流程中不需要暂存。在合并回主数据之前,可以直接从功能分支进行单独更改。

看起来像这样......

  1. git fetch origin; git checkout -b feature/1234 origin/master
  2. 处理该功能。
    1. 进行更改。
    2. 运行开发测试,修复直到它们通过。
    3. 提交。
    4. 重复。
  3. 根据需要更新功能分支。
    1. git fetch origin
    2. 如果不共享,git rebase origin/master
    3. 如果共享,git merge origin/master
  4. git push -u origin feature/1234
    1. CI服务器针对feature/1234运行自动化测试。
    2. 如果失败,请返回第3步。
  5. 创建feature/1234master的拉取请求。
  6. 质量保证测试feature/1234
    1. 如有必要,请更新功能分支(请参阅步骤3)。
    2. 如果失败,请返回第2步。
  7. 功能通过QA后,它会合并到master
    1. 合并到主人。 git merge --no-ff master(或使用Bitbucket内置的合并功能)
    2. 删除远程分支。 git push origin :feature/1234
    3. 删除本地分支。 git branch -d feature/1234
  8. 关键区别在于在合并之前,直接从功能分支进行QA&#d。没有必要维护单独的分段分支和重复合并。没有未经测试的分支会合并到任何内容中。

    值得注意的是,通过将master合并(或重新定位)到其中来更新要素分支具有与将要素分支合并到master中相同的内容。这就是您可以直接从功能分支进行QA的原因。

    应该使用staging分支来跟踪您为下一个候选版本测试的内容。它被用作QA的稳定点,以保护候选版本免于master的更改。它只不过是正常历史上的一个地方。在上面的示例中,staging可能指向提交2。

    另请注意,在完成功能后,您可以进行小型提交,而不是执行一次大git commit -a。修正错字?测试&承诺。添加新方法?测试&承诺。进行重构?测试&承诺。这会将您的工作分解为易于理解的块,更容易映射每一行,并解释其原因。结合测试,它使调试更容易。它是在最后一次提交时传递的,所以从那时起它必须改变。如果git diff很小,则更容易发现导致错误的更改。如果你认为改变是一个坏主意,那么更容易抛出这种改变。

    我的核心理念是,在正常操作下,功能工作应该是孤立的合并应该简单开发分支应该随时为QA做好准备即可。开发人员不应该合并到多个分支(如Skullcandy)。分支之间的樱桃采摘变化应该是一种特殊的操作。开发分支应该进行CI测试。在合并到开发之前,应该完成功能分支。暂存和生产应该只是开发分支上的旧提交。

    Git比SVN更灵活,特殊情况可以在发生时进行处理。如果需要热修复和樱桃采摘,则应尽快回滚开发。您甚至可以使用rebase重写历史记录并平滑所有内容以使正常流程更好地工作。我知道重写历史的这个想法可能会让你现在感到烦恼,你会习惯它。

    这使得分支机构的开发更快更简单,并且增加了可以查看和合并更改的人数。