Skip to content
m42e edited this page Jul 9, 2013 · 12 revisions

Introduction

Git Flow is not a tool. First and foremost, it's a workflow.

That being said, this page is mostly about the tool making that workflow even easier to use. So google "git flow" for more general background info (this page can get you started.)

Another important point to note is that there is an open-source version of git flow here: https://github.com/nvie/gitflow. This version is quite heavily modified for use with Gerrit, so these are unfortunately not compatible. Currently the this implementation only focuses only on the "git flow feature" function, which is the one that is relevant for everyday developers (as opposed to integrators, etc.)

What's a Feature Branch?

Feature branches are branches created to do new feature development and should be branched off the develop branch. A feature in this case being a small set of code that completes a sub-section of a business case, or in SCRUM terminology it could be a scenario where a group of tasks complete a story.

Always try to make the lifetime of a feature branch as small as possible and if at all possible, something that can be completed by an individual or team of developers in a single day. If you are using SCRUM, no story should last more than the length of your sprint so that would be the hard upper limit. This makes the merging of various features back into the develop branch much simpler and allows for better Continuous Integration.

Once the feature has been completed and merged back into the develop branch it should be deleted so as to ensure that no new code can be added to that specific feature branch.

Derivations from the official git flow model

Gerrit

The original Git Flow tool is not designed to be used with Gerrit: Once a feature branch is finished, the content is merged directly into the local develop branch. For this reason, a Gerrit-friendly version has been created based on the following thinking:

  • When development of a feature is considered done, the entire content of the feature branch is submitted to Gerrit as a single review.
  • If merging the feature into the develop branch would cause a conflict, the merge conflict must be solved on the feature branch before submitting to Gerrit.
  • If changes are needed due to the review, these are done as new commits on the feature branch.
  • Once the review is closed and the code has been merged into develop, the feature branch is deleted.

Several new commands have been added to the "git flow feature" utility to support this. These are described further down this article.

