DEV Community

Alex Bespoyasov
Alex Bespoyasov

Posted on • Updated on


Refactoring Tools: Tactic Git for Smoother Refactoring

Let's continue our series of short posts about code refactoring! In it, we discuss technics and tools that can help you improve your code and projects.

Today we will discuss how to use Git to make refactoring easier and simplify future work with the code.

Use Small Atomic Commits

As we discussed previously, during refactoring, we want to avoid big change sets.

Small commits help us by splitting a large chunk of work into smaller and simpler ones. The smaller the change, the easier it is to evaluate it and find issues in it.

Commits become atomic if they represent an independent unit of work. Basically, we can say that if a commit evolves a code base from one valid and working state to another valid and working state, this commit is atomic.

Atomic commits help us with switching to other tasks at any point in time since the code always works and can be built.

When we make our commits both atomic and small, we make it easier for the reviewer to review the changes and at the same time make it possible for us to switch between different tasks even if the refactoring isn't yet finished. The project development becomes more flexible and safer.

Evaluate Changes with Diffs

Before making a commit, take a look at the changes in the diff. Check if the diff contains only the updates you want to stage.

Sometimes developers get distracted from their work and miss the moment when the commit starts containing something unrelated to the current task.

It's especially true when we use automated refactoring tools in the IDE or automated code formatters and linters.

For example, a formatter might update code in a different way than we expect from it:

// Before applying the formatter:

function setDiscount(discount) {
  if (user.isVip) = discount, -= discount

// After:

function setDiscount(discount) {
  if (user.isVip) ( = discount), ( -= discount);

// What we actually want:

function setDiscount(discount) {
  if (user.isVip) { = discount; -= discount;
Enter fullscreen mode Exit fullscreen mode

In the diff, we can see what exactly changes and decide if we want this change to be staged:

Diff shows the current change set

Stash Changes to Switch Tasks

When refactoring in small steps and using atomic commits, it's easier to switch from refactoring to another task using git stash.

Stashing helps us save the progress we've made and switch to another branch or roll the code back to the last working state.

It allows us to check out another branch to fix a sudden bug or test a hypothesis about the code without losing any work done during the refactoring session.

Prepare for Future Bisect

In “97 Things Every Programmer Should Know”, there's a chapter named “Know Your Next Commit”.

It describes the idea of building a narrative out of the commit messages. This narrative can help us in the future when debugging the code.

One of my favorite technics of debugging is using bisection. That is going through the commit history using binary search and checking what commit introduced the bug.

When refactoring, we can embrace this idea and think about our commits beforehand so that the future history is clean and convenient to use.

For example, we can:

  • Use only one refactoring technic per commit;
  • Avoid adding features or fixing bugs;
  • Or use stash and rebase to reorder changes in a way that makes more historical sense.

And, of course, always keep in mind the main idea of why we do it.

More About Refactoring in My Book

In this post, we discussed Git and how to use it for making refactoring easier but only scratched the surface of the topic of refactoring in general.

If you want to know more about refactoring and improving your code, I encourage you to check out my online book:

The book is free and available on GitHub. In it, I explain the topic in more detail and with more examples.

Hope you find it helpful! Enjoy the book 🙌

Top comments (0)