or “How I Learned to Stop Worrying and Love
git rebase -i”.
I’ve been working with
git in a more professional setting lately. We maintain our new cosmological code,
git now and I can’t be as lazy as I have been with other
git repos. We maintain 2 bare repos and about a dozen developers pull from us, so I like to be careful about what I push off.
Problem is, I don’t normally work that way. I like to code things quickly and try them, keeping track of changes as I go. Think “cowboy” development with very frequent commits. So, I could end up with a very messy commit history. Luckily,
git rebase comes to the rescue.
So at the end of a bout of local coding, the commit history looks something like this.
… many commits down to …
For many reasons, I cannot rebase commits already pushed to a remote, so I need to update the remote tracking branch at this point. A simple
git fetch origin master does the job. Now I can rebase off this commit and rewrite my messy history.
I find the tip of origin/master, copy the sha, and run
git rebase -i [origin sha]. I think there is simpler way to do this, like
git rebase -i origin/master, but I haven’t tried it. I like to be sure I’m rebasing off the right commit for now.
Now, my editor opens up and shows a list of the commits since then. For each commit, I have several choices. Here’s what git displays during a rebase:
# Rebase 3272740..9ef6432 onto 3272740 # # Commands: # p, pick = use commit # r, reword = use commit, but edit the commit message # e, edit = use commit, but stop for amending # s, squash = use commit, but meld into previous commit # f, fixup = like "squash", but discard this commit's log message # x, exec = run command (the rest of the line) using shell # # If you remove a line here THAT COMMIT WILL BE LOST. # However, if you remove everything, the rebase will be aborted. #
And here’s a snapshot of what I ended up with this time.
So I will squash 5 commits, reword 3 of the commit messages, and leave everything else as is.
After saving and closing the editor, git opens each commit I want to reword or squash while rebasing. I make the changes I want, and git finishes with “Successfully rebased and updated refs/heads/master”.
Now my commits show up as a single line of development off of the latest commit on origin/master.
Let’s just hope the non-sequential commit datetimes don’t confuse anyone.
Don’t forget to
git push origin master after all that.