These days Git is the standard version control system, though a little bit advanced topics like to remove commits from a branch might be a question some developers. With git and a few commands you can undo changes and modify the commit history. This is especially useful when you need to remove a commit from a branch after it has been pushed to a remote repository. In this blog post, we will explore the different methods you can use to remove a commit from a branch after it has been pushed. We will cover step-by-step instructions for each method, as well as some best practices and potential pitfalls to watch out for. Whether you’re a beginner or an experienced Git user, this post will help you confidently manage your Git commit history and keep your codebase organized.
Imagine we have branch with following this commit history:
(init:8dea3ce)----(a:8d1a72)----(b:f661dc6)----(c:6d6407f)----(d:ecc4432)
Code language: Bash (bash)
Remove n last commits from branch after push
One situation that may arise is the need to remove the n last commits from a branch after they have already been pushed to a remote repository. This can happen if changes were accidentally committed, or if a branch was merged prematurely, and it’s necessary to undo those changes.
Step 1: back up
Checkout the branch from which you want to remove the commits, and create a new branch from the current branch as a backup.
git checkout [branch-name]
git branch [backup-branch-name]
Code language: CSS (css)
Step 2: Reset to state you want to be
Reset the branch to the commit just before the ones you want to remove using the command:
# This will remove the last 2 commits from the branch's history
git reset --hard HEAD~2
# Alternatively you can use the commit-hash you want to reset to
git reset --hard f661dc6
# your branch looks like this now
# (init:8dea3ce)----(a:8d1a72)----(b:f661dc6)
Code language: Bash (bash)
Step 3: push changes to origin (server if you call it)
Force push the updated branch to the origin using:
git push origin <branch-name> --force
Code language: Bash (bash)
This is necessary because the branch’s history has changed and you want to overwrite the remote branch with your updated branch.
Step 4: team members update
If other people are working on the same branch, you should communicate the changes you made to them, as they will also need to update their local branches.
For other team members ,to get a branch in their local repository to be exactly the same as the remote origin branch, they can use the following command (this their local commits on the branch is going to be deleted):
git fetch origin
git reset --hard origin/branch-name
Code language: Bash (bash)
Remove specific commits from branch middle of the branch after push (clean way)
To remove specific commits from a Git branch after they have been pushed to a remote repository, the most commonly used and safest method is to revert the commits. Reverting creates a new commit that undoes the changes made in the specified commit, keeping a record of the undo action. Note that you might not like this extra commits but this why the rest of your team does not need to anything.
Here’s how to regenerate a branch focusing only on reverting commits:
Identify the commit to revert: Use the Git log command to identify the commit that you want to revert. The commit hash or message can be used to reference the commit. (let’s revert commit b of example above)
Revert the commit: Use the Git revert command to create a new commit that undoes the changes made in the specified commit. The command is as follows:
git revert -i <commit-hash>
# example revert commit b:
git revert f661dc6
# your branch looks like this now
#(init:8dea3ce)----(a:8d1a72)----(b:f661dc6)----(c:6d6407f)----(d:ecc4432)----(revert:a1b2c3d)
Code language: Bash (bash)
This will create a new commit that undoes the changes made.
Push the changes: After reverting the commits, push the changes to the remote repository using the Git push command
Revert multiple commits
If you want to revert multiple commits, you can use the following command:
git revert <start-commit>..<end-commit>
Code language: Bash (bash)
Remove specific commits from branch middle of the branch after push (dirty way)
Sometimes you want some commits to be removed from branch history as if it never happened .To remove specific commits in the middle of a Git branch without creating a new commit, you can use Git’s interactive rebase feature. Interactive rebase allows you to modify the branch history by selectively editing, deleting, or combining commits. Here’s how to remove commits in the middle of a branch without creating a new commit:
Identify the commits to remove: Use the Git log command to identify the commits th
at you want to remove. Note down the commit hashes or messages.
Start interactive rebase: Use the Git rebase command with the -i or –interactive option to start interactive rebase. The command is as follows:
git rebase -i <commit-hash>
# example rebase commit b:
git rebase -i 8d1a72
Code language: Bash (bash)
This will open a text editor displaying a list of the branch’s commits from the specified commit to the current one.
pick f661dc6 b
pick 6d6407f c
pick ecc4432 d
# Rebase 8d1a72d..ecc4432 onto 8d1a72d (3 commands)
#
# Commands:
# p, pick <commit> = use commit
# r, reword <commit> = use commit, but edit the commit message
# e, edit <commit> = use commit, but stop for amending
# s, squash <commit> = use commit, but meld into previous commit
# f, fixup [-C | -c] <commit> = like "squash" but keep only the previous
# commit's log message, unless -C is used, in which case
# keep only this commit's message; -c is same as -C but
# opens the editor
# x, exec <command> = run command (the rest of the line) using shell
# b, break = stop here (continue rebase later with 'git rebase --continue')
# d, drop <commit> = remove commit
# l, label <label> = label current HEAD with a name
# t, reset <label> = reset HEAD to a label
# m, merge [-C <commit> | -c <commit>] <label> [# <oneline>]
# . create a merge commit using the original merge commit's
# . message (or the oneline, if no original merge commit was
# . specified); use -c <commit> to reword the commit message
#
# These lines can be re-ordered; they are executed from top to bottom.
#
# If you remove a line here THAT COMMIT WILL BE LOST.
#
# However, if you remove everything, the rebase will be aborted.
#
Code language: Bash (bash)
Above most likely opens in vim editor, if you are new to it, it would be an extra complication in addition to rebasing. It is important not to panic and read all commands, as well as get familiar with basics of vim editor (understanding two modes of Command and Insert and how to save and exit :wq! while in command mode).
If at the middle of rebase you found things are not going your way you can always exit the rebase mode and try again.
git rebase --abort
Code language: Bash (bash)
Delete the commits: In the editor, locate the commits that you want to delete and delete their corresponding lines. Save and close the editor. I want to remove commit b then I edit the text and use drop for that commit
drop f661dc6 b
pick 6d6407f c
pick ecc4432 d
Code language: Bash (bash)
Merge conflict: There is a good chance that you end up with merge conflicts when you drop one or few commits
Resolve all conflicts manually, mark them as resolved with
“git add/rm “, then run :
git rebase --continue
Code language: Bash (bash)
You keep doing it until the rebase is completed. Git will now apply the changes and remove the selected commits from the branch history. Verify that the branch history has been updated as expected. your branch should look like this :
(init:8dea3ce)----(a:8d1a72)----(c:6d6407f)----(d:ecc4432)
Code language: Bash (bash)
Push the changes: After completing the rebase, push the changes to the remote repository using the Git push command. The command is as follows:
git push <remote> <branch-name> --force
Code language: Bash (bash)
If other people are working on the same branch, you should communicate the changes you made to them, as they will also need to update their local branches.
For other team members ,to get a branch in their local repository to be exactly the same as the remote origin branch, they can use the following command (this their local commits on the branch is going to be deleted):
git fetch origin
git reset --hard origin/branch-name
Code language: Bash (bash)
Conclusion
In Git, there are several ways to remove commits from a branch, including reset, revert, and rebase. While all three methods achieve similar outcomes, they differ in their approach to removing commits, and understanding the differences is essential to selecting the right approach for the task at hand.
Reset removes commits by resetting the branch to a previous commit, permanently discarding any changes made in the removed commits. This method is useful when the commits to remove are the most recent ones and the changes they introduced are no longer needed. However, reset should be used with caution, as it is something everyone using the branch should be aware of and act on it.
Revert removes commits by creating a new commit that undoes the changes introduced in the removed commit, while still keeping a record of the removed commit. This method is useful when you want to remove commits without losing the changes they introduced, such as when the changes are no longer needed, or when the removed commits are part of a shared branch, and their deletion may affect other team members’ work.
Rebase rewrites the history of the branch, in this case by applying changes from the removed commits and excluding the commits themselves. This method is useful when the commits to remove are scattered throughout the branch history and not the most recent ones. Rebase allows you to selectively edit, delete, or combine commits in the branch’s history, without creating a new commit, making it a powerful tool for managing branch history. But again everybody who uses the branch should be aware of it and update their branch accordingly.
Leave a Reply