Restoring a Branch the Reflog Remembers
Deleting a branch that still contains work you need is a mistake most Git users make at some point. The commits themselves are not necessarily gone, though: Git keeps a journal of every movement of the HEAD pointer in your local repository. This journal, the reflog, records checkouts, commits, merges, rebases, and cherry-picks, which makes it a reliable safety net.
Suppose you have a branch named feature/login checked out. To delete it, you first switch to another branch, since Git will not let you remove the current HEAD branch. The branch disappears, but a quick git reflog shows the sequence of events. The reflog is sorted chronologically with the newest entries on top, so the git checkout that preceded the deletion is the most recent item. To undo the mistake, create a new branch that starts at the state recorded before that checkout, using the SHA-1 hash shown in the reflog:
git branch feature/login <SHA-1-of-pre-deletion-state>
Your branch is now restored with all its commits intact.
Relocating a Commit to the Correct Branch
Many teams reserve long-running branches like main or develop for integrations only, yet a commit can still end up there by accident. The fix involves two operations: copy the commit to the right branch, then remove the original from the wrong one.
Start by switching to the intended destination branch and use git cherry-pick with the commit's hash to bring the change over:
git checkout <destination-branch>
git cherry-pick <commit-hash>
The commit now exists on the correct branch, but the original is still present on the long-running branch. Switch back to that branch and erase the unwanted commit with git reset:
git checkout <long-running-branch>
git reset --hard HEAD~1
The HEAD~1 argument tells Git to move one revision behind HEAD, dropping the topmost commit. The history of the long-running branch is clean again, and the commit lives where it belongs.
Rewording a Commit That Isn't the Latest
The --amend option of git commit only works on the most recent commit. For older commits, you need interactive rebase. The first step is to run:
git rebase -i <parent-commit-hash>
The hash you supply must be the parent of the commit whose message you want to edit, so that commit appears in the list. An editor window opens with a list of the commits that come after the base commit. Resist the urge to edit the message here; this step only declares what kind of manipulation applies to which commit. Replace the pick keyword on the relevant line with reword, then save and close the editor.
A second editor window opens, this time containing the current message of the marked commit. Make your edits, save, and the message is updated. Interactive rebase rewrites the commit history from that point forward, so commits that follow are replayed on top of your change.
Repairing an Old Commit with Fixup
For a broken or incomplete commit, the fixup mechanism is a clean solution. Rather than adding a separate "band-aid" commit that clutters the history, fixup lets you create that corrective commit and then fold it into the original one, discarding the correction itself in the process.
fixup does not care what went wrong: a forgotten file, an incorrect change, or a typo all work the same way. It produces a history that reads as if the mistake never happened.
The workflow starts with creating a special commit. If you have changes in a file like error.html that fix the problem, stage them and commit with:
git commit --fixup <broken-commit-hash>
Git marks this as a fix for the commit with the given SHA-1 hash (2b504bee in the example). The second step is to start an interactive rebase session, because fixup is part of that toolset:
git rebase -i --autosquash <parent-commit-hash>
The provided hash is the parent of the broken commit. The --autosquash option saves manual work: in the editor window that opens, Git has already marked the corrective commit with the fixup keyword and moved it directly below the commit it repairs. Since fixup combines the marked commit with the one immediately above it, there is nothing left to do but close the window.
When the rebase finishes, the broken commit contains the corrective changes, and the temporary fixup commit has been removed from the history. What remains is an uncluttered sequence of commits, with the original mistake effectively erased.



