Git Best Practice¶
We use git for version control management. Repositories are usually hosted on
GitHub. In this document we assume that you are already familiar with the common
terminology around version control in git. If terms like
branch don’t have a clear meaning for you
please consider reading up on git online first.
https://www.atlassian.com/git good introduction, but dives deep too
https://help.github.com covers a lot of detail and github specifics
When setting up new dev machine make sure that your git identity is properly configured.
git config --global user.name "YourFirstName YourLastName" git config --global user.email "email@example.com" # configure other useful options git config --global pull.rebase true # review git config --list
Below are the main guiding principles, we will expand on that through out the document
Treat commit history as a form of documentation
Group related changes together
Avoid combining unrelated changes into one commit
Communicate intent and context of the change not just what changed
Maintain mostly linear history
In the ideal world code is written once and is perfect from the start: there are no mistakes and all future uses are anticipated and catered for at the time of inception. In this perfect world every new commit is new code which adds new features. In the real world people make mistakes in the code, third party APIs change without any warning, code formatting is sometimes off, all these things stand in the way, all need to be fixed in the process of developing the new feature. While all these changes are necessary, they are still incidental to the core task of new feature development. We should try to put each incidental change into a separate commit. Separating “preparatory work” from “actual new feature” really helps with code review.
Commit messages are an important communication channel, use them to communicate information that can not be easily extracted from the code: why was the change necessary, what that means for code that might depend on the code that got changed. Try to provide context for the change without being overly verbose.
Git is a very flexible tool and allows for a broad range of workflows, changes
can be happening in a number of parallel branches, those branches can then be
merged in any order creating a rather non-linear history which can be hard to
follow. We adopt a more constrained approach, commonly referred as “Feature
Branch Workflow”. In short this means that there is one main branch
develop, no major work is done in the main branch, instead new features
are developed in separate feature branches, those then get merged into the main
branch when ready.
Commit Message Format¶
Good commit messages make collaboration easier. Commit message should consist of short summary line, 50 characters of less, followed by a blank line, followed by expanded description. It is fine to omit expanded description and the blank line before it if the change is small. Start your summary line with a capital letter, don’t put full stop [.] at the end of the summary line.
Many tools, GitHub including, expect this format and sticking to it makes inspecting history more accessible.
When writing the summary line prefer to use the “imperative mood” (i.e. “spoken or written as if giving a command or instruction”). So use
Fix spelling mistake in the help message
Fixed spelling mistake in the help message
Write it as if finishing this sentence: “When applied this commit will …”, but still start with a capital letter. For a more expanded exploration of the topic see https://chris.beams.io/posts/git-commit/
Clean Linear History¶
Pull with Rebase¶
When grabbing changes from remote use
--rebase switch, this keeps history
linear by replaying your changes on top of remote changes.
git pull --rebase origin master. Alternatively make pull with
rebase a global default
git config --global pull.rebase true. Your editor
probably has this option, certainly PyCharm supports pulling with rebase.
Cleanup Before Sharing¶
Just like code can be edited, so can be git history. You don’t need to type out perfect code on the first try, you don’t need to delay committing your code until it’s “just right”, “work in progress” commits are perfectly fine so long as you clean it up before sharing your changes.
The easiest and most common method is to amend the very last commit
commit --amend. Maybe you want to correct a typo in the commit message, or you
forgot to add a new file, you can easily amend last commit. Your editor most
likely supports that out of the box.
A more comprehensive method is Interactive Rebase, it allows to re-order
commits, squash independent commits into one, update commit messages for older
commits and more. While you can use it with just plain command line
rebase -i HEAD~3, it’s probably best to use some kind of GUI client for
complex tasks like that. Maybe your editor/IDE already supports that, if not try
some of the tools listed below
Bug Fix Workflow¶
Create issue on GitHub, if not created already
Create new branch with a reasonable name,
Develop a fix and hopefully unit tests
Commit your changes to local branch
Pull changes from main branch into your branch with rebase
Push your branch to GitHub
Create pull request
New Feature Workflow¶
As far as git mechanics go new feature development is similar to Bug Fix
Workflow. New features are developed in a feature branch. Since new feature
development is likely to take longer than a bug fix it becomes important to keep
your branch in sync with the main branch to minimize the pain of one massive
merge at the end. So make sure to run
git pull --rebase origin develop every
so often in your feature branch.
Again since it takes longer, it’s best to push your branch to GitHub even if you
are not ready to merge it back into the main. This gives visibility of the work
to other team members and also serves as an offsite backup of your work. Note
that it is still OK to “edit history” in your feature branch even if that
history has been pushed to GitHub, but you will need to force push your
changes when you do:
git push --force. We assume that feature branch is your
“private branch”, and so nobody will be impacted by history edits. If that’s not
the case, i.e. multiple people are working on the same branch, then you should
not edit history you have shared with others. Don’t worry you can still cleanup
the history later on when feature development is complete just before creating a
Creating pull request for a new feature is a little bit more involved than for a bug fix. Particularly for larger changes please take care to document the work you done in detail using GitHub comment interface, you can use markdown for formatting. Try to make the reviewers job easier by providing context of the change that might be difficult to extract from the code diff alone.
Travis and Coveralls Integration¶
We use free service Travis CI https://travis-ci.org to automatically run unit tests when new code is pushed to GitHub. When running unit tests we extract “code coverage” statistics for given test run. We use Coveralls https://coveralls.zendesk.com/ to keep track of how code coverage percentage changes over time. The expectation is that code coverage percentage increases over time or at least doesn’t go backwards by a lot for too long. As new features are added so are the unit-tests that test new code.
When accepting pull requests GitHub gives you three different options. The default behavior is to create a merge commit “Merge pull request”. Use this option for larger requests.
For smaller changes, a bug fix or a small feature, couple of small commits in size, use the “Rebase and merge” option. This will make it look like the feature was developed directly in the main branch.