Squashing complete history before a certain tag
Following scenario: I have a repo with a large history (migrated from SVN which was used since 2006) and want to push the newer history to an external server.
I have a tag, say
mytag and want to delete all commits that occurred before that tag but want to keep the history that occurred since this tag.
I tried to do it like in the accepted answer of Rebase many commits to one in Git. What am I doing wrong?, but this results in endless conflict resolving.
I just want to throw away the history while being able to merge my local repo (that still holds the large history) to the remote repo (with the short history).
How do I achive that?
2 Solutions collect form web for “Squashing complete history before a certain tag”
Update: note that in the below I’m assuming that
mytag only has one parent commit, otherwise it’s a bit more complicated.
First, let’s assume that you only have one root commit and that it’s
f414f31. (If you need to find all the root commits you can do that with the first command in this answer.)
To be safe, let’s create a new branch for this operation, so your branch
master is left as it was, just in case the results aren’t as you would like.
git checkout -b new-master
Reset this branch to the root commit:
git reset --hard f414f31
Now change the working tree and the index to be the same as the commit just before
git merge --squash mytag^
Then create a commit from the index – if you want to rewrite the root commit, you can do that with
git commit --amend, but I would prefer to keep one commit in common between your old and new histories, so I’d just do:
Now what you need to do is to replay all your work since (and including)
mytag on top of that commit. This is what
git rebase is intended for, but by default it will linearize all the history that you’re trying to replay. If have you many merge commits in the history since
mytag, that may be the reason that you see many conflicts.
So, if you don’t mind the history being linearized and you can fix the conflicts (possibly with the help of
git rerere) you could just do:
git rebase --onto new-master mytag^ master
However, if there are merges in that history, and you would prefer to keep them, you could try adding the
--preserve-merges) option, which will try to recreate them:
git rebase -p --onto new-master mytag^ master
You ask a further question in the comments below about the case where you have two root commits. In that case, you could just pick one of them, and use
git commit --amend after the squashed merge to create a completely new root commit for the rewritten history.
If you want to rewrite/delete history, then you are looking for git filter-branch. Here’s a nice thread that discusses how to remove commits. The $drop variable would be the commit before your mytag.