3

Take this repo structure:

Server (main repo)
    ProjectA (subrepo)
    SharedLibrary (subrepo)

Client (main repo)
    ProjectB (subrepo)
    SharedLibrary (subrepo)

SharedLibrary points to the same folder (this is Windows), it is not a separate copy/clone under each main repo.

Assume each main repo has two changesets, 0 and 1(tip). We start with both main repos at the 1(tip) revision.

Take the following steps:

  1. In the Client repo, update to changeset 0. This updates ProjectB and SharedLibrary to earlier but matching revisions.

  2. ProjectA is now out of sync with SharedLibrary. Step 1 updated SharedLibrary to an older revision than what is required for ProjectA, which is still at 1(tip).

  3. In the Server repo, we want to update SharedLibrary to the correct revision for ProjectA, so we run hg update tip in the Server main repo. This does NOT update SharedLibrary to the correct revision. It leaves SharedLibrary in the same revision as step one.

  4. Go back to Client repo and run hg update tip. SharedLibrary is now at the correct revision for both ProjectA and ProjectB.

It appears updating in the Server repo isn't checking to see if SharedLibrary is at the correct revision. Is this behavior expected, or is there a better way to do this?

Martin Geisler
  • 72,968
  • 25
  • 171
  • 229
Casey Wilkins
  • 2,555
  • 2
  • 23
  • 31
  • The purpose of a *sub*-repo is to be *under* the main repository, that's what *sub* means, anything else is not how it's meant to work so I wouldn't be surprised that it works poorly. You need to clone it for each. – Lasse V. Karlsen Mar 12 '12 at 14:24
  • @Lasse V. Karlsen, how do I keep SharedLibrary consistent? Push/pull between the clones? – Casey Wilkins Mar 12 '12 at 14:29
  • No, each clone is a clone of a "central" main repository that you push/pull against, ie. a third clone. – Lasse V. Karlsen Mar 12 '12 at 14:30
  • 1
    @LasseV.Karlsen, Thanks. I'm new to Mercurial, but that makes sense and may clear up some other issues I was having. If I understand you correctly, I basically need to clone the SharedLibrary from its own "central" repository into the Server and Client folders/repos. – Casey Wilkins Mar 12 '12 at 14:35
  • Correct, that's how it is designed to work. – Lasse V. Karlsen Mar 12 '12 at 14:37

1 Answers1

2

What you're seeing is that hg update will merge when the working copy is dirty. Let me explain it with a normal file first. Imagine you have a repository with two revisions. I'm at revision 0 and foo is modified:

$ hg diff
diff --git a/foo b/foo
--- a/foo
+++ b/foo
@@ -1,3 +1,3 @@
 first
 second
-third
+third line

You see I changed the third line. Now, if I run hg update 1 the modification will be merged with how foo looks like in revision 1:

$ hg update 1
merging foo
0 files updated, 1 files merged, 0 files removed, 0 files unresolved

The modification is still there and foo is still dirty:

$ hg diff
diff --git a/foo b/foo
--- a/foo
+++ b/foo
@@ -1,3 +1,3 @@
 first line
 second
-third
+third line

When you did

$ cd client
$ hg update 0

you made sure that SharedLibrary was updated to the revision described in .hgsubstate for revision 0 in client.

When you then went to server, the SharedLibrary subrepo was no longer at the revision mentioned in .hgsubstate at revision 1 in server. In other words, the working copy in server was dirty — a hg commit would result in a new .hgsubstate file being committed.

Mercurial preserves this modification when you hg update in server and this is why you see that SharedLibrary wasn't made current when you updated. Use hg update -C if you want to make the subrepo current.

The idea behind this feature is that you can test different versions of your subrepos. When hunting for a bug, it's often necessary to update the main repository to older versions and so it's convenient that the modifications to the subrepo revisions stay in place.

Note that the confusing situation you're seeing isn't caused by how you've re-used the same subrepo twice. However, as Lasse points out, the real way to use a single subrepo in multiple projects is to put it once on your server and then clone it into your local clones — once per clone.

I've described this in more detail, but briefly you should follow the recommendations and maintain an identical structure on both server and clients. Use SharedLibrary = SharedLibrary paths in your .hgsub file to maintain this structure. Link the repositories together on the server-side (see my other answer) to make a single repository appear under several different URLs/directories.

When starting out with subrepos, then beware of tight coupling. If you can, then try to use a proper dependency management system such as Maven+Nexus for Java based projects.

Community
  • 1
  • 1
Martin Geisler
  • 72,968
  • 25
  • 171
  • 229
  • That explains it. Would you agree with Lasse on making Client and Server pull their own clones of SharedLibrary from a central repo? I switched it over this morning and I agree with him, it seems to be the right way to handle it. Your thoughts? – Casey Wilkins Mar 12 '12 at 19:53
  • @Casey: yes, I agree fully with Lasse, he knows what he's talks about! :-) – Martin Geisler Mar 12 '12 at 20:12
  • 1
    Thanks Martin for the great answer and explanation. And yes, I have figured out that Lasse is some kind of super code ninja :) – Casey Wilkins Mar 13 '12 at 15:15