Working on a group project in Git, I did the smart thing with my code. I made a branch and proceeded to edit my files. I also did a dumb thing. I made four commits.
The first was for the first, ugly, functional version of the code. The second was a less ugly, kind of broken version. The third was the rewrite and the fourth was the working version. When I wanted to submit my changes for a review, it was going to be ugly. I did not need or want people looking at four commits They only wanted the one.
Now I’m a weird person for how I do commits. I add a new feature like a new function to parse things, and I commit that. Then I change my CSS and commit that. And so on and so on. This means I can look through my commit history and see exactly when I made a change. When I’m ready to do my release, I document all the changes based on that commit log and have it as my message.
But when you’re working with a team, and all they want is one clean commit? Well I’m their worst nightmare. There is a cure for this, though! You can squash your commits, merging them all into one.
Actually it’s rebase. It can be squash too, though. I ran the following command which says to rebase my last 4 commits:
git rebase -i HEAD~4
That opens up another editor
pick b17617p Crap I need to do this thing! pick 122hdla Added feature HUMAN to autogenerate a humans.txt file pick nw9v88a Changed comment avatar size to 96px pick 8jsdy1m Updated CSS for comment avatars to make them a circle # Rebase b17617p..8jsdy1m onto b17617p # # 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. #
Now here’s where it’s weird. The first one,
b17617p is the one I have to merge everything into. And it has the worst commit message, doesn’t it? Oh and I was totally not using the right formatting for how the company wants me to format my commits. They want the comment to be “Feature: Change” so I would have “Humans: Added new feature to autogenerate humans.txt”
Since I knew I wanted to merge it all and totally rewrite the commit, I just did this:
pick b17617p Crap I need to do this thing! squash 122hdla Added feature HUMAN to autogenerate a humans.txt file squash nw9v88a Changed comment avatar size to 96px squash 8jsdy1m Updated CSS for comment avatars to make them a circle
Which, once saved and exited, gave me this:
# This is a combination of 4 commits. # The first commit's message is: Crap I need to do this thing! # This is the 2nd commit message: Added feature HUMAN to autogenerate a humans.txt file # This is the 3rd commit message: Changed comment avatar size to 96px # This is the 4th commit message: Updated CSS for comment avatars to make them a circle # Please enter the commit message for your changes. Lines starting # with '#' will be ignored, and an empty message aborts the commit. # Explicit paths specified without -i nor -o; assuming --only paths... # Not currently on any branch. # Changes to be committed: # (use "git reset HEAD <file>..." to unstage) # # new file: LICENSE # modified: README.textile # modified: Rakefile # modified: bin/jekyll #
Since everything with a
# is ignored, I deleted it and made it this:
Humans: New Feature -- Humans.txt is now autogenerated Comments: Changed avatar size to 96px and edited CSS to make it a circle
Yeah, that’s it. Admittedly, these should be two separate changes, but they’re all a part of the same project in this case so it’s okay.
Of course, at the end of this, I looked at my code on our web tool and swore, because I’d left a debug line in. My hero Mike said “Don’t worry! ammend!”
I made my change, instead of a normal
git commit -a -m "These are my changes" I ran a
git add FILENAME and
git commit --ammend to fix up your most recent commit.
It lets you combine staged changes with the previous commit instead of committing it as an entirely new snapshot. It can also be used to simply edit the previous commit message without changing its snapshot.
And yes, it’s pretty awesome. Use it wisely.