How to restructure a mercurial repository with two

2019-07-12 19:20发布

问题:

The history of my repository looks like:

A -- B -- C (branch "foo")
      \
       -- D (branch "bar")

The two branches are both "shipping" branches, and are essentially different frontends to a common backend.

All the code used to be in one branch, with the foo or bar features turned on or off by a compiler switch, but I branched to make it easier to work with each individually.

The problem is that the common "backend" files, by themselves, probably should be a separate branch - and I often want to just work on those common files. Because of the way I created these branches, the history is a bit screwed up: in branch bar's past, it used to have features from foo.

Currently, I simply make changes on one branch and then use hg transplant to copy the same changes to the other branch.

Instead, I'd like to be able to make changes this way:

       __ C __ D'   (branch "foo")
      /      /
A -- B -- D         (branch "backend")
      \      \
       -- E -- D''  (branch "bar")

That is, work on the branch backend, and then in each of the shipping branches (foo and bar), I use hg merge backend.

What's the best way to go from my current situation to the one I'm describing? The only way I can think of is:

  1. Remove all foo and bar features, and name that branch backend.

  2. Delete the old foo and bar branches.

  3. Manually add foo features to backend and name that branch foo, and likewise for bar.

Is there a better way?

Also, is this the right thing to do?

回答1:

How many changesets are there on branches foo and bar? Are the backend (transplanted) changesets separated from frontend changesets?

If the changesets are not many, and they are clean, then you might want to do this:

       C -- 1 -- 2 -- D -- 3   (branch "foo")
      /      
A -- B ----------- C" -- D"   (branch "backend")
      \      
       C' -- 4 ------ D' --- 5   (branch "bar")

(Here A, B, C, D are backend-related; 1, 2, 3 are foo-related; 4, 5 are bar-related.)

— i.e., create your brach backend based on the most recent common ancestor of foo and bar, then transplant all backend-related changesets there. From this point on, you'll be able to merge backend into either branch.



回答2:

I chose to split it into multiple repositories instead of several branches in one repository, as follows:

  1. I closed the bar branch.

  2. I cloned the original repository into a new repository backend.

  3. I removed all of the foo-related code.

  4. I pulled those changes into the main repository, and then immediately backed out of them (so the foo code remains). This became my foo repository.

  5. I cloned the backend repository into a new repository bar.

  6. I copied-and-pasted all of the files from the now-closed bar branch into the bar repository.

This kept my history for foo, and lost the history's continuity for bar (although all the history is still there, if I needed it); and now both foo and bar are clones, with modifications, of the backend repository, which is exactly what I wanted.