Beyond Rebase: A Novel Approach to Atomic Commits with Git Stash

In the ever-evolving landscape of software development practices, the concept of atomic commits has gained significant traction. A recent blog post from developer Iain explores a fresh perspective on implementing this practice, rejecting traditional approaches like rebase and stacked diffs in favor of a solution built on Git's native stash functionality.

Understanding the Atomic Commit Movement

Atomic commits represent a fundamental shift in how developers interact with version control. At their core, atomic commits are single logical units of code that can pass CI builds independently. Each commit should represent one cohesive change or feature that makes sense on its own, leaving the codebase in a working state at every step.

The benefits of this approach are compelling:

  • Easier code reviews, as each commit can be reviewed independently
  • Enhanced bisect capabilities, since every commit passes tests
  • The option to implement pure CI trunk-based development, with developers pushing directly to the main branch

As Iain explains in his blog post: "Think of it like saving your progress in a video game at checkpoints that actually make sense, rather than saving randomly in the middle of a boss fight."

The Problem with Existing Solutions

Despite these clear benefits, many developers struggle to implement atomic commits effectively. Iain identifies a common pattern where developers begin with a functional test, make it fail, then build units of code using TDD until the test passes. This approach often results in working branches containing code that doesn't align with the logical units required for atomic commits.

Existing solutions to this problem have significant drawbacks:

  • Stacked Diffs: Iain describes this as "overkill for when you're just working on a single reviewable feature which needs multiple commits."
  • Reordering Commits and Pushing for WIP: This approach, he notes, "sounds like a lot of work."
  • Other Complex Workarounds: These often involve "special crafting of PRs in a very particular way to hide the broken commits" or using "special code review tools and processes to work around the fact that we're not being pure in our actions and intentions."

"The other solutions are fundamentally workarounds," Iain argues. "They both work off the concept that there is going to be code that is not going to pass the build and that we will intentionally splinter off from that broken state."

A Git-Native Solution

Iain's approach is refreshingly simple: use Git as it was intended. "Git has the features we need—if we use them correctly, this issue goes away completely," he explains.

The core insight is that developers are conflating two distinct use cases:

  1. Storing work-in-progress code
  2. Tracking code intended for permanent project history

Instead of forcing commits to handle both scenarios, Iain proposes using Git's stash functionality for temporary work and commits for permanent changes. "Stash was designed to store files while we switch branches, and that's the only time you really need your WIP code set aside temporarily," he notes.

However, manually managing stash operations can be cumbersome. "If we do it correctly by hand, that's a lot of git commands and tons of work," Iain admits. "So realistically, no one with a brain is going to do it."

The Atomic Stash Solution

To bridge this gap, Iain developed a set of three Git commands that automate the stash-based atomic commit workflow:

  1. astash: Manages stash sessions

    • start: Creates a metadata file indicating an active stash session
    • list: Shows branches with active stash sessions
    • finish: Closes the stash session and reverts commands to standard behavior
  2. acommit: Commits changes while managing stash operations

    • Passes through to the standard commit command
    • Automatically stashes designated files, commits remaining changes, and unstashes afterward
    • Results in a clean commit without manual stash management
  3. acheckout: Handles branch switching with stash awareness

    • Automatically stashes changes when leaving a branch with an active stash session
    • Restashes when switching to a branch with an existing stash session
    • Behaves normally when no stash session exists

Implementation Example

The workflow Iain demonstrates is straightforward:

git astash start
git acommit -am "Add my changes"
git acheckout -b new-branch
git acheckout old-branch
git astash finish
git acommit -am "Final changes"

This sequence shows how the commands integrate seamlessly into a typical development workflow while maintaining atomic commit principles.

The Philosophy Behind the Solution

What makes Iain's approach compelling is its philosophical foundation. Rather than adding complex new tools or workflows, it leverages Git's existing functionality in a more intentional way.

"I would rather just automate the tricky things and try and blend it in as easy as possible to my workflow," Iain explains. "I find if people need to go out of their way too much they will just refuse to do it despite the benefits. If things just work, they will be used and solve problems."

This user-centric approach to tooling—making the right thing the easy thing—aligns with many successful developer tools and practices.

Industry Implications

The rise of atomic commits reflects broader trends in software development:

  1. Increased Emphasis on Code Quality: As systems grow more complex, maintaining clean, understandable histories becomes more critical.
  2. Shift Toward Trunk-Based Development: The ability to push directly to main branches requires confidence that each change is safe and reversible.
  3. Automation of Best Practices: Tools like Iain's script automate adherence to good practices, removing friction from developer workflows.

Looking Forward

Iain's solution represents one approach to solving a persistent developer challenge. By leveraging Git's native features rather than building complex abstractions, he's created a tool that integrates naturally into existing workflows.

The repository for these scripts is available at https://github.com/that-guy-iain/git-atomic, inviting further development and community contribution.

As development practices continue to evolve, tools that simplify the adoption of good principles—rather than adding complexity—are likely to find significant adoption. Iain's work on atomic commits exemplifies this approach, offering developers a practical path to cleaner version control without sacrificing productivity.