DEV Community

Orchestrating deliberate and meaningful changes to software systems continually is one of the core features of a good software development process. When collaborating in teams, changes are the language of communication, theoretically at least.
In practice, changes are defined by reading diffs (differences) rather than entire files. Think about it, when reviewing a pull request in GitHub, your eyes are focused on the red and green lines which represents the additions and deletions within the context of the unchanged code.
In this article we'll take a different approach when working with changes. The goal is to convince you that adopting a change-focused way of thinking will impact the way you review, debug, and merge code. You’ll also learn about how to think in patches as a mental model and the anatomy of diffs.
Simplifying complexity is a very essential skill, thus we’ll discuss atomic commits as units of intent and practical techniques for crafting reviewable changes and organizing intentional pull requests.
How to think about code changes as patches
Have you ever used a patch tape to cover a specific wounded area of your body? this is how you should think of changes. When you’re fixing a bug or working on a feature branch, your changes are patches.
In this case, you can describe patches as small, focused, self-contained modifications that tell a complete story on their own. A very important characteristic of patches is that they don't try to fix everything at once or mix unrelated concerns. The idea is to create that boundary between “after” and “before” states.
A patch-focused approach is not just about commits. It should be incorporated as a way of communicating clearly. Let’s dive deeper by referencing the Linux kernel development team approach on this approach.
The kernel developer style guide recommends that each patch needs to be a self-contained logical whole. If your description starts to get long, that's a sign you probably need to split up your patch. This is because the maintainers receive thousands of patches and following this practice, enables them to evaluate changes efficiently across a globally distributed team.
The idea you should pick from this section is that when you write changes, write it as if you won’t be there to explain them. This way others can work with your code faster, and with fewer questions.
💡 Run
git show HEAD
to view the most recent commit as a patch, complete with metadata, commit message, and the diff of changes. This helps develop a patch-oriented mindset.
Make every commit an atomic unit of intent
An atom is the smallest amount of anything. In our context, an atomic commit abstracts a single, indivisible change that accomplishes a single purpose.
One developer said that working with atomic git commits means your commits are of the smallest possible size. Each commit does one, and only one simple thing, that can be summed up in a simple sentence.
Following this approach means that when something in code breaks, you can easily identify and revert problematic changes without undoing unrelated work. One git tool that helps you achieve this is git bisect
.
This tool performs a binary search through commit history to find where a bug was introduced. When bisect
identifies a specific commit as the source of a problem, an atomic approach means you'll immediately understand the precise scope of what went wrong.
How to make atomic commits
Let’s illustrate this practically using the expressjs code repo. If you run git log --oneline
you’ll see the last 5 commits.
With git bisect
if there’s a bad commit you want to fix, it will walk through your commit tree and pinpoint the exact change that introduced the issue.
This is the exact change that caused the issue, isolated in one atomic commit.
Notice how easy it was to pick this out? that’s the power of atomic commits.
However, achieving this level of discipline will require some adjustments to your git workflow. So, instead of committing all changes at once, we recommend using git add -p
(interactive patch staging) to select specific chunks for each focused commit.
With this workflow, when you catch a bug or minor mistake, you don’t have to pollute your commit history with unrelated changes. Just use --fixup
+ rebase -i --autosquash
to preserve that narrative clarity.
You can think of this as climbing a staircase. You can’t see the top of—you focus on the next step, complete it, and commit. While it can feel like extra work initially, but the clarity and control it provides quickly becomes indispensable at the end.
So far, you’ve learned how to think like a patch and how to implement an atomic-commit based workflow to making changes. Now let’s talk about diffs.
What makes a git diff meaningful and easy to review
In Git, diff
is a tool used to show the differences between various commits, branches, or files. Its core feature is to inspect changes in your codebase, which allows you to see what has been added, modified, or deleted. However, not all diffs are meaningful. A diff is meaningful if it has these characteristics:
- It addresses a single concern
- It's appropriately sized—not too large, not overly granular
- It excludes unrelated noise like formatting or whitespace changes
This means, when a reviewer is going through your code changes, they should be able to quickly grasp what’s changing and why without any filtering. Noisy, unfocused diffs are costly because:
- They slow down code review by forcing reviewers to untangle mixed concerns.
- They increase the risk of merge conflicts by unnecessarily touching many files or lines.
- Most importantly, they hide functional changes, thereby making bugs harder to spot.
That’s whyl we recommend self-reviews. This means that before opening a pull request, inspect your changes using git diff
or your IDE’s comparison view. Ask:
- “Does this diff clearly express my intent?”
- “Did I include anything accidental?”
- “Should I split this into smaller, more logical commits?”
The mental model you should adopt towards diffs is that you’re contributing a clear, intentional change that makes your codebase easier for others to work with. Why does this even matter?
Why Thinking in Diffs Scales Better for Growing Teams
In a small team of 1 - 3 engineers, just atomic commits are enough cause it’s easier to track and fix your own mistakes.
But once you have 8 or more developers working in the same codebase, pull requests start piling up, merge conflicts increase, and the backlog of complex, unfocused changes for reviewers becomes unmanageable. This is where a diff-centric workflow can save lives.
The biggest gains of meaningful diffs show up in code review and debugging. Most notably, merge conflicts happen less often because atomic commits reduce the "collision surface" where changes overlap. Bugs are easier to track down, since git bisect
can isolate the exact change that introduced an issue.
Furthermore, onboarding becomes faster—new team members can follow the project’s evolution step by step, rather than getting lost in scattered or oversized changes.
A clean commit history becomes a map, not a mess. When you’ve created meaningful diffs with atomic commits, you’ve completed 80% of the work. The other 20% is in creating pull requests that are clear and intent-focused.
How to write clear, intent-focused pull requests
Large pull requests are harder to review properly. Reviewers need to skim through the changes, as a result, feedback becomes too vague, and important issues are often missed.
When unrelated changes are bundled together, it becomes difficult to spot high-impact changes. Code review tools like CodeRabbit help with this by analyzing diffs line by line and surfacing suggestions based on intent. The more focused the diff, the more accurate and useful the feedback becomes.
So what does “intent-focused PRs” mean in this context? An intent-focused PR applies the philosophy of make one cohesive change, but at a higher level. The PR should focus on a single feature, bug fix, or improvement, and communicate that clearly to the reviewers.
Here’s a good example from the React repo: facebook/react#32819. This PR starts with a clear title and detailed description of intent
You can also see clean atomic commits:
Meaningful diffs also make it easy to create focused discussions like this:
This is how a well-scoped PR should look like. The diff is readable, and the reviews are fast.
6 rules for writing pull requests that get reviewed fast
Here are six checklist items you should always keep in mind when making PRs
- State what changed and why: The PR title and description should clearly explain both the change and the reason behind it.
- Keep your feature branches focused on one purpose: Use a dedicated feature or bugfix branch for each task.
- Don’t let unrelated changes accumulate: Avoid including refactors, formatting, or cleanup unless directly tied to the change.
- If scope creep happens during review (say you find another bug), spin that off into a separate PR.
- Review your own diff before pushing: Always check your PR diff before assigning reviewers.
- Keep PRs reasonably sized: Aim to stay under 200 lines of change whenever possible.
Why thinking in changes makes you a better developer
Shifting from thinking in code to thinking in changes is a way of reframing your developer workflow as a process of small, intentional improvements.
This mindset shapes how you use Git, structure commits, write pull requests, and review each other’s work. Focused diffs, atomic commits, and purpose-driven PRs create cleaner history, speed up reviews, and make codebases easier to understand.
Before you commit or open a pull request, pause and look at the diff. Ask yourself:
“Does this change stand on its own? Will another developer understand my intent from this alone?”
When the answer is yes, you’re not just pushing code—you’re contributing a clear, intentional change that makes your codebase easier to work with. That’s the real work of software development.
That's a Wrap!
Hope you found this blog Helpful. If so, Feel Free to share this with your Peers!
Follow CodeRabbit for more content like this.
Share your thoughts in the comment section below! 👇
Thank you so much for reading! 🎉
For further actions, you may consider blocking this person and/or reporting abuse
Top comments (13)
Oh, wow. I thought I was good at writing changes. LOL. Seems like I have a lot to learn. anyways. Great piece. Can you write something on open-source best practices and stuff?
Haha, we always keep learning.
When I was exploring, I too had this same feeling.
Really appreciate your support, David!
Ya, But great write up.
Great Write up!
Thanks for checking out, Akshay!
Nice One,Arindam!
Thanks for checking out!
Super well written article.
Thanks a lot for supporting!
Well written article, Arindam!
Thanks for checking out Shefali!
Great article. I loved the blend between concepts and actions in this piece. Most especially the "How to make atomic commits" section.
One realization that really helped my groking-git process was, nothing (by design principle) is ever deleted. Git history (as a series of related commits) is effectively immutable. If you ever find yourself trying to dig around to remove something, remember:
git commit
writes in stone. Anything else is fighting a core feature of the version control system.