Qeebrato
Qeebrato

Reputation: 131

squash multiple historical commits

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.

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

Upvotes: 4

Views: 1338

Answers (3)

ntshetty
ntshetty

Reputation: 1305

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

Upvotes: 3

Qeebrato
Qeebrato

Reputation: 131

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

Upvotes: 0

Chris
Chris

Reputation: 8656

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.

Upvotes: 3

Related Questions