I have several advanced scenarios I would like to solve, but I don't know how. I hope you can help:
A - B - C - D - E
. I would like to add the changes from commit D
into commit B
and remove commit D
. How?A - B - C
. Commit B
contains a file that should not have been committed. How to remove it from the commit?A - B - C - D
. Commit C
contains a file that should have been committed with commit B
. How to remove it from commit C
and add it to commit B
?Please note: All commits are in my working copy only and have not yet been pushed.
My answers use git rebase
quite a lot. If you're new to rebasing, be sure to read this chapter on git rebase first
git cherry-pick B
rebase -i A
and swap the C/D revisions, squashing B+D together.git rebase -i B
, mark B as edit and apply changes.
Now to really remove the objects from the object database you may need to use filter-branch on all branches containing the object. After that, it may take a while for reflogs to expire. If the object is a security sensitive one, you may want to
git gc --aggressive --prune=tomorrow
. The Pro Git book has a section on removing objects.
Withgit-filter-branch
always remember to include--tag-name-filter cat
, see comments
If all of C should be in B, simply
git rebase -i B
mark C
with squash and it will squash the commits together.
If it gets any more involved than that (only a single file from C needs to go in B), I'd split the job into smaller steps that can be solved as in the above steps:
- split commit C in two parts: one (C.1) to merge into commit B and one (C.2) to keep as the new 'C'. E.g. from the Git Pro chapter linked above:
If you wanted to split a commit, for instance, you would specify 'edit' for that commit:
pick fc62e55 added file_size pick 9824bf4 fixed little thing edit 21d80a5 added number to log pick 76b9da6 added the apply command pick c264051 Revert "added file_size"
And then when you get to the command line, you revert that commit and create two (or more) new ones. Lets say 21d80a5 modified two files, file1 and file2, and you wanted to split them into seperate commits. You could do this after the rebase dropped you to the command line :
$ git reset HEAD^ $ git add file1 $ git commit 'first part of split commit' $ git add file2 $ git commit 'second part of split commit' $ git rebase --continue
And now instead of 5 commits, you would have 6.
- rebase to merge commits B and C.1
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