I’ve been using git for well over a decade now. During this time I’ve explored a few different workflows, checked out thousands of branches and made countless commits. It’s been a while though since I had to teach anyone how to use git so I thought it might be a good idea to put a page together with my workflow for future reference.
Gitflow
Before we get started, a quick note on gitflow: Don’t do this, this way lies pain, suffering and madness. The only positive might be the ability to simultaneously have multiple “live” versions of a codebase but involves a tonne of management.
Starting work on a feature
When starting work on a new feature, I generally switch over to the trunk (master
or main
) branch and get latest using git checkout main && git pull
. By doing this, I’m bringing my local state forward to match the server (github, gitlab) is one way to minimise the number of conflicts you have with other work being done.
From there, I’ll either hack away or branch out immediately with something like git checkout -b feat/some-words-to-describe-work
. The reason I often tend to start hacking first is that I generally discover things that might need to be tidied up that’ll allow developing my feature easier.
For such a side-quest, it often makes sense to put an MR/PR up with just the refactoring first while you continue working on your feature.
Continuing work on a feature
Code reviews can take a while, and that’s completely understandable. I’d rather my co-workers get to reviewing my code when they’ve already been distracted by a meeting rather than nudging them immediately.
While I’m waiting for my first set of changes to be reviewed, I usually get started on the next changeset by branching off my previous work. This way, I have all my refactors / initial changes while I work on the next piece.
Rebasing
Once my first set of changes has been reviewed, I can immediately merge that into the trunk and rebase any subsequent branches on top of the new commits. Rebasing here is important if we’re merging or squash-merging commits into the trunk as this will mean that we have different commit hashes with the same changes in our subsequent branches.
I’ll generally do an interactive rebase here using git rebase -i main
which allows me to pick only the commits from my subsequent branch and drop any that have already been merged into the trunk. This is the key part of the workflow that ensures I don’t conflict with my past self.
This is an example with two change sets but this workflow can work for any number of subsquent changes, you just need to keep in mind which commits have already been merged into the trunk when rebasing.
Bonus: Interactive staging
This is another amazing git feature that I’ve been using more and more over the past couple of years. Essentially, when staging changes, instead of staging everything, you can choose to stage only the “hunks” that make sense for a particular commit. This means you can break up large changes (even when they are in the same file) into commits that makes sense for your reviewers. How this works probably deserves a post of its own, here’s the man page for now.
This by no-means is a comprehensive guide but rather my current workflow and the commands I use 99% of the time. There’s still times when I have to google or reference a previous disaster from oh shit git. Even after 10 years, there’s plenty of learning to do!