Stop AI Changing Code You Did Not Ask It To Change

Ask for a one-line fix, get a 400-line diff. Why AI coding tools overreach, and the six habits that keep the change the size you asked for.

Steve Jefferson
Steve Jefferson
Developer Advocate
5 August 20261 min read

You asked the AI to fix one function. It fixed the function, renamed three variables in a file you did not mention, reformatted the whole module, and quietly swapped a library call for a different one. The tests still pass. The diff is 400 lines. This is the most common complaint about AI coding assistants. You can stop AI changing code you did not ask it to change, but the fix is mostly in how you set up the request, not in scolding the model afterwards.

The short answer: constrain the surface before you ask, give the model something to check itself against, and review the diff rather than the result. Each of those is worth a section.

Why AI changes code you did not ask it to change

Two causes, and they need different responses.

The first is that the model is optimising for a good final state, not a small change. Ask it to fix a bug and it sees adjacent code it considers worse, so it improves that too. From its point of view this is helpful. From yours it is an unreviewable diff.

The second is context. If the model can see a file, it treats the file as fair game. Give it your whole repository and the scope of "fix the login bug" silently expands to "improve everything I noticed on the way past". This is a context engineering problem before it is a prompting problem.

Neither cause is a defect you can complain away. Both respond to structure.

Constrain the surface, not just the instruction

The single most effective change is to reduce what the model can touch.

  • Work on one file at a time when the change is local. Open only that file. If your tool has a way to scope context to a selection, use it. A model that cannot see utils.ts cannot refactor utils.ts.

  • Say which files are in scope explicitly, and say the rest are frozen. "Change only src/auth/session.ts. Do not modify any other file. If a change elsewhere is required, describe it and stop."

  • Ask for a patch, not a rewrite. Requesting a unified diff against the current file makes the size of the change visible in the output itself, which tends to make models more conservative about it.

  • Turn off whole-repo indexing for surgical work. It is invaluable when you are exploring and actively harmful when you are making a two-line fix.

The pattern here is the same one that makes prompts for AI app builders work: reduce the space of acceptable answers before asking, rather than filtering afterwards.

Give it a rule it can check itself against

Most tools now support a persistent instructions file that gets included with every request. This is where the rules that never change should live, so you stop retyping them and the model stops forgetting them halfway through a session.

A version that earns its place:

text
Scope rules for this repository:
- Change only the files I name. Never touch other files.
- Never rename existing symbols unless renaming is the task.
- Never reformat code you did not otherwise change.
- Never swap a dependency for another one. Propose it, do not do it.
- If the task cannot be done inside the named files, stop and explain why.
- Prefer the smallest change that makes the test pass.

Two notes on this. Keep it short: a long rules file competes for attention with the actual task and gets skimmed. And phrase rules as prohibitions with a defined escape hatch ("stop and explain") rather than as bare prohibitions, because a model with no legal move will usually invent an illegal one.

Review the diff, never the summary

The model's own description of what it changed is a summary written by the same process that made the change. It is frequently accurate and it is never evidence.

Practically:

  • Read git diff before you read the chat response. If the diff is bigger than you expected, that is the finding, before you have looked at a single line of logic.

  • Commit before every AI-assisted change, so git checkout . is always available and cheap. This one habit converts "it wrecked my file" from a crisis into an eight-second undo.

  • Stage selectively. git add -p lets you take the two hunks you wanted and drop the eleven you did not, which is often faster than arguing the model down to the right change.

  • Watch for silent dependency swaps specifically. They rarely show up in tests and they change your security surface.

This is the same discipline covered in more depth in reviewing AI-generated code before you ship it. The difference here is that you are reviewing for size first and correctness second.

A worked example

Here is the difference the setup makes, on a real-shaped task: a session token is being treated as expired one hour early because the comparison uses local time instead of UTC.

The version that goes wrong:

text
The login keeps expiring early, can you fix it

The model has the repository indexed. It finds the comparison, fixes it, then notices the file also parses dates in two other places, normalises those, extracts a shared helper, moves it to a new lib/time.ts, updates six import sites, and adds a dependency for date handling because the standard library version was verbose. All of that is defensible. None of it was requested, and the review cost just went from thirty seconds to twenty minutes.

The version that behaves:

text
In src/auth/session.ts only, the expiry comparison on line 42 uses local
time and should use UTC. Change only that comparison. Do not touch other
files, do not extract helpers, do not add dependencies. Return a unified
diff. If the fix requires changes outside this file, stop and tell me.

That produces a four-line diff you can read at a glance. If a shared helper genuinely is the right call, you will find out from the model saying so, and you will make that decision as its own task with its own review, which is where a change of that size belongs anyway.

The general principle is worth stating plainly: every constraint you leave unstated is one the model will resolve in the direction of doing more. Not because it is careless, but because "more improvement" is the only reading of an ambiguous request that never looks lazy.

When it still overreaches

Sometimes you do everything above and it still rewrites the world. Three responses, in escalating order:

Restate the constraint in the same message as the correction. "That changed four files. Revert to the original and change only session.ts, nothing else." Do not start a fresh conversation; the model needs to see what went wrong.

Shrink the task. A request that keeps producing sprawling diffs is usually a request that is genuinely too big. Split it. "Extract the token check into its own function" and "fix the expiry comparison" behave much better as two turns than one.

Switch modes. Some tools distinguish a conversational ask from an autonomous agent run. If a coding agent is repeatedly overstepping, an inline, single-suggestion mode gives you the smaller edit surface. The tradeoff between those two working styles is covered in AI pair programming versus autocomplete.

A quick checklist

  • Commit before you ask.

  • Name the files in scope and freeze the rest.

  • Keep a short repository rules file with a defined stop condition.

  • Ask for a patch when the change is small.

  • Read the diff before the explanation.

  • Stage hunks selectively rather than accepting wholesale.

Six habits, none of which take more than a few seconds, and together they turn the most annoying thing about AI coding tools into a non-issue.

Common questions

Why does AI keep reformatting my whole file?

Usually because a formatter runs on save inside the model's own edit loop, or because the model applied its default style to the file rather than matching yours. A rule prohibiting reformatting of untouched code fixes the second case. Committing a formatter config to the repository fixes the first.

Can I stop it renaming my variables?

Yes, and it needs to be explicit. Models treat clearer naming as an improvement, so "do not rename existing symbols unless renaming is the task" has to be stated. It works reliably once it is in a persistent instructions file.

Is it better to work file by file or give it the whole repo?

Whole repo for exploration, understanding, and anything that genuinely spans modules. File by file for fixes. The mistake is leaving full context on for the surgical work because you left it on for the exploration.

What if the model insists a wider change is necessary?

Sometimes it is right. The useful move is to make it argue in words rather than in code: "explain what else needs to change and why, do not change it". Then you decide, and if you agree, you scope the follow-up yourself.

How did this land?

About the author

Steve Jefferson
Steve Jefferson

Developer Advocate

Steve builds something with Swarmz every week and writes up what worked, what broke, and what he'd do differently. Tutorials and hands-on guides are his lane.

Share

Get the next post in your inbox

One email a month. Product updates, engineering posts, and the best of Built with Swarmz.

I agree to receive emails about AI building tips and Swarmz product news. Unsubscribe any time.