简体   繁体   English

Git 多个功能分支的工作流程

[英]Git Workflow for Multiple Feature Branches

Let's say I'm working on a feature that involves changes to multiple components of a system.假设我正在开发一个涉及对系统多个组件进行更改的功能。 As an example, let's say I need to update a daemon, server, and client.例如,假设我需要更新守护程序、服务器和客户端。 My current workflow would leave me with branches/commits like this:我当前的工作流程会给我留下这样的分支/提交:

m1---m2---m3  <- master
           \
            d1---d2  <- daemon
                  \
                   s1---s2  <- server
                         \
                          c1---c2  <- client

With these branches, I could create 3 pull requests on GitHub, merging client -> server , server -> daemon , and daemon -> master .有了这些分支,我可以在 GitHub 上创建 3 个拉取请求,合并client -> serverserver -> daemondaemon -> master This all works fine, until I need to add a commit on a branch other than client .这一切都很好,直到我需要在client以外的分支上添加提交。 For example, let's say I make a commit on daemon :例如,假设我在daemon上提交:


m1---m2---m3  <- master
           \
            d1---d2---d3  <- daemon
                  \
                   s1---s2  <- server
                         \
                          c1---c2  <- client

Now I'm left in "rebase hell", where I need to rebase server onto daemon , client onto server , etc. Is there a way to move s1 to d3 and take downstream branches like client with it in one command?现在我留在“变基地狱”中,我需要将server变基到daemon ,将client变基到server等。有没有办法将s1移动到d3并在一个命令中使用它的下游分支,如client Thus leaving a final state like this and my pull requests in tact:因此留下一个像这样的最终 state 和我的拉取请求:


m1---m2---m3  <- master
           \
            d1---d2---d3  <- daemon
                       \
                       s1---s2  <- server
                             \
                             c1---c2  <- client

In theory you should only need to merge daemon and client with master if you're branching in this manner but, it's not really an ideal way to split work unless each upstream change is dependent on the previous component and even then you might want to save integration for the overall feature release/merge rather than doing it at each child component.从理论上讲,如果您以这种方式分支,您应该只需要将daemonclientmaster合并,但是,除非每个上游更改都依赖于前一个组件,否则这并不是拆分工作的理想方式,即使那样您可能想要保存集成整体功能发布/合并,而不是在每个子组件上进行。

In Example 2 all commits but d3 are already in client so you could simplify your workflow(s) to either 1, 2, or 3 steps:在示例 2 中,除d3之外的所有提交都已在client中,因此您可以将工作流程简化为 1、2 或 3 个步骤:

  • Example 1 : merging client -> master brings in everything.示例 1 :合并client -> master带来一切。
  • Example 2 : merging client -> master brings in everything but d3 .示例 2 :合并client -> master会引入除d3之外的所有内容。 Cherry pick (or rebase commit only) d3 to client or master. Cherry pick(或仅 rebase 提交) d3到客户端或主控。
  • Example 2 (alt - simplest): Merging daemon -> client -> master would bring in d3 and server .示例 2 (alt - 最简单):合并daemon -> client -> master将引入d3server
  • Example 2 (alt 2): Merge upstream branches ( daemon , server ) before downstream PR ( client -> master ).示例 2 (alt 2):在下游 PR ( client -> master ) 之前合并上游分支 ( daemon , server )。

A safer way to do this might be to simply branch master once to create an integration branch and then branch and merge (when resolving) each component so you can test their interoperability without updating your production branch.一个更安全的方法可能是简单地将 master 分支一次以创建一个集成分支,然后分支并合并(在解析时)每个组件,这样您就可以在不更新生产分支的情况下测试它们的互操作性。 This would be where you're doing reviews and then merging that to master once release is ready.这将是您进行审核的地方,然后在发布准备好后将其合并以掌握。

This, of course, means 1 more merge rather fewer but wouldn't involve branching feature chaining and would make it easier to catch bugs before release.当然,这意味着 1 次合并而不是更少,但不会涉及分支功能链,并且会更容易在发布之前捕获错误。 Sometimes you don't want the fewest merges or the cleanest history, you want guardrails.有时您不想要最少的合并或最干净的历史记录,您需要护栏。

It may feel like it's "rebase hell", but the reality is you only need a single rebase command, and then you simply need to repoint the middle branch(es) to their new respective commits.感觉就像是“变基地狱”,但实际上您只需要一个变基命令,然后您只需将中间分支重新指向它们各自的新提交。 So that's 1 rebase command followed by n-2 branch resets, where n is the number of PR's (branches) you will have.所以这是 1 个 rebase 命令,然后是n-2分支重置,其中n是您将拥有的 PR(分支)的数量。 In your example with 3 branches it's kind of a two-liner:在您的带有 3 个分支的示例中,它是一种两条线:

git rebase d2 client --onto d3
# Now for each middle branch, reset to the corresponding new commit ID:
# Look at the log of client to see the new s2 ID
git branch -f server <new-commit-id-of-s2>

If you had many branches chained in this way or you needed to do this often, surely you could automate the reset portion if desired (eg commit messages and author name/dates will be the same, etc).如果您有许多以这种方式链接的分支,或者您需要经常这样做,那么您当然可以根据需要自动执行重置部分(例如,提交消息和作者姓名/日期将相同等)。 However, considering that branching in this way is (generally) a theoretical anti-pattern, I hope it wouldn't happen often enough to warrant spending too much time automating something that can be done manually quickly enough.但是,考虑到以这种方式进行分支(通常)是一种理论上的反模式,我希望它不会经常发生,以至于需要花费太多时间来自动化可以足够快地手动完成的事情。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM