DEV Community

Paul J. Lucas
Paul J. Lucas

Posted on

Good Git Hygiene Practices

Introduction

Whether you’re writing code for a personal project or for your day job, you very likely are (or should be) using a source code version control system. That’s most likely Git. While there are many opinions on what the best branching strategy is (that I’m not going to discuss here), there are a few independent things you can do to maintain good Git “hygiene” (that I am going to discuss here).

Background

Over the years, one phenomenon I’ve noticed is that I often end up “under the car” — my own personal term to describe the following situation:

  • You’re humming along working on some code and you discover a bug in existing code that should be fixed regardless of what you’re currently working on, or needs to be fixed in order to continue working on what you’re currently working on.
  • You decide to pause what you’re doing and fix that bug.
  • While working on that bug, you might discover another bug that should be fixed regardless of the current bug.
  • And so on ....

A slight variation is that, instead of discovering a bug, you realize that some bit of architecture needs to be rearchitected a bit, or a new small feature or other change were done, it would greatly simplify what you were originally working on. So, again, you decide to pause what you’re doing and go and do that first.

I recently experienced this phenomenon again. While working on a fix for an issue in cdecl, I realized that the unrelated enhancement of allowing the -t command-line option to be specified twice to suppress predefining all types would make debugging the original issue easier, so that’s what I did.

Why do I refer to this as “under the car?” It comes from the TV show Malcolm in the Middle, specifically a scene from S03E06, “Health Scare,” 2001. I think that video perfectly captures this phenomenon, that is you start out to do X, but realize you need to do Y (and possibly Z) first. Like Hal, you’ve also very likely experienced this phenomenon in your every-day (non-software) life as well.

What Not to Do

Before getting to what you should do, I’ll mention what you should not do:

  • You should not simply include either the fix for the unrelated bug or the code for the unrelated feature as part of the code you’re currently working on.

Why not? While it is the least-effort thing you can do, you should not do it because:

  • It makes the diff for your original code longer. (Ideally, the diff for any change should be as small as possible.)
  • Should you need to revert, you can’t easily revert your new code independently from the unrelated bug or feature.
  • Similarly, you can’t easily cherry-pick your new code independently from the unrelated bug or feature.

If you’re working as part of a team, you should also not do it because:

  • It makes the diff more confusing to reviewers.
  • It makes testing your changes independently harder on QA.

What to Do Instead

There are a few choices, but the better choice depends on whether you are working by yourself on your own project, or part of a team. If by yourself, you can:

  • Stash” your current set of changes in a segregated stack returning the current branch to the way it was before you made any changes.
  • Fix the other bug or add the other feature and commit the change.
  • “Pop” the stash from the stack reapplying your previous changes and resume what you were originally working on.

Something like:

$ git stash
# Edit files to fix other bug or add other feature.
$ git add .
$ git commit -m"<message>"
$ git stash pop
Enter fullscreen mode Exit fullscreen mode

If the fix for the other bug or change for the other feature is a bit more involved, you might want to create a separate branch for it, in which case the steps go something like:

$ git stash
$ git checkout master
$ git branch other-bug-fix-branch
$ git checkout other-bug-fix-branch
# Edit files to fix other bug or add other feature.
$ git add .
$ git commit -m"<message>"
$ git checkout master
$ git merge other-bug-fix
$ git checkout original-branch
$ git merge master
$ git stash pop
Enter fullscreen mode Exit fullscreen mode

If you’re using pull requests (PRs), then you’d change the last few lines to:

# ...
$ git commit -m"<message>"
$ git push -u origin other-bug-fix
# Review on web site.
# Merge on web site into master.
$ git checkout master
$ git pull
$ git checkout original-branch
$ git merge master
$ git stash pop
Enter fullscreen mode Exit fullscreen mode

This assumes you use some web user interface (such as that of Github or Gitlab) to do the review and eventual merge of the PR.

The advantage of a separate branch is that you can return to your original branch and keep working on it while your other-bug-fix branch is being reviewed. If the bug fix doesn’t affect the code you were originally working on, you can skip the pull and merge from master.

Note that if you were originally working on a branch other than master, you can simply commit your current (incomplete) changes to that branch rather than stash.

Stash Merge Conflicts

Just as with an ordinary merge, git stash pop can also result in merge conflicts. You fix them as with ordinary merge conflicts, add the conflicted files, and commit.

When a merge conflict occurs, the pop doesn’t actually pop: Git merges the changes from the stash, but leaves the stash on the stack just in case. After you fix the conflicts and commit, you should delete the stash via:

$ git stash drop
Enter fullscreen mode Exit fullscreen mode

Conclusion

If you ever find yourself “under the car,” you can use either stashing or branches to continue work while maintaining good Git hygiene.

Top comments (0)