Git and git based platforms have become ubiquitous for versioning in software development. At same time since git is a powerful tools with many features, there is no one official way of using git. Searching for "git branching model" produces articles with sometimes contradictory information, which can be confusing, particularly for new users.
This post aims to summarize standard git practices that are used in open-source projects, and in particular in the scientific Python community. The described workflow is a variation of "Github flow" as was popularized by Github. It aims to be simple, and easy to understand starting point with one recommended way of doing things, while allowing to be adjusted as needed for more complex situations and deployment scenarios.
Main ideas
The general idea of git workflow based on feature branches is illustrated on the following figure.
The main development branch is master
which should always contain a working
version of the code and be ready to be deployed. To make additions to the code, one would
create a new branch for each feature or bug fix being worked on, and make a Pull Request (PR), a request
to include the code in master. For instance,
git checkout master
git checkout -b feature-1
# Make code changes
git commit -a -m "Adding feature 1"
git push
Once the Pull Request passes quality controls checks, including automatic checks and manual code review it can be merged into master. It is recommended to use Continious Integration (CI) to automatically run unit tests and code style linters on each commit.
To make releases and deploy, one would create a tag on master, e.g.
git checkout master
git tag v0.1.0
git push origin v0.1.0
Notes:
- When merging PR you should squash commits ("Merge & Squash" button on Github). This allows to obtain only one commit on master per pull request, which helps keeping history clean, and facilitate backporting of changes to other branches.
- You should give self explanatory names to feature branches. For instance for a bug fix that fixes overflow
error in sparse matrices, the branch name could be
fix-overflow-sparse
. - To synchronize or resolve conflicts in a feature branch, merge master in:
git fetch origin && git merge origin/master
Don't rebase or rewrite history in PRs, as that would make reviewing consecutive changes in PRs more difficult. - Do not forget to always return to master (
git checkout master
) before creating new branches.
Working with forks, and contributing to open-source projects
It frequently happens that one needs to contribute to a project without having write access to its repository. This is in particular the case for most open-source projects.
In this case Github, Gitlab and other git hosting platforms have a mechanism of
forks. That is a to make a copy of the repository to a location that you can
edit (origin
), from which you can make Pull Requests to the main repository
(upstream
).
The workflow in this case, illustrated on the following figure is very similar to that of the previous section. One still creates feature branches, except that PRs are made to the upstream repository master branch.
To synchronize your fork's master with changes in the upstream repository, one would do,
git remote add upstream <upstream-repo-url> # just once
git fetch upstream
git checkout master
git rebase upstream/master
Pull Requests can be synchronized with a similar apporach, except that one would use,
git merge upstream/master
instead of a rebase.
Notes:
- never make Pull Requests from your forks'
master
branch, always create a specific feature branch. - Once a Pull Request is merged, its branch can be deleted.
Adding release branches
For larger projects, it might be useful to add bug fix releases that don't include new features.
In this case, we can create a release branch originating from the latest
release tag. Both new features and bug fixes are first contributed to master,
then bug fixes are backported using e.g. git cherry-pick <commit-hash>
to the
release branch.
Then a new tag is added on the release branch to make a new release.
Conclusions
We have reviewed a simple git workflow that can be used for new projects or to start contributing to open-source projects. For a more detailed discussion about git branching models, see for instance the initial GitLab flow article.