The Git Undo Toolkit – Part 4 – How To Undo Branch Changes In Git?

Welcome back to “The Git Undo Toolkit”! In our previous blogs, we have explored how to undo changes in your working directory, staging area, and even committed history. In this blog post we are going to cover how to fix any mistakes that might happen to a git branch. Branches are the core component of a collaborative development in Git, allowing for parallel work and experimentation. But what happens when you make a mistake related to the branch itself, rather than just the commits on it? This post will guide you through undoing various branch-related mishaps, both locally and on your remote repository.

Common Mistakes in Branch Management:

Being a human being, mistakes can occur at any time and any place, including in a git branch. Here are some of the frequent scenarios you might encounter:

  • Accidental Branch Deletion: You delete a local or remote branch and then realized it was has an important bits of code, critical to your project.
  • Incorrect Branch Merges/Rebases: You perform a git merge or git rebase operation and then realized that the target or source branch was not correct.
  • Misnamed Branch: You created a branch with a typo, did your changes, commit and pushed the changes to remote repository and then realized there was a typo in the branch name and now you want to correct the branch name on both local and remote repository.
  • Branch History Not In Sync: Your local branch have become out of sync with the remote after a merge/rebase operation, leading to issues with git pull or git push.

Now, let’s explore how to address these situations and rectify your branch-related mistakes.

Scenario 1: Recovering a Deleted Local Branch

Question: How do I recover a local branch that I accidentally deleted using git branch -d or git branch -D?

Answer: You can recover a deleted local branch by inspecting your git reflog to find the commit hash where the branch was last active, and then recreate the branch from that specific commit.

Code:

# 1. View your reflog to find the commit hash where your branch was last active
git reflog

# Expected output format (look for entries where your branch was active or checked out):
# a1b2c3d HEAD@{0}: checkout: moving from feature/new-design to main
# e4f5g6h HEAD@{1}: commit: Add new design components (This was likely the last commit on 'feature/new-design')

# 2. Recreate the branch from its last known commit hash
git branch <recovered-branch-name> <commit-hash>

Explanation: The git reflog command maintains a local history of your HEAD‘s movements. This includes every time you commit, checkout, merge, or rebase. Even if a branch is deleted, its past references are stored in the reflog. By carefully examining the entries, you can identify the commit ID that the deleted branch was pointing to before its removal. Once you have this commit ID, git branch <new-name> <commit-id> allows you to create a new branch pointing directly to that commit, effectively restoring your deleted branch.

Notes/Warnings:

  • git reflog entries eventually expire (default 90 days), so prompt action is best.
  • If the branch only existed locally and was never pushed, git reflog is your primary method of recovery.
  • This method recovers the branch pointer, but not the remote tracking if it was lost.

Scenario 2: Undoing a Local Merge

Question: How do I undo a git merge operation that I performed locally, before it has been pushed to the remote repository?

Answer: If you’ve merged a branch locally and realize it was a mistake (e.g., wrong branch merged, or it introduced unexpected issues), you can use git reset --hard to move your current branch’s pointer back to the commit before the merge.

Code:

Bash

# 1. View your commit history to find the commit hash *before* the merge commit
git log --oneline

# Example log output:
# fedcba9 (HEAD -> develop) Merge branch 'feature/bugfix' into develop
# abcde12 (origin/develop, main) Last commit on develop before merge

# 2. Reset your branch to the commit immediately preceding the merge
git reset --hard <commit-hash-before-merge>

Explanation: A git merge creates a new merge commit that combines the histories of two branches. To undo this operation, you essentially want to remove that merge commit and any subsequent commits from your branch’s history. git reset --hard <commit-hash> moves your HEAD and the current branch pointer to the specified commit, and importantly, it discards all changes in your working directory and staging area that occurred after that commit. This effectively brings your branch to its state before the merge.

Notes/Warnings:

  • DANGER: git reset --hard is a destructive command. It will discard all uncommitted changes in your working directory and staging area. Ensure you have no uncommitted work you wish to keep before using it.
  • This operation only affects your local repository. If the merge was already pushed, you would need to revert or force push (which is out of scope for this guide).

