Git is something we use everyday. As a disclaimer, for people involved in CQRS/ES solutions, the workflow may be slightly different. A better architectural approach allows the use of a different set of git commands as the workflows can leverage a much higher than normal level of parallelism in developing solutions. At the same time, there are git patterns that are always helpful.
No Back Merges
As outlined in our developer guidelines, keeping work organised is important for keeping the solution maintainable and mixing and matching features that are needed for release. One anti-pattern that beginners fall victim to early on in Git is the idea that to keep up to speed with others’ efforts, they can merge master or other higher-order branches into their feature/task/WIP branch. This now ties separate efforts together and can’t be separated easily at all. The guideline above has a link to a rudimentary git hook that you can use to watch for people accidentally making a merge from the wrong side.
Another mistake that beginners make is dealing with a dirty tree and the propensity to
git reset --hard to get to a clean state so they can do other operations like switching branches. To clean the tree, use
git stash -u as it is a reversible action.
git reset --hard is one of the few ways in git where you don’t get a safety rope and can do some serious damage. If you do this by mistake and had some important changes that were not added to the index yet, they are gone forever. As a simple to follow rule, don’t use
git reset --hard to clean your working tree ever – always use
git stash -u for the same effect.
To add, your stash is not pushed up so even if you are cleaning large files, they will not affect any remotes.
Look at the Log
The default log command is very verbose in git meaning you see fewer commits per page. Further, by default, it doesn’t show some important information like references of commits if there any and it shows no graph.
To show the branches, we’ll turn on decoration by default with:
git config --global log.decorate auto
Then we’ll shrink each commit to a nice colourful line:
git config --global format.pretty "%Cred%h%Creset -%C(yellow)%d%Creset %C(white)%s%Creset %C(yellow)(%cr) %C(bold blue)<%an>%Creset"
When the log is to be shown we will still need to usually issue
--graph. For this reason, a shell like fish-shell is beneficial as it will autocomplete commands with the options that were used last.
git log --all --graph
Log output gets a pager application (less by default) no matter how few lines are shown. We can turn off paging if the output is less than a page worth’s of information with:
git config --global core.pager 'less -XF'
Status’ Verbal Diarrhea
When there are lots of changes, git status can be very verbose. Once you’re used to the output, you can minimise it with this setting. To make git status behave as before, you can add the
--no-short option to git status.
git config --global status.short true
Preserve Where You Started Your Branch
By default, git will fast-forward your branch to match the other branch if you have no changes on your side. Typically this is ok for doing a fetch and a merge instead of pull if you want to inspect what was fetched from the remote before updating your local branch. This depends on your team. If you make all merges make a merge commit, you have the chance of others forgetting to
--ff-only when doing a separate fetch and merge. The scenario to watch for is updating master with a feature that you completed and nothing else happened on master in that time. So by default, a finished branch should always be merged with a merge from master like this:
git merge --no-ff featureX
You can use commands that you would on a remote on the very same repo you are in. Just replace the remote name with a period. This allows you to reset branches like this:
git push . HEAD^:master
This will make git check if you are potentially losing commits. You don’t get this with resetting references.