Some useful Git tips
Tools
Atlassian’s SourceTree is probably the best GUI for Git, but is only available for Windows/Mac. It integrates with gitflow but does not have a good built-in merge tool.
GitFlow
nvie/gitflow is a useful tool based on to implement a branching model as described in this famous article by Vincent Driessen (this tutorial also helps). The model uses clearly specified master/development/feature/release/hotfix branches that are automatically supported by the tool. For instance, you can:
-
Create a Release that will merge your current Development with Master and also Tag it
-
Create a Hotfix that will be based on Master and merged with Development when closed
- gitflow keeps a linear history of versions on the master branch. If there is the need to keep multiple versions at the same time (for instance fixing v0.1 after v0.5 has been released) this SO answer can provide some guidance. We’ve also had a good experience by not releasing the new versions, instead deciding to keep them on Development and manually tagging - this breaks the history, but allows us to keep working on v0.14 (deployed version with the client) while still keeping track of our sprints with tags.
Merge vs. Rebase
We should aim to lower the amount of useless git commits in our git history. For instance, in the below screenshot we have 23 commits but 10 merge commits:
This happened because people were working and commiting locally but not keeping their local repository in sync with the remote. When trying to push, someone else had already commited to the remote and that would cause an ancestor conflict; this would mean that when pulling a new automatic merge commit would be created (merging the remote and local branches).
To prevent that from happening:
-
Stash your changes, pull from the remote, stash pop to apply your changes on top of the latest version, commit, then push. See this article; or
-
Use a feature branch if you want to have multiple commits. It is useful to merge development>feature before merging feature>development to resolve conflicts, and we’ll have merge commits that “make sense”:
-
On the terminal use
git merge --no-ff --log
(avoids fast-forward and adds all history messages to the merge commit); or -
If you have already created your commits, when pulling use rebase instead of merge (on SourceTree it’s the last checkbox when pulling, on terminal use
git pull --rebase
). This will “rewrite your local history” so you are applying your changes on top of the latest version of the code (only use rebase when pulling; avoid rebasing one branch with another).