Confused repository.

Simon King simon at simonking.org.uk
Tue Dec 2 21:50:22 UTC 2014


> On 2 Dec 2014, at 18:36, Rob Landley <rob at landley.net> wrote:
> 
> On 12/02/14 06:29, Simon King wrote:
>> On Tue, Dec 2, 2014 at 9:02 AM, Rob Landley <rob at landley.net> wrote:
>>> I accidentally commited a change on top of another change I thought I'd
>>> rolled back, and since rollback won't go more than one back that means
>>> my working repository is toast,
>> 
>> Before I answer your other questions, I should point out that the
>> recommended way to fix this would be to "hg update" to the parent of
>> the change that you didn't want, and if necessary use "hg graft" to
>> transfer the commit that you *did* want into the right place.
>> Unfortunately, this will leave a dangling pair of changes in your
>> repository, which will cause errors when you "hg push" unless you
>> specify which revision you want to push.
>> 
>> The safest way to remove the dangling changes is to clone your local
>> repository using the "-r" switch to specify the revision that you want
>> to keep.
> 
> Unfortunately dreamhost has a history of leaving old (security pached
> but not version updated) software on the server, and I've hit a problem
> several times where I cloned locally and then rsynced up a .hg that the
> webserver couldn't read because I forgot to init it with
> --no-spinning-rims or whatever the new feature was the old thing didn't
> understand. And then I always have an hour of tracking down what it was
> and fixing it.
> 
> (Because my laptop has a copy of the website on 127.0.0.1 and then I
> rsync the whole directory up to the server to publish my local changes.
> My working directory has .hg as a symlink into the ~/www copy.)
> 

I’d be interested to hear why you use rsync rather than “hg push” to publish your changes on the server.

> Maybe it's no longer an issue, but about the third time that happened I
> developed an aversion to locally cloning something I intend to publish.
> (The past couple months Dreamhost has been sending me emails about
> updating servers to the 2012 ubuntu release, I should try again…)
> 

I’m not sure you will ever be able to say “it’s no longer an issue”. Repository formats change over time as bugs are fixed and new features are added. Mercurial makes strong guarantees that newer versions of hg will always be able to read (and write) old repositories, but the reverse obviously isn’t true. “hg push” is the best way to transfer data to a remote repository and ensure that the software on the remote server can read that data.

>> The experimental "evolve" extension provides a cleaner way of doing
>> all this - I think you would just run "hg prune <bad-revision>",
>> probably followed by "hg evolve".
>> 
>> http://mercurial.selenic.com/wiki/EvolveExtension
> 
> I eventually fixed it by copying a new snapshot of the .hg directory
> down from the server, doing an hg checkout in there with it messing
> around with working directory files I didn't care about, and then
> copying the new .hg into my working directory with all the changes that
> needed commiting. That fixed whatever setting it was.
> 
> One of the things I've always liked about mercurial is its repository
> format is transparent and understandable. This was an instance where I
> couldn't find the setting that needed fixing. (Things like .hg/branch
> and .hg/cache/branchheads are human readable text... but they all
> referenced the _current_ commit, not the weird historical commit it was
> stuck on.)
> 
> If the answer is "man was not meant to know, install an extension"... I
> guess the answer to my question is "there isn't a human readable setting
> you could have edited with vi".
> 
>>> so I replaced the .hg subdirectory with
>>> the one from the website (copying the hgrc file out of it first) and now
>>> the repository thinks the "current" version is an old commit from July,
>>> even though the .hg directory I cloned from has the newer commits up to
>>> yesterday.
>>> 
>>> Where is it getting this information from?
>> 
>> The "currently checked out revision" is stored in the .hg/dirstate file
>> 
>> http://mercurial.selenic.com/wiki/DirState
> 
> Giant binary blob. I was afraid of that.
> 
> Oh well, mercurial having a friendlier repo format than git was nice
> while it lasted. (Or at least me not having noticed…)

I don’t know the history of the dirstate file, but a quick glance at http://selenic.com/hg/file/142b5d5ec9cc/mercurial/dirstate.py suggests that it has been a binary file for a very long time. It has to be loaded by lots of commands that you run regularly (status, diff, commit etc.) so I guess it is important that it is quick to load. I don’t know why the working directory parents need to be recorded in the same file, but it probably makes atomic updates easier.

>>> $ strace hg identify 2>&1 | grep '^open(' | wc -l
>>>    621
>>> 
>>> Is there any way to do a checkout without changing files in the current
>>> directory?
>>> 
>> 
>> The command "hg debugrebuilddirstate" can be used to change the parent
>> revision of the working directory without touching any files in the
>> working directory. As with all debug* commands, you should fully
>> understand what you are doing before using it.

(As Matt pointed out, the command you want here is “debugsetparents”, not “debugrebuilddirstate”)

> 
> I'm trying to fully understand what I'm doing. Unfortunately, I got
> spoiled by things like .hgtags being human readable and human editable
> (Matt's 2006 OLS presentation was quite convincing). Now I've got to do
> the equivalent of windows registry edits instead.
> 
> *shrug* Time marches on...
> 

I’m not sure this is entirely fair. Would you also expect to be able to edit the files in .hg/store, perhaps to create new commits entirely in vi? If not, which files would you accept as binary and which would you want as text?

Simon


More information about the Mercurial mailing list