The connection to gerrit is performed using REST api and curl. Additionally JSON.sh (https://github.com/dominictarr/JSON.sh.git) is used to parse the data of gerrit.

To setup the connection you should set the following config parameters git config gerrit.baseurl https:///gerrit git config gerrit.usern git config gerrit.pwd

Namespaces

The concept of namespaces was added to the git flow branching model. All branches described in the git flow model are duplicated for each namespace. To uniquely identify them, the regular branch names are prefixed with the namespace. So for instance, if there are two develop branches: foo/develop and bar/develop. When you start a feature branch it will be based on one of those develop branches, and it's name will reflect which one, e.g. bar/feature/some-feature-name.

Git Flow Commands

Beside the normal git commands, the following "git flow" commands are likely to be useful:

  • git flow feature start -- Create a new feature branch
  • git flow feature submit -- Submit the contents of a feature branch as a single Gerrit review
  • git flow feature delete -- Delete a feature branch that has been merged in Gerrit or abandoned
  • git flow feature log -- Show git log for the commits in a feature branch
  • git flow feature message -- Edit the commit message that will be used for the single Gerrit commit
  • git flow feature publish -- Share the feature branch for collaborative development
  • git flow feature track -- Use a previously shared feature branch
  • git flow feature fromreview -- Create a feature branch from an ongoing Gerrit review

git flow feature start

git flow feature start <name> [<base>]

This creates a new feature branch with the given name.

The new feature branch will use the same namespace as the branch that is checked out when you run the command.

If you specify base, a different starting branch can be specified (currently broken).

git flow feature submit

git flow feature submit [<name>]

Simply put, this command creates a standalone commit (not on any branch), containing all the changes in the feature branch squashed together (let’s call this generated commit “squash commit”). The generated squash commit is then sent for review to Gerrit.

This command does not modify your feature branch, except if you choose to edit the commit message for the whole feature, in which case the edited message is stored as en empty commit at the tip of your branch.

More specifically the following steps are taking:

  1. Check if the feature branch is shared and the remote branch has commits the local branch does not.
  2. Fetch the latest remote develop branch
  3. Check if the feature branch can be merged cleanly onto the latest develop. (If the merge cannot be done cleanly, start a manual merge on the feature branch.)
  4. Prompt user for commit message for the entire feature. (If the commit message is changed, create a commit in the feature branch recording the new message.)
  5. Squash all changes of the feature branch into a single stand-alone commit (not put on the feature branch).
  6. Push the squash commit to Gerrit for review.

git flow feature delete

git flow feature delete [<name>]

This command deletes the specified (or by default, current) feature branch.

Before deletion, a warning is given if the contents of the feature branch has not been merged into develop.

If the feature branch is shared, the option is given to also delete the shared branch.

git flow feature log

git flow feature log [<name>] [<options>] [[--] <path>...]

Show commit log for the commits in a feature branch.

Works the same way as git log, except the commit range is predefined to be all commits in the feature branch. The feature branch can optionally be specified using the name parameter, otherwise the currently checked out feature branch is assumed.

git flow feature message

git flow feature message [<name>]

This command is used to edit the overall commit message for a feature branch.

When a feature branch is submitted for review using git flow feature submit, the user is always prompted to edit the overall commit message, but this command can be used to edit the message without subsequently submitting the feature for review.

The edited commit message is stored as an empty commit on the feature branch.

git flow feature publish

git flow feature message [<name>]

This command is used to start sharing a feature branch for collaborative development.

After a branch is shared, anyone can start working on the same feature by issuing a git flow feature track command.

On a shared branch, simply use git pull to download remote updates, and git push to upload commits you have added.

Note that when working on a shared branch, you are strongly discouraged from using "git rebase" to rewrite the history of that branch.

git flow feature track

git flow feature track <name>

This command is used to work on a feature branch previously shared by someone using git flow feature publish.

After the shared branch is tracked, simply use git pull to download remote updates, and git push to upload commits you have added.

Note that when working on a shared branch, you are strongly discouraged from using "git rebase" to rewrite the history of that branch.

git flow feature fromreview

git flow feature fromreview <name>

This command is used to create a feature branch from an open Gerrit review.

Before using this command, checkout the latest patchset from Gerrit using the command provided on the review page. After doing this, you should be in "detached head" mode, at which point you can run git flow feature fromreview some-name to create a feature branch called some-name containing a single initial commit corresponding to the patchset you checked out from Gerrit.

This is useful to upload changes to an ongoing Gerrit review when you don't have access to the original feature branch. Maybe the feature branch was not shared and original author went on holiday, or maybe you accidentally deleted the feature branch before the Gerrit review was merged...

Use of Change-Id's

What happens when you use git flow feature submit, is that a completely new commit is created, containing all changes in the feature branch squashed into one. Let’s call this generated commit “squash commit”. Since no single commit on the feature branch is ever pushed to Gerrit (only the generated squash commit is), Change-Id's of commits in the feature branch are not directly meaningful to Gerrit.

However, some of them have a special meaning to the Git Flow tool itself:

Feature Change-Id

Normally, a new Change-Id would be created for the squash commit every time you used "git flow feature submit". This is because the squash commit is generated on-the-fly from the contents of the feature branch, and is not stored anywhere other than being sent to Gerrit for review. Thus, if you were to submit the same feature branch more than once, a new squash commit would be created which would receive a different Change-Id. In turn the second submit would start a completely separate Gerrit review, and this, of course, is not the desired behavior.

To solve this, the Change-Id for the squash commit is derived from the Change-Id of the very first commit in the feature branch (by xor'ing it with 11111..., in case you were wondering). This way, every developer with access to the branch will be able to submit it for review with the same change ID.

There are two reasons for not directly re-using the unmodified Change-Id from the first commit:

  • It gives the possibility to also make separate reviews of individual commits on the feature branch (although this is not recommended, because it's stupid) .
  • Due to a bug in Gerrit, if a feature branch is shared, all reviews with Commit-Id's matching a commit in the feature branch are automatically closed.

Deriving the squash commit Change-Id in a reversible way also means that it is possible to re-create a git-flow compatible feature branch from the corresponding Gerrit review. By reversing the process, the value that should be used for the first commit in the feature branch can be derived from the Change-Id of the Gerrit review. This is essentially what the =git flow feature fromreview= command does for you.

Message Change-Id

There is another "magic" Change-Id derived from the Change-Id of the first feature commit. (This time xor'ed by 22222...).

This Id is magic because the newest commit in the feature branch containing it, will be used as default commit message when issuing the git flow feature submit command.

This is used to record the overall feature commit message in the feature branch, so that you don't have to type it in every time you submit the feature to Gerrit. (Let's be honest, you won't always get it right the first time.)

For instance, git flow feature message will create an empty commit in your feature branch with this magic Change-Id in the commit message.