I have a commit I want to fixup. what am I doing wrong?
git commit --fixup bdf55a7c12996e3af853c27ca4ff6c670e826c5e
On branch foo
nothing to commit, working tree clean
git --version
git version 2.31.0
You mention in a comment:
I didn't realize it wasn't meant for commit messages.
There is currently no git commit
option that is meant for that.1 Instead, you need to run git rebase -i
(as you would normally anyway) and then change the pick
line for that particular commit to a reword
line.
I still don't think I understand how to use the fixup tool correctly ...
The thing to understand here is that git commit --fixup
and git commit --squash
are relatively late inventions. What comes first is git rebase --interactive
. (There is a whole lot more background to understand as well, but let's just assume that you understand exactly what git rebase
does and how it does it, via repeaeted cherry-picking. If you don't, that's a separate question—which is already asked and answered here on StackOverflow, so search for those Q&As.)
Now, since rebase is essentially a series of cherry-pick operations, we observe that a mechanical, automatic, copy-every-commit-as-is rebase is kind of boring. We add some excitement!!! (insert blockbuster movie explosions and loud noises here) by turning the series of cherry-picks into a block of commands:
pick a123456 subject line from that commit
pick b789abc another commit subject line
pick cef0123 ... etc ...
pick d456789 and so on
Then, having made up this "instruction sheet", we give you—the user—the opportunity to edit this instruction sheet.
You can change the order of the pick
lines, for instance. This means that instead of the cherry-picks being done in the original order, they're done in the new order you choose. So you can re-shuffle the order of commits. If you got one commit wrong, and used a later commit to fix it up somehow, you can put the wrong-and-fixup commits next to each other!
So far, that's not a whole lot of help. You change:
pick a123456 subject line from that commit
pick b789abc another commit subject line
pick cef0123 ... etc ...
pick d456789 and so on
pick eabcdef whoops
into:
pick a123456 subject line from that commit
pick b789abc another commit subject line
pick eabcdef whoops
pick cef0123 ... etc ...
pick d456789 and so on
where the "whoops" commit repairs a mistake you made in commit b789abc
. OK, so if you run these instructions, the rebased result is that the mistake-commit and the fixing-commit are now adjacent, rather than separated by (the copies of) commits cef0123
followed by d456789
.
But now we add more options. Rather than just pick
, for instance, we add the option squash
. This tells Git that instead of just cherry-picking commit eabcdef
—the one that fixes the earlier commit—it should turn the two commits into a single combined commit. It should also take the commit log messages from the two commits, and put them into a single temporary file and use that temporary file as the commit message ... after giving you a chance to edit that file!
So now you can edit the two commit messages down into a single commit message, for the combine commit that results from squashing the defective commit together with its repair commit! That's the original idea here.
1There is an in-progress effort to add a new commit option just for this.
So, with an interactive rebase that knows only two options—pick
and squash
—we get the following abilities:
Now that we can do this much, let's think about what other things we might want to be able to do:
If there's a typo in some commit message, it would be nice to be able to fix it.
So, to our two existing options—pick
and squash
—let's add a reword
option. This will cherry-pick the commit, but will also throw us into our editor to let us change the commit message first.
If there's a goof-up in a commit, but we have a fix for it and we don't need to fix its commit message, it would be nice to be able to put the fixup commit right after the broken commit. We can already do that by moving it around and using squash
. But this throws us into our editor. It would be nicer to just keep the commit message from the broken commit, while squashing the two commits.
So, to our existing options, let's add a fixup
option. This will do the squashing, just like squash
does, but won't put us into our editor. It will throw away the fixup commit's message entirely, keeping the message from the slightly broken commit while squashing in the fixup.
These give us some of the commands that interactive rebase can do. We get a few more (like edit
, which picks the commit but then stops, as if there were a conflict) before we stop and declare that our interactive rebase feature is nifty and should be part of Git and get it into a Git release. Then it sits there in Git for some years.
Now that some years have gone by, we say: Hey, it might be nice if we could have git commit
annotate a commit, at the time we make it, to say that it's a squash or fixup commit that git rebase --interactive
should turn into a squash
or rebase
automatically. This is the situation you've walked into. You came in late in the movie, and aren't aware of all this background, but now you've read some spoilers to explain the first part of the movie and how we got here.
This explains why you get the error you do: a --fixup
commit is supposed to be fixing a goof in the committed files. It's not for fixing up the commit message. There is no way to do that with git commit
just yet. Instead, you have to run the git rebase -i
yourself, and change the pick
line to a reword
line.