Is it possible to clone with hgsubversion in steps? - mercurial

I'm trying to clone a rather large subversion repository with hgsubversion.
hg clone --startrev 8890 svn+https://my.reposit.ory/trunk trunk_hg
After about an hour, the clone operation aborts with an out of memory message:
[r20097] user: description
abort: out of memory
Is it possible to specify an end revision for the clone operation and get the remaining revisions with a pull? Or somehow break up the clone in smaller steps?

You can specify a stop revision with -r for clone, as others have suggested. Another option (if you kept the clone where things crashed) would be to just run hg pull in the trunk_hg copy. You might have to edit/create .hg/hgrc yourself to add the [paths]\n default = svn+https://my.reposit.ory/trunk, since I think we add that at the end of the cloning process. Maybe run hg svn rebuildmeta before your pull just for good measure in case the tracking metadata for hgsubversion got hosed when the OOM happened.
I hope this helps!

http://www.selenic.com/mercurial/hg.1.html#clone
Could try using the -r <revid> flag to clone only a particular changeset. Though that may or may not work with hgsvn.

Cloning with a limited range of revisions and then pulling is the recommended method and I can confirm that it works flawlessly for svn repositories in the several GB size range.

Here is a workaround to clone the whole svn repo:
start cloning
abort it immediately (Ctrl+C in windows)
than hg pull
you've got out of memory
repeat step 3 until you check out all commits

Related

Mercurial error: repository is unrelated

I've just started with Mercurial, I have a 'central' repository on Bitbucket which I cloned onto one machine and made changes and committed and pushed. I then cloned from Bitbucket to another machine committed and pushed which was fine. I then came back to the first machine, made changes committed and attempted to push, but got the error message. What am I doing wrong? Should I have pulled first? How can I resolve the error and push? Any help is appreciated!
Darren.
A Mercurial repository gets its identity when you make the first commit in it. When you create a new repository on Bitbucket, you create an empty repository with no identity.
When you clone this repository to machine A and make a commit and push it back, then you brand the repository. If you have cloned the repository on the second machine before pushing from the first, then you can end up in the situation you describe.
Please run hg paths on the machine where you cannot push. Then make a separate clone of the repository it says it will push to. Now examine the first changeset in each repository with
hg log -r 0
If the initial changesets are different, then you have two unrelated repositories, as we call it in Mercurial. You can then export the changes you cannot push as patches and import them in the other.
If you're pretty sure the push path is correct, it may be worth it to just export your changes to patches from the problem repo, clone again from Bitbucket and then import the patches into the new repo. This will either just work or reveal a bad/corrupted commit.
I would like to share knowledge about Mercurial internals.
Repositories unrelated when they have no any same revisions.
Corresponding piece you can find in mercurial/treediscovery.py:
base = list(base)
if base == [nullid]:
if force:
repo.ui.warn(_("warning: repository is unrelated\n"))
else:
raise util.Abort(_("repository is unrelated"))
base is a list of roots of common parts in both local/remote repositories.
You always may know how repositories are different by:
$ hg in $REMOTE
$ hg out $REMOTE
You always may checks roots of both (after cloning both locally):
$ hg -R $ONE log -r "roots(all())"
$ hg -R $TWO log -r "roots(all())"
if output from above commands doesn't share IDs - those repositories are unrelated. Due to hash properties it is very impossible that roots be equal accidentally. You may not trick roots checking by carefully crafting repositories because building two repositories looks like these (with common parts but different roots):
0 <--- SHA-256-XXX <--- SHA-256-YYY <--- SHA-256-ZZZ
0 <--- SHA-256-YYY <--- SHA-256-ZZZ
impossible because that mean you reverse SHA-256 as each subsequent hash depends on previous values.
Having this info I believe any Devs be able to troubleshoot error: repository is unrelated.
See also Mercurial repository identification
Thanks for attention, good hacking!
You get this message when you try to push to a repository other than the one that you cloned. Double-check the address of the push, or the default path, if you're just using hg push by itself.
To check the default path, you can use hg showconfig | grep ^paths\.default (or just hg showconfig and look for the line that starts paths.default=).

Discard a local branch in Mercurial before it is pushed

