Adopting a workflow – a wise act

Now that you learned how to perform good commits, it's time to fly higher and think about workflows. Git is a tool for versioning, but as with other powerful tools, like knives, you can cut tasty sashimi or relieve yourself of some fingers.

The things that separate a great repository from a junkyard are the way you manage releases, the way you react when there is a bug to fix in a particular version of your software, and the way you act when you have to make users beta-test the incoming features.

These kinds of actions belong to ordinary administration for a modern software project. However, very often, I still see teams get out of breath because of the poor versioning workflows.

In this second part of the chapter, we will take a quick look at some of the common workflows alongside the Git versioning system.

Centralized workflows

As we used to do in other VCSes, such as Subversion and so on, even in Git, it is common to adopt a centralized way of work. If you work in a team, it is often necessary to share repositories with others, so a common point of contact becomes indispensable.

We can assume that if you are not alone in your office, you would adopt one of the variations of this workflow. As we know, we can get all the computers of our co-workers as remote, in a sort of peer-to-peer configuration. However, you usually don't do this, because it becomes too difficult to keep every branch in every remote in sync.

Centralized workflows

How they work

In this scenario, you usually follow these simple steps:

  1. Someone initializes the remote repository (in a local Git server, on GitHub, or on Bitbucket).
  2. Other team members clone the original repository on their computer and start working.
  3. When the work is done, you push it to the remote to make it available to other colleagues.

At this point, it is only a matter of internal rules and patterns. It is improbable that you and your colleague will work together simultaneously in the master branch, unless you are indomitable masochists.

Feature branch workflow

At this point, you probably will choose a feature branch approach, where every single developer works on their branch. When the work is done, the feature branch is ready to be merged with the master branch. You will probably have to merge back from the master branch first because one of your other colleagues has merged a feature branch after you started yours, but after that you basically have finished.

Feature branch workflow

GitFlow

The GitFlow workflow comes from the mind of Vincent Driessen, a passionate software developer from the Netherlands. You can find his original blog post at http://nvie.com/posts/a-successful-git-branching-model.

His workflow has gained success over the years, at the point that many other developers (including me), teams and companies started to use it. Atlassian, a well-known company that offers Git related services such as Stash or Bitbucket, integrates the GitFlow directly in its GUI tool, the SourceTree.

Even the GitFlow workflow is a centralized one, and it is well described by this figure:

GitFlow

This workflow is based on the use of some main branches. What makes these branches special is nothing other than the significance we attribute to them. These are not special branches with special characteristics in Git, but we can certainly use them for different purposes.

The master branch

In GitFlow, the master branch represents the final stage. Merging your work in it is equal to making a new release of your software. You usually don't start new branches from the master branch. You do it only if there is a severe bug you have to fix instantly, even if that bug has been found and fixed in another evolving branch. This way to operate makes you superfast when you have to react to a painful situation. Other than this, the master branch is where you tag your release.

Hotfixes branches

Hotfixes branches are branches derived only from the master branch, as we said earlier. Once you have fixed a bug, you merge the hotfix branch onto master so that you get a new release to ship. If the bug has not been resolved anywhere else in your repository, the strategy would be to merge the hotfix branch even into the develop branch. After that, you can delete the hotfix branch, as it has hit the mark.