Scenario 3: Undoing a Local Rebase

Question: How do I undo a git rebase operation that went wrong or was applied to the incorrect base locally, before it has been pushed?

Answer: Rebasing rewrites commit history, making it potentially destructive. However, git reflog is your savior for local rebases. You can use it to find the state of your branch before the rebase and reset to that point.

Code:

# 1. Inspect the reflog to find the commit hash of your branch *before* the rebase started
git reflog

# Example reflog output:
# f1g2h3i HEAD@{0}: rebase finished: returning to refs/heads/feature/x
# j4k5l6m HEAD@{1}: rebase: ...
# n7o8p9q HEAD@{2}: rebase: ...
# ...
# xyz1234 HEAD@{5}: checkout: moving from main to feature/x (This was the branch state *before* rebase)
# abcde12 HEAD@{6}: rebase: Start of rebase

# 2. Reset your branch to the desired pre-rebase commit
git reset --hard <commit-hash-before-rebase>

Explanation: A git rebase operation rewrites your branch’s history by creating new commits. If the rebase was unsuccessful (e.g., due to conflicts, incorrect base, or accidentally skipping steps), you need to revert your branch’s HEAD pointer to its state before the rebase began. git reflog is important here as it records the state of your HEAD at different points in time. By checking the reflog entries for rebase or checkout operations related to your branch, you can identify the commit hash that represents the branch’s state prior to the problematic rebase. A subsequent git reset --hard to that commit will effectively undo the rebase, returning your branch to its previous state.

Notes/Warnings:

  • DANGER: git reset --hard will discard all local changes in your working directory and staging area.
  • This operation should only be performed locally. Never undo a pushed rebase this way without extreme caution and coordination with your team, as it rewrites history and will cause major issues for your team members.

Scenario 4: Renaming a Local Branch

Question: How do I rename a local Git branch if I made a typo or want to change its name?

Answer: Renaming a local branch is a straightforward process using the git branch -m command.

Code:

# If you are currently on the branch you want to rename:
git branch -m <new-branch-name>

# If you are on a different branch and want to rename another local branch:
git branch -m <old-branch-name> <new-branch-name>

Explanation: The git branch -m command is used for “move” or “rename” a branch. If you are currently on the branch you wish to rename, you only need to provide the new name. If you are on a different branch, you must specify both the old and new names for the branch you want to rename. This command only modifies the branch name in your local repository.

Notes/Warnings:

  • This command only renames the local branch. To rename the corresponding remote branch, you’ll need additional steps (see Scenario 7).
  • Ensure you are not on the branch you are renaming when using the git branch -m <old> <new> syntax.

Scenario 5: Deleting a Remote Branch

Question: How do I delete a branch from the remote repository that was created by mistake or is no longer needed?

Answer: You can delete a remote branch using git push with the --delete flag or a shorthand syntax.

Code:

# Using the --delete flag (recommended for clarity):
git push origin --delete <branch-name>

# Using the shorthand syntax (older but common):
git push origin :<branch-name>

Explanation: When you use git push origin --delete <branch-name>, you are explicitly instructing Git to remove the specified branch from the origin remote. The shorthand git push origin :<branch-name> is equivalent and effectively means “push nothing from my local empty reference to the remote branch <branch-name>,” which results in its deletion. This action will permanently remove the branch from the remote server.

Notes/Warnings:

  • Deleting a remote branch is permanent and affects all collaborators.
  • Ensure the branch is truly no longer needed before deleting.
  • If the branch is protected on the remote server, you might not have the necessary permissions to delete it.

Scenario 6: Renaming a Remote Branch

Question: How do I rename a remote branch after I have already renamed it locally?

Answer: Renaming a remote branch involves a sequence of steps: first, renaming your local branch, then deleting the old branch from the remote, and finally pushing your newly named local branch to the remote.

Code:

# Assume you have already renamed your local branch (e.g., using 'git branch -m old-name new-name')

