Building in Public#building-in-public

Committed node_modules by Mistake? How to Undo It in Git

By Mohamed Abdi Guled

One missing .gitignore entry, and suddenly your repo has tens of thousands of new files.

Accidentally Committing node_modules: A Termux Git Horror Story

*One missing .gitignore entry, and suddenly your repo has tens of thousands of new files.*

Every developer has a version of this story, but it hits differently when you're watching it unfold on a phone screen with no easy way to visually diff a few hundred thousand lines of change.

How It Happened

Working in Termux without the muscle memory of a desktop IDE's built-in git integration means every git operation is manual — git add, git status, git commit — typed out, not clicked. Somewhere in that manual process, a .gitignore file either wasn't present yet or didn't include node_modules/, and a git add -A or git add . swept up the entire dependency folder along with the actual code changes.

The first sign something was wrong was the commit taking noticeably longer than usual, and git status afterward showing an overwhelming wall of file paths — dependency internals that had never been meant to enter version control.

Why This Is Worse Than It Sounds

node_modules isn't just large — it's actively harmful in a git repository. It bloats the repo size permanently in history (even after removal, the bad commit remains in history unless rewritten), it makes every future clone and pull slower, and on a mobile connection with limited data, pushing tens of thousands of extra files is a real, felt cost, not just an abstract inefficiency.

The Fix

The recovery had two parts. First, a proper .gitignore entry for node_modules/ (along with other build artifacts that shouldn't be tracked) to stop the bleeding going forward. Second, git rm --cached -r node_modules to remove the folder from git's tracking without deleting it from the actual filesystem — the distinction matters, since the goal is to stop tracking the files, not delete the dependencies the project needs to run.

After that, a commit removing the tracked files, and a push. The historical commit with the bad node_modules addition still technically exists in git history, but going forward the repository stays clean.

Building a Standard .gitignore From the Start

The longer-term fix wasn't just adding node_modules/ reactively — it was adopting a standard, comprehensive .gitignore template for Next.js projects from the very first commit of any new project going forward, covering not just node_modules/ but build output directories, environment files, and OS-specific junk files that have no business in version control either. Treating this as a one-time setup step, copied in before writing a single line of application code, removed an entire category of future mistakes rather than relying on remembering to add exclusions reactively each time something new needed ignoring.

The Mobile-Specific Lesson

On a desktop, this kind of mistake is often caught immediately — a bloated commit is visually obvious in most git GUIs before you even finish typing a commit message. In a terminal-only mobile workflow, there's no such visual safety net. The fix wasn't really about git — it was about building the habit of running git status and actually reading the output before every commit, especially early in a project before .gitignore is fully configured.

What the Push Actually Felt Like

There's a specific kind of dread in watching a git push progress indicator crawl far slower than it ever has before, on a mobile connection where every megabyte is felt, and not immediately knowing why. The first instinct was to assume a network problem — the same category of issue that had caused SSL failures elsewhere in the project — before git status revealed the actual scale of what had been staged. Scrolling through a file listing that runs into the thousands, on a phone, searching for the point where legitimate project files end and dependency internals begin, is its own small ordeal; there's no folder-tree sidebar to visually collapse node_modules into a single line the way a desktop file explorer would offer by default.

Rewriting History, or Not

A more aggressive fix exists beyond git rm --cached: rewriting git history entirely with a tool like git filter-repo or the BFG Repo-Cleaner to remove the bad commit's bloat retroactively, rather than just stopping it going forward. That path was deliberately not taken here — rewriting history on a repository with any collaborators or existing clones is disruptive, and for a solo project at this stage, the pragmatic choice was accepting that one bloated commit exists in history permanently, in exchange for not risking a more complicated history rewrite on a connection and toolchain with less margin for error than a desktop setup would have.

Takeaway

A .gitignore file isn't optional boilerplate — it's the single highest-leverage file in a repository for anyone developing without a GUI to catch mistakes visually. Set it up before the first commit, not after the first accident.

📬 Get the latest AI tool reviews

Expert picks and comparisons, weekly. No spam.

← Back to Blog