4

I have an SVN history of some 20000 commits. I moved to Git and kept the history. Now i'm at 26000 commits, and I want to squash all commits from 1 to 20000.

  • Initial commit: a4f5d18
  • Migration to git: 5a42d81
  • HEAD: 933eff

I tried checking out 20000 and rebasing:

git checkout 5a42d81
git rebase squash a4f5d18

But i get:

fatal: Needed a single revision
invalid upstream squash
Qeebrato
  • 131
  • 7

3 Answers3

3

How many commits you want retain, specify that number in the below command

git rebase -i HEAD~6000

or more precisely

git rebase -i a4f5d18

Retain the 6000 commit from below( as pick) and change the rest of the pick to squash

if rebase succeeded

 git log

You can see all your commits squashes to one commit

and better you push the changes to remote, otherwise when you pull again you will see all commits.

git push -f
Oliver Williams
  • 5,966
  • 7
  • 36
  • 78
ntshetty
  • 1,293
  • 9
  • 20
3

If I understand correctly, your main branch looks like:

master: 1 -> 2 -> 3 -> .. -> 20000 -> A (First non migrated commit) -> B -> C -> ..

And you'd like to get to:

master: 1' (All your migrated commits) -> A' -> B' -> C' -> ..

I think you could follow the approach of using git rebase HEAD~26000 (first commit hash probably easier) and changing pick to squash, but it might be fiddly/time consuming.

One potentially viable solution would be to create a new commit with the contents of your first 20000. Probably worth testing on a backup branch.

git checkout <last migrated commit hash> -b backup-master

backup-master: 1 -> 2 -> 3 -> .. -> [20000] -> A (First non migrated commit) -> B -> C -> ..
                                       ^- you are here.

git reset --soft <first migrated commit hash>

backup-master: [1] -> 2 -> 3 -> .. -> 20000 -> A (First non migrated commit) -> B -> C -> ..
                ^- you are here         ^- the working directory tree/index reflects this commit 

Amend your initial commit contents/message (or create a new commit if you'd prefer).

git commit --amend

Now backup-master should contain your squashed migration commits, let's move the new commits.

git checkout master

git checkout -b master-rebase (just in case we mess something up).

git rebase backup-master - I believe this will work because git is aware of the merges required to successfully rebase. If this works, you should be done, master-rebase will contain your desired result.

If this fails, you might have better success with rebase --onto.

git rebase --onto <destination commit> <parent of first desired commit> <last desired commit>

I.e. git rebase --onto backup-master <A>~1 master`

If this works it will place you on a commit that isn't currently on any branch, so you'll need to create one:

git checkout -b rebase-success.

A more thorough explanation of rebase --onto can be found here.

Chris
  • 8,268
  • 3
  • 33
  • 46
  • 1
    Thanks, this is the approach I was looking for, even although the actual rebasing isn't any faster and you don't get to see its progress unlike with the interactive rebase solution. NB: I had to create the branch after the soft reset since this resulted in a detached head state. – Qeebrato Aug 10 '17 at 12:55
  • Ah, that's a good point, I'd overlooked that the `reset` step would leave you with a detached head. Updated the answer to add a `-b ` to the initial checkout step. – Chris Aug 10 '17 at 13:05
  • @Chris I followed your approach and left with two histories at the end. One runs from --root to master, another from --root to rebase-success. Is this expected? – Candy Chiu Mar 01 '21 at 01:20
  • Hey, it's been a while since I answered this so I might have to get my head back in the game, what do you mean two histories? I think the intention was that you'd have a backup branch in case anything went wrong, but the successful rebase should be the one you're after. – Chris Mar 01 '21 at 09:51
  • @Chris let's say we start with one branch, the master, with 26000 commits. After the series of operations, I was able to create a new branch rebase_successful which contains 6001 commits. master still exists with 26000 commits. How do I re-point master to this new branch and delete the original master? – Candy Chiu Mar 01 '21 at 14:36
  • Ah, it's getting a little outside the scope of this question at this point, as it's not exactly clear what your setup is. If it's just you working on a lone repo, you could delete the other `master` branch, and just create a new branch called master. Or you could checkout `master` and use `reset` to point the head at `rebase_successful` branch tip. If you're working with other's there's slightly more to consider (as you would be affecting shared history). – Chris Mar 01 '21 at 15:05
0

I ran into trouble with whitespaces, in all three scenarios (interactive rebase, soft reset, rebase onto). Git has the possibility of grafting branches, which developed into the replace function:

git replace -f 5a42d81 a4f5d18
git filter-branch
Qeebrato
  • 131
  • 7