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:
In the Client repo, update to changeset 0. This updates ProjectB and SharedLibrary to earlier but matching revisions.
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).
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.
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?
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.