简体   繁体   中英

Git feature branch workflow

In a game project I am working on (small team of about 10), we have the common Git workflow of having a development branch (the main branch) and then several feature branches, which once completed and pass code review, get merged back to the development branch.

One issue we are facing though, is how to proceed with the next feature (that depends on the last feature) when the last feature hasn't yet passed code review and so is not merged back into development.

For example.

Lets say I have 3 tasks to do. Where each task builds on the code of the previous task (they can't be worked on independently)

To keep it simple, the tasks might be something like:

[Task1] - Add player code [Task2] - Add player code extensions (needs code from Task1) [Task3] - Add more player code bits (needs code from Task2)

So I:

Create a feature branch from development for [Task1] Work on [Task1] until completion Submit a pull request for [Task1] (lets say it takes a few days for code review)

Now I need to work on [Task2], but [Task2] builds on what I did in [Task1]. I can't create my feature branch from development as the [Task1] code has not been merged yet (as it's still in code review)

Should I:

a) Create the [Task2] feature branch from development and merge the [Task1] feature branch into it

or

b) Create the [Task2] feature branch from the [Task1] feature branch

Whilst the above might be manageable, it all gets really messy when you now have to work on [Task3], yet [Task1] is still being code reviewed.

Not to mention that if [Task1] has code review changes, they now have to be merged to [Task2] and then to [Task3] etc

What are my options in this scenario?

Usually you simply try to avoid this, but of course sometimes you can't. A simple alternative is if the later tasks might alter the architecture of the first task, then you could work on them together as one larger feature and merge them together in a single Code Review. Or even break it up into 3 smaller merges after you're done with all 3 tasks. But assuming neither of those are good options for you, let's proceed with your scenario as asked.

The general algorithm goes something like this:

  1. Base task2 off of task1 , and base task3 off of task2 .
  2. Monitor task2 , task1 , and main and rewrite higher numbered branches when anything changes.

#1 is simple, and #2 is usually what people stress out about, particularly when the branches are worked on by different people, or when any branch other than main is shared by multiple people. The reality though, is that "rewriting" a branch is relatively simple to do; it's communicating the change properly and instructing others what to do about it that's more difficult. In your case that may not be a problem at all if you're the one working on all 3 tasks, because you can rebase (rewrite) all 3 branches whenever you feel like it without messing up anyone else. As an added bonus, Git version 2.38 added a new option called rebase --update-refs which enables you to quickly rewrite all of the branches in one command.

Here's an example of how it could work with the new --update-refs option.

Sneak Preview: You're going to make all of your changes on the task3 branch!

Let's assume each task branch is 2 commits ahead of the previous task branch:

A(main)-B-C(task1)-D-E(task2)-F-G(task3)

During the code review of task1 , someone recommends a change. Since you are the owner of all three task branches, you can do all of your changes to any of them while having task3 checked out. So make your fix on task3 in commit X :

A(main)-B-C(task1)-D-E(task2)-F-G-X(task3)

Now you are going to do an interactive rebase ( -i ) in conjunction with the new option ( --update-refs ):

git rebase -i --update-refs main task3 # You can remove "task3" if it's already checked out

You'll be presented with a file in an editor showing the commits in reverse order, so X will be at the bottom. You'll also see the commands that will update the other branches for you, for example something like:

pick 655be8a Commit B
pick 5a07e2f Commit C
update-ref refs/heads/task1

pick 40564e0 Commit D
pick 2706e8c Commit E
update-ref refs/heads/task2

pick 43b4c59 Commit F
pick 4945a1b Commit G
pick c09f14a Fix Commit B # Note this is Commit X

Now move commit X up to somewhere between commit B and the update-ref command for task1 . Perhaps you want to add it as an additional commit, or squash it into another commit if it's just a minor tweak:

pick 655be8a Commit B
fixup c09f14a Fix Commit B # Note this is Commit X
pick 5a07e2f Commit C
update-ref refs/heads/task1

pick 40564e0 Commit D
pick 2706e8c Commit E
update-ref refs/heads/task2

pick 43b4c59 Commit F
pick 4945a1b Commit G

Now save the file and close it, and the rebase will begin. When it's finished it will have re-written all 3 branches, and then you can force push out all of the branches that are being reviewed. Here's a related question that talks about pushing multiple branches after using rebase --update-refs .

Note: This answer assumed you were the only one working on all 3 branches. If that's not the case, you'll need to let others know that you force-pushed these branches so they can either delete their local copy and re-check it out, or do a hard reset to the latest version, or if they have unshared commits they can rebase their changes onto the latest version.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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