Many times it happens that I have few commits on my local Hg repository which I don't want to push and sometimes I want to remove the local branch altogether. But I cannot rollback more than one commit which leaves me no choice than creating a new clone and download the whole repository again. This feels stupid, since if I could just delete my local branch which has not affected the remote repository in anyway, then I wouldn't have to create and setup a new clone. So, is it how it is in Mercurial or is there some way to discard a local branch?
Thanks!
If you enable the mq extension (bundled with Mercurial), you can use hg strip. Be careful, though, as this will modify the history of your repository. The safe method is to clone your repository up to the revision preceding the creation of the branch you want to discard, then to pull the remaining changesets that you want to keep.
I know its too late but it may be useful for any one:
If your branch is not pushed yet.
First rollback changes hg rollback only if you have done commit but
not yet pushed
Second run hg update --clean
Third run hg branch any-existing-branch
Fourth run hg pull -u
If you find yourself doing this often perhaps you should be using bookmarks instead of named branches. http://stevelosh.com/blog/2009/08/a-guide-to-branching-in-mercurial/

How do you delete a commit in Mercurial?

I want to completely delete a Mercurial commit as if it was never entered in the repository and move back to my prior commit.
Is this possible?
If it was your last commit and you haven't pushed it anywhere, you can do that with rollback. Otherwise, no. Not really. Time to change your passwords.
Edit: It has been pointed out that you can clone from an older revision and merge in the changes you want to keep. That's also true, unless you have pushed it to a repo you don't control. Once you push, your data is very likely to be very hard to get back.
You can try to remove mq info about your commit.
For this you need to go File->Settings->Extensions.
There check mq and restart gui.
After that just right click on unneeded commit and
ModifyHistory->Strip
To edit the history I would use the Histedit Extension extension.
hg histedit 45:c3a3a271d11c
However keep in mind this only makes sense in a situation where you have not yet pushed the commits to the public repository, you own the public repository and/or you can account for all the clones out there. If you receive the following error:
abort: can't rebase immutable changeset 43ab8134e7af
It means that Mecurial thinks this is a public changeset (see phases) that has already been pushed - you can force it to be a draft again doing:
hg phase -f -d 45:c3a3a271d11c
I encounter this fairly often. I make a commit and then pull to push. But then there is something incoming that makes my newly made commit unnecessary. A plain hg rollback isn't enough because it only undoes the pull...
This is the thing to do:
hg strip <rev>
Things are painless when you don't push your changesets anywhere.
If it's more than one commit and/or you already pushed it somewhere else, you can clone your repository and specify the last changeset that should be cloned.
See my answer here how to do this:
Mercurial: Fix a borked history
If you only committed locally and didn't push, you can just create a clone locally (as described in my link) and you're done.
If you already pushed to some remote repository, you would have to replace that with your clone.
Of course it depends if you are able (or allowed) to do this.
You can use "hg backout" to do a reverse merge basically. All options are discussed in the freely available book "Mercurial: The Definitive Guide":
http://hgbook.red-bean.com/read/finding-and-fixing-mistakes.html
If using tortoise you can use modify history > strip...
Yes. Unless I am mistaken, as of v2.3 (rel. 2012/08/01) you can use the HisteditExtension with a drop command to drop a commit, along with strip or backout to remove changes.
A simple Google search on the feature: https://www.google.com/webhp#q=histedit+drop
In 2022 I do use evolve extension. It is one of the best extensions for this purpose.
To prune unwanted changeset, if you for example did a quick hack to get the code working:
$ echo 'debug hack' >> file1.c
$ hg commit -m 'debug hack'
Now you have a proper patch you can do hg prune .:
$ hg prune .
1 files updated, 0 files merged, 0 files removed, 0 files unresolved
working directory is now at 2a39221aaebb
1 changesets pruned
If you push the change to the remote repository you will find only obsolescence markers:
$ hg push
searching for changes
no changes found
remote: 1 new obsolescence markers
To check the changes to your local repo you can pull from the remote one:
$ hg pull
pulling from ssh://userid#server/repo
searching for changes
no changes found

Copy Mercurial repository with uncommitted changes