In Git, there is a trick to group similar branches: you have to name them using a common prefix followed by a slash /. For the hotfix branches, I recommend the hotfix/<branchName> prefix (for example hotfix/LoginBug of hotfix/#123 for those who are using bug-tracking systems, where #123 is the bug ID).

These branches are usually not pushed to remote. You push them only if you need the help of other team members.

The develop branch

The develop branch is a sort of beta software branch. When you start to implement a new feature, you have to create a new branch starting from the develop branch. You will continue to work in that branch until you complete your task.

After the task is completed, you can merge back to the develop branch and delete your feature branch. Just like hotfix branches, these are only temporary branches.

Like the master branch, the develop branch is a never-ending branch. You will never close nor delete it.

This branch is pushed and shared to a remote Git repository.

The release branch

At some point, you need to wrap up the next release, including some of the features you implemented in the last few weeks. To prepare an incoming release, you have to branch from develop, assigning at the branch a name composed of the release prefix. This will be followed by the numeric form of your choice for your release branch (for example release/1.0).

Pay attention. At this stage, no more new features are allowed! You cannot merge develop onto the release branch. You can only create new branches from that branch for bug fixing. The purpose of this intermediate branch is to give the software to beta testers, allowing them to try it and send you feedback and bug tickets.

If you have fixed some bugs onto the release branch, the only thing to remember is to merge them even into the develop branch, just to avoid the loss of the bug fix. The release branch will not be merged back to develop.

You can keep this branch throughout your life, until you decide that the software is both mature and tested sufficiently to go in production. At this point, you merge the release branch onto the master branch, making, in fact, a new release.

After the merge to master, you can make a choice. You could keep the release branch open, if you need to keep alive different releases; otherwise, you can delete it. Personally, I always delete the release branch (as Vincent suggests), because I generally do frequent, small, and incremental releases (so, I rarely need to fix an already shipped release). As you certainly remember, you can open a brand new branch from a commit (a tagged one in this case) whenever you want. So, at most, I will open it from that point only when necessary.

This branch is pushed and shared to a common remote repository.

The feature branches

When you have to start the implementation of a new feature, you have to create a new branch from the develop branch. Feature branches start with the feature/ prefix (for example, feature/NewAuthenitcation or feature/#987 if you use some feature- tracking software, as #987 is the feature ID).

You will work on the feature release until you finish your work. I suggest that you frequently merge back from develop. In the case of concurrent modifications to the same files, you will resolve conflicts faster if you resolve them earlier. Then, it is easier to resolve one or two conflicts a time than dozens at the end of the feature work.

Once your work is done, you merge the feature onto develop and you are done. You can now delete the feature branch.

Feature branches are mainly private branches. However, you could push them to the remote repository if you have to collaborate on it with some other team mates.

Conclusion

I recommend that you take a look at this workflow, as I can assure you that there was never a situation that I failed to solve using this workflow.

You can find a deeper explanation with the ready-to-use Git command on Vincent Driessen's blog. You can even use GitFlow commands Vincent made to customize his Git experience. Check them out on his GitHub account at https://github.com/nvie/gitflow.

The GitHub flow

The previously described GitFlow has tons of followers, but it is always a matter of taste. Someone else found it too complex and rigid for their situation. In fact, there are other ways to manage software repositories that have gained consensus during the last few years.

One of these is the workflow used at GitHub for internal projects and repositories. This workflow takes the name of GitHub flow. It was first described by the well-known Scott Chacon, former GitHubber and ProGit book author, on his blog at http://scottchacon.com/2011/08/31/github-flow.html.

This workflow, compared to GitFlow, is better tailored for frequent releases. When I say frequent, I say very frequently, even twice a day. Obviously, this kind of flow works better on web projects, because to deploy it, you have to only put the new release on the production server. If you develop desktop solutions, you need a perfect oiled update mechanism to do the same.

GitHub software basically doesn't have releases, because they deploy to production regularly, even more than once a day. This is possible due to a robust Continuous Delivery structure, which is not so easy to obtain. It deserves some effort.

The GitHub flow is based on these simple rules.

Anything in the master branch is deployable

Just like GitFlow, even in GitHub flow, deployment is done from the master branch. This is the only main branch in this flow. In GitFlow, there are not hotfix, develop, or other particular branches. Bug fixes, new implementation, and so on are constantly merged onto the master branch.

Other than this, code in the master branch is always in a deployable state. When you fix or add something new in a branch and then merge it onto the master branch, you don't deploy automatically, but you can assume your changes will be up and running in a matter of hours.

Branching and merging constantly to the master branch, which is the production-ready branch, can be dangerous. You can easily introduce regressions or bugs, as no one other than you can assure you have done a good job. This problem is avoided by a social contract commonly adopted by GitHub developers. In this contract, you promise to test your code before merging it to the master branch, assuring that all automated tests have been successfully completed.

Creating descriptive branches off of the master

In GitFlow, you always branch from the master branch. So, it's easy to get a forest of branches to look at when you have to pull one. To better identify them, in GitHub flow, you have to use descriptive names to get meaningful topic branches. Even here, it is a matter of good manners. If you start to create branches named stuff-to-do, you would probably fail in adopting this flow. Some examples are new-user-creation, most-starred-repositories, and so on (note the use of dashes). Using a common way to define topics, you will easily find branches you are interested in, looking for topics' keywords.

Pushing to named branches constantly

Another great difference between GitHub flow and GitFlow is that in GitHub flow, you push feature branches to the remote regularly, even if you are the only developer involved and interested in it. This is done even for backup purposes. Even if I already exposed my opinion in merit, I can't say this is a bad thing.

A thing I appreciate about GitFlow is that this habit of pushing every branch to the remote gives you the ability to see, with a simple git fetch command, all the branches currently active. Due to this, you can see all the work in progress, even that of your team mates.

Opening a pull request at any time

In Chapter 3, Git Fundamentals – Working Remotely, we talked about GitHub and made a quick try with pull requests. We have seen that basically they are for contributing. You fork someone else's repository, create a new branch, make some modifications, and then ask for a pull request from the original author.

In GitHub flow, you use pull requests massively. You can even ask another developer of your team to have a look at your work and help you, give you a hint, or review the work done. At this point, you can start a discussion about using the GitHub pull request to chat and involve other people, putting their usernames in CC. In addition, the pull request feature lets you comment even a single line of code in a different view, letting users involved proficiently discuss the work under revision.

Merging only after a pull request review

You can now understand that the pull requested branch stage we saw earlier becomes a sort of review stage. Here, other users can take a look at the code and even simply leave a positive comment, just a +1 to make other users know that they are confident about the job, and they approve its merge into master.

After this step, when the CI server says that the branch still passes all the automated tests, you are ready to merge the branch in master.

Deploying immediately after review

At this stage, you merge your branch into master, and the work is done. The deployment is not instantly fired, but at GitHub, they have a very straight and robust deploy procedure. They deploy big branches with 50 commits, but also branches with a single commit and a single line of code change, because deployment is very quick and cheap for them.

This is the reason why they can afford such a simple branching strategy, where you put on the master branch, and then you deploy, without the need to pass through the develop or release stage branch, like in GitFlow.

Conclusions

I consider this flow very responsive and effective for web-based projects, where basically you deploy to production without focusing too much on versions of your software. Using only the master branch to derive and integrate branches is faster than light. However, this strategy could be applied only if you have these prerequisites:

  • A centralized remote ready to manage pull requests (as GitHub does)
  • A good shared agreement about branch names and pull requests usage
  • A very robust deploy system

This is a big picture of this flow. For more details, I recommend that you visit the GitHub related page at https://guides.github.com/introduction/flow/index.html.

Conclusions

Other workflows

Obviously, there are many other workflows. I will spend just few words on the one that (fortunately) convinced Linus Torvalds to realize the Git VCS.

The Linux kernel workflow

The Linux kernel uses a workflow that refers to the traditional way in which Linus Torvalds has driven its evolution during these years. It is based on a military-like hierarchy.

Simple kernel developers work on their personal branches, rebasing the master branch in the reference repository. Then they push their branches to the lieutenant developer's master branch. Lieutenants are developers who Linus assigned to particular topics and areas of the kernel because of their experience. When a lieutenants have done their work, they push it to the benevolent dictator master branch (Linus branch). Then, if things are OK (it is not simple to cheat him), Linus would push his master branch to the blessed repository, the one that developers use to rebase from, before starting their work.

The Linux kernel workflow
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset