views:

108

answers:

2

I'm using Mercurial in a recent project. On the web server where I'm deploying the project I have a slightly different config file with production settings. The problem is when I pull and update, I often have to merge and commit as well.

Is this the correct workflow? It seems strange that in order to be able to continue to update I have to be committing the changesets, I figured a merge would integrate them into my production branch and continue to do so each time i update. Is this a distributed version control paradigm I'm just not used to yet?

+4  A: 

This was sort of handled in this question, but I think your question is better in that it seeks a little more clarity.

In short: Yes, it's normal. Here's a bit of an expanation:

You start out with this in the main repository (where the boxes are changesets):

main: --[E]--[F]--[G]

then you clone to the production server and add a changeset, H, that does the deployment customization. So the deployment repo looks like this:

production: --[E]--[F]--[G]--[H]

and then more work happens on the main repo, adding changesets, I and J, making the main repo look like:

main: --[E]--[F]--[G]--[I]--[J]

which when pulled to production looks like:

production:  --[E]--[F]--[G]--[I]--[J]
                            \         
                             \-[H]

with two heads, which you merge to get:

production:  --[E]--[F]--[G]--[I]--[J]
                            \         \
                             \-[H]-----[K]

where K is just J plus the changes you originally did in H.

Now more work happens in main, giving:

main: --[E]--[F]--[G]--[I]--[J]--[L]--[M]

which you pull in production giving:

production:  --[E]--[F]--[G]--[I]--[J]--[L]--[M]
                            \         \
                             \-[H]-----[K]

and then you merge and get:

production:  --[E]--[F]--[G]--[I]--[J]--[L]--[M]
                            \         \         \
                             \-[H]-----[K]-------[N]

So every time you bring changes in from main, you're doing one merge, and creating one new changeset (this time N).

I think that's okay, and it is "normal".

You can, however, avoid it by using some of the answers in the question I linked to above and there's a new trick you can use to keep modifying the original H's parents (and content) so that it always moves to the end of whatever is the new tip.

The trick is the Rebase Extension and it would yield linear history on production (though you'd still be doing what's essentially a merge to get it). I'm not a fan of it because I don't like changing changesets after they're committed, but since H is never leaving the production box it's okay.

The other answers were mercurial queues and making the production changes live in the dev repo and get triggered by something that's different in the production environment (like the Host: header).

Ry4an
So basically I should continue to pull,update,merge,commit each time? I'll never push the server's branch back to the mainline, so I guess this is alright.
Soviut
This is a great explanation of the DVCS side of things, but the actual solution to your problem (IMO) is never to commit the server-specific settings into Mercurial in the first place (see Steve Losh's answer).
Carl Meyer
Soviut: yes, that's what I'd do, but I hope it's become clear that while that's okay, in the end it's a matter of preference about who formal you want to be.Carl: yeah, that's on of the suggestions that came up in the similar question to which I linked, but I just get so wiggy about anything existing outside of source control, but I know that's not universal.
Ry4an
I feel weird committing on the server with "server update." as my commit message. Just not used to the fact that its a separate branch that will never get pushed.
Soviut
+4  A: 

One option is to keep the server-specific deployment settings out of the version control repository entirely.

This means uploading them and changing them by hand on the server, but eliminates the need to constantly merge. It also keeps things like database passwords out of version control, which is probably a good thing.

For example, when I work on a Django application I check in a settings.py file that contains:

  • All the settings that won't vary between servers (site name, installed Django apps, etc).
  • "Server-specific" settings (database location, etc) for local development.
  • The line from deploy import * at the end.

The from deploy import * line pulls in all items in the deploy.py file if one exists. On a test/staging/production server I'll create this file and put the server-specific settings inside. Because the import happens at the end of settings.py these will overwrite any of the local-development-specific settings in the main settings file.

Doing it this way means that everything needed to run and develop locally is checked into version control, but no server-specific and/or sensitive information (like passwords) are checked in (and so never needs to be merged). It requires a little bit of extra work to set up (adding the import line and creating the deploy.py file on the server initially).

This particular scheme is for a Django project, but maybe a similar idea would work for you.

Steve Losh
That's a totally reasonable approach, but I also get so nervous when there's anything important that's not in source control. I liked your winning mercurial queues suggestion over here better: http://stackoverflow.com/questions/1255624/mercurial-keep-2-branches-in-sync-but-with-certain-persistent-differences/1256040#1256040
Ry4an
That's basically what I've done, but my production_settings.py is checked into the repo as well. Some settings *were* changed on the server, but I think it would make sense to simply blow away the server branch, set all the production_settings correctly in the repo, then re-clone it. Hopefully that will avoid ever needing to recommit.
Soviut
@Ry4an: I completely forgot I answered that question, hah. I don't like keeping passwords in version control because I get nervous that some day I'll accidentally make the repo public on BitBucket or something.
Steve Losh