Moving uncommitted work to the right branch Jump to heading
Everyone does it: an hour into a change, git status reveals you are on the default branch, or on the branch from last weekβs ticket. The work is fine; its location is not. Git handles this better than its reputation suggests β uncommitted changes usually travel with a branch switch, and where they cannot, the stash or a scratch commit covers it. The one thing to avoid is the panicked git checkout that discards them. This recipe covers each case, within stashing and work-in-progress recovery.
When to use this approach Jump to heading
- Work in progress is on the wrong branch and you noticed before committing.
- You committed to the wrong branch and want to move the commits.
- Some of the changes belong on one branch and some on another.
- A branch switch was refused because it would overwrite local changes.
- If you have already committed and pushed, this is a different problem β cherry-pick and revert instead.
Step 1 β Try the simple switch first Jump to heading
Git carries uncommitted changes across a switch whenever doing so is unambiguous.
git status --short
git switch -c feat/PAY-812-refund-window # The changes come with you; nothing was stashed or committed
git status --short
git rev-parse --abbrev-ref HEAD # Verification: the original branch is unchanged
git diff --stat main This works whenever the files you have modified are identical in both branches, which is the overwhelmingly common case when the new branch is created from the current commit. A switch to an existing branch with different content in those files is the case Step 2 covers.
Step 2 β Use a stash when the switch is refused Jump to heading
git switch other-branch
# error: Your local changes to the following files would be overwritten by checkout git stash push -u -m 'refund window work, moving to the right branch'
git switch other-branch
git stash pop # Verification: the changes are present on the intended branch
git status --short
git stash list # empty, if the pop succeeded If the pop conflicts, the entry survives and the conflict is resolvable β the procedure is in resolving conflicts when popping a stash.
Step 3 β Move commits that landed on the wrong branch Jump to heading
If you committed before noticing, the commits themselves have to move.
# Where they should have gone
git switch -c feat/PAY-812-refund-window # Remove them from the branch they landed on
git switch main
git reset --keep origin/main # Verification: main matches the remote, the commits are on the new branch
git log --oneline -1 main
git log --oneline origin/main..feat/PAY-812-refund-window --keep rather than --hard is deliberate: it refuses rather than discarding if there are uncommitted changes that would be lost, which is exactly the safety you want while moving things around. The distinction between the reset modes is covered in when to use git revert vs git reset.
Step 4 β Split changes that belong on two branches Jump to heading
Frequently the work contains two unrelated things, and only one of them belongs here.
# Stash only the paths that belong elsewhere
git stash push -m 'unrelated config change' -- config/services.yaml # Commit what remains on this branch, then move the stash
git commit -am 'feat(payments): clamp the refund window'
git switch -c chore/config-tidy origin/main
git stash pop # Verification: each branch contains only its own change
git diff --stat origin/main
git diff --stat origin/main feat/PAY-812-refund-window # For a split inside a single file, stage hunks selectively
git add -p src/payments/refund.ts
git commit -m 'feat(payments): clamp the refund window'
git stash push -m 'the rest, for another branch' SAFETY WARNING β never use
git checkout -- .orgit restore .to βclean upβ while sorting this out. Both discard uncommitted changes immediately and there is no reflog for content that was never committed. If you need a clean tree, stash it β the stash is recoverable and a discard is not.
Step 5 β Verify both branches before moving on Jump to heading
# The branch you moved away from should be untouched
git diff --stat origin/main main # The branch you moved to should have exactly the intended work
git log --oneline origin/main..HEAD
git status --short # And nothing should be left behind on the stack
git stash list Validation checklist Jump to heading
Frequently Asked Questions Jump to heading
Why did the switch work without a stash? Jump to heading
Because Git only refuses when carrying the changes would be ambiguous β that is, when the files you modified differ between the two branches. Creating a new branch from the current commit never has that problem, which is why the simple case works so often and surprises people who expect to need a stash.
Can I move work to a branch that does not exist yet on the remote? Jump to heading
Yes, and it is the common case: git switch -c creates it locally and git push -u origin HEAD publishes it. Doing the push immediately is worth the habit, because it converts local-only work into something with a backup.
What if the work spans a commit that was already pushed? Jump to heading
Then moving it means rewriting published history, which needs the care described in safe git rebase -i for shared branches. Often the better answer is to leave the commit where it is and cherry-pick it onto the right branch, accepting that it exists in both places until one is cleaned up.
Related Jump to heading
- Stashing & Work-in-Progress Recovery β the parent topic and what the stash stores.
- Resolving Conflicts When Popping a Stash β when the move does not apply cleanly.
- When to Use git revert vs git reset β the reset modes used when moving commits.