This topic describes how to roll back code after an unexpected merge or commit introduces unwanted changes.
Common Git commands
Git provides two commands for recovery: revert and reset. Because they have different effects, choose the command that best suits your needs based on the descriptions below.
revert
Rolling back a specific commit with this method is a merge operation that preserves all other commits and does not require a force push to the remote.
reset
When you roll back to a specific commit, all subsequent commits are completely removed from the commit history, and a force push to the remote repository is required.
Common reset commands:
git reset --hard HEAD^ # Roll back to the previous version
git reset --hard HEAD^^ # Roll back two versions
git reset --hard HEAD~3 # Roll back three commits. You can use ~n to roll back n commits.
git reset --hard <commitID> # Reset to a specific commitYou must then use a force push to update the remote repository.
A force push overwrites the commit history on the remote repository. This data cannot be recovered.
When to use a force overwrite
Errors can occur when you push or merge a branch. For example:
You accidentally use a force push when your local branch is behind the remote branch, causing the remote branch to roll back to an older version.
You use a force push to overwrite the remote branch after your local branch has diverged from it.
You merge an unapproved code review, adding unreviewed commits to the target branch.
In these cases, you typically need to force overwrite the target branch. This operation restores the target branch to a previous version and discards all the incorrectly merged commits.
The scenarios described below discard the incorrect commit history. If you need to preserve these commits, use the revert command described earlier.
Restore a branch to a newer version
Use this method when a remote branch is accidentally rolled back to an older version and you need to restore it to a more recent one.
This can happen when a developer's local branch falls behind the remote branch. If they perform a force push, their older local version overwrites the remote branch, causing other developers' commits to be lost.
The following example shows how to restore a corrupted main branch.
Step 1: Find the correct version
Find the most recent correct version in the activity feed: Go to the Activity page of your code repository. In the push history, find the last valid push to the branch you want to restore. For this example, we will use the main branch.
The activity feed usually flags force push events. You can use this record to see how the branch was changed. In this example, a force push overwrote the branch with commit add6fcd3. By looking further back in the activity history, you can find the most recent normal push. The commit ID from that push, 79b769, is the version you need to restore.
Step 2: Restore the branch with a force push
Once you have the target commit ID, you can restore the branch.
If the commit you want to restore has become a dangling commit, the server may not be able to recover it due to Git's garbage collection mechanism. If this happens, the server no longer has a record of the commit, and you must find it in a local repository.
What is a dangling commit?
If a commit is not associated with any reference, it is a dangling commit. For example, a commit with the ID 79b7691d3e3b6ca19bb8f4f6c76023443735362c once existed only on the master branch. If you reset the master branch to a previous commit, this commit is no longer associated with any reference and becomes a dangling commit. You can use git fsck --dangling --no-reflogs to display the dangling commits in the current repository.
Why are dangling commits garbage collected?
When a server accumulates many loose objects, Git's garbage collection (gc) process compresses them to reduce storage and improve performance. Dangling commits, which are unreachable from any reference, are considered disposable. The server automatically deletes them after a certain period, and they are also removed when garbage collection is triggered manually.
In the example above, we need to restore the main branch to commit 79b7691d3e3b6ca19bb8f4f6c76023443735362c.
If a local repository still contains the commit, create a new branch from it and use that branch to force overwrite the remote branch. Run the following commands:
# Create a new branch named main-recover from the target commit git checkout 79b7691d3e3b6ca19bb8f4f6c76023443735362c -b main-recover # Use the main-recover branch to overwrite the remote main branch git push --force origin main-recover:mainIf no local repository has the commit, but the server has not yet garbage-collected the object, you can create a new branch from that commit on the server and then recover it. Follow these steps:
In Codeup, go to the Branches page and click New. In the branch name field, enter a custom name, such as
main-recover. In the Source field, enter the target commit ID:79b7691d3e3b6ca19bb8f4f6c76023443735362c.Pull the
main-recoverbranch to your local machine and use it to force overwrite the remotemainbranch:# Fetch the remote main-recover branch to your local machine git fetch origin main-recover:main-recover # Locally, verify that main-recover is the version you want to restore git log main-recover # Overwrite the remote main branch with the main-recover branch git push --force origin main-recover:mainAfter these steps, the
main-recoverbranch overwrites themainbranch, restoring it to the desired state. All incorrect commits added after the restored version are discarded.
Restore a branch to an older version
You may need to overwrite a branch to an older version when unexpected content is merged into a remote branch. For example, a developer might push commits directly to the main branch from their local machine if push rules are not configured. Another case is when a code review is mistakenly merged, requiring the target branch to be rolled back.
This process is relatively simple because you are typically rolling back newly added content. The commit you want to restore to is still part of the branch's history, so you just need to find the correct commit ID.
You can find the target commit ID by asking your team or by checking the Codeup Activity page.
For example, to roll back the main branch to commit add6fcd3efb163349cba4b4cc8fdfefe49befb6d, run the following commands:
# If your local branch is already synced with the corrupted remote, you can reset it directly
git reset --hard add6fcd3efb163349cba4b4cc8fdfefe49befb6d
# Use the corrected local main branch to overwrite the remote branch
git push --force origin main:main
# If your local branch contains your own work, create a new recovery branch instead
git checkout add6fcd3efb163349cba4b4cc8fdfefe49befb6d -b main-recover
# Then, use the recovery branch to overwrite the remote branch
git push --force origin main-recover:mainRestore a deleted branch
If a branch is accidentally deleted, you can restore it by finding its last commit ID. The recovery process is similar to previous scenarios because it relies on locating a specific commit.
On the Codeup Activity page, find the last commit ID of the deleted branch. For example, if the
devbranch was deleted, its last commit waseba83265a7096d656f582161e4e42010bb4b89f7.Recreate the branch from the commit ID
eba83265a7096d656f582161e4e42010bb4b89f7:In the branch name field, enter
dev, and then click OK to create the branch.