Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Steps needed to allow hgsubversion SVN clone to push back

I am working on a team that uses SVN primarily, whereas I prefer to use Mercurial when possible. I set up an hg clone of the SVN repo using hgsubversion, and several basic pulls/commits/pushes seemed to function fine.

Now after 2 weeks of local development (during which time I've merged in changes from an external hg repo, and merged in changes from the SVN repo multiple times), I've attempted to push to the SVN repo, but failed with this message:

abort: Sorry, can't find svn parent of a merge revision.

I've found other users encountering the same problem, with how-tos on how to avoid this issue going forward, but I haven't encountered anything that seems to address condensing multiple parallel commits to clean up an existing hgsubversion repo.

What is the best way that I can rectify matters without losing my own commits? (With step-by-step instructions?)

like image 271
Jon L. Avatar asked Mar 17 '11 07:03

Jon L.


People also ask

Does SVN commit push?

Correct, svn commit will push your local modifications to the server. Take a look at the Basic Work Cycle to get a quick-ish overview of the commands you'll typically use.

How do I clone a Subversion repository?

You can clone from a SVN repo using the git svn clone command. -s = If your SVN repo follows standard naming convention where main source is in “trunk”, branches are created in “branches”.

What does SVN revert do?

Reverts any local changes to a file or directory and resolves any conflicted states. svn revert will revert not only the contents of an item in your working copy, but also any property changes.

What are two best practices while working with SVN?

Establish a branching and tagging practice. Tag major bug fixes at the beginning and end of the work. Maintain tags (and possibly branches) for production/qa releases.


1 Answers

You can't push hg merges into a subversion repository, since SVN can't understand them. You need to rebase your changes on top of the latest SVN commit.

Edit Steps to flatten the history:

Warning, be prepared to do have lots of merge conflicts

You need the mq and rebase extension activated

The first step is to create a backup repo, since you will need it as a reference for the upcoming merge conflicts (expect many of them).

Say your graph looks like this:

C1--C2--C3------M1--C5--C6--C7---M2--
  \            / \              /
   \--B1--B2--/   \--B3--B4-B5-/

Then the second step is to rebase B1+B2 on top of C3: hg rebase -b B2 -d C3

-b use the common base of both branches as the start for the branch to rebase, so mercurial finds that B1 is the first deviation commit und uses this even when you say B2 to rebase. -d specifies the destination of the rebased branch.

Wen you encounter merge conflicts then ensure that the result of B2' = M1, else you will get lots of conflicts in the following revisions.

Afterwards Merge M1 is gone and your graph looks like this:

C1--C2--C3--B1'--B2'--C5'--C6'--C7'---M2'--
                   \                 /
                    \--B3'--B4'-B5'-/

and now you do the same for the second merge: hg rebase -b B3' -d C7', which makes your repo look like this:

C1--C2--C3--B1'--B2'--C5'--C6'--C7'--B3''--B4''--B5''

Repeat until you have an all linear version history.

After you have flattened the history you need to reorder your commits on top of the svn commits. Say your repo now looks like this (S=subversion commit, C=local commit):

S1--S2--S3--C1--C2--S4--S5--C3-C4--C5--C6--C7--S6--S7

Now you import everything from (including) C1 into a mercurial queue (hg qimport -rC1:). To view all created patches use hg qseries.

Then you unapply all patches (hg qgoto C1.diff [this is the first one in qseries], followed by hg qpop). Then you remove the subversion ones (hg qdelete S4.diff S5.diff S6.diff S7.diff).

Now is the time to re-fetch the svn commits (hg pull »svn-remote«). Then you reapply all local patches, one by one with hg qpush, and fix all merge conflicts which are now occurring. When you are done with one conflict, you can move the current patch into a mercurial commit with hg qfinish -a, and send your current state with hg push »svn-remote«.

like image 174
Rudi Avatar answered Oct 14 '22 08:10

Rudi