Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Making mercurial subrepositories behave like subversion externals

Tags:

mercurial

The FAQ, and hginit.com have been really useful for helping me make the transition from svn to hg.

However, when it comes to using Hg's subrepository feature in the manner of subversion's externals, I've tried everythign and cannot replicate the nice behavior of svn externals.

Here's the simplest example of what I want to do:

  1. Init "lib" repository This repository is never to be used as a standalone; it's always included by main repositories, as a sub-repository.

  2. Init one or more including repositories To keep the example simple, I'll "init" a repository called "main"

  3. Have "main" include "lib" as a subrepository

  4. Importantly -- AND HERE'S WHAT I CAN'T GET TO WORK: When I modify a file inside of "main/lib", and I push the modification, then that change gets pushed to the "lib" repository -- NOT to a copy inside of "main".

Command lines speak louder than words. I've tried so many variations on this theme, but here's the gist. If someone can reply, in command lines, I'll be forever grateful!

1. Init "lib" repository

$ cd /home/moi/hgrepos ## Where I'm storing my hg repositories, on my main server

$ hg init lib

$ echo "foo" > lib/lib.txt

$ hg add lib

$ hg ci -A -m "Init lib" lib

2. Init "main" repository, and include "lib" as a subrepos

$ cd /home/moi/hgrepos

$ hg init main

$ echo "foo" > main/main.txt

$ hg add main

$ cd main

$ hg clone ../lib lib

$ echo "lib=lib" > .hgsub

$ hg ci -A -m "Init main" .

This all works fine, but when I make a clone of the "main" repository, and make local modifications to files in "main/lib", and push them, the changes get pushed to "main/lib", NOT to "lib".

IN COMMAND-LINE-ESE, THIS IS THE PROBLEM:

$ /home/moi/hg-test

$ hg clone ssh://[email protected]/hgrepos/lib lib

$ hg clone ssh://[email protected]/hgrepos/main main

$ cd main

$ echo foo >> lib/lib.txt

$ hg st

M lib.txt

$ hg com -m "Modified lib.txt, from inside the main repos" lib.txt

$ hg push

pushing to ssh://[email protected]/hgrepos/main/lib

That last line of output from hg shows the problem.

It shows that I've made a modification to a COPY of a file in lib, NOT to a file in the lib repository. If this were working as I'd like it to work, the push would be to hgrepos/lib, NOT to hgrepos/main/lib. I.e., I would see:

$ hg push

pushing to ssh://[email protected]/hgrepos/lib

IF YOU CAN ANSWER THIS IN TERMS

OF COMMAND LINES RATHER THAN IN ENGLISH,

I WILL BE ETERNALLY GRATEFUL!

Thank you in advance!

Emily in Portland

like image 420
Emily Dickinson Avatar asked Apr 03 '10 05:04

Emily Dickinson


People also ask

How to add an external in tortoisesvn?

Simply right drag the file or folder from one working copy to where you want those to be included as externals. A context menu appears when you release the mouse button: SVN Add as externals here if you click on that context menu entry, the svn:externals property is automatically added.

What is a Subrepo?

Subrepositories is a feature that allows you to treat a collection of repositories as a group. This will allow you to clone, commit to, push, and pull projects and their associated libraries as a group. This feature was introduced in a preliminary form in Mercurial 1.3 and has been improved steadily since then.


2 Answers

Oops, sorry for the formatting in previous answer. Here it is again, formatted!

So, here are the two scenarios most folks will be faced with:

A) Using subrepositories in a completely local situation. This is Ryan's solution, essentially. I imagine only developers working solo will be in this boat.

    cd /home/moi/hgrepos
    hg init lib
    cd lib
    echo foo > lib.txt
    hg ci -A -m Init

    cd /home/moi/hgrepos
    hg init main
    cd main
    echo foo > main.txt
    echo lib = ../lib > .hgsub
    hg clone ../lib
    hg add .hgsub main.txt
    hg ci -m Init

    cd /home/moi/hgrepos
    hg clone main main-clone
    cd main-clone/lib
    echo "Modified while on main trunk" >>lib.txt
    hg commit -m "Modified lib.txt, while on main trunk"
    hg push
    cd /home/moi/hgrepos/lib
    hg update
    1 files updated, 0 files merged, 0 files removed, 0 files unresolved

    cat lib.txt
    foo
    Modified while on main trunk

-----------------------------------------------------------------

B) Using subrepositories over ssh.
I imagine most developers working on teams will be in this boat.

1) Set up lib

cd /home/moi/hgrepos
hg init lib
cd lib
echo foo > lib.txt
hg ci -A -m Init

2) Set up main

cd /home/moi/hgrepos
hg init main
cd main
echo foo > main.txt
echo lib=ssh://[email protected]/hgrepos/lib > .hgsub
hg clone ssh://[email protected]/hgrepos/lib lib
hg add .hgsub main.txt
hg ci -m Init

3) Clone lib to hgtest dir

cd /home/moi/hgtest
hg clone ssh://[email protected]/hgrepos/lib lib

4) Clone main to hgtest dir

cd /home/moi/hgtest
hg clone ssh://[email protected]/hgrepos/main main

5) Modify lib.txt while on main trunk

cd /home/moi/hgtest/main/lib
echo "Modified while on main trunk" >>lib.txt
hg commit -m "Modified lib.txt, while on main trunk"
hg push

6) Verify that lib.txt got changed in the lib repository

cd /home/moi/hgtest/lib
hg pull
hg update
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
cat lib.txt
foo
Modified while on main trunk
like image 24
2 revs, 2 users 79% Avatar answered Sep 21 '22 22:09

2 revs, 2 users 79%


The problem is with your .hgsub file. It points to where the lib repo is, so if lib is a sibling to main it should be:

lib=../lib

Also your hg add lib and hg add main lines don't make sense. To what repo outside of main and lib are those being added? You're running them while in in /home/moi/hgrepos.

Here's your script with some tweaks:

+ cd /home/ry4an/hgtest
+ hg init lib
+ echo foo
+ cd lib
+ hg commit -A -m Init lib
adding lib.txt
+ cd /home/ry4an/hgtest
+ hg init main
+ echo foo
+ cd main
+ echo lib=../lib
+ hg clone ../lib
destination directory: lib
updating to branch default
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+ hg add .hgsub main.txt
+ hg commit -m Init main: initial file and a .hgsub
committing subrepository lib
+ cd /home/ry4an/hgtest
+ hg clone main main-clone
updating to branch default
pulling subrepo lib
requesting all changes
adding changesets
adding manifests
adding file changes
added 1 changesets with 1 changes to 1 files
3 files updated, 0 files merged, 0 files removed, 0 files unresolved
+ cd main-clone
+ echo foo
+ hg commit -m Modified lib.txt, from inside the main repos
committing subrepository lib
+ hg push
pushing to /home/ry4an/hgtest/main
pushing subrepo lib
searching for changes
adding changesets
adding manifests
adding file changes
added 1 changesets with 1 changes to 1 files
searching for changes
adding changesets
adding manifests
adding file changes
added 1 changesets with 1 changes to 1 files

To do that over ssh:// you need only make a single change. When cloning the main repo change hg clone main main-clone to hg clone ssh://host/hgtest/main main-clone -- cloning the main automatically clones the lib -- that's the subrepo benefit.

Here's a log of that working:

+ cd /home/ry4an/hgtest
+ hg init lib
+ echo foo
+ cd lib
+ hg commit -A -m Init lib
adding lib.txt
+ cd /home/ry4an/hgtest
+ hg init main
+ echo foo
+ cd main
+ echo lib=../lib
+ hg clone ../lib
destination directory: lib
updating to branch default
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+ hg add .hgsub main.txt
+ hg commit -m Init main: initial file and a .hgsub
committing subrepository lib
+ cd /home/ry4an/hgtest
+ hg clone ssh://localhost/hgtest/main main-clone
The authenticity of host 'localhost (::1)' can't be established.
RSA key fingerprint is 0c:58:d6:d3:d3:16:14:ee:3b:be:01:bc:c7:3c:92:0b.
Are you sure you want to continue connecting (yes/no)? yes
ry4an@localhost's password: 
requesting all changes
adding changesets
adding manifests
adding file changes
added 1 changesets with 3 changes to 3 files
updating to branch default
pulling subrepo lib
ry4an@localhost's password: 
requesting all changes
adding changesets
adding manifests
adding file changes
added 1 changesets with 1 changes to 1 files
3 files updated, 0 files merged, 0 files removed, 0 files unresolved
remote: Warning: Permanently added 'localhost' (RSA) to the list of known hosts.
+ cd main-clone
+ echo foo
+ hg commit -m Modified lib.txt, from inside the main repos
committing subrepository lib
+ hg push
ry4an@localhost's password: 
pushing to ssh://localhost/hgtest/main
pushing subrepo lib
ry4an@localhost's password: 
searching for changes
remote: adding changesets
remote: adding manifests
remote: adding file changes
remote: added 1 changesets with 1 changes to 1 files
searching for changes
remote: adding changesets
remote: adding manifests
remote: adding file changes
remote: added 1 changesets with 1 changes to 1 files
like image 57
Ry4an Brase Avatar answered Sep 21 '22 22:09

Ry4an Brase