Git is a very powerful version control system and much of its power comes from its very simple basic structures. Git is mostly a manager of blob trees and even the most complex operations are basically tree operations.
The power of Git brings also a great flexibility, which means that Git doesn't dictate a specific workflow, leaving the programmer or the team to come up with a reasonable procedure.
Two Git workflows are very widespread, for different reasons. The first is the GitHub model and the second is the gitflow one.
The GitHub model is widely used, because nowadays GitHub is the most used code management and collaboration website for open source projects. GitHub makes use of a workflow based on Pull Requests, and you can find some useful resources about it in the relative section at the end of the post.
Gitflow was proposed by Vincent Driessen in 2010 and quickly become one of the most used workflows, due to the fact that it covers most of the common needs of a developing team and is very easy to learn. Its workflow is based on different types of branches that are created when specific events occur in the team: a new feature has to be developed, a new release shall be published, a bugfix shall be quickly put in production, etc.
I personally find gitflow a very useful workflow and always use it even when I'm developing alone on a personal repository. It helps me to keep things in order and the beautiful set of tools named "gitflow AVH Edition" by Peter van der Does minimizes the number of operations I have to remember.
GitHub and gitflow
When working with GitHub, however, gitflow is not your best choice, mostly because of the big difference between the two ways of managing new features. GitHub wants you to put everything in a branch and submit a Pull Request, keeping the branch alive. The project maintainer then reviews the code and possibly merges your changes. At that point you are free to delete the branch and update your master.
Gitflow, on the other hand, usually makes you close features by merging into the special branch called
develop, because is from that branch that you create releases (that are put into
master). Closing a feature branch and merging the feature into
develop is what does not work well with GitHub, since when you close the branch your Pull Request cannot be finalized.
Sure, you can leave a gitflow feature branch open, publish it, send your Pull Request and eventually delete it without closing the feature, but this way you are just partially using gitflow, not to mention the fact that this way some commands (such as
git flow feature finish) become "dangerous", since they shall be avoided to preserve the GitHUb workflow integrity.
I will suggest here a procedure that allows to manage the local repository with gitflow, while hosting the remote repository on GitHub, without preventing to use gitflow features and GitHub Pull Requests.
The basic idea
The concept that allows to use both workflows is very simple: gitflow, when used locally to develop new features, makes use of the sole
develop special branch. Every feature is created from that repository and eventually merged back there, so
develop for a local repository becomes a sort of big feature branch.
Given this consideration we may create a local branch that tracks a remote one with the same name, and make it our GitHub feature branch, i.e. the branch that will be used to create a Pull Request. Locally, we create a Git symbolic reference to that branch and we call the reference
develop, thus enabling the use of the gitflow workflow and tools.
When we finish adding features to the local feature branch (
develop) we may squash the commits as usual and perform a forced push to the GitHub repository.
We may also maintain more than one GitHub feature branch, we just need to move the symbolic reference to the branch we want to work on. On every
develop branch we may use gitflow features just like in a standard gitflow-enabled repository.
Obviously things change when we talk about releases. If the maintainer wants to use gitflow to create releases he or she needs to merge Pull Requests into their
develop branch. This is not yet possible on GitHub web interface, but is already possible with command line Git. It however breaks a little the GitHub flow so I wouldn't suggest it at the moment. This feature has been already requested to the GitHub team (see this comment)
A simple procedure
To use the described procedure you just need to have a local repository with gitflow enabled, i.e. you need to have two branches
develop, possibly with
Then setup the repository issuing the following commands
$ # Move to the master branch $ git checkout master $ $ # Rename develop to _develop $ git branch -m develop _develop $ $ # Create the feature branch $ git checkout -b new_feature $ $ # Push the feature branch to the remote (GitHub) and track it $ git push -u origin new_feature $ $ # Alias the feature branch with the name develop $ git symbolic-ref refs/heads/develop refs/heads/new_feature
When you need to change your working feature branch just run
$ # Just change the target of the symbolic reference $ git symbolic-ref refs/heads/develop refs/heads/other_feature
and if you need to go back to the original state execute the following commands
$ # Remove the symbolic reference $ git symbolic-ref --delete refs/heads/develop $ $ # Rename the original develop branch $ git branch -m _develop develop
To squash commits into your feature branch and force push run these commands:
$ # Make sure we are dealing with our feature branch $ git checkout new_feature $ $ # Rebase on master (this is a develop, after all) $ git rebase -i master $ $ # Force a push on GitHub $ git push origin +new_feature
gitflow gh command
This repository is a fork of the official gitflow repository and inplements a new gitflow command
gh to easily perform what has been described in this post. The changes are implemented in the
github_support branch, which has been developed with the modified gitflow program itself.
As of 22-06-2015 I submitted a PR to the official gitflow repository, but I do not know if it is going to be accepted.
If you are interested in using this feature feel free to clone my gitflow repository and report any issue either there or in the PR itself. As soon as the PR is processed, I'll update this section.
gh command is described in the README. It currently provides six commands: enable, disable, activate, import, squash and publish.
- The GitHUb workflow official documentation
- The gitflow original post
- The gitflow AVH Edition official repository
- Some insights on Git objects
- Another solution to work with GitHub and gitflow: HubFlow
2015-06-23: Added a section about a gitflow fork that implements the concepts explained in the post.