For a lot of us, version control does two things which are contradictory:
it keeps checkpoints as we work so we can easily roll back, and
wraps up our work into a tidy package for others to use.
git commit --amend is one tool that solves this. It will “open up” the previous commit, adding staged files and allowing you to re-edit the commit message.
Make your “checkpoint” commit, e.g. with a failing spec.
Get your specs working again.
Stage your changes like you normally would using git add.
Instead of git commit, do git commit --amend.
Edit the message to describe the feature. This will be the commit’s new message, and it will contain all the changes.
A related command: git rebase -i (“interactive”). If you didn’t use --amend, you can go back and condense commits together as if you had. With this command, you can interactively rebase, using the “squash” command to combine multiple commits together.
Git is powerful, and Github is its killer app. I use them for all my projects. That being said,
Git is more difficult than it ought to be, but until now I couldn’t put my finger on why
I was doing some mundane Linux command line work when I had my flash of insight. I’ve been using Linux for years, but I almost made a typical newbie mistake with the mv command. I wanted to rename a file:
mv /path/to/old_name new_name
Urp! I stopped, because this would not have just renamed the file, but moved it into my current directory as well. And then I recalled the typical mv tutorials which usually explain how the unix filesystem works, and how with that understanding, mv’s behavior makes sense.
In other words, mv combines two conceptual functions into one thing, simply because that’s the underlying implementation.
And I realized that this kind of “implementation leakage” occurs with many git commands. The non plus ultra evidence is the excellent post, Git Reset Demystified by Scott Chacon. It’s about git’s equivalent to svn revert — a very important function, undoing your changes. But even though Scott is very knowledgable about git and even authored the book, Pro Git, he
…never strongly understood the command beyond the handful of specific use cases that I needed it for. I knew what the command did, but not really how it was designed to work.
It’s no wonder that ordinary git users don’t fully grasp these commands. In a confirmation of my theory about git’s problems, Scott presents this 6×4 table as a learning aide:
A second example is the well written O’Reilly book Version Control with Git. It teaches the internal implementation of git before explaining how to fully use it. Or, as David Eisinger says,
…until you wrap your head around its internal model, it’s easy to wind up in a jumble of merge commits or worse.
Git and github are awesome pieces of software. Last year, I happily switched from subversion to git just like, years ago, I switched from CVS to Subversion. Another evolutionary step. I use GitHub for lots of reasons. The biggest is that it’s the best front-end to git that I’ve found. And so now I use Git+GitHub for 15 or so projects; some open source like HTTP Assertions, and some private code, like the OregonLaws.org web app.
The one little problem
Everything goes along happily until git decides you need some help. And so, in a fit of well intentioned verbosity, git coughs up three terminology-packed paragraphs of text that we’ve all seen:
As I learn git, I’m experiencing advantages that I haven’t seen described together. Also, I haven’t seen a description from the perspective of the real-world differences in your files, so here goes:
Subversion uses a single, central repository which is in a remote place. And in your project, it maintains .svn/ directories in every sub-directory. Git on the other hand, gives each developer their own full-fledged repository. And then, instead of relying on many hidden directories in your project, it creates one that lives only in the top-level directory; in .git/. So again: that’s the only place it stores info; nowhere else in your code.