Using gitflow without toolsets
Demo of a simple git project implementing gitflow without any tools
Gitflow is a git workflow model with predictable branching patterns, including developing new features, shipping out releases, and handling hotfixes. Vincent Driessen came up with the original idea in 2010. Eventually helper CLIs came out (which I recommend using) that hide away the complexity of the flow steps. I will write about these in an upcoming post. Although, I find it useful to know what is going on under the hood before committing to a new automation toolset.
This blog post goes through a quick demo of a project using gitflow, and the various steps it goes through, from working on a feature to releasing it into production.
You can clone the repo for this post here https://github.com/joeshub/gitflow-demo, or better yet follow along step by step.
Start a new sample git project
mkdir gitflow-demo && cd gitflow-demo touch README git commit -am "first commit" git remote add origin firstname.lastname@example.org:joeshub/gitflow-demo.git git push -u origin master
Our Working tree is always the
develop branch in gitflow. Create a new develop branch locally and push it up. You should now have 2 branches upstream;
git checkout -b develop git push -u origin develop
New development in gitflow is always done in a feature branch, based off the develop working tree branch. Feature branches are by convention prefixed with
feature and a slash, so the format is
git checkout -b feature/foo develop echo "console.log('foo');" >> foo.js git commit -am "Adding foo file"
Now let's assume we or another team member wants to simultaneously work on a different feature. We just create a new branch for it that tracks develop.
git checkout -b feature/bar develop echo "console.log('bar');" >> bar.js git commit -am "Adding bar file"
Merging features into develop
When ready, we send a pull request for the feature so it can be merged into the develop branch.
For simplicity, here we are going to just merge
feature/foo back into
develop without sending an PR, and push it back into develop.
git checkout develop git merge feature/foo git push
Rebasing from develop into a feature branch
Now let's switch to our feature/bar branch. To get the latest changes that have landed in develop, we need to
rebase from there. This will do a rewind/apply/replay so that your changes get added on top of any new updates to develop since you last pulled. You will want to do this rebasing from develop step often while working on a feature branch to avoid messy conflicts.
git checkout feature/bar git rebase develop # First, rewinding head to replay your work on top of it... # Applying: Adding bar file
If you run a git log you will see your change to
bar.js is now the last commit in your branch, and the other foo features that have already landed in develop.
git log --pretty=oneline --abbrev-commit # 8b404a5 (HEAD -> feature/bar) Adding bar file # 195431c (origin/develop, feature/foo, develop) Adding foo file # fed3007 (origin/master, master) initial commit
Now we just repeat the same steps as before. We
push our feature upstream into develop. Again we are skipping the PR step here for simplicity.
git checkout develop git merge feature/bar git push
We always create release branches from develop. They are always prefixed with
release/ in gitflow, for example
release/1.0. This allows work to continue on develop, while we do a release. We then push our new release branch upstream. Normally a build & deploy step runs which pushes the release to a staging environment for testing and QA.
git checkout -b release/1.0 develop git push -u origin release/1.0
Fixing issues after a release
Looks like QA found a bug! In this case, bar.js needs to output text in all caps.
To fix bugs found in a release branch, we make edits to the release branch and merge those changes back into the release branch, and normally this goes through a PR step as well. In larger teams, you can also create a new branch to track the bug fix and send a PR to merge this into the release branch.
echo "console.log('BAR');" > bar.js git commit -am "hot fix bar.js" git push
After bug fixes are released, we need to make sure to merge the release branch changes into our main develop branch.
git checkout develop git merge release/1.0 git push
Releasing to production from master
Once a release is tested, it is then released into production. So we will merge our release branch into master as well.
git checkout master git merge release/1.0 git push
Tagging master allows us to track the release version that's currently out on production. Once we've tagged
master we are finally ready to deploy that tag into production.
git tag v1.0.0 git push origin v1.0.0
Hot fixing bugs in production
After our release went out, marketing looked at the ALL CAPS and decided it wasn't very nice. So we need to do a hot fix to our production code.
Using the gitflow naming convention, we create a branch off of
hotfix/ and the bug being fixed, for example
git checkout -b hotfix/fixes-bar-caps master echo "console.log('bar');" > bar.js git commit -am "hotfix removes all caps in bar.js"
Once ready, we will merge the hotfix into master. Then we'll re-tag a release and push that tag to master.
git checkout master git merge hotfix/fixes-bar-caps git push git tag v1.0.1 git push origin v1.0.1
We also need to make sure to merge the hotfix back into our develop branch, to keep it up to date with master.
git checkout develop git merge hotfix/fixes-bar-caps git push
Cleaning up branches after a release
After you're done with a release, it's good to clean up branches that have already been merged in. At this point you will have the following branches:
git branch -avv # develop 00b2d00 [origin/develop] hotfix removes all caps in bar.js # feature/bar 8b404a5 Adding bar file # feature/foo 195431c Adding foo file # hotfix/fixes-bar-caps 00b2d00 hotfix removes all caps in bar.js # master 00b2d00 [origin/master] hotfix removes all caps in bar.js # release/1.0 c26f0f3 [origin/release/1.0] hot fix bar.js # remotes/origin/develop 00b2d00 hotfix removes all caps in bar.js # remotes/origin/master 00b2d00 hotfix removes all caps in bar.js # remotes/origin/release/1.0 c26f0f3 hot fix bar.js
To clean up we can delete the feature and hotfix branches.
git branch -d feature/foo git branch -d feature/bar git branch -d hotfix/fixes-bar-caps git branch -avv # develop 00b2d00 [origin/develop] hotfix removes all caps in bar.js # master 00b2d00 [origin/master] hotfix removes all caps in bar.js # release/1.0 c26f0f3 [origin/release/1.0] hot fix bar.js # remotes/origin/develop 00b2d00 hotfix removes all caps in bar.js # remotes/origin/master 00b2d00 hotfix removes all caps in bar.js # remotes/origin/release/1.0 c26f0f3 hot fix bar.js
Automating gitflow with tooling
As I mentioned earlier, while knowing all the inner workings of gitflow is helpful, there are tools built that automate some of these steps. I'll write a quick post on those tools next.