# 1. Delete the old branch from the remote:
git push origin --delete <old-remote-branch-name>

# 2. Push your newly named local branch to the remote:
git push origin <new-local-branch-name>

# 3. (Optional but recommended) Set the upstream tracking for your new local branch:
git push origin -u <new-local-branch-name>

Explanation: Git does not have a single command to directly “rename” a remote branch. The typical workflow is to treat it as a deletion of the old remote branch followed by the creation of a new remote branch with the desired name. After renaming your local branch, you push to delete the old remote reference and then push the new local branch to establish it on the remote. The git push origin -u <new-local-branch-name> command is important for setting up the upstream tracking, so future git pull and git push commands on your local new branch correctly interact with its remote counterpart.

Notes/Warnings:

  • This operation affects the remote repository and potentially other collaborators.
  • If collaborators are working on the old remote branch name, they will need to update their local references (git fetch --prune and then re-checkout or re-track the new branch).
  • Ensure you have the necessary permissions to delete and create branches on the remote.

Scenario 7: Recovering a Deleted Remote Branch

Question: How do I recover a remote branch that was accidentally deleted from the remote repository?

Answer: If you or a team member still has an up-to-date local copy of the deleted remote branch, you can simply push that local branch back to the remote to recreate it.

Code:

# 1. Ensure you have the local branch that corresponds to the deleted remote branch.
#    If not, you might need to find it using git reflog or ask a teammate who has it.
git checkout <local-branch-name-corresponding-to-deleted-remote>

# 2. Push your local branch to the remote, which will recreate the branch there.
git push origin <local-branch-name-corresponding-to-deleted-remote>

Explanation: When a remote branch is deleted, Git only removes the remote reference to that branch. The actual commit objects it pointed to are still in the repository, and if you or a collaborator still have a local copy of that branch, its commit history is preserved locally. By executing git push origin <local-branch-name>, you are effectively telling the remote to create a new branch reference with that name, pointing to the same commit history as your local branch.

Notes/Warnings:

  • This method only works if a local copy of the branch still exists somewhere.
  • If no local copy exists, recovery becomes significantly more complex, potentially requiring server-side access to Git’s “reflog” or backups.
  • Ensure your local copy is indeed the correct and desired state of the branch before pushing.

Summary

ScenarioProblemPrimary Command(s)Impact/ScopeWarnings/Notes
Recovering Deleted Local BranchAccidentally deleted a local branch.git reflog, git branchRecovers local branch pointer; no remote impact.reflog entries expire; must find last commit hash.
Undoing Local MergeMerged wrong branch locally.git reset --hardRewinds local branch history; discards subsequent commits and working directory changes.DANGER: Destructive; discards uncommitted work. Only for unpushed merges.
Undoing Local RebaseRebase went wrong locally (e.g., messy).git reflog, git reset --hardRewinds local branch history; discards rebased commits and working directory changes.DANGER: Destructive; discards uncommitted work. Only for unpushed rebases.
Renaming Local BranchLocal branch name typo.git branch -mChanges local branch name only.Does not affect remote branch.
Deleting Remote BranchRemote branch is no longer needed.git push origin --deleteRemoves branch from remote repository.Permanent deletion; affects all collaborators; requires remote permissions.
Renaming Remote BranchRemote branch name typo.git push origin --delete, git push origin <new>, git push origin -u <new>Deletes old remote branch, pushes new local branch to create new remote branch. Affects remote repository and collaborators.Requires remote permissions; collaborators need to update their references.
Recovering Deleted Remote BranchRemote branch accidentally deleted.git push origin <local-branch>Recreates the remote branch from an existing local copy.Only works if a local copy exists; ensure local copy is correct.

Reference

Related Items

Author

Debjeet Bhowmik

Experienced Cloud & DevOps Engineer with hands-on experience in AWS, GCP, Terraform, Ansible, ELK, Docker, Git, GitLab, Python, PowerShell, Shell, and theoretical knowledge on Azure, Kubernetes & Jenkins.
In my free time, I write blogs on ckdbtech.com

Leave a Comment