🧙♂️ Git sorcery
- Published on
It was a fine Friday afternoon. I was working on a feature ticket, clacking away on my keyboard. The feature was pretty simple to implement. I had fleshed out the implementation on a whiteboard, and I was done coding in under an hour.
I complete the feature and then test it. Everything works, great! Let's commit and push.
git commit -m "feat(its-alive): the monster is stirring"
git push
Enumerating objects: 5, done.
Counting objects: 100% (5/5), done.
Delta compression using up to 12 threads
Compressing objects: 100% (3/3), done.
Writing objects: 100% (3/3), 305 bytes | 305.00 KiB/s, done.
Total 3 (delta 2), reused 0 (delta 0)
remote: Resolving deltas: 100% (2/2), completed with 2 local objects.
remote: error: GH006: Protected branch update failed for refs/heads/main.
remote: error: 3 of 3 required status checks are expected.
Uh-oh! I forgot to switch to a feature branch. All my commits are now on main
.
Well, thankfully Git is forgiving.
Moving to an existing branch
If I had an existing local branch, all I need to do is:
- checkout the branch
git checkout feature-frankenstein
- merge with
main
git merge main
- remove the commits from
main
git checkout main
git branch -f main HEAD~3 # make master point to some older commit
- continue the work on existing branch
git checkout feature-frankenstein
Moving to a new branch
In this particular scenario, I did not have an existing local branch. So I had to create one.
- create a new branch, from
main
git branch feature-frankenstein
- remove the commits from
main
git checkout main
git branch -f main HEAD~3 # make master point to some older commit
- continue the work on the newly created branch
git checkout feature-frankenstein
Alternatively, there's git reset --hard <commit-id>
instead of git branch -f
, to reset to a particular commit id. Use this with caution because, if you don't merge your changes first, they will be lost.
Another one with Stash
Using git reset HEAD~n
we can undo the last n
commits (and their messages) to main
, yet leave all working files intact. Then we can stash away all the working file changes, switch to a new branch, and pop the stash.
git reset HEAD~3
git stash
git checkout -b feature-frankenstein # git branch create && git checkout branch
git stash pop
When to use this?
- If your primary purpose is to roll back master
- You want to keep file changes
- You don't care about the messages on the mistaken commits
- You haven't pushed yet
- You want this to be easy to memorize
- You don't want complications like temporary/new branches, finding and copying commit hashes, and other headaches
It doesn't preserve the mistaken commit messages, so you'll need to add a new commit message to this new commit. (getting this should be easy by using command history)