Strip a Mercurial branch on the server side - mercurial

We have a SOLUTION folder (Mercurial repository) in whitch we have a PROJECT folder, that is also a Mercurial repository.
So two repositories: one - the root(solution) folder and other - a subfolder of the root folder(the project) (yes strange but it is like this)...
Everything worked, but one day someone somehow included the SOLUTION branch into the PROJECT repository... So all the history from the Solution branch was included in parralel with the Project branch into the PROJECT repository....
Now is a little mess in the PROJECT repository... There is need to clean that repository...
Locally it worked by applying the hg strip rev XXS (where XXS was the revision number of the very first node from the freshly added Solution branch in the Project repository).
But it seems there is no strip equivalent on the server?!
Every time we'll pull incoming changes in the Project repository, the "Solution" branch will be re-imported....
Is there a way to manage it on the server side?

Of course the same solution would also work on the server. Thus you need login access to the server itself to execute the same local history operation on it. But for the default setup (publishing server) a push will never remove changesets which are present on a remote location; when you history edit your local repository, the changes will not all propagate: only additions to the graph will, but no deletions.
If such changes to the remote server are expected to be pushed, and this is a regular thing, you might want to look into use of phases and how to setup a non-publishing server, e.g. a server with mutable history: Phases#Publishing_Repository.
Mind that such a workflow also means that every single one of the people with push privilige has to change their default phase to 'draft' instead of 'public' - at least for that project.

kill the server repo. start a fresh one, then from local:
hg push -rev XXR
where XXR is the last rev you want to keep.

Related

Mercurial - how to make a local central repository

I would like to have a central repository in a directory on my local computer without setting up a server.
Context: I am working with my boss on a local server inside our LAN. We both are using a vnc connection onto the server, and are doing our work there for simplicity reasons. I would like to set it up so that I can have a copy of my scripts for development, and then when I get to a release, I will push it to a different directory that my boss can then run them from (or even better pull from to his own set and run from there).
I read that you can create a hg server by running 'hg serve', but I do not want to open it up to the LAN, because I don't want it to be accessible.
I tried running 'hg push /home/source' and it gave me an error.
I then ran 'hg init' while in that directory and tried again. It looked like it worked, and then didn't show any files in the directory. I ran status and it showed nothing, and then ran log and it showed the commits.
... without setting up a server
One way I've used to share a "central" Mercurial repository without having to deal with any "server" issues is to have the "central" repository in a folder on Dropbox.
For example, suppose:
your repository is named "repo" and that your "private" copy is in ~/repo
your Dropbox directory on your computer is ~/Dropbox/
Then:
cd ~/Dropbox
hg clone ~/repo
Now suppose you make some changes in ~/repo. You can then "push" them from ~/repo to ~/Dropbox/repo, or (more easily, as explained below) "pull" them into ~/Dropbox/repo when you're ready.
To make updating the "central" repository convenient, you might like to create a script such as:
#!/bin/bash
cd ~/Dropbox/repo
hg tip
hg pull -u
hg tip
Notice that in the script, there is no need to specify the source from which to pull; the hgrc file that's created when you created the clone keeps track of that. (Thank you, hg.)
If your colleague has direct access to a folder on your computer, then you could still adopt the strategy described above, without using Dropbox.
Needless to say, there are many variations.
Needless to say also, if more than one person attempts to commit changes to the shared folder, chaos can easily ensue.

Mercurial - Rename/Merge Repository

We use Mercurial and have set up a repo server to which all local/developer changes are pushed to/pulled from. I came back from vacation to find that one of our repos has been replaced. Apparently a developer was having issues pushing commits to it and figured the only solution was to blow away the repo on our server and push a new one from his machine under a new name. Not sure how, but in doing this we lost all the change history of the project before it was blown away.
I still have the full repo history on my local machine up to that point and would like to merge the new repo with the old repo and have the full change history retained. I'm hesitant to do a pull/update to my machine in case I lose the history.
I also want to update the name of the repo directory on the server because now some of our tools have broken paths to the repo and would prefer reverting back to the original directory name insted of updating all our tools' references.
I think I can use the hg rename to do what I want regarding the rename, but how do I merge the two repos into one?
I found a way to merge by following (somewhat) the instructions here: https://www.mercurial-scm.org/wiki/MergingUnrelatedRepositories
First I made a copy of my local repo in case things went sideways
I cloned the repo on the server to the name I wanted it to be and which matched my local repo
I did a pull on the server repo to my local one and instead of doing an update, did a merge
Resolved merge diffs and committed locally
Pushed changes to new server repo, confirmed full change history was in place
Removed old server repo

How can I keep some modifications from propagating in mercurial?

I am developing a web database that is already in use for about a dozen separate installations, most of which I also manage. Each installation has a fair bit of local configuration and customization. Having just switched to mercurial from svn, I would like to take advantage of its distributed nature to keep track of local modifications. I have set up each installed server as its own repo (and configured apache not to serve the .hg directories).
My difficulty is that the development tree also contains local configuration, and I want to avoid placing every bit of it in an unversioned config file. So, how do I set things up to avoid propagating local configuration to the master repo and to the installed copies?
Example: I have a long config.ini file that should be versioned and distributed. The "clean" version contains placeholders for the database connection parameters, and I don't want the development server's passwords to end up in the repositories for the installed copies. But now and then I'll make changes (e.g., new defaults) that I do need to propagate. There are several files in a similar situation.
The best I could work out so far involves installing mq and turning the local modifications into a patch (two patches, actually, with logically separate changesets). Every time I want to commit a regular changeset to the local repo, I need to pop all patches, commit the modifications, and re-apply the patches. When I'm ready to push to the master repo, I must again pop the patches, push, and re-apply them. This is all convoluted and error-prone.
The only other alternative I can see is to forget about push and only propagate changesets as patches, which seems like an even worse solution. Can someone suggest a better set-up? I can't imagine that this is such an unusual configuration, but I haven't found anything about it.
Edit: After following up on the suggestions here, I'm coming to the conclusion that named branches plus rebase provide a simple and workable solution. I've added a description in the form of my own answer. Please take a look.
From your comments, it looks like you are already familiar with the best practice for dealing with this: version a configuration template, and keep the actual configuration unversioned.
But since you aren't happy with that solution, here is another one you can try:
Mercurial 2.1 introduced the concept of Phases. The phase is changeset metadata marking it as "secret", "draft" or "public". Normally this metadata is used and manipulated automatically by mercurial and its extensions without the user needing to be aware of it.
However, if you made a changeset 1234 which you never want to push to other repositories, you can enforce this by manually marking it as secret like this:
hg phase --force --secret -r 1234
If you then try to push to another repository, it will be ignored with this warning:
pushing to http://example.com/some/other/repository
searching for changes
no changes found (ignored 1 secret changesets)
This solution allows you to
version the local configuration changes
prevent those changes from being pushed accidentally
merge your local changes with other changes which you pull in
The big downside is of course that you cannot push changes which you made on top of this secret changeset (because that would push the secret changeset along). You'll have to rebase any such changes before you can push them.
If the problem with a versioned template and an unversioned local copy is that changes to the template don't make it into the local copies, how about modifying your app to use an unversioned localconfig.ini and fallback to a versioned config.ini for missing parameters. This way new default parameters can be added to config.ini and be propagated into your app.
Having followed up on the suggestions here, I came to the conclusion that named branches plus rebase provide a simple and reliable solution. I've been using the following method for some time now and it works very well. Basically, the history around the local changes is separated into named branches which can be easily rearranged with rebase.
I use a branch local for configuration information. When all my repos support Phases, I'll mark the local branch secret; but the method works without it. local depends on default, but default does not depend on local so it can be pushed independently (with hg push -r default). Here's how it works:
Suppose the main line of development is in the default branch. (You could have more branches; this is for concreteness). There is a master (stable) repo that does not contain passwords etc.:
---o--o--o (default)
In each deployed (non-development) clone, I create a branch local and commit all local state to it.
...o--o--o (default)
\
L--L (local)
Updates from upstream will always be in default. Whenever I pull updates, I merge them into local (n is a sequence of new updates):
...o--o--o--n--n (default)
\ \
L--L--N (local)
The local branch tracks the evolution of default, and I can still return to old configurations if something goes wrong.
On the development server, I start with the same set-up: a local branch with config settings as above. This will never be pushed. But at the tip of local I create a third branch, dev. This is where new development happens.
...o--o (default)
\
L--L (local)
\
d--d--d (dev)
When I am ready to publish some features to the main repository, I first rebase the entire dev branch onto the tip of default:
hg rebase --source "min(branch('dev'))" --dest default --detach
The previous tree becomes:
...o--o--d--d--d (default)
\
L--L (local)
The rebased changesets now belong to branch default. (With feature branches, add --keepbranches to the rebase command to retain the branch name). The new features no longer have any ancestors in local, and I can publish them with push -r default without dragging along the local revisions. (Never merge from local into default; only the other way around). If you forget to say -r default when pushing, no problem: Your push gets rejected since it would add a new head.
On the development server, I merge the rebased revs into local as if I'd just pulled them:
...o--o--d--d--d (default)
\ \
L--L-----N (local)
I can now create a new dev branch on top of local, and continue development.
This has the benefits that I can develop on a version-controlled, configured setup; that I don't need to mess with patches; that previous configuration stages remain in the history (if my webserver stops working after an update, I can update back to a configured version); and that I only rebase once, when I'm ready to publish changes. The rebasing and subsequent merge might lead to conflicts if a revision conflicts with local configuration changes; but if that's going to happen, it's better if they occur when merge facilities can help resolve them.
1 Mercurial have (follow-up to comments) selective (string-based) commit - see Record Extension
2 Local changes inside versioned public files can be easy received with MQ Extension (I do it for site-configs all time). Your headache with MQ
Every time I want to commit a regular changeset to the local repo, I
need to pop all patches, commit the modifications, and re-apply the
patches. When I'm ready to push to the master repo, I must again pop
the patches, push, and re-apply them.
is a result of not polished workflow and (some) misinterpretation. If you want commit without MQ-patches - don't do it by hand. Add alias for commit, which qop -all + commit and use this new command only. And when you push, you may don't worry about MQ-state - you push changesets from repo, not WC state. Local repo can also be protected without alias by pre-commit hook checking content.
3 You can try LocalBranches extension, where your local changes stored inside local branches (and merge branches on changes) - I found this way more troublesome, compared to MQ

