git-rebase-i-playground
git-rebase-i-playground copied to clipboard
A playground/lab to test different use cases of git rebase -i
Learn "git rebase -i" with this lab/playground
Want to learn how to properly use git rebase -i (also known as an interactive rebase) without putting your production
repo at risk? You're in the right place! The script included in this repo will create
a git repo (with 2 cloned copies) that has synthetic checkins and branches. It makes
for an ideal testing ground to experiment with git rebase -i without going insane.
Getting Started
- Clone this repo:
git clone [email protected]:dmuth/git-rebase-i-playground.git cd git-rebase-i-playground./init.sh- Stand up a set of Git repos with some nested branches./init-with-feature-branches.sh- Stand up a set of Git repos with multiple feature branches./git-config.sh- Run this to set the following aliases:
st,ci,co, andlg. These will make for less typing and easier viewing of logs.
- Run this to set the following aliases:
This will create the following repo and directories, each with about a dozen commits:
dev-1alice- A clone of the repo made by "Alice", with two branches:branch1andbranch2.branch1is a branch from main whilebranch2is based onbranch1. That is by design (and is based on a True Story, heh).dev-2bob- A clone of the repo made by Alice's co-worker "Bob", only containingmain.repo.git- A "bare" clone of the repo. Note that if youcdto this directory, commands likegit log --pretty=onelinewill work just fine. That is useful for debugging.
NOTE: Running init.sh will remove those directories if they already exist. This is so that you can have a "clean slate" every time you run the script.
The tree looks like this:
Why would you want to use git rebase -i?
Running git rebase -i commit_id will bring up recent commits in the system editor and allow
you to reorder the commits, edit the commit message, or even delete commits.
Why would you want to delete a commit? Probably the most common reason is that you made many commits to a feature branch that you would like to squash into a single commit. Or perhaps you made a feature branch based on another branch, and want to deploy the changes from that feature branch but not the branch it's based on. (Happened to me once!)
Any caveats?
Anytime you rebase, you are rewriting history. If you changes have already been pushed, you will need to push them again, and history will be overwritten. If other users have already checked out the branch in question, this will cause a merge on their end, which will (eventually) wind up on the server's repo, and in your repo. It will make the commit history just slightly uglier.
Exercises
Once that you have the repos set up, here are some sample exercises to try (answers below) in dev1-alice:
- Switch the order of commits
04-fourthand05-fifth - Merge the changes of
branch2intomainbut NOT the changes ofbranch1 - Squash the two commits in
branch1then push toorigin - Switch the order of commits
04-fourth and 05-fifth, push toorigin - Switch the order of commits
01-first-will-conflictand02-second-will-conflict, THEN push toorigin - Run
git rebase -iand delete commit04-fourth. Then recover it. - Switch the order of commits
01-first-will-conflictand02-second-will-conflict
Hints
Here are some hints to lead you in the right direction but without fully giving away the solution
- Switch the order of commits
04-fourthand05-fifth- Make sure you are going far enough back in the revision history...
- Merge the changes of
branch2intomainbut NOT the changes ofbranch1- You'll need to remove some commits...
- Squash the two commits in
branch1then push toorigin- You'll need to overwrite what's already there...
- Switch the order of commits
04-fourth and 05-fifth, push toorigin- There's more than one way to do this
- Switch the order of commits
01-first-will-conflictand02-second-will-conflict, THEN push toorigin- You'll need to handle a merge conflict AND overwrite history in the origin...
- Run
git rebase -iand delete commit04-fourth. Then recover it.- The commit wasn't technically deleted...
- Switch the order of commits
01-first-will-conflictand02-second-will-conflict- You're going to have to resolve that merge conflict...
Troubleshooting
If things go wrong, here are some suggestions:
- First, the nuclear option:
./init.sh- This will reset your Git repo to the initial state. Useful for if you've gone down a hole and you just want to start over. - Running
git statusat any time will not harm you, and will provide you with some useful info and what you need to do next. git rebase --abortwill back out of the current rebase.git log --pretty=oneline --graph- Will print a listing of commits in the current branch.git log --pretty=oneline --graph --all- Will print a listing of commits across all branches, and show which branches are based on what commits.- The
tigtool available at https://github.com/jonas/tig is super useful for browsing the commit history of a branch
Solutions
Solutions can be found here.
FAQ
Q: What's the story with Alice and Bob?
A: Alice and Bob are used as placeholder names in cryptology, science, and engineering literature: https://en.wikipedia.org/wiki/Alice_and_Bob I find using the names to be useful because then I don't have to focus on the underlying details quite as much.
Additional Resources
- https://www.atlassian.com/git/tutorials/rewriting-history/git-rebase
- https://thoughtbot.com/blog/git-interactive-rebase-squash-amend-rewriting-history
- https://git-scm.com/docs/git-rebase
- https://git-scm.com/book/en/v2/Git-Tools-Rewriting-History
- https://www.dmuth.org/howto-safely-use-git-rebase-i/ - My blog post on this topic
- http://gitready.com/advanced/2009/01/17/restoring-lost-commits.html
- http://effectif.com/git/recovering-lost-git-commits
- http://gitready.com/intermediate/2009/02/09/reflog-your-safety-net.html
TODO
- I want to make some simple/slides graphs that show the state of the Git tree for some of the exercises
Contact
My email is [email protected]. I am also @dmuth on Twitter and Facebook! Additional ways to find me are on my website.