FAQ: A Pasted Hunk Is Not a Commit Object
You pasted a tidy diff into the merge request thread. You told the reviewer the bug was already fixed. Did the branch ref actually move after that paste?
I call that leap out before I trust a green shell. A model prints a hunk, and a scratch shell looks green. Why do we treat that pair as a real commit?
A hunk is only text sitting in a buffer. A commit is an object with a parent and tree. I want that split to feel boring and mechanical.
Where a draft is allowed to live
Free model access can draft the hunk you paste. A free server can host the scratch shell you poke. Disclosure: This article was prepared as part of MonkeyCode's product outreach.
I treat those two options as a drafting bench only. I do not treat them as a merge receipt. If both options vanished, this checklist would still stand.
I will not name a model or quote a quota here. I do not have a measured uptime figure for you. Read current limits in the console, not in this post.
Claims that skip the object
People repeat four claims when a draft looks clean. Each claim skips a Git fact you can check locally. I want the corrections to be commands, not slogans.
Myth one: the reply moved the branch
The model answered with a convincing unified diff. Your editor can still hold the old file bytes. The remote branch can still point at yesterday's commit.
Which ref changed after the model finished speaking? If you cannot name the ref, the branch never moved. A reply stays untrusted text until you create a commit.
Myth two: the scratch shell is the job tree
You compiled once on a shared free server. The prompt looked green, so the review felt done. Your runner image, user, and workdir can still differ.
Why would those two filesystems match by default? The scratch host may hold a package the job image lacks. The job can fail on import while the chat stays proud.
I treat that free server as a scratch pad only. The pipeline checks out the commit you actually pushed. Those two trees are not one snapshot.
Myth three: free access pins the model
Someone says the free model is the one CI uses. Which identifier did you store beside the commit? A menu label is not a lock entry in your repo.
I do not claim the vendor swaps models on a clock. I claim you cannot honor a pin you never wrote down. No stored id means no promise of the same draft later.
Record the label you saw as a human note. Do not pretend that note is a dependency lock. Re-run tests on the commit, not on chat memory.
Myth four: wrapped prose still applies
Models often wrap a diff in friendly explanation. Git apply wants a patch, not a paragraph above it. A single sentence over the hunk can break the apply.
Did you strip the wrapper before you ran the check? Save the raw reply, then extract a clean patch. Never apply straight from the chat window itself.
Checks on a throwaway branch
This is a proposed workflow, not a production log. I have not published timings from a private fleet. Run it on a sample repo and stop on any failure.
set -eu
mkdir -p .proposals
# Paste only the diff. Leave the chat prose out.
cp /tmp/model-reply.diff .proposals/idea.diff
base="$(git rev-parse HEAD)"
printf 'base=%s\n' "$base" > .proposals/idea.note
git apply --check .proposals/idea.diff
git apply --index .proposals/idea.diff
git diff --cached --check
git diff --cached --stat
The first command records the base SHA you claimed. The check asks whether the hunk still matches that base. The index apply stages the hunk without a commit yet.
The cached check catches markers and whitespace errors. The stat line shows scope before you write a message. If the check fails, do not quietly patch around it.
When apply --check fails
Do not rerun the model with a vague try-again note. Capture the reject output and read the missing context. Which failure are you looking at, drift or a moved base?
git apply --reject .proposals/idea.diff || true
find . -name '*.rej' -print
git diff --numstat
A reject file means the context lines were not found. A numstat surprise means your tree changed past the hunk. Refresh the base SHA before you ask for another draft.
Ask for a fresh hunk against that exact tree. Shrink the change if the model rewrote unrelated lines. Then run the same check before you even think of pushing.
Bind the note to the SHA
Read the staged stat before you commit anything. Commit locally only after the scope still looks right. Then record the new SHA beside the drafting note.
git commit -m 'Fix parser crash on empty token'
new="$(git rev-parse HEAD)"
printf 'result=%s\n' "$new" >> .proposals/idea.note
git status --short --branch
What the note must contain
Three lines are enough for a later reader. A base SHA, a menu label, and a result SHA. Leave the result blank until the commit exists.
base=<sha from git rev-parse HEAD>
seen_label=<menu label copied from the console>
result=<sha after you commit>
The note shows intent, and the SHA is the artifact. Push that commit to the merge request branch. Let CI check out the result SHA, not your home directory.
Will the runner clone your free server session for you? It will build a fresh tree from the commit you pushed. If the job needs a clean workdir, the job creates one.
A job that only checks identity
Set EXPECTED_SHA from the result line in your note. Pass that value as a CI variable you type yourself. The job fails if HEAD is any other object.
# Proposed check. Unexecuted example. Identity only.
check_commit_identity:
script:
- test "$(git rev-parse HEAD)" = "$EXPECTED_SHA"
- git status --porcelain
The job needs an image that already contains git. I am not naming an image, because yours may differ. Pin that image in the project, not in this FAQ.
That comparison is the gate a scratch shell cannot fake. A green prompt on the free server never sets this variable.
A decision table
Use this table before you call a scratch host a gate. I keep it next to the proposal note, not in the chat.
| Question | Free model plus free server | GitLab gate |
|---|---|---|
| Need a first hunk? | Yes, saved as text | Not yet |
| Need apply --check? | Yes, on a known base | Do not skip |
| Need a merge result? | No | Yes, after push |
| Need the same draft later? | Only with patch plus SHA | Never from memory |
| Need secrets in the prompt? | No | Use CI variables |
| Need the job tree identity? | No | Yes, the result SHA |
The middle column is a drafting aid, not a verdict. The right column is the gate I actually trust. I do not let convenience replace that gate.
Fail this test on purpose
Create a branch from a SHA you can name aloud. Ask the free model for a one-file hunk only. Save the reply as text outside the chat pane.
Prove the check can fail
Confirm git apply --check passes on that same SHA. Change one context line in the target file. Confirm the check now fails because the context moved.
That failure is the lesson, not an inconvenience. Commit only a hunk that passed the check. Push it and read the checkout SHA in the job log.
Does the log name your result, or the scratch host? Delete the scratch session after the job is green. If the branch dies with the session, you never committed.
Limits I will not talk past
This workflow does not review the safety of a hunk. A clean apply can still ship a dangerous change. Read the diff and keep your normal review path.
This checklist does not pin a model or a machine. I did not publish a rate limit or a hardware shape. Those facts change, so read them when you start a session.
A passed check only says the hunk matched that base. It does not say the commit exists, or that CI ran. You still need the SHA, the push, and the job.
Do not drop secrets into the model prompt. Do not commit notes that contain private local paths. Ignore the proposal folder if those notes stay personal.
grep -qxF '.proposals/' .git/info/exclude || printf '%s\n' '.proposals/' >> .git/info/exclude
That exclude line is local to your clone only. It does not change the project's shared ignore file. Teammates will not inherit your scratch notes from it.
Who should skip this
Skip this if policy forbids external model drafts. Skip this if you must sign commits and cannot sign here. Skip this if the diff touches auth, billing, or migrations.
Those diffs need a slower human review than this FAQ. A scratch apply is the wrong proof for that kind of risk. Skip this if you need a recorded image id for later rebuilds.
This note stores a label, a base, and a result SHA. It does not store a runner image digest or a cache key. Do not pretend the note closes that gap for you.
The picture I want in review
Hold three objects before you type the word fixed. The reply is text you saved in a file. The commit is a SHA you created on purpose.
The job is a fresh checkout of that same SHA. Free model access helps you write the first text. A free server only lets you poke at that text.
That help is convenience, not a substitute for the SHA. If the current plan changes, keep the checklist anyway. The myths fail the same way on any other host.
Before you comment that it is fixed
Open the merge request and paste both recorded SHAs. Paste the cached stat you saw before the commit. Then stop describing the chat as if it were the branch.
I still want a model when I need a first draft. I do not want that draft voting on the merge. If you draft in MonkeyCode, run one stale-hunk check first.
Do that before the next comment that says fixed. You will see a boring context mismatch, not a mystery. Keep that failure next to the note and the result SHA.
Top comments (0)