git commit --amend

By Will Braynen

Scenario. You saved your work by “doing a commit”, but then you realized you would like to make changes to it.

Alternative solution. Do a new commit, then do an interactive rebase to squash your new commit with your most recent commit before that.

Solution. Amend your most recent commit!

* Jargon. Git is a tool you would use to save your work, a commit is the saving of your work, the source code is the programming instructions you would write for the computer, and a commit message is a note about the saved work that you would write for other devs or for your later self.

As far as git is concerned, a commit is composed of: (a) your source code, and (b) a commit message.* Among other things. So, when editing your last commit, you can edit either one: the source code or the commit message. Below I will show you how.

Of course many people do not use git from the command line. Instead, they often use some piece of GUI (e.g. SourceTree or Tower or GitUp), which in turn uses git under the hood. Here, however, I will only talk command line because, no matter what UI, we all have a terminal.

Modifying the source code in the most recent commit

Assuming you have not yet staged your changes: (Otherwise, just don’t git add.)

$ git add .
$ git commit --amend

The “add” stages your changes. (In case you had trouble parsing that, the word “stages” in that last sentence is a verb.) After all, you might not want to commit all your changes. Staging tells git which files (or which parts of a file) you want to save with this commit. The “commit --amend” adds your staged changes to the last commit and launches your default git editor to give you a chance to also edit the commit message.

Editing the commit message (and not the source code)

Let’s assume you have no staged changes. (And if you do, unstage them using git reset.) With nothing to commit, to change the commit message you would simply amend your last commit like so:

$ git commit --amend

This will bring up your default git editor, asking you what you want the commit message to be. Update the commit message and save-exit your editor. (I assume git commit --amend is what GitUp does under the hood when you click “Edit Message”.)

What the heck is GIT?

Git is a version-control tool. Today, knowing how to use git is essential for software development in an industry setting.

When I was in school, I would save multiple copies of the files that represented my source code, in a new folder each time, one copy per version. I would append to the folder’s name the current date and even the time of day for copies saved on the same day. That way, if I broke something, I could always “undo”: I could back up a little and restore a working version of the source code.

Then, at some point still in college, in Prof. Stark’s operating systems class, I discovered version control. Something called CVS (birth year 1990). No relation to the drug store. CVS was not only more convenient, handy commands and all, than keeping multiple copies of entire directories and files wholesale, but it was also more storage efficient. That’s because all version control needs to do really is store the diff—the thing that’s changed from one version of the file to the next—which ends up being very efficient when code changes are small compared to what does not change from version to version.

Then, already after college, I discovered newer source-control tools: Microsoft Visual SourceSafe (birth year 1994), which was integrated with Microsoft’s Visual Studio IDE, and Subversion/svn (birth year 2000). Today I use a tool called git (birth year 2005), which is essentially a semi-decentralized version of Subversion with an extra layer. The extra layer is this: in addition to a commit and a checkout (which are analogous to “saving a file” and “opening a file”), there is a push and a pull (e.g. to push the changes to a “central” server or pull them from that server instead of continuing to work with a local copy).

The action of saving something is called “a commit”. A commit is a save. The things you learn about a tool like git then are how to undo your work (“revert a commit”), how to combine your work with other people’s work (“merge branches”, “rebase a branch”, and “resolve merge conflicts”), and how to pick out a good piece of work while discarding a bunch of other work you don’t want to keep (maybe by “cherry-picking a commit”). This is all also very handy if you are trying to figure out what code change introduced a particular bug; so version control is not only good for developing new features, but also for debugging old ones.

Version control not only keeps you sane, but it also allows you to coordinate your work with that of your colleagues. In school I worked primarily by myself on pieces of code. Collaboration was called cheating or plagiarism. In a work setting, however, I typically work as part of a team. This means that the source code needs to branch, branches then need to be combined, then branched again, then combined again, and so on. For example, I work in my branch and you work in yours; or we create a branch for a new feature and then branch off that feature branch into branches for individual contributors; then, when the individual contributors have all implemented their piece of the larger feature, their changes are combined by merging them into the feature branch and the feature branch, once tested by QA/QE (Quality Assurance/Quality Engineers), merged into the release branch that will go out to real users (e.g. customers). And yes, the tree metaphor goes all the way: the whole thing is called a source tree.

It’s true, different people have different preferences and different opinions about all this. For some reason, people rarely say, “it depends”, even when they should, as if one thing is always better than another in all respects and all situations. Devs argue over “git strategies” and “git flows” and about whether “merge” is better than “rebase”, reminiscent of Editor Wars. (And yes, my default git editor is emacs.) But now you know about git and about amending a commit to either modify previously committed source code and/or to edit the message that accompanied that source code.