git: squash/fixup earlier commit
If you're just looking for the easy solution for fixing up earlier commits, read the question! It explains it all. But since Elmarco was asking for a slick way, here we go:
As of Git 1.7.0, there is an --autosquash
option for rebase
, which does what you want. There is also the --fixup
and --squash
options for commit
to make things easier. With some aliasing you can probably even get the whole thing into a single command.
I'd suggest upgrading to the newest Git for maximum awesomeness:
git/Documentation/RelNotes $ grep -i -A1 autosquash\\\|fixup *
1.7.0.txt: * "git rebase -i" learned new action "fixup" that squashes the change
1.7.0.txt- but does not affect existing log message.
--
1.7.0.txt: * "git rebase -i" also learned --autosquash option that is useful
1.7.0.txt: together with the new "fixup" action.
1.7.0.txt-
--
1.7.3.txt: * "git rebase -i" peeks into rebase.autosquash configuration and acts as
1.7.3.txt: if you gave --autosquash from the command line.
1.7.3.txt-
--
1.7.4.txt: * "git commit" learned --fixup and --squash options to help later invocation
1.7.4.txt- of the interactive rebase.
--
1.7.4.txt: * "git rebase --autosquash" can use SHA-1 object names to name which
1.7.4.txt: commit to fix up (e.g. "fixup! e83c5163").
1.7.4.txt-
I created some aliases to make it easier to use the git commit --fixup
and git commit --squash
commands added in git 1.7. Add these to your ~/.gitconfig
:
[alias]
fixup = !sh -c 'REV=$(git rev-parse $1) && git commit --fixup $@ && git rebase -i --autosquash $REV^' -
squash = !sh -c 'REV=$(git rev-parse $1) && git commit --squash $@ && git rebase -i --autosquash $REV^' -
Usage:
$ git commit -am 'bad commit'
$ git commit -am 'good commit'
$ git add . # Stage changes to correct the bad commit
$ git fixup HEAD^ # HEAD^ can be replaced by the SHA of the bad commit
The bad commit can be several commits back.
My current git work flow is so --fixup
/--squash
intensive, that I wrote a new git-fixup
command that handles most of the annoying bits automatically:
-
git fixup
shows the modified files grouped under that latest commits that touch the same files -
git fixup -a
commits all those changes as--fixup
changes with their corresponding "parent" commits -
git fixup -r
does an automaticgit rebase --autosquash
for all the fixup commits
A lot of changes are such that just the three commands above are enough to get the job done, no copy-pasting of commit-id's or reading thru the git log
to find the right --fixup
targets.
Source: https://github.com/ohmu/git-crust