Remove spurious commit parent pointer

This will correct the parents without changing anything else (eg. committer dates):

git filter-branch --tag-name-filter cat --parent-filter 'test $GIT_COMMIT = [sha of 1.02-6] && echo "-p [sha of 1.02-3]" || cat' -- 1.02-1..master

You will have to replace the bracketed text with the appropriate commit IDs. If you have more downstream branches that need to be rewritten, change 1.02-1..master to --all and be prepared to wait.

Of course, don't use this or any other solution if others have branched from any commits after the ones you want to edit. They will hate you.


The easiest way to do this (in git >= 1.6.5) is to use:

git replace --edit <sha>

and remove/add/change the Parent: lines.

Once you are happy the change is right, you can rewrite the commits to make the change permanent:

git filter-branch --tag-name-filter cat -- --all

In some cases it'll be noticeably quicker to only rewrite the commits involved and not the full history (thanks to Michael for mentioning this in the comments); e.g. to rewrite only commits on the current branch:

git filter-branch --tag-name-filter cat -- <new parent sha>..head

If you're not sure, use --all, otherwise you risk ending up with other branches/tags still referencing the temporary replacement object.


You can do it manually using the git commit-tree internal command.

We want to edit the commit tagged 1.02-6 to remove the spurious parent pointer (to 56a2f3b5948ab54c9239c2b384a6ea9eb1f410c4).

First, read the information from the existing commit object:

user@host:/path/repo.git$ git cat-file -p 1.02-6 
tree c658aa1ebcf2bf2a607696c7868b875be72fb01f
parent 56a2f3b5948ab54c9239c2b384a6ea9eb1f410c4
parent 4e671bf1d2298729c9e5cfd8229051cfe2c40831
author James Damour (Suvarov454) <[email protected]> 1146319620 -0400
committer Bazaar Package Importer <[email protected]> 1146319620 -0400

The "main/" in the Section line of debian/control should be assumed.

Extract the commit message using git log --format=%B -n 1 1.02-6.

Now create a new commit with the same content (excluding the spurious parent link, and the committer info):

git log --format=%B -n 1 1.02-6 | \
    GIT_AUTHOR_NAME="James Damour (Suvarov454)" \
    GIT_AUTHOR_EMAIL="[email protected]" \
    GIT_AUTHOR_DATE="1146319620 -0400" \
    git commit-tree c658aa1ebcf2bf2a607696c7868b875be72fb01f \
        -p 4e671bf1d2298729c9e5cfd8229051cfe2c40831

This created a new commit, and printed its hash (cc32e66...). Now turn it into a new branch:

git checkout -b fixed_commit cc32e66

and rebase master onto the new branch:

git checkout master
git rebase fixed_commit

And we're done:

Finished

You probably want to delete the old branches and re-tag the appropriate commits.


Actually it might be easier to use git filter-branch --parent-filter. I haven't tried that.


You could try a rebase. There is an example a bit down (search for --onto) that I think is similar to your case.

I think you need to do

git rebase --onto 1.02-1 1.02-3

which should put everything after 1.02-3 onto 1.02-1 and that is probably what you want.

Remember that the hashes will be different on everything from the first changed commit but I assume you are doing this as a first step in moving from bzr so no-one else should have cloned this yet.