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.
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.
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:
- ActiveAdmin initial installation
- Custom configs
- Add comments explaining stuff
- Fix typo
- Custom views
- Remove delete and create buttons
- Custom styles
- Validations
- More validations
- 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.
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 develop
branch.
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:
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
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.
This is (almost entirely) a shameless copy-paste from the following great blog posts:
If you need to fix bugs on the development branch (different from hotfixes): nvie/gitflow#24