Why are my mercurial bundles including "extra revisions" - mercurial

We use bundles to synchronize our mercurial repositories over email.
For the past few hundred revisions, we've noticed the bundle size is typically around 600k, no matter what we include. It appears that Mercurial is including revisions other than what we're specifying. I theorized that it was from open branches, but closing all of our branches didn't fix it. When I create a bundle for the latest revision, it says that it includes 5 revisions.
I would normally expect our bundles to only be a few dozen kilobytes.
Under what circumstances would Mercurial include other revisions in a bundle?

Have you looked inside the resulting bundles to see what changesets are in there. You can do that with the incoming command on the receiving repo. Here are some tips:
https://www.mercurial-scm.org/wiki/LookingIntoBundles

Closing the branches may not be enough. Try closing, then merging the branch.

Related

Synchronizing actual version of Mercurial repository for multiple workplaces

I have three different Linux-based working places, each with a different computer. I need to have a repository synchronized to keep coding on the latest version each time I move from a workplace to another. You can always commit and push to, say, bitbucket and then pull from another computer, but this is not the purpose of a commit.
Other similar posts did not help, like Synchronizing a collection of Mercurial repositories.
Any suggestion?
Your two primary options for exchanging temporary work between repositories are Mercurial Queues and the evolve extension.
Mercurial Queues are documented fairly extensively here. To use them for your purpose, you have to put the patches under version control (explained near the bottom of the chapter) and can then push them to/pull them from a shared patch repository. Note that the book is a few years old and Mercurial has added some convenience features in the meantime. These days you can do operations on the patch repository directly via the --mq option (e.g., hg init --mq, hg commit --mq, hg push --mq) and don't need a bash alias for convenience.
Evolve is probably more intuitive; it provides a fairly straightforward approach to shared mutable history. You can commit changes in one repository, push the changes to a shared repository, pull from another and uncommit or alter them, then push them back.
In order to set this up, you need a shared repository somewhere that is declared as non-publishing. You do this by adding the following lines to its .hg/hgrc:
[phases]
publish = False
This prevents changesets exchanged through this repository from becoming public (at which point, they'd become immutable).
You will also need to install the extension first (unlike MQ, which is part of core Mercurial).
Note that Bitbucket currently does not support obsolescence markers, which are crucial for the functioning of changeset evolution, so you will need to host the shared repository in a different place. Evolve functions not by deleting outdated changesets, but by marking them as obsolete and hiding them (obsolescence markers also track how old and new changesets are related). Because Bitbucket does not support these markers, obsolete changesets will become visible again if pushed there. (Note that you can still use evolve locally or between evolve-aware repositories and use Bitbucket for public stuff.)
Slightly different ways:
Handwork
MQ with MQCollab extension
Commits with "classic" exchange between repos using MuliRepo extension (just don't forget hg pull on every workplace before pull - and add all remote repos into [multirepo] section on each workplace)
Automated way
Create additional "central hub" and use AutoSync extension

How to graft from other repository?

I have two repositories with tho different mercurual named branches, say V1 and V2. The branches are divergent since about one-two years. I'd like to graft some changesets from one repo into the other, without pulling the changes.
I don't want to pull the changes for multiple reasons.
I don't want to conflict developers with history of multiple branches, because there will be enough local branches to care about.
I want to have single branch central repos and developers could accidently push the second branch. The central branches would interact with SVN and should have only one branch per repo. I know I could use central hooks, to prevent such a push, but I don't want questions like, can't push, or how can I do that.
The size of the repo would grow to multiple gigabytes (before pull about 700MB). As I understand, it's because of deficites of current mercurial storage format.
I know, the transplant extension can do the work. I tried it, but I can't force other developers to handle rejects instead of simply use a merge tool. Is there an other way?
In fact there are more then two repos with each a branch, but for the example simplicity two should be enough.
You might be able to do the work in an intermediate repo:
Pull in the changes
Do whatever grafting/rebasing/transplanting you need
Strip out the things you pulled in step 1. or if that doesn't work:
Pull only the changes from the branch you want into the actual repo
You'd end up with a repository that includes your desired change sets, but not all the history from the unwanted branch.
Follow-up to #DanMan
Pull needed branch into intermediate repo
Strip unwanted changesets in clone
hg pull CLONE in real target
Write a tool, a hg-extension or extend the graft command so it can graft from a second repository, similar to the transplant extension.
Yes, the implementation is not so easy as adding the second-repo-functionality in the transplant command. The transplant extension simply uses a patch from an other repo instead of one from own repo. But I think also for graft there is no technical reason, not to do that.
If I understand right, grafting of a single file change is not more than calling the merge tool with the files:
(base) the parent of the to-graft changeset
(my changes) the target revision, on which to graft
(theirs) the to-graft refision
So in order to graft a file change from an other repo, the whole file from other repo is needed before the to-graft changeset was applied (base) and after it was applied (theirs). Technically it should be no problem.
Additionally the implementation
need to determine, which files are affected by the changeset to graft
need to handle deletions correctly
need to handle file renamings (not sure, how complicated it is)
All that should be possible, I see no real technical problems.

Is there a way to skip a commit when pushing

I had commited an exploratory and buggy changeset locally. The bug has been fixed in the next local commit. Now I want to push the debugged version but in a way that skips the buggy local commit. Is there a way to do this simply.
Short answer: no.
Long answer: you can leave a chain of recent commits out of a push but you can't miss out parts of the chain when you push. This is because mercurial tracks the changes you made at the point of committing and your most recent changeset probably doesn't make sense outside of the context of the buggy one.
Options:
Some people would recommend using the MQ extension to avoid this problem in the future.
Some people would recommend using the MQ extension to strip out both changesets and then re-commit only the fixed version. This can cause trouble, particularly if you've already shared your changesets with anyone.
Some people (including me) would recommend just leaving your repository as it is and pushing both changesets. There's only shame in a buggy changeset if you don't fix it.
4 Some people (including me) would recommend using the MQ extension for folding two consecutive changesets into single before push
5 Some people would recommend using the histedit or colapse extension for folding two consecutive changesets into single before push
You could try this :
Export the commit you want to go through as a patch
Re-clone your repository in a new directory
Apply the patch
Now perform the single commit to your shared repository

Mercurial repo inside a repo

Is it possible to create a mercurial repository inside an existing mercurial repository?
The idea is to handle subdirectories of a repository as different repositories, how do you do that?
I'm not talking about subrepos (at least, if I understood the purpose of subrepos...), but if this is how subrepos do exist for, I got it wrong and I'll try to get it right :)
Thanks
~Aki
EDIT: To be more clear, I'd like to know what happens, the practices and the implications of having a repository inside another one, without specifying modules/subrepos.
In other words: what happens if I just do:
hg init globalRepo
hg init globalRepo/subRepo
and use these two repositories as-are?
It works well. Long before the subrepo support was added in Mercurial 1.3, lots of folks kept their entire home directories in a mercurial repo for tracking their .bashrc files and the like. Then within their home dir they'd have many clones of other repos.
Whenever you invoke mercurial (without the -R option) it looks in the current directory for a .hg directory and then just keeps going up directories until it finds one. So if you're in a repo that is in a repo, your commands will always act on the innermost repo you're in.
The caveat is that you want to make sure not to have files added to the outer repo that end up inside the inner repo. Then you'll have two repos updating the same files.
As you can see in this SO question, you can make that kind of nested hg init, even though it is usually reserved for defining subRepo (which is not what you are after).
Normally it should work as two independant repos, but I would advise adding an hgignore rule in the globalRepo in order to ignore the subRepo content altogether.
Here are some docs on nested repositories.

Ponderings of a Subversion User: What is a "branch" in Mercurial terms?

I'm a Subversion user, and I think I've got my head mostly around it all now. So of course now we're thinking of switching to Mercurial, and I need to start again.
In our single repository, we have the typical branches, tags, trunk layout. When I want to create a feature branch I:
Use the repo browser to copy trunk to branches/Features/[FeatureName].
Checkout a new working copy from branches/Features/[FeatureName].
Start working on it.
Occasionally commit, merge trunk in, resolve conflicts and commit.
When complete, one more merge of trunk, then "Reintegrate" the feature branch into trunk.
(Please note this process is simplified as it doesn't take into account release candidate branches etc).
So I have questions about how I'd fulfil the same requirements (i.e. feature branches rather than working on trunk) in Mercurial:
In Mercurial, is a branch still within the repository, or is it a whole new local repository?
If we each have a copy of the whole repository, does that mean we all have copies of each other's various feature branches (that's a lot of data transfer)?
I know Mercurial is a DCVS, but does that mean we push/pull changes from each other directly, rather than via a peer repository on a server?
I recommend reading this guide
http://stevelosh.com/blog/2009/08/a-guide-to-branching-in-mercurial//
In Mercurial, is a branch still within
the repository, or is it a whole new
local repository?
The equivalent of the subversion way of working would be a repository with multiple heads in mercurial. However, this is not the idiomatic way of doing things. Typically you will have only one head in a given repository, so separate repositories for each branch.
If we each have a copy of the whole
repository, does that mean we all have
copies of each other's various feature
branches (that's a lot of data
transfer)?
Yes, if you look at the history of the head of your local repository, then you'll be able to see all the feature branches that were merged in. But mercurial repositories are remarkably space efficient. For example, I have done a hg clone https://www.mercurial-scm.org/repo/hg to get the source for mercurial itself, and it is only 34.3 MB on an NTFS file system (compared to the source code download, which is 1.8 MB). Mercurial will also make use of hardlinks if your file system supports it, so there is little overhead if you clone a repository to another location on the same disk.
I know Mercurial is a DCVS, but does
that mean we push/pull changes from
each other directly, rather than via a
peer repository on a server?
One way of working is indeed to have each developer expose a public repository in which he pushes his own changes. All other developers can then pull what they want.
However, typically you'll have one or more "blessed" repositories where all the changes are integrated. All developers then only need to pull from the blessed repository. Even if you didn't explicitly have such a blessed repository I imagine people would automatically organize themselves like that, e.g. by all pulling from a lead developer.
Steve Losh's article on branching in mercurial linked above is fantastic. I also got into some explaining of branching and how the DAG works in a presentation I gave a couple of months ago on mercurial that's out on slideshare. The pertinent slides start at slide #43.
I think that understanding that all commits to the same repository are stored in a DAG (Directed Acyclic Graph) with some simple rules really helps demystify what's going on.
a node with no child nodes is a "head"
the root node has no parents
regular nodes have a single parent
nodes that are the result of a merge have two parents
if a merge node's parents are from different branches, the child node's branch is inherited from the first parent
Named branches are really just metadata labels on commits, but really aren't any different than the anonymous branches that happen when you merge someone elses work into your repository, or if you go back to an earlier version and then make a commit there to make a new head (which you can later merge).