Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Remove spurious commit parent pointer

I imported a Bazaar repository into Git (using git bzr), but the resulting repository contains a spurious commit parent link:

Spurious parent link

Notice that the commit tagged 1.02-6 is based off the 1.02-3 commit, but 1.02-1 is unnecessarily also marked as a parent. (Note: All the commits in this part of the repo are tagged; there are no commits between the ones shown.)

I have tried rebasing in several ways (on the master branch: git rebase 1.02-3, git rebase -i upstream-1.02, git rebase --onto 1.02-1 1.02-3, git rebase --root upstream-1.02 --onto=other_branch), but in each case it fails with a merge conflict. These seem to be attempting more than is necessary; the history is correct except for an extra parent pointer being recorded in the commit tagged 1.02-6.

How do you remove the link in order to linearize the history? Is there a better way than manually cherry-picking all the commits in sequence?

like image 763
Mechanical snail Avatar asked Jan 09 '13 19:01

Mechanical snail


3 Answers

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.

like image 102
JosephH Avatar answered Sep 24 '22 16:09

JosephH


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.

like image 44
Mechanical snail Avatar answered Sep 24 '22 16:09

Mechanical snail


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.

like image 2
hypehuman Avatar answered Sep 26 '22 16:09

hypehuman