Mercurial central server file discrepancy (using 'diff to local')

Newbie alert!
OK, I have a working central Mercurial repository that I've been working with for several weeks.
Everything has been great until I hit a really bizarre problem: my central server doesn't seem to be synced to itself? I only have one file that seems to be out-of-sync right now, but I really need to know how this happened to prevent it from happening in the future.
Scenario:
1) created Mercurial repository on server using an existing project directory. The directory contained the file 'mypage.aspx'.
2) On my workstation, I cloned the central repository
3) I made an edit to mypage.aspx
4) hg commit, then hg push from my workstation to the central server
5) now if I look at mypage.aspx on the server's repository using TortoiseHg's repository explorer, I see the change history for mypage.aspx -- an initial check-in and one edit. However, when I select 'Diff to local', it shows the current version on the server's disk is the original version, not the edited version!
I have not experimented with branching at all yet, so I'm sure I'm not getting a branch problem.
'hg status' on the server or client returns no pending changes.
If I create a clone of the server's repository to a new location, I see the same change history as I would expect, but the file on disk doesn't contain my edit.
So, to recap:
Central repository = original file, but shows change in revision history (bad)
Local repository 'A' = updated file, shows change in revision history (good)
Local repository 'B' = original file, but shows change in revision history (bad)
Help please!
Thanks,
David
Sounds like you're looking at the working copy on the central repo. Just like your local repo, there is a working copy. Running hg update (or "Update to branch tip" in TortoiseHg) should sync the central repo's working copy to the latest.
This is normal, as the repository on the server has two components: the actual repository of changesets (in the .hg subdirectory), and a working copy. When you push changes from the local repository on your workstation to the server repository, it updates the repository files on the server (in the .hg subdir), but it does not change the working copy files (outside the .hg subdir): this would require an explicit update operation on the server to change the working copy.
If the server repository is only being used as a repository, and you do all your actual work in clones, then you're probably better off using a "bare repository" on the server (just delete the working copy files and just keep only .hg subdirectory itself).

Storing separate named branches in mercurial without having to merge them

It's my first time using a DVCS and also as a lone developer, the first time that I've actually used branches, so maybe I'm missing something here.
I have a remote repository from which I pulled the files and started working. Changes were pushed to the remote repository and of course this simple scenario works fine.
Now that my web application has some stable features, I'd like to start deploying it and so I cloned the remote repository to a new branches/stable directory outside of my working directory for the default branch and used:
hg branch stable
to create a new named branch. I created a bunch of deployment scripts that are needed only by the stable branch and I committed them as needed. Again this worked fine.
Now when I went back to my initial working directory to work on some new features, I found out that Mercurial insists on only ONE head being in the remote repository. In other words, I'd have to merge the two branches (default and stable), adding in the unneeded deployment scripts to my default branch in order to push to the main repository. This could get worse, if I had to make a change to a file in my stable branch in order to deploy.
How do I keep my named branches separate in Mercurial? Do I have to create two separate remote repositories to do so? In which case the named branches lose their value. Am I missing something here?
Use hg push -f to force the creation of a new remote head.
The reason push won't do it by default is that it's trying to remind you to pull and merge in case you forgot. What you don't want to happen is:
You and I check out revision 100 of named branch "X".
You commit locally and push.
I commit locally and push.
Now branch X looks like this in the remote repo:
--(100)--(101)
\
\---------(102)
Which head should a new developer grab if they're checking out the branch? Who knows.
After re reading the section on named branchy development in the Mercurial book, I've concluded that for me personally, the best practice is to have separate shared repositories, one for each branch. I was on the free account at bitbucket.org, so I was trying to force myself to use only one shared repository, which created the problem.
I've bit the bullet and got myself a paid account so that I can keep a separate shared repository for my stable releases.
You wrote:
I found out that Mercurial insists on only ONE head being in the remote repository.
Why do you think this is the case?
From the help for hg push:
By default, push will refuse to run if it detects the result would
increase the number of remote heads. This generally indicates the
the client has forgotten to pull and merge before pushing.
If you know that you are intentionally creating a new head in the remote repository, and this is desirable, use the -f flag.
I've come from git expecting the same thing. Just pushing the top looks like it might be one approach.
hg push -r tip