C.W.K.
Stream
Lesson 01 of 04 · published

Split a Mixed Working Tree

~24 min · playbook, staging

Level 0Untracked Rookie
0 XP0/47 lessons0/14 achievements
0/100 XP to next level100 XP to go0% complete

Split a mixed working tree into clean commits

This is the playbook to memorize. You sat down meaning to fix a bug. Three hours later, the working tree contains: the actual bug fix, a typo you fixed in passing, a debug log you added and forgot to remove, an unrelated config tweak, and a refactor of one helper that "while I was here" felt obvious. Pushing that as one commit is sloppy and pollutes history. The job is to split the result into clean, separate commits without losing any change.

The procedure. 1. git status -sb to see what is in front of you. 2. git diff to actually read every modified line and decide which logical group it belongs to (bug fix vs typo vs refactor). 3. git stash push -k to set the unstaged work aside while you commit the staged piece — or skip stashing and go straight to git add -p, picking only the hunks that belong to the first concern. 4. git commit with a focused message. 5. Repeat for the next concern: git add -p, commit. 6. When the working tree is clean, run git log --oneline -p -n 5 and read the result — three or four commits should each tell one coherent story.

If something goes wrong mid-split — you accidentally staged the wrong hunk and committed it — you have options. git reset --soft HEAD~1 undoes the commit while keeping the changes staged. From there, git restore --staged --worktree on specific files lets you reset state and start over. Nothing destructive happens until you discard or push.

The discipline that prevents the situation: never sit down to "make changes" without a clear sentence saying which change you are making. "I am fixing the empty-search bug" is a good intent. "I will work on the code" is how you end up with the mixed tree. When something incidental needs to happen — refactor, typo — note it on a TODO list and address it in a separate, deliberate commit afterwards. Discipline is cheaper than splitting later.

Code

Split routine — copy-paste-able·bash
# 1. Survey:
git status -sb
git diff

# 2. Stage the first concern's hunks only:
git add -p src/search.js src/api.ts
# (use 'y/n/s/e' to accept, reject, split, or edit hunks)

# 3. Sanity-check what is staged:
git diff --staged

# 4. Commit with a focused message:
git commit -m "fix(search): handle empty result array in /api/search"

# 5. Continue with the next concern:
git add -p docs/api.md
git commit -m "docs(api): clarify /search response shape"

# 6. Final pass — commit anything benign that is left:
git status -sb
Recovery if you committed too much·bash
# Just realized the last commit grabbed the typo + the refactor
# in the same commit, oops:
git reset --soft HEAD~1          # undo the commit, keep changes staged

# Now selectively unstage the refactor hunks:
git restore --staged -p src/helper.js

# Re-commit just the fix:
git commit -m "fix(search): handle empty array"

# Stage and commit the refactor separately:
git add -p src/helper.js
git commit -m "refactor(helper): extract result-formatter"

External links

Exercise

Engineer the situation deliberately in a scratch repo: in one editing session, fix a real bug (the "primary" change), add an unrelated debug log somewhere else, and tweak a comment. Now split. Use git add -p to stage only the bug fix and commit it. Then unstage and re-stage the debug log removal, commit. Then the comment, commit. End with git log --oneline -p -n 3 and confirm three clean commits. Note in writing the moment in your real workflow when you most often produce mixed trees.

Progress

Progress is local-only — sign in to sync across devices.
Spotted a bug or have feedback on this page?Report an Issue

Comments 0

🔔 Reply notifications (sign in)
Sign inPlease sign in to comment.

No comments yet — be the first.