21

I have a project that contains traces to another project of myself that I've used as a kind of a template project. Now I want to remove these traces entirely from the repository. Basically I want to cut off the old junk commits. So I have

A -- B -- C -- D -- E -- F

and want to get something like

D -- E -- F

with A -- B -- C being completely removed from the repository.

Alex
  • 8,245
  • 8
  • 46
  • 55

3 Answers3

33

Assuming master is at commit F:

 # create a new branch with D's content
$ git checkout --orphan temp <d-sha1>
$ git commit

 # rebase everything else onto the temp branch
$ git rebase --onto temp <d-sha1> master

 # clean up
$ git checkout master
$ git branch -d temp

If you want to completely remove the old loose objects (A, B, & C), first make sure you have exactly what you want. This cannot be undone. Once you have confirmed it's what you want, run:

$ git reflog expire --expire=now --all
$ git gc --prune=now
vergenzt
  • 9,669
  • 4
  • 40
  • 47
  • Awesome, thanks! I guess a "git push -f" overwrites the remote repo with the new one? – Alex Jul 27 '12 at 13:00
  • 2
    Yep. Do be careful, though, since you are editing history. If anyone else has pulled from your repository, they're going to have a hell of a time figuring out what happened. `F` is *no longer the same commit*, so if they try to commit to `F` and push, it's not going to work. – vergenzt Jul 27 '12 at 13:05
  • 1
    Additional flag for the commit command: you can use `git commit -C ` to reuse the commit message, author, date etc. of the "original" commit D. – akavel Dec 10 '15 at 16:57
  • 1
    after issuing ``git rebase --onto temp master`` I get ``First, rewinding head to replay your work on top of it... Fast-forwarded master to temp.`` – maslick Dec 16 '18 at 19:03
  • There are a lot of conflicts, how can we change merge strategy so conflicts will be resolved automatically ? – hsafarya Mar 12 '19 at 10:05
  • This ends up with a single commit on the new main branch, so it doesn't seem to result in the desired D -- E -- F. – Matt Jul 12 '23 at 02:06
0

Was trying to follow @vergenzt answer but git started to apply patches from the 1st commit which was 3000+ commits before the one I needed to start from.

My purpose was to make smaller repo for the new project that is based on current one. Unfortunately I needed some history to be preserved from current project (several months). This is how I finally managed to do it:

Command line tool was not quite convenient to do this because you will need to resolve conflicts. Fortunately there is a Rebase feature in TortoiseGit where you need to provide 2 barnches: master (left) and temp (right). Then skip all commits before the one where your temp branch on including commit (select commits and use 'skip' in right click menu). After rebase started you will get some conflicts which you can resolve right in the rebase GUI. I always picked "use master branch version" in right click menu. This took much less time then bothering with CLI. After everything was done I've additionally copied all project files from latest version of original repository upon files in new repository (overwrite all) to make sure nothing lost. I've got only several files that were in .gitignore and somehow were not ignored. Other files were same.

I hope this helps someone.

Swayok
  • 436
  • 3
  • 12
0

I know that's an old question, but I landed here today searching about this topic...

For the large amount of commits problem, you can try using "-X theirs" or "-X ours" in the rebase command, i.e.

git rebase -X theirs -i HEAD~20

the difference between the two it's explained here

I hope that can be useful to someone

Angantyr
  • 23
  • 4