Skip to content

Instantly share code, notes, and snippets.

@yugarinn
Last active January 29, 2019 22:13
Show Gist options
  • Save yugarinn/d4eb1e230291681f5629d5833db79391 to your computer and use it in GitHub Desktop.
Save yugarinn/d4eb1e230291681f5629d5833db79391 to your computer and use it in GitHub Desktop.
Gitflow Blog Post

YAGFBWP

"Yet Another Gitflow Based Workflow Post"

Introduction

Working with Git is easy. At the same time, it has enough depth and features to let you screw up your codebase at a considerable level. That's why the web is full of Git tutorials, blog posts and articles. That's also why a bunch of smart people have come up with certain Git workflows to avoid finding yourself lost in a sea of unmanageable changes. Let's dig into one of them.

As every decent Version Control System, Git has three core functionalities: store content, track changes to that content, and distribute the content and change history to possible collaborators. The way those changes are stored and organized is entirely up to the developer. This is going to be a very opinionated post about how to organize your Git workflow. I will explain how one these already existing workflow works, and introduce some small rules and changes on top of it. Said workflow is, obviosuly, Gitflow, created by Vincent Driessen.

Prerequisites

From this point onwards some basic Git knowledge will be assumed, tasks like initializing a repository, commiting changes, branching... Should these concepts sound alien to you, I highly recommend you check out these links:

Core concepts by example (By Github):
https://guides.github.com/activities/hello-world/

Read about the most common Git commands. Kinda like a cheatsheet (By Bitbucket):
https://confluence.atlassian.com/bitbucketserver/basic-git-commands-776639767.html

This covers the basic fundamentals of how Git works. A bit of theory (By Git, actually):
https://git-scm.com/book/en/v2/Getting-Started-Git-Basics

Feel ready now? Perfect, let's continue!

Please bear in mind that I will not use a pure implementation of Gitflow, but rather one based on it that has been working pretty well for me and the teams I have been a part of. If you want to read about the actual Gitflow workflow you can find links at the end of the article.

How it works

Once you look at it hard and close enough you will realize that Gitflow is nothing more than a branching model for Git. It defines a set of rules about the kind of branches to set up and how the merges between them should work. The main idea behind it is to divide your branches into 2 main categories plus 3 supporting ones:

  • master
  • develop
  • feature
  • bugfix
  • hotfix

master and develop

The two main branches, master and develop, are intended to keep track of your project's history. The master branch stores the release history, so it should only get updated once there are enough changes to justify a new release. The develop branch is intended as an integration branch for all your feature branches and to keep track of all the actual changes to the codebase.

The first step then is to create a complementary develop branch from master.

$ git init
Initialized repository in ~/code/my-project/.git/

$ git add -A && git commit -m "Initial commit"
...

$ git branch develop
$ git branch -a
  develop
* master

TODO: add diagram

feature branches

Since the two main branches are used just for history tracking, we need somewhere else to do the actual work. That's what the feature branches are for. Every new feature to be developed in the project has to be worked on in a feature branch, the work commited as often as possible, and once it is finished merged back into develop. This forces the team to make every feature as independent from the others as possible.

Once you have enough feature branches finished and merged into develop to be considered a new stable point, or release, develop should be merged into master and that merge commit given a tag, this tag usually being a semver version. feature branches should never interact directly with master.

TODO: add diagram

Squash merging

Now, when you are working on a feature branch, you should commit as much as logically possible, but, once you merge a feature back into develop it's highly recommended to use the --squash option: $ git merge --squash <feature-branch-name>. This allows you to merge all changes from the feature branch into develop as a single commit. Doing so ensures a clean commit history on develop where every commit is related to a single feature. If you want a more detailed log in the develop branch you can ommit the --squash option. In either case, after the merge, the feature branch should be deleted.

# Currently in a branch where several commits were made, and it's ready te be merged into develop
$ git checkout develop
$ git merge feature/my-kinda-cool-feature --squash

bugfix and hotfix branches

These two last categories are intended to tackle the same issue: bugs. But the workflow and use cases are slightly different. The bugfix branches work the same as the feature ones, only instead of developing new features you just fix bugs. On the other hand, the hotfix features are intened to fix critical bugs detected in production, and as such, have the privilege to work around the regular branching flow. These are the only branches that come directly from master and are merged back into it, so the critical bug is dealt with as fast as possible. After that the hotfix should be merged into develop as well so life is good again.

Local merges VS Pull Requests

While merging features locally and pushing the merge upstream might fit perfecty well in your workflow, there is a pretty good chance that you are already using some web based platform to manage your remote repositories (Github, Bitbucket, Gitlab...) and that said platform has Pull Requests as one of it's features.

Pull Requests are a way of wrapping your merges around a nice UI and offer a place to comment or discuss the changes introduced by the new branch before merging it. The actual interface might vary from platform from platform but the basics steps are the following:

  1. Push your branch upstream
  2. Open a new Pull Request from your branch to the destination branch (usually develop).
  3. Someone else reviews the changes implemented, might request new changes.
  4. Once there's a consensus between the pull requester and the reviewers the Pull Request is accepted and the branch merged.

This is a Good ThingTM because it encourages the team to review each others code and have an open conversation about the work being done.

If you want to read further about Pull Requests, the three main Git online platforms offer a rather good documentation about their Pull Request process:

Recapping

The basic workflow is as follows:

  1. Initially, create two branches: master and develop.

feature branch lifecycle

  1. Create feature branches from develop.
  2. Work on a feature branch, commit as frequently as possible.
  3. Merge/Pull request back into develop.
  4. Once enough feature branches have been merged into develop, merge develop back into master and give it a version tag.

bugfix branch lifecycle

  1. Create bugfix branch from develop.
  2. Bugfixin' time!
  3. Merge/Pull request back into develop.

hotfix branch lifecycle

  1. Create hotfix branch form master.
  2. Bugfixin' time!
  3. Merge back into master.
  4. Merge into develop.

Examples

Initializing the repository

$ git init # Initialices the repository
Initialized repository in ~/code/my-project/.git/

$ git add -A && git commit -m "Initial commit" # Creates the fist commit
...

$ git branch develop # Creates the develop branch
$ git branch -a # Lists all the current branches
  develop
* master

Working on a feature branch

$ git checkout develop # Change to develop
$ git checkout -b feature/n001-oauth-login # Creates and checkouts to new feature branch
# ...
# Work is done, commits are made.
# ...
$ git add -A
$ git commit -am "Add new login logic"
$ git push --set-upstream feature/n001-oauth-login
# At this point some else reviews the feature branch and approves/rejects it.
# After the pull request is approved, either the reviewer or yourself merges the feature to develop
$ git checkout develop # Change back to develop
$ git pull # Update develop with the already merged feature changes

Working on a bugfix branch

$ git checkout develop # Change to develop
$ git checkout -b bugfix/n002-malformed-jwt # Creates and checkouts to new feature branch
# ...
# The bug is fixed, commits are made.
# ...
$ git add -A
$ git commit -am "Fix JWT generation"
$ git push --set-upstream bugfix/n002-malformed-jwt
# At this point some else reviews the bugfix branch and approves/rejects it.
# After the pull request is approved, either the reviewer or yourself merges the bugfix to develop
$ git checkout develop # Change back to develop
$ git pull # Update develop with the already merged bugfix

Working on a hotfix branch

$ git checkout master # Change to master
$ git checkout -b hotfix/n003-database-connection-broken # Creates and checkouts to new feature branch
# ...
# The bug is fixed, commits are made.
# ...
$ git add -A
$ git commit -am "Fix database credentials retrieval"
$ git checkout master # Change back to master
$ git merge hotfix/n003-database-connection-broken
$ git push
$ git checkout develop
$ git merge hotfix/n003-database-connection-broken
$ git push

Drawbacks

Welp, this workflow is really designed around the idea that you have a product for which you make a new release every couple weeks, so if that's not your case this model might hurt your development speed or add unnecesary complexity.

References / Further reading

https://datasift.github.io/gitflow/IntroducingGitFlow.html
https://hackernoon.com/gitflow-is-a-poor-branching-model-hack-d46567a156e7
https://www.atlassian.com/git/tutorials/comparing-workflows/gitflow-workflow
https://www.atlassian.com/git/tutorials/making-a-pull-request
https://nvie.com/posts/a-successful-git-branching-model
https://medium.com/@willhayjr/the-architecture-and-history-of-git-a-distributed-version-control-system-62b17dd37742
https://evilmartians.com/chronicles/git-push---force-and-how-to-deal-with-it
https://chris.beams.io/posts/git-commit
https://maryrosecook.com/blog/post/git-from-the-inside-out
https://csswizardry.com/2017/05/little-things-i-like-to-do-with-git
https://www.endoflineblog.com/gitflow-considered-harmful

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