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.

  • Git Extensions + Git For Windows: Fetching Branch that does not exist Locally does not Create New Local Branch
  • Is code safe in git repository on a remote server? How to secure it?
  • How to check if a Git Repo has uncommitted changes using Python
  • Exact `svn export` equivalent command for git?
  • What is the purpose of “git push -u” command?
  • Git diff reports local changes 'old mode' / 'new mode'
  • 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?

  • git branch permissions
  • Can I use git-svn to clone a specific branch of a remote SVN repo and commit back to it?
  • Change Git Root Folder contents to a Subfolder
  • How do I configure Eclipse to use an existing git repository with existing source code?
  • Github - how to include info in your source
  • Passworded ssh key suddenly does *not* require that I type the password
  • 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 mytag:

    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:

    git commit

    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 -p (--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.

    Git Baby is a git and github fan, let's start git clone.