This chapter follows Working with remotes.
Mistakes are normal: wrong files in a commit, work half-done when a hotfix arrives, a bad merge on a shared branch. Git separates moving refs, changing the index and working tree, and adding new commits that undo old ones. Pick the tool that matches whether history is already public.
Stash
When you must switch branches but are not ready to commit:
git stash push -u -m "WIP login form"git stash listgit stash applygit stash popgit stash clear-u includes untracked files. apply keeps the stash entry; pop applies and removes it. Stash is a stack of WIP snapshots, not a substitute for small commits on a feature branch.
Amend the latest commit
Forgot a file in the last commit?
git add forgotten.tsgit commit --amendGit replaces the tip commit with a new one (new hash). Safe only if you have not pushed that commit, or your team accepts rewriting the remote branch.
Reset: move the branch and optional trees
git reset moves the current branch to a commit, then optionally updates index and working tree:
| Mode | Branch | Index | Working tree |
|---|---|---|---|
--soft |
Moves | Unchanged | Unchanged |
--mixed (default) |
Moves | Matches commit | Unchanged |
--hard |
Moves | Matches commit | Matches commit |
git reset --soft HEAD~1git reset HEAD file.txtgit reset --hard origin/maingit reset HEAD file.txt unstages without moving the branch (same idea as git restore --staged). --hard discards local changes—use deliberately.
flowchart TB
subgraph before [Before reset --hard to older commit]
B1[Branch at C3]
WT1[Working tree has edits]
end
subgraph after [After reset --hard]
B2[Branch at C1]
WT2[Working tree matches C1]
end
before --> afterRestore without moving the branch
git restore --staged file.txtgit restore file.txtgit restore --source=HEAD~2 --staged --worktree path/restore copies from a commit into the index and/or working tree while HEAD stays put.
Revert: new commit that undoes an old one
On shared branches, avoid rewriting history. git revert creates a commit that applies the inverse patch:
git revert abc1234git revert -m 1 merge_commit_shaUse -m 1 when reverting a merge commit (choose the mainline parent). Prefer revert over interactive rebase once others may have pulled the bad commit.
Undo a merge in progress or just finished
git merge --abortgit reset --merge ORIG_HEADORIG_HEAD often points at HEAD before the last merge. reset --merge tries to preserve uncommitted changes outside conflict paths.
Cherry-pick
Copy one or more commits onto the current branch:
git log other-branch --onelinegit cherry-pick ec24ds24git cherry-pick a1b2c3d d4e5f6aOriginal commits stay on their branch; new commits with new hashes appear on HEAD. Typical uses: port a bugfix to release/2.x, salvage commits from an abandoned branch.
gitGraph commit id: "base" branch fix checkout fix commit id: "fixA" checkout main commit id: "main1" checkout main commit id: "fixA_on_main"
Resolve conflicts like a merge, then git cherry-pick --continue.
Rewriting large history locally
Accidentally committed a huge binary across many commits? git filter-repo (preferred over deprecated filter-branch) removes paths from all history:
git filter-repo --path huge.bin --invert-pathsRewrites every commit touching that path. Treat like force-push: coordinate with anyone who cloned the repo.
Next: Merging versus rebasing.