How do I use Mercurial to integrate major revisions?
First, I am new to Mercurial and distributed source control systems as a whole. Generally I have used perforce, so I'm going to use perforce terminology in order to keep what I'm trying to say clear.
My issue is that I'm making a game based on an open source engine, and that engine has regular code drops. However, I am also making some changes to the engine code myself, in my own depot. I need to set things up so that I can easily merge changes from code drops in to my own code, without losing my changes, and without having to examine every single file manually.
In 开发者_开发问答Perforce, what I'd do is have a branch for just the engine code, and then my main branch, and all engine code drops would be submitted to the engine code branch, and then I would integrate the engine code branch in to the main code branch. Resolve problems, submit, and voila.
I feel like this is pretty close to how it would work in Mercurial, only I'm missing some minor piece of understanding to help me figure it out. First, I'm not sure if my engine code should be in a branch, or a completely separate repository. And even if I did know that, I'm not clear as to how I'd move code back and forth and keep them properly separate.
Sorry if this is kind of a kitchen sink question. I tend to learn by tossing myself in the deep end.
First of all, I would separate the engine and the game in two repository. It helps if you want to use the modified engine elsewhere, if you want to contribute back to the original project, if you want to put someone on the engine but not on the game(s),... And to bring them back together, simply use the subrepo
feature.
Now in the field of the game engine modifications, as long as there is no conflicting change, you simply have to pull
, merge
then commit
.
Let's hypothesis a scenario:
1----2----4----5---------8----A----B <---- your changes
\ / / /
---3-------6----7----9----/ <---- original changes
One day you begin to use the engine (1). The engine is updated (2) but it is ok for you and you use it like that. In fact no, you have to change something (4), in the same time, changed are made on the original one (3). No problem, just fetch them (5) pull->merge->commit
. Oh, they made a change (6) and another one (7). OK, let's include them (8) pull->merge->commit
. And so on, they made changes (9), you make changes (A) and you merge them (B).
One unnatural thing to remember when switching from centralized to distributed version control is that branching and merging is a normal (and lightweight) process, not an exceptional one. Some people merge hundreds of time per day.
For more understanding try to search for "mercurial workflow" (here I exposed a minimal one) and read the excellent book Mercurial: The Definitive Guide by Bryan O'Sullivan
Follow up about comments
Consider a minimal project like this one:
mygame/
├── .hg/
├── .hgsub
├── lib/
│ └── engine/
│ ├── enginefile.cpp
│ └── .hg/
├── mygame.proj
└── src/
└── mygamefile.cpp
And now your comments:
Also, I would like to be able to work on all my game's content in the same repository[...]
If I understand well, in fact, you want to "be able to work on all [your] game's content in the same [project]". Correct me if I made a false guess.
Here, the two directories containing a .hg
subdirectory are separate repositories (mygame
and engine
). But you can nest them without making separated projects in your IDE. So two nested repositories, but only one project. In your build configuration (Makefile
s, solutions, ...), you can even make references from mygame
to engine
as the engine
sub-repository is always present (typically to use headers from the engine in your game).
[...] would it be possible to get it slightly more specific? Example commands, repositories, paths, etc?
- For the paths, look at the second figure.
- To update the engine, in the
engine
directory (cd lib/engine
):hg pull
,hg merge
,hg commit -m "merge new original with my modifications"
,cd ..
,hg commit -m "updated to new engine version"
, now you have the new version with your changes included. - For other basic use, it looks like other version control system. In your case, this article could be useful to map perforce to mercurial commands.
It sounds like you could do almost exactly the same thing you do with perforce using named mercurial branches in a single repository:
hg branch engine-code
hg ci -m "created engine code branch"
# add the engine code drop
hg ci -m "new drop"
hg update default
hg merge engine-code # merges engine-code drop into your default branch
# test the result of the merge, then commit it:
hg commit -m "merged new engine drop"
That's the initial setup. After that, when you want to add a new drop it's similar:
hg update engine-code
# add the new drop
hg ci -m "nother new drop"
hg update default
hg merge engine-code
hg ci -m "merged another new engine drop"
What you want is called a "vendor branch" -- a branch where you keep the clean code drops from your upstream vendor. You then make your own modifications in another branch and regularly merge in code drops that you have put into the vendor branch. Very much like you described it yourself in the question how krupan described it in his answer.
I have written a set of slides that explain how vendor branches work Mercurial. You should be able to follow them with your Perforce background. Searching the Mercurial mailinglist for "vendor branch" also shows many good hits.
精彩评论