I want to combine two commits that are not in order into one.
For example, if I execute the command git rebase -i HEAD~3
:
pick 8h47n1f Update documentation and release-notes #a
pick 8n32b7a Implemented some random function #b
pick a73ncj1 Update documentation and release-notes #c
I want to combine line a and c into one commit before pushing.
My current way of accomplishing this is to reorder my commits in the following way:
pick 8h47n1f Update documentation and release-notes #a
squash a73ncj1 Update documentation and release-notes #c
pick 8n32b7a Implemented some random function #b
So far I have not witnessed any dangerous side effects. Does anyone know if I could really break something by doing this? Is there a better, safer way to do what I'm trying to accomplish?
This is the best way (and afaik the only way) to achieve it. You can't do anything that couldn't be reverted (for example you can always abort rebase process on conflicts).
The list presented by the interactive rebase (git rebase -i
) is, in a simplistic view, just a script for automated execution of cherry-picks. The list is fully editable, you can even delete everything and write a whole new and completely different list. Git will just checkout the base commit and then execute the list commands in order.
There is a way to reorder the commits in the list automatically: using autosquash. From git-rebase
documentation:
--autosquash --no-autosquash
When the commit log message begins with "squash! …" (or "fixup! …"), and there is a commit whose title begins with the same …, automatically modify the todo list of rebase -i so that the commit marked for squashing comes right after the commit to be modified, and change the action of the moved commit from
pick
tosquash
(orfixup
). Ignores subsequent "fixup! " or "squash! " after the first, in case you referred to an earlier fixup/squash withgit commit --fixup/--squash
.This option is only valid when the
--interactive
option is used.If the
--autosquash
option is enabled by default using the configuration variablerebase.autoSquash
, this option can be used to override and disable this setting.
In your example, when creating the commit c, use git commit --squash <commit-a>
(also works with --amend
, if the commit already exists). When git rebase -i
is issued (assuming you set rebase.autoSquash
), the list will be presented as you want it.
The only issue regarding interactive rebase is when combining the -p
and -i
options. Again, from git-rebase
docs, in the Bugs section:
The todo list presented by
--preserve-merges --interactive
does not represent the topology of the revision graph. Editing commits and rewording their commit messages should work fine, but attempts to reorder commits tend to produce counterintuitive results.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With