I have an mercurial repositry a bitbucket.org and a clone on my wokstation. The clone has some uncommited (unfished) work in it. I have to copy these clone to my laptop because I will be on a trip for one or two weeks and want to do some work.
Is there a simple and save way to copy the repository with its uncommited changes to another device? I knew I could clone the repo from the workstation to my laptop but this won't copy uncommited work.
Simply copy the entire repository's folder.
Just commit that work. That work needs to be finished to be committed is left-over CVS/SVN thinking. Commit it, and then update to its parent and work on whatever else you want to work on. When eventually the work is done you're pushing a changegroup not individual changesets, so no one will have the uncompiling stage at the end of those interstitial changesets on them.
Avoiding committing work in Mercurial (using shelve, attic, copying repos, etc.) is the only way to lose work -- avoid it.
I prefer my first answer (commit it) but if you positively can't bring yourself to commit unfinished work then you should be using Mercurial Queues with a patch queue that lives in its own repository. This is easily done with:
hg qinit --create-repo
Then you import your uncomitted changes as a patch using:
hg qnew --force name-for-this-work
then you can:
hg qcommit -m "work in progress"
Then you can qclone that repo and get both the work in progress and the base repository on which it's overlayed. More details are available in the Mercurial book's chapter on queues.
Really, though, there's just never a good reason to have uncommitted work for more than an hour or two.

What is the best Mercurial clone / repository strategy?

There can be:
1) just clone from remote repo as needed (each new one can take 20 minutes and 500MB)
2) clone 2 local ones from remote repo, both 500MB, total 1GB, so always have 2 local repo to work with
3) clone 1 local one from remote repo, called it 'master', and then don't touch this master, but clone other local ones from this master as needed
I started off using (1), but when there is a quick bug fix, I need to do a clone and it is 20 minutes, so then method (2) is better, because there are 2 independent local repos all the time.
But then sometimes a repo becomes "weird" because there are merges that do damages and when it is fixed on the remote repo, any local repo's merge that shows up in hg outgoing will cause damage later when we push again, so we just remove that local repo and clone from remote again to start "fresh", taking 20 minutes again. (Actually, we can use local repo 2 first, rename local repo 1 as repo_old, and then before sleep or before going home, do a clone again)
Is (3) the best option? Because on a Mac, the master takes 500MB and 20 minutes, but the other local clones are super fast and takes much less than 500MB because it uses hard link on a Mac (how to find out how much disk space without the hard linked content?). And if using (3), how do we do commits and push? Suppose we clone from remote repo to local as "master", and then clone local ones as "clone01", "clone02", 03, etc, then do we work inside of clone01, and then when an urgent fix is needed, we go to master, do an hg pull, and hg update, and go to clone02 and also do hg pull and hg update, and fix it on clone02, test it, and hg commit, hg push to the master, and then go to master, and do an hg push there? And then when clone01's project is done, again go to master, pull, update, go to clone01, pull, update, merge, test, commit, push, go to master, push to remote repo? That's a lot of steps!
Maybe a fourth option might work better in your case: Mercurial Queues that are kept in a local Mercurial repository.
Using MQ you can:
Clone the master repository locally.
Work on your code and keep your changes isolated in patches.
When new updates from upstream are available, remove your batches, apply the updates, and then re-apply your patches on top of the new update.
Once you're happy with your work, fold it into your local repository and push it upstream.
You don't have to keep the patches in a local repository, but it's a nice bonus option that is worth considering.
Chapter 12 from Mercurial: The Definitive guide explains the process in fairly good detail.
I don't know that your understanding of the space considerations are correct. When cloning a local repository Mercurial will use hardlinks for the .hg directory, the actual repository, which takes up no additional space. The working directory takes up space (though hopefully not 500GB!) but the .hg directory only looks like it does depending on the tools you use to check.
If you do a clone -U you create a clone without a working directory and it should take up almost no additional space and be created almost instantly.
I always keep a clone -U of the central repo in an unmodified state and then create clones off of that as needed. I push directly from those clones back to the remote repository.
Mercurial Queues look really powerful, but I've never given myself the time
to read all that documentation, just to be able to put my current work aside to
work an a small bug.
I use the attic extension.
It'll be like this:
...working happily, but then there is a quick bug fix...
$hg shelve work
...quickly fix the bug...
$hg ci
$hg unshelve
...continue with work
Sometimes I get an idea, but no time to really play with it. To prevent me from forgetting it.
...working happily, idea drops in...
$hg shelve work
...start a unittest for the idea or some other unfinished piece of code, enough to sketch the idea
$hg shelve idea
$hg unshelve work
...continue with work
$hg ls
idea
*C work