Git rebase -I is not that scary

birdculture1 pts0 comments

git rebase -i is not that scary — akrm al-hakimi ← journal

one of the most shocking things i've encountered in my early career as a junior dev is the fear surrounding git rebase -i.

even amongst some of my co-workers, who are in many ways, magnitudes smarter than i am, it seems to be a pattern<br>in a lot of devs to be afraid of this command.

what it actually does<br>when you run:<br>git rebase -i HEAD~4<br>git does something delightfully mundane: it opens a text file. if you are working out of the terminal and haven't fiddled around with your git settings, git config --global core.editor "_YOUR-EDITOR_"<br>is a good way to allay your fears of conquering vim.<br>pick a1b2c3d Add user model<br>pick e4f5g6h Fix typo in user model<br>pick i7j8k9l Add login endpoint<br>pick m0n1o2p WIP debugging login

# Commands:<br># p, pick = use commit<br># r, reword = use commit, but edit the commit message<br># s, squash = use commit, but meld into previous commit<br># f, fixup = like "squash" but discard this commit's message<br># d, drop = remove commit<br>a worthy thing to note here for new rebasers is that this is a plan, not an action. nothing has technically happened yet, aside from the fact a rebase has begun.<br>if you change your mind, you just run git rebase --abort and either restart or give up (ideally the former).

each line is an instruction, in which a replaying of the commit you target is commenced. you may mix and match these instructions to your liking.

r a1b2c3d Add user model<br>pick e4f5g6h Fix typo in user model<br>pick i7j8k9l Add login endpoint<br>d m0n1o2p WIP debugging login

# Commands:<br># p, pick = use commit<br># r, reword = use commit, but edit the commit message<br># s, squash = use commit, but meld into previous commit<br># f, fixup = like "squash" but discard this commit's message<br># d, drop = remove commit what happened here:

1. in this example, git is going to 'pause' on the first commit, allowing you to reword its message.

2. d or a drop deletes the WIP debugging commit entirely. this same result can be achieved by simply deleting the line entirely.

the middle two commits were untouched, despite us mutating the surrounding commits. the end result is 3 total commits instead of 4.

honestly, that's it. it's not a big fucking deal. if you can internalize what that example does, interactive rebasing becomes a tool that will make your life easier, not harder.

there's a common thing among people as well that love to undermine the purpose of interactive rebasing. without getting into those<br>arguments, i will just openly say: in my opinion, if you don't care about a clean branch history (a tiny fraction of the improvement rebasing provides) than i am more inclined to<br>be skeptical of how serious you are about your software.

"but what if i mess it up?"<br>it is very hard to actually lose work here, for three reasons.<br>you can bail out at any time. as aforementioned with git rebase --abort<br>your branch snaps back to exactly where it was before you started..<br>rebase doesn't destroy commits — it makes new ones. this is the key mental model. rebase<br>doesn't edit your old commits; it creates new ones and just moves your branch pointer to them. the old commits<br>still exist in git's object database, unreferenced but intact,<br>for some amount of time before garbage collections comes in.

the reflog remembers everything. this was especially important for me to understand when i wiped one of my co-workers branches history in my first internship<br>thinking they wanted to drop previous commits they had made. git keeps a journal of everywhere your branch has pointed:

git reflog find the entry from before the rebase and restore it:<br>git reset --hard HEAD@{4}<br>the entire rebase is undone. this safety net is always there, which means the worst realistic outcome of a<br>botched rebase is a few minutes of you perusing through the reflog.

and if even the reflog feels too daunting (though if you've made it this far into my post, i would hope you are competent enough to handle it), there's of course, the low-tech insurance policy:<br>git branch backup-before-rebase<br>now the pre-rebase state has a name. if anything goes wrong,<br>git reset --hard backup-before-rebase and you're home safe.

conflicts

sometimes a replayed commit conflicts with an earlier change (usually when reordering, or when rebasing<br>onto an updated main). git stops and literally prints the instructions: resolve the conflict like you<br>would a merge conflict, git add the files, then git rebase --continue.

i think that this is probably what annoys people the most. but conflicts are not a new concept to git. in fact i would argue that<br>in the context of interactive rebasing, conflicts are actually easier to resolve than in a merge. this is because you are only dealing with one commit at a time, and not the entire branch.

obligatory warning

as with literally anything in software, you should take great care and effort to understand what you are doing, especially with something destructive like rebasing.<br>yes, work can be recovered but...

commit rebase pick commits rebasing branch

Related Articles