FUN with Git
Git is used as a DVCS for every FUN project involving code or documentation. In this chapter, you will find how we use Git on a daily-basis to code and collaborate with the team.
If you are looking for a good introduction to Git, take a look at the Git In Practice book from Mike McQuaid.
Git conventions
Commit granularity
We tend to favor low granularity-but-consistent commits to a long series of commit. If you have multiple commits in a feature branch, it means that you had to address multiple issues to achieve your feature. We can run the test suite on every commit and it should always stay green 😎.
Commit message
We follow an emoji-driven commit message format adapted from Angular guidelines. A typical commit message should look like:
Type, scope and subject
Where type must be an emoji unicode character (e.g. 🎉 and not :tada:
) chosen from the gitmoji guide.
And the scope should point to the django application or stack component that may be affected, e.g.:
docker
apps:core
plugins:foo
The subject contains succinct description of the change:
use the imperative, present tense: "change" not "changed" nor "changes"
don't capitalize first letter
no dot (.) at the end
💩 Bad
❤️ Good
Body
Just as in the subject, use the imperative, present tense for the body: "change" not "changed" nor "changes". The body should include the motivation for the change and contrast this with the previous behavior.
In other words, you should explain WHY you do what you do, and what was the context that led you to do it the way you do it. It should not be a list of the things you change, because that's what git diff
is here for.
Try to see the commit message as a "brain dump" of the state of your mind at the moment of committing the changes.
You can also imagine someone angry chasing you in 6 months and asking:
Why on earth did you do this ??
You surely wouldn't answer with a list of what you did. You would try to explain and justify what you did 6 months ago. The problem is that, at that time, you will have forgotten about all these details... and your changes may be misunderstood. This may lead to tensions and criticism on the quality of your work. Worse, someone may revert an important change for lack of understanding the implications. Ironically, the angry person will most probably be... the future you!
Here is an example of a good versus a bad commit body:
💩 Bad
❤️ Good
Footer
The footer should contain any information about breaking changes and is also the place to reference GitHub/GitLab issues that this commit closes.
Breaking changes should start with the word BREAKING CHANGE
: with a space or two newlines. The rest of the commit message is then used for this.
Git commit-msg
hook
commit-msg
hookCommits are usually checked in the project CI, but you can install gitlint as a git commit-msg
hook so that gitlint checks your commit messages locally after each commit.
For this, install the gitlint
package globally using pip
:
Install the commit-msg
hook:
Note that gitlint
cannot work together with an existing hook. If you already have a .git/hooks/commit-msg
file in your local repository, gitlint
will refuse to install the commit-msg
hook.
gitlint
should now be runned locally for each commits you make.
If you want to manually trigger gitlint
for your last commit message, use the following command:
Git workflows
We use different workflows to handle collaborative coding with Git. The chosen workflow depends on the context and historical reasons. If you need more insights on popular Git worflows, we invite you to read this section of the Git in Practice book.
Open-source projects
For the sake of simplicity, to ease interaction with the community, we use the GitHub flow for open-source projects. In a few words:
the
master
branch is always stable and deployable,tags from the master branch are considered as releases,
contributors have to fork or create a new feature-branch to work on (if they are allowed to in the original repository) and propose a pull request to merge their branch to
master
.
FUN private projects
Historically, we use Git Flow for internal projects. You will find plenty of resources on the web about this workflow, so in a few words:
the
master
branch is considered as a stable and always deployable branch,the
develop
branch is a working branch where developped features are merged,contributors have to work on feature-branch that will target the
develop
branch,hotfix and release branches are merged to
master
and back-ported todevelop
,release branches create tags on the master branch when they are closed.
Working with forges
Declaring issues
For now, new issues are declared in a dedicated Trello board. This is a temporary situation. In the following, we will describe how it should be 🤓
When declaring a new issue, please describe as much as possible the purpose of your issue, and eventually make a proposal on how it should be solved or investigated. Choose wisely a label for this issue and please do not assign someone to it (unless you already discussed with her verbally and had an agreement).
Working with pull requests (PR)
We recommend to create a pull request (PR) or merge request (MR) in GitLab semantic as soon as possible with the WIP
flag preceding your PR title, e.g. WIP: 😎(docker) add mongo service
.
When your work is done on this PR, remove the WIP
flag and please ensure that:
your feature or fix is **tested ** (all continuous integration tests should be green and code coverage should not decrease),
your feature is documented,
your branch is up-to-date with the target branch (it should be rebased and force-pushed).
Once all of those requirements are met, ask for a review of your code by assigning maintainers to your PR. Your changes should be approved by at least one contributor of the core team to be merged.
Last but not least, a code review should not take more than half an hour per PR to be profitable for everyone. It means that you have anticipated the amount of changes required to achieve your work. If those changes are bigger than 500 lines, then you may consider to split your feature in multiple PRs.
Note that the target branch (develop
or master
) will be write-protected, i.e. no one is allowed to push to it. Hence you will need to use the forge UI to merge your PR once all tests are green and your changes have been approved. Our PR merging strategy is: rebase and merge ; we do not want a merge commit.
Releasing new software version
Whatever the language you are using on a FUN project, cooking a new release (e.g. 4.18.1
) should follow a standard procedure described below:
Create a new branch named:
release/4.18.1
,Bump the release number in the appropriate file, i.e. for python projects, the
setup.cfg
(or__init__.py
, depending on the way you handle your package version) and/orpackage.json
for node-based projects,Update the project's
Changelog
following the keepachangelog recommandations,Commit your changes with a structured message:
add a title including the version of the release and respecting the above described format using the 🔖 release emoji,
paste in the body all changes from the changelog concerned by this release, removing only the markdown tags and making sure that lines are shorter than 74 characters.
Open a pull or merge request depending on the current forge of the project,
Wait for an approval from your peers,
Merge your pull or merge request,
Checkout and pull changes from the
master
branch,Tag & push your commit:
git tag v4.18.1 && git push origin --tags
Unless the CI has already taken care of it (check on the Circle CI config if there is a release job defined), manually release your version on GitHub.
Ensure your release is published on the package index.
Checking project tags consistency
As we are only Humans, we are error-prone per se. To avoid tagging consistency errors, we recommend to integrate the following tests in the project's continuous integration workflow before publishing a new release:
In this example script $CIRCLE_TAG
is an environment variable defined by the contious integration platform (CircleCI in this case) with the pushed tag value, and, $TARGET BRANCH
is the Git
branch that should have been tagged (e.g. the master
branch).
Last updated