Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is DVCS (Mercurial) not for me?

I work in a company where we create a lot of small customer-specific applications. We are a few developers but most of the time there is only one developer per project.

Customer1
    ProjectX
        App
        Tests
    ProjectY
        App
        Tests
Customer2
    Project2
Products
    Product1
Common

Today everything is stored in a single repository.

The process is simple.

  1. A developer takes on a new project for a customer
  2. Create a new folder for the project
  3. Code in new project
  4. Do some maintenance in another project
  5. Check in updates to maintenance project
  6. More work in new project
  7. Check in new project
  8. Deliver to customer

There is no tagging nor branching. Earlier versions are checked out based on date.

This process has served well for many years but there are a few pain points with the current tool (CVS)

  • Slow. Checkout takes minutes even if nothing has changed. History is stored on the server so diffs takes too long time
  • Adding new projects. If you worked with CVS you know it is like: add folder, add files in folder, add next folder...
  • No way to back out obvious errors (checking in binaries etc)
  • No support for renaming which makes necessary refactoring even more painful.

I have used Mercurial privately for some time and would like to extend it to all developers.

I might have got it all wrong but there are a few things that I don't understand how to implement in our organization.

CVS commits are current folder only but in mercurial they are repository wide. In our case it means that committing maintenance work in one folder will also commit yet unfinished stuff in another folder. (I assume we could do hg ci ./** in changed folders but that is not allowed on merge, at least that is what the documentation says If you are committing the result of a merge, do not provide any filenames or -I/-X filters.)

The common practice in Mercurial is to have one repository per project.

One repository per project is OK for us but it creates some other issues like:

How to manage multiple repositories on the central server?
If a developer creates a new project he eventually need to push his changes. Just doing

hg push http://localhost:8000/Customer1/NewProject

crashes the hg-webserver with an ugly stack dump and hangs the client.

The way I understand it is that the developer need access to the server shell to add the new repository to a configuration file and restart hgweb

The alternative is to use SSH or a share (are there benefits using SSH instead of a file share?)

cd Customer\NewProject
hg init
hg clone --noupdate --pull . //mercurialshare\Customer\Project
echo "[paths]" >.hg\hgrc
echo "default=//mercurialshare\Customer\Project" >>.hg\hgrc

hg push

Works, but is a bit to complicated for some developers

All developers need to have all projects.
(Not really all but many projects are linked so they need to be present and it is easiest to just have all)

With many existing projects and new ones added weekly we need a way to pull all projects in one go and also clone new ones.

I was thinking that subrepos could solve the "global" pull but the following line in the documentation is a showstopper

"When we commit, Mercurial will attempt to create a consistent snapshot of the state of the entire project and its subrepos. It does this by first attempting to commit in all modified subrepos and then recording the state of all subrepos."

Back to the single repository problem of global commits.

(Tried a few variants of hg ci .hgsub .hgsubstate <subrepo> but .hgsubstate seem to only be updated on full commits. Other users will not see project changes without an explicit hg pull --update in the project folder)

My current thinking is to have a batch file in the root that pulls all projects

Any other ideas on how to use mercurial in our organization?

Edit

Thanks for the reply. I am currently evaluating how one repository per project will work for us. I put a batch file at the top level

FOR /F %%x IN (repolist.txt) DO (
    If EXIST .\%%x\.hg (
        ECHO Pull %%x
        hg pull --update --repository .\%%x
    ) ELSE (
        ECHO Clone %%x
        mkdir .\%%x
        hg clone --pull %1\%%x .\%%x
    )
)
like image 367
adrianm Avatar asked Nov 07 '10 20:11

adrianm


1 Answers

Your right in saying that Mercurial is designed for one project per repo. It's also a lot nicer when you work like this because the history of different projects are kept separate.

Trying to have multiple projects in a DVCS repo just causes pain.

Personally I prefer serving projects via SSH rather than HTTP. One reason is the ability to...

# hg init blah
# hg clone blah ssh://server/blah

If you're serving via HTTP this doesn't work (as you've found out). I'm surprised it causes a hard crash though :-/

The sub-repos method of getting all projects isn't quite as you describe it. It's not that you're back to global commits (projects can be developed individually), but that the super-project stores the version of the sub-projects it depends on. This is exactly what you want if you have (for example) a library as a subproject, but the release depends on a specific version. Effectively a sub-repo link is a bookmark into another repo at a specific version.

Not really what you're after though.

Possibly, the common stuff should be a sub-repo of the projects that need it. Each project might then be frozen on a different version of the same code and you've got no problems. That would need a little thinking about.

Otherwise the script idea is probably easiest.

like image 149
Paul S Avatar answered Sep 23 '22 20:09

Paul S