Skip to content

Instantly share code, notes, and snippets.

@dmfrancisco
Created March 2, 2013 19:07
Show Gist options
  • Save dmfrancisco/5072619 to your computer and use it in GitHub Desktop.
Save dmfrancisco/5072619 to your computer and use it in GitHub Desktop.
Another Git Workflow

Another Git Workflow *

This workflow is heavily based on the branching model presented by Vincent Driessen on his blog and applies its tool, git-flow, to make it extremely easy to follow.

git-flow is a collection of Git extensions to provide high-level opinionated operations that fit seamlessly into the usual development cycle of agile projects for the web. Its structure includes a development branch and topic branches for features, release branches for your staging environment and a master branch for production. It also offers a neat way to fix bugs already under production. Finally, each operation explains what was done after its execution, which helps you understand commands while you are not used to them yet.

So you should start by installing git-flow. Next, initialize a new repository or choose an existing one:

git flow init

If you're initializing a new repository, this will create some new branches. If you are "converting" an existing one, don't worry, git-flow will just store some configurations in your .git/config file and will keep your repository unchanged. It will ask you a bunch of questions, but you probably want to accept the default values:

No branches exist yet. Base branches must be created now.
Branch name for production releases: [master] 
Branch name for "next release" development: [develop] 
How to name your supporting branch prefixes?
Feature branches? [feature/] 
Release branches? [release/] 
Hotfix branches? [hotfix/] 
Support branches? [support/] 
Version tag prefix? []

After you have answered the questions, git-flow sets your default branch to develop (or whatever you named it, but from now on we'll assume you accepted the defaults), since that’s the one you will be working on.


Feature branches

Starting a new feature

New user and tech stories are implemented in a feature branch. Nothing gets done in master — it must always be stable. Occasionally, minor improvements can be added directly into the develop branch. For those, simply use Git like you’re used to. But let’s imagine that we want to add an administration interface to our app:

git flow feature start admin --fetch

This will update the local develop branch with remote changes, create a new branch called feature/admin (based on the develop branch) and switch to it. Now, start committing on your feature.

Working on the feature

Commit early, commit often. Commit as you get work done and don't worry if you end up with a lot of "bug fix" or "fixed typo" commits. Your commit history may look like this:

  1. ActiveAdmin initial installation
  2. Custom configs
  3. Add comments explaining stuff
  4. Fix typo
  5. Custom views
  6. Remove delete and create buttons
  7. Custom styles
  8. Validations
  9. More validations
  10. Improve models and rake task

Looking at these commits, it’s pretty messy. That’s cool though, this is an accurate representation of what you did, however there are a few things to note.

In a team environment they are seeing a lot of pointless commits. It’s more for them to read and review. There will be no desire to ever roll back to a stage in the commit history where the code didn’t have those "More validations", so being able to roll back to that point seems silly. These could all be summed up in fewer commits. In the next section we will improve our feature's history and merge it back to develop.

Needless to say, you can share this branch with other team members that are working on the same feature. git-flow does not forbid you to keep using vanilla Git commands — you can push and pull as usual. On the other hand, git-flow offers publish, track and pull commands for this too.

Completing the feature

After you are done working on the admin interface, you can diff it against the develop branch:

git flow feature diff admin

This allows you to review any changes visually (similar to the Git command git diff develop feature/admin). If this final check goes well then you are almost ready for merging it into develop. Because feature/admin is a non-production branch, you can rebase it. Rebasing allows you to reword, reorder and merge commits. What we do now is:

git flow feature rebase -i admin

What this does is replays those commits against develop and interactively (-i) allows us to modify them (it's similar to the vanilla Git command git rebase develop -i). Running that command might leave you looking at something a little like this:

pick df0321b ActiveAdmin initial installation
pick 1ed9323 Custom configs
pick af11cef Add comments explaining stuff
pick 4ebe438 Fix typo
pick a64fe9e Custom views
pick 64073f0 Remove delete and create buttons
pick 4ebe438 Custom styles
pick 8b83cbc Validations
pick 324f2a2 More validations
pick 211185a Improve models and rake task

The word pick can be replaced with a number of things, but the most common one is f, for fixup, and it means you want to merge that commit into the previous one and discard the commit's message.

What we want to do here is to merge some of those commits and improve the commit messages. We need to modify the above to look like this:

pick df0321b ActiveAdmin initial installation and configuration
f 1ed9323 Custom configs
f af11cef Add comments explaining stuff
f 4ebe438 Fix typo
pick a64fe9e Custom pages for each resource in ActiveAdmin
pick 64073f0 Removed buttons and views of unwanted actions in ActiveAdmin
pick 4ebe438 Custom styles for the ActiveAdmin pages
pick 8b83cbc Improved data model and updated rake task for legacy data import accordingly
f 324f2a2 More validations
f 211185a Improve models and rake task

Use discretion when rebasing — only fixup commits if you really feel you need to. If you end up with ten commits and you feel that you need to keep all ten then by all means, please do so. Be careful when you reorder commits too, since it may lead to more conflicts to resolve. (By the way, there's a way to autosquash commits based on their commit messages but I don't like it so much.)

Now, simply finish the feature with:

git flow feature finish admin

The command will merge the feature branch feature/admin into develop, remove the feature branch, and checkout the developbranch.


Release branches

When all features are complete, simply start a release branch (again, this will be based on develop):

git flow release start v0.1.0

Bump the version number, pull this branch into your staging server (with git flow release track v0.1.0) and probably fix some last-minute bugs. When you finish a release branch, it’ll merge your changes to master and back to develop, so you don’t have to worry about your master being ahead of develop. It will also add a tag for this new version.

You can check that eveything went ok with git log --all --graph --decorate --oneline -n60, which will output something like this:

git-graph

You probably want to add an alias for that last command in your ~/.gitconfig. For example, as git graph:

[alias]
    graph = log --all --graph --decorate --oneline -n60

Hotfix branches

The last thing that makes git-flow a powerful tool is it’s ability to handle hotfixes. You start and finish a hotfix branch like anything else, but it’s based on master so you can quickly fix it when something is broken under production and merge it back to master and develop using finish.


Credits

This is (almost entirely) a shameless copy-paste from the following great blog posts:

@dmfrancisco
Copy link
Author

In the example for the interactive rebase, I used a shortcut to simplify the explanation. I thought changing the commit message directly would work, but it doesn't. You can use r, for reword, instead of pick. Alternatively, if you use squash instead of fixup you will also be prompted to enter a new commit message for the merged commits.

@dmfrancisco
Copy link
Author

If you need to fix bugs on the development branch (different from hotfixes): nvie/gitflow#24

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment