38 | Erasing Commits |
You can tell Git to erase commits. This is contradictory to most version control systems, but you can treat any commit that you haven’t already shared with the rest of the world as something that can be adjusted as necessary.
A word of caution before we get into specifics, though. Don’t delete commits that you’ve shared without a very good reason. Deleting commits causes the history to be rewritten, causing the ripple effect problems like a git rebase. If you’ve shared commits, your best bet is git revert (see Task 36, Reverting Commits).
You can use git rebase a couple of different ways to handle deletes. First, you can add the -i parameter to go into an interactive rebase. Once launched, delete the line (or lines) for the commit you don’t want to keep, save and exit the editor, and you’re off.
Second, you can use --onto to tell Git to rebase onto the commit you want to get rid of. You must specify three parameters: first, you specify the commit you want to start on (the commit before the commit you want to delete); second, you specify the commit before the one you want to start at again; third, you specify the final commit you want available.
Dissecting the command from the opposite page, you’re telling Git you want to rebase HEAD (HEAD^ through HEAD, or the last commit) onto c2d2245.
You can also use git reset to remove any number of the latest commits off the end of your repository. You can use --hard to remove the changes from both your index and your working tree, but be careful. This deletes any changes you have in your working tree. git stash (see Task 26, Temporarily Hiding Changes) is a good idea if you have changes you want to hang on to.
Remember, you can always use git reflog (see Task 40, Retrieving “Lost” Commits) if one of these commands goes awry. Be mindful of your working tree, though. It warrants repeating: git reset --hard deletes uncommitted changes from your working tree, and those uncommitted changes can’t be retrieved.
What To Do... |
| prompt> git rebase -i <commit to erase>^ |
For example, to erase commit c2d2245, use this:
| prompt> git rebase -i c2d2245^ |
| ... launches editor ... |
Delete the line that contains the c2d2245 commit, and then save and exit the editor so git rebase can run.
For example, imagine these commits in your repository:
| c2d2245 |
| / 2245d2c |
| / / |
| o--o--o--o |
| |
| HEAD |
| 224cd25 |
Use the following to delete commits 224cd25 and 2245d2c:
| prompt> git rebase --onto c2d2245 HEAD^ HEAD |
| First, rewinding head to replay your work on top of it... |
| Applying: add API object for interacting with remote API |
And after the rebase is successful, the branch looks like this:
| c2d2245 |
| / |
| o--o |
| |
| HEAD |
| prompt> git reset --hard HEAD^ |
Task 16, Rewriting History by Rebasing
Task 36, Reverting Commits
Task 40, Retrieving “Lost” Commits
3.145.101.81