How to Git Good for Much Win
There once was a man from New Zealand,
Who came bearing the fruits of experience,
Rebase, don’t merge!
Delete, don’t comment!
Branch, don’t conflict!
Squash, when possible,
Force, only personally,
But, above all––
Revert, don’t reset.
–apocryphally paraphrased from Jacob Mattingley
For those of you just starting your start-up odysseys, even those of you with considerable solo programming experience, you might find… you don’t know how to work well with other people :(
It’s not that you don’t get along day-to-day! Sure, you get drinks after work and there was that time you taste-tested all the lunch delivery and potentially saved their lives from an undiagnosed shellfish allergy… it’s just that when you try to merge your code together––instead of a sublime union of thought and… thought––you’re met with an all too familiar despair:
As the recursive, cthontic screams echo across your screen, you can’t help but wonder: why?
Git
is an interesting technology. Initially devised by Linus Torvalds for non-linear workflow management––it is best used for… linear workflow management. Git
is powerful enough to where you can dig yourself into, through, and out of a grave of incalculable depth in a free-form, branching, communistic kind of way. To express it less than delicately: it was designed to traverse the landscape of …hell!
But hell is scary! …and exhausting. If given the option, why not make for milder, more accomodating climes? Somewhere with healthcare and year-round alpine skiing. Like Switzerland.
Doesn’t that sound nice? As the diagram implies, the secret is to not use the vast majority of Git
. For starters, add this to your ~/.gitconfig
:
[color] ui = true [format] pretty = %C(magenta)%h%Creset %Cgreen[%cr]%Creset (%an) %s
Now your git log
will actually be useful.
Next, but perhaps most importantly never merge
! Only rebase
! This will ensure your changes are placed on top of all existing changes into your target branch if you use the following flow:
#while in feature branch
git rebase master
git checkout master
git rebase <feature-branch>
git push origin master
It seems a little circular, but it forces your changes to be applied after all current commits on master.
Another helpful tip: before your rebase master into your feature branch, squash your feature branch down to atomic commits. That way, you only have to deal with conflicts once:
#while in feature branch
git rebase -i <last commit hash on master>
In your text editor, change all the pick
s into s
s except for the ones you want to exist atomically in name. An atomic commit is one that you could potentially revert together or cherry-pick
individually. You can also reorder commits and squash them into atomic units at this point.
In short, I present the following precepts for the predication of the state of Git Switzerland:
- Don’t comment code, delete it
- Don’t merge, only rebase
- Squash feature-branch commits into atomic commits
- Name-space your feature branches with ‘/’, i.e.
git checkout -b kamalasaurus/feature-branch
; this keeps you from having to compete for branch names with your coworkers - Never perform destructive changes to master (force, reset, squash)
- Delete dead and committed branches immediately
Meaning your git
existence will be forevermore defined by:
git checkout -b <feature-branch>
#while in feature branch
git rebase -i <last commit hash on master>
git rebase master
git checkout master
git rebase <feature-branch>
git push origin master
git branch -d <feature-branch>
git push origin :<feature-branch>
If you or your coworkers stray from the narrow path, I have an unfortunate bit of news to deliver:
You’re already in git hell. You just haven’t realized it.