◉RORK LABJP
●GPT-6.1 SOL — Added to Rork's model menu (09-29) with Low, Medium and High effort; included on Pro and Max●SONNET 5.5 — Claude Sonnet 5.5 is selectable: strong at UI design and faster than Sonnet 5 (09-28)●SONNET 4.5 — Retires on the Claude API on 11/30, 27 days left. If your app calls it, check the migration target●SDK 58 — Moves to React Native 0.88. R8 is now on by default in Android release builds, and iOS prebuild generates a SceneDelegate●OBSERVE — EAS Observe now records native crashes too (SDK 57.0.21 or later, 10/07)●NEW — My App Open Ad Only Showed When the App…●GPT-6.1 SOL — Added to Rork's model menu (09-29) with Low, Medium and High effort; included on Pro and Max●SONNET 5.5 — Claude Sonnet 5.5 is selectable: strong at UI design and faster than Sonnet 5 (09-28)●SONNET 4.5 — Retires on the Claude API on 11/30, 27 days left. If your app calls it, check the migration target●SDK 58 — Moves to React Native 0.88. R8 is now on by default in Android release builds, and iOS prebuild generates a SceneDelegate●OBSERVE — EAS Observe now records native crashes too (SDK 57.0.21 or later, 10/07)●NEW — My App Open Ad Only Showed When the App…
Articles/Dev Tools
⬡ Dev Tools/2026-09-19Beginner

Reading only what Rork changed: the diff routine I run after every re-export

How to read a fresh Rork export as a diff against the last one: clear tracked files before you copy, strip the noise before you count, and stop once before the merge commit lands.

Rork611Git3exportdiffindie development44

One evening I dropped a fresh export straight on top of my working folder. By morning, a layout fix I had made by hand was back to its original broken state.

Losing the fix stung less than the fact that I went a full day without noticing. I had not looked at a diff. The moment I copied over that folder, the previous state existed nowhere.

I work as an indie developer with a handful of apps that have been in the stores for years, so I thought I was in the habit of watching changes land. But when the other side of the change was generated code, I still slipped into treating it as one big blob to receive and one big blob to replace.

Now I read every export in the same order before I take it in. There is very little to memorize. Four commands carry the whole thing.

Don't let generated code land on the branch you work on

An export is not a patch. It is the entire project as of that moment, which means it arrives with enough force to sweep up whatever you fixed by hand.

So separate the place where code arrives from the place where it grows. Keep one branch that only ever receives exports, and leave the branch you edit untouched.

Generated results arrive on a branch; the merge is mine to approve. That is the one line I hold to even on the days I am in a hurry.

# Move to the receiving branch (create it if it doesn't exist yet)
git switch rork-export 2>/dev/null || git switch -c rork-export

If you export to GitHub, the branch that output lands on already serves as your receiving branch. If the export comes down as a folder of files, start by creating one of your own, as above.

Delete the tracked files before you copy the new export in

This is the step that pays for itself the fastest.

When you copy a new export over an old folder, additions and modifications show up fine. Deletions do not. A screen or component that was removed on the generating side stays on your disk, and it never appears in the diff.

That is exactly how a settings screen you were sure you had deleted ends up shipping inside a build. So before copying, drop the tracked files.

# Delete only the files Git is currently tracking
# (.git and untracked things like your local .env survive)
git ls-files -z | xargs -0 rm -f
 
# Copy the new export in; leave .git alone
rsync -a --exclude '.git/' "$EXPORT_DIR"/ .
 
# Deletions, additions and modifications all land in the index
git add -A
git status --short | head -20

You should see something along these lines:

D  src/screens/OldSettings.tsx
M  package.json
M  app.json
A  src/screens/Settings.tsx

That leading D is the line a plain copy would never have produced. Since git ls-files only lists tracked files, an .env or a key excluded by .gitignore stays put — which also means that if you have tracked those files, this step takes them with it. I wrote about why the ignore rules belong before the first git init in Set up .gitignore before you run git init on exported Rork code.

Strip the noise before you count the diff

Open git diff as-is and lock files and generated directories fill the screen. Faced with a few thousand lines, most of us stop reading. And a diff you stopped reading is a diff you approved.

So cut it down before counting.

git diff --cached --stat -- . \
  ':(exclude)package-lock.json' \
  ':(exclude)yarn.lock' \
  ':(exclude)ios' \
  ':(exclude)android'

':(exclude)…' is Git's pathspec syntax for leaving things out. Unlike .gitignore, it changes nothing about tracking state — it only changes how you read this one time. What is left tends to look like this:

 app.json                 |  6 ++++--
 package.json             |  3 ++-
 src/screens/Settings.tsx | 84 ++++++++++++++++++++++++++++++---
 3 files changed, 79 insertions(+), 14 deletions(-)

What you can safely exclude comes down to one question: do you edit that place by hand?

PathWhy it's usually noiseWhen to keep it in
package-lock.json / yarn.lockResolution output; the intent shows up in package.jsonWhen a version was pinned deliberately
ios/ / android/Often regenerated by prebuildWhen you edit native code by hand
Icons and splash imagesBinary diffs you can't read; looking is fasterWhen they changed and you didn't touch them

If you do keep native folders under your own hand, read them instead of excluding them. The related question of what actually gets uploaded lives in .easignore replaces .gitignore: checking what EAS Build actually uploads.

The three files I open every single time

Once the volume is manageable, order matters. I don't start with the big screen files. I open the small ones first, because config and dependencies can change behavior in three lines.

# Read config and dependencies before anything else
git diff --cached -- app.json app.config.ts package.json

Three things get my attention.

  1. Permissions and usage strings. One added camera or location declaration is one more thing to justify in review. If a permission you don't use shows up, take it back out right there.
  2. Dependency versions. Some versions climb with every generation. The climbing isn't the problem; shipping without knowing it climbed is.
  3. Inlined values. Keys that belong in environment variables sometimes appear directly in source.

The third one slips past human eyes, so pull the added lines out mechanically.

# Pull key-looking text out of added (+) lines only
# False positives are expected; over-matching is the right setting here
git diff --cached -U0 -- '*.ts' '*.tsx' '*.js' '*.swift' '*.kt' \
  | grep '^+' \
  | grep -Ei '(api[_-]?key|secret|token)[^a-z0-9]{0,3}[=:]' \
  | head

-U0 drops the surrounding context lines; without it, unchanged lines mix into the + side and the output gets hard to scan. If nothing comes back, that is your answer for this round.

Stop once before the merge commit lands

Finally, bring the diff you just read into your own branch. Whether or not I pass --no-commit here turned out to be the difference that mattered.

git switch main
git merge --no-commit --no-ff rork-export
 
# The last look before anything enters your branch
git diff --cached --stat
 
# Only after confirming your hand-made fixes survived
git commit -m "Take in the latest Rork export"

--no-commit leaves the merge sitting in the index instead of committing it. If a fix of yours got wiped, you can recover your side with git checkout HEAD -- <file> and then commit. One place to stop is all it takes to remove the irreversibility I ran into that first evening.

When there's a conflict, I keep my hand-written side without hesitating. Generated code can be asked for again. The reasoning behind a manual fix doesn't come back in the same shape.

What's left after you can read the diff is a separate judgment: which bugs to fix yourself, and which to hand back to Rork. I put that line in Telling apart the bugs Rork can fix from the ones you should: a triage routine for exported code.

Next time you re-export, just create the receiving branch. The reading routine can come later and still arrive in time. That is where I started too.

Share

Thank You for Reading

Rork Lab is ad-free, supported entirely by members like you. We publish practical guides daily with implementation code, benchmarks, and production-ready patterns. If you've found it useful, we'd love to have you on board.

  • ✦Copy-paste ready implementation code
  • ✦New advanced guides published daily
  • ✦$5/mo or $10 for lifetime access
View Membership →

If you found this article helpful, a small tip ($1.50) would mean a lot to us. Your support helps keep this site ad-free and covers server and hosting costs.

Related Articles

⬡ Dev Tools2026-09-03
When a link opens the browser instead of your app, look at the signing key before assetlinks.json
Android App Links fail silently when the certificate fingerprint does not match. Here is the real keytool output, the upload key versus app signing key trap, and a small checker you can run before you deploy.
⬡ Dev Tools2026-10-30
It runs in development but the iOS Release build dies on launch — checking whether a missing scheme is the cause
In an expo-router app, an app.json with no scheme can crash only the iOS Release build at launch. Why Debug and Android survive, the two ways to fix it, how to think about leaving the scheme out on purpose, and a pre-submission check.
⬡ Dev Tools2026-10-27
Claude Sonnet 4.5 Leaves the API on November 30. Find the Model IDs Hard-Coded in Your App First
Claude Sonnet 4.5 is scheduled to retire from the API on November 30, 2026. A small script finds the model IDs written into your app's code and config, so you can replace them and check again.