I have an existing repository that I'm working on, yet recently I've learned a lot about good practices and the git itself. I wanted to shake my history to my liking, especially some early commits.
Below is the fragment of the current history. I want to rebase the e5cb9b8 commit onto the 1a92e84 so I can have just one/two levels of depth in the history graph (visually, changing the parent of e5cb9b8). I've tried rebasing
git rebase -p --onto 1a92e84 e5cb9b8 master
and cherrypicking into new branch created from 9ecbe00. Cherrypicking gets me flat history, rebase fails with the following message
error: commit ca230d8c048d22de6f219da8a22e70a773827c38 is a merge but no -m option was given.
fatal: cherry-pick failed
Could not pick ca230d8c048d22de6f219da8a22e70a773827c38
* | 45a0a21 - (7 weeks ago) #17 Updates README.md - Kamil Pacanek
|/
* ca230d8 - (8 weeks ago) Merge pull request #2 from KamilPacanek/feat/rmb-support-removing-parts - Kamil Pacanek
|\
| * e5cb9b8 - (8 weeks ago) Adds support for removing parts on ReactorCells - KamilPacanek
* | 1a92e84 - (8 weeks ago) Merge pull request #1 from KamilPacanek/enable-gh-pages - Kamil Pacanek
|\ \
| |/
| * 81761ff - (8 weeks ago) Adds GH Pages support - KamilPacanek
|/
* 9ecbe00 - (8 weeks ago) Initial commit - KamilPacanek
Expected:
* | 45a0a21' - (7 weeks ago) #17 Updates README.md - Kamil Pacanek
|/
* ca230d8' - (8 weeks ago) Merge pull request #2 from KamilPacanek/feat/rmb-support-removing-parts - Kamil Pacanek
|\
| * e5cb9b8' - (8 weeks ago) Adds support for removing parts on ReactorCells - KamilPacanek
|/
* 1a92e84 - (8 weeks ago) Merge pull request #1 from KamilPacanek/enable-gh-pages - Kamil Pacanek
|\
| |
| * 81761ff - (8 weeks ago) Adds GH Pages support - KamilPacanek
|/
* 9ecbe00 - (8 weeks ago) Initial commit - KamilPacanek
I've searched the StackOverflow for similar issues and it seems like no one described such modifications so deep into the history.
Ok, for future readers and myself I'm writing down the solution for my problem. @alfunx answer was a key to solve it - I've tracked down in other topic explanation of git rebase
and git rebase --onto
and started to experiment on my repository. Through trial and error, I've managed* to achieve the expected history graph by executing
git rebase -ir --onto 1a92e84 81761ff develop
and replacing followig fragment of todo-list
label onto
# Branch KamilPacanek/feat/rmb-support-removing-parts
reset onto
pick e5cb9b8 Adds support for removing parts on ReactorCells
label KamilPacanek/feat/rmb-support-removing-parts
# Branch enh/add-uranium-cells
reset 9ecbe00 # Initial commit
merge -C 1a92e84 onto # Merge pull request #1 from KamilPacanek/enable-gh-pages
merge -C ca230d8 KamilPacanek/feat/rmb-support-removing-parts # Merge pull request #2 from KamilPacanek/feat/rmb-support-removing-parts
label branch-point
with following (changed the reset position and removed one, redundant, merge commit):
label onto
# Branch KamilPacanek/feat/rmb-support-removing-parts
reset onto
pick e5cb9b8 Adds support for removing parts on ReactorCells
label KamilPacanek/feat/rmb-support-removing-parts
# Branch enh/add-uranium-cells
reset onto
merge -C ca230d8 KamilPacanek/feat/rmb-support-removing-parts # Merge pull request #2 from KamilPacanek/feat/rmb-support-removing-parts
label branch-point
*)
Actually, there was more to do to achieve that state, but I don't want to obfuscate the solution with secondary issues. First git rebase
failed with that message:
error: refusing to update ref with bad name 'refs/rewritten/Implement-durability-loss.'
hint: Could not execute the todo command
hint: label Implement-durability-loss.
As you can see I have a period at the end of the commit message. After I solved that (with another rebase with reword
command) I was able to move forward.
Also, it seems like git rebase --abort
doesn't clear the refs that are created during git rebase -r
.. so I had a mess in history. Solved that one via rm -rf .git/refs/rewritten
. Another thing, I had a leftover .git/sequencer folder that was removable via git revert --quit
.
The base you chose for the rebase is wrong and should be 81761ff
instead of e5cb9b8
. I would suggest you to do an interactive rebase and use --rebase-merges
instead of --preserve-merges
. So the command should be:
git rebase -ir --onto 1a92e84 81761ff master
Now, Git will probably produce one additional merge commit. To avoid that and to produce your desired outcome, you should adjust the todo-list to something like:
label onto
pick e5cb9b8 Adds support for removing parts on ReactorCells
label new
reset onto
merge -C ca230d8 new
pick 45a0a21 #17 Updates README.md
# Remaining commits...
In the todo-list, label
can be used to mark the current commit (HEAD
), and reset
can be used to set the HEAD
to some commit/label. merge
is obviously used to produce a merge commit, -C
makes the merge use the same commit message as the original merge commit.
This is quite advanced and really not needed for most users and use cases, so please consider man git-rebase
, section Rebase Merges (or the online version here) for more in depth information. The example there is actually quite similar to your situation.