15. Removing a commit from a branch
Goals
- Learn to delete the branch's latest commits.
Revert
is a powerful command of the previous section that allows you to cancel any commits to the repository. However, both original and cancelled commits are seen in the history of the branch (when using git log
command).
Often after a commit is already made, we realize it was a mistake. It would be nice to have an undo command which allows the incorrect commit(s) to be immediately deleted. This command would prevent the appearance of one or more unwanted commits in the git log
history.
01 The reset
command
We have already seen the reset
command and have used it to set the staging area to be consistent with a given commit (we used the HEAD
commit in our previous lesson).
When you run the reset
command along with a commit reference (HEAD
, branch or tag name, commit hash, etc.), the command will...
- Point the current branch to the specified commit.
- Optionally reset the staging area so it will comply with the specified commit.
- Optionally reset the working directory so it will match the specified commit.
02 Check our history
Let us do a quick scan of our commit history.
Run
git log
Result
$ git log
86364a1 2023-11-28 | Revert "Oops, we didn't want this commit" (HEAD -> main) [Alexander Shvets]
6a44bec 2023-11-28 | Oops, we didn't want this commit [Alexander Shvets]
b7614c1 2023-11-28 | Added HTML header (tag: v1) [Alexander Shvets]
46afaff 2023-11-28 | Added standard HTML page tags (tag: v1-beta) [Alexander Shvets]
78433de 2023-11-28 | Added h1 tag [Alexander Shvets]
5836970 2023-11-28 | Initial commit [Alexander Shvets]
We see the last two commits in this branch are "Oops" and "Revert Oops". Let us remove them with the reset
command.
03 Mark this branch first
Let us mark the last commit with tag
, so you can find it after removing a commit(s).
Run
git tag oops
Result
$ git log
86364a1 2023-11-28 | Revert "Oops, we didn't want this commit" (HEAD -> main, tag: oops) [Alexander Shvets]
6a44bec 2023-11-28 | Oops, we didn't want this commit [Alexander Shvets]
b7614c1 2023-11-28 | Added HTML header (tag: v1) [Alexander Shvets]
46afaff 2023-11-28 | Added standard HTML page tags (tag: v1-beta) [Alexander Shvets]
78433de 2023-11-28 | Added h1 tag [Alexander Shvets]
5836970 2023-11-28 | Initial commit [Alexander Shvets]
04 Reset commit to before oops
In the history log above, the commit tagged v1
is before the "Oops" and "Revert Oops" commits. Let us reset the branch to that point. As the branch has a tag, we can use the tag name in the reset
command (if it does not have a tag, we can use the hash of the commit).
Run
git reset --hard v1
git log
Result
$ git reset --hard v1
HEAD is now at b7614c1 Added HTML header
$ git log
b7614c1 2023-11-28 | Added HTML header (HEAD -> main, tag: v1) [Alexander Shvets]
46afaff 2023-11-28 | Added standard HTML page tags (tag: v1-beta) [Alexander Shvets]
78433de 2023-11-28 | Added h1 tag [Alexander Shvets]
5836970 2023-11-28 | Initial commit [Alexander Shvets]
Our main branch is pointing at commit v1
and the "Revert Oops" and "Oops" commits no longer exist in the branch. The --hard
parameter makes the working directory reflect the new branch head.
05 Nothing is ever lost
What happened to the wrong commits? They are still in the repository. Actually, we can still refer to them. At the beginning of the lesson, we created the oops
tag for the canceled commit. Let us take a look at all commits.
Run
git log --all
Result
$ git log --all
b7614c1 2023-11-28 | Added HTML header (HEAD -> main, tag: v1) [Alexander Shvets]
86364a1 2023-11-28 | Revert "Oops, we didn't want this commit" (tag: oops) [Alexander Shvets]
46afaff 2023-11-28 | Added standard HTML page tags (tag: v1-beta) [Alexander Shvets]
6a44bec 2023-11-28 | Oops, we didn't want this commit [Alexander Shvets]
78433de 2023-11-28 | Added h1 tag [Alexander Shvets]
5836970 2023-11-28 | Initial commit [Alexander Shvets]
We can see that the wrong commits are not gone. They are not listed in the main
branch anymore but still remain in the repository. They would still be in the repository if we did not tag them, but then we could reference them only by their hashes. Unreferenced commits remain in the repository until the garbage collection software is run by system.
06 Reset dangers
Resets on local branches are usually harmless. The consequences of any "accident" can be reverted by using the proper commit.
However, other users sharing the branch can be confused if the branch is shared on remote repositories.