mercurial phases, warning when changing phase to secret - mercurial

Whenever I change a phase from draft to secret, I get a warning. I don't see a danger, am I missing something?
Also is there a way to turn off the warning, and not have to add --force? If I am always overriding the “safety” then one day I will accidentally change phase from public. As far as I can see public is the only phase that should never be changed. (If we should only move phases forward, and start on the second phase/step, then the first phase/step is useless).
So the questions are:
Am I missing something in my understanding, is moving from draft to secret ever dangerous? Why should I be worried? what should I be looking out for? what could go wrong?
How do I allow change to secret, if current phase is draft, without a warning or use of --force? May be some sort of alias, preferably also works in tortoise.

Secret phase changesets are, well, "secret" and this changeset with descendants will not be pushed|pulled on sync
is there a way to turn off the warning, and not have to add --force?
From hg help phase
Unless -f/--force is specified, "hg phase" won't move changeset from a lower phase to an higher phase. Phases are ordered as follows:
public < draft < secret
-
If we should only move phases forward, and start on the second phase/step, then the first phase/step is useless
You can change phase by hand (-s -f), when (if) it needed
How do I allow change to secret, if current phase is draft, without a warning or use of --force?
Nohow. You must use --force (directly or in alias)

Related

Can I "break" an hg working copy in such a way that it must be reverted before commit?

I have a utility script that will configure the local developer instance to mimic a specific production one - copy over the correct connection strings, client files, etc - thereby making it easy to investigate certain issues.
Because this is all done locally this changes files in the working directory. The first thing the script does therefore is print out a big fat warning to caution developers not to commit and revert changes when they are done. However it is possible to forget or miss this warning as cruft from my build system scrolls by and I wonder if its possible to go further.
Is it possible to do something to the hg repo so that a commit will be rejected and the developer would have to revert first?
I realize there are some variables to the question as far as revert what and commit what but given that I'm not even sure that this is possible, I am willing to take close-with-caveats for an answer.
This is exactly what hooks are for. You would need a precommit hook on every repo or possibly the pretxnchangegroup.
By creating a precommit hook (script) that checks for a specific file or a specific change, you can fail the commit and print out whatever warning you need. The return value of the script indicates to mercurial if the transaction is valid or not.
Use the following generic sample to check for the presence of certain files that would be committed, before accepting or rejecting the changesets.

Incorrect "Can't rebase immutable changeset" error

Occasionally, when I do a pull with rebase, I get the following error:
abort: can't rebase immutable changeset fa044e766d1f
hint: see hg help phases for details
Funny thing is, that changeset that errors (and it is the same one every time) is very old, and is already public.
Here's a screenshot:https://db.tt/xHiOxm6R
It appears that I can just ignore the message (at least, so far, I've not gotten into any trouble by doing so), but obviously, I'd like to help Hg resolve this issue so that its not going to continue to be a hassle in the future.
Thanks.
Update
hg out does not list it. The clone is probably about 6 months old. Also, as far as I know, none of the other developers are experiencing this problem.
(note: I can't see the screenshot due to a strict firewall).
You mention that the error occurs every time on a changeset that "is very old, and is already public." This should give you a hint as to why you're getting the error.
Changesets in Mercurial have 3 possible phases:
- public : changeset is visible on a public server
- draft : changeset is not yet published
- secret : changeset should not be pushed, pulled, or cloned
Changesets that are at draft and secret are considered to be mutable, that is you can change their history, modify them (perhaps change the author, for example), and so on.
Changesets that are at public are considered immutable, you "cannot" change anything about them when they are in this phase. The reason being, they have already been seen by the outside world, and so if you make any modifications, it could cause issues. The theory is that you can't remove a changeset that's public - if you tried to change it, you would simply create another changeset.
That said, you can force the phase of a changeset back to draft like so:
hg phase -d -f <changeset_id>
This would allow you to rebase, or modify the changeset in some other way.
However, this would not remove the original changeset in the "outside world"... that already exists, and will until the end of time itself. It would simply create a new one that does mostly the same thing.
So, if you did try to resolve the issue, you would likely just create a new issue in its place.
Caveat: as I can't see the screenshot from here, I may revise my answer later.
Update: A quick note - having seen the screenshot, that looks like a very old changeset, which makes me wonder just what you're trying to rebase. As Kindread mentions above, merging would be your best bet here.

split a hunk in hg; change tolerance

I use the hunk-by-hunk or hunk selection approach to committing: instead of commuting all changes I made to a file, I commit related parts. E.g. I wrote a function and a test, compiled to ensure it works and then commit the function and the test separately. For this I use built-in functionality in tortoiseHg and RecordExtention when in the console.
Now I have two edits separated by only one unchanged line, thus falling in hg's tolerance of one hunk. I want to commit only the former for now. How?
The record extension doesn't let you split hunks further, but the less-standard CRecord extension does.
Just to put it out there, but what you're doing is usually considered bad practice because it guarantees that you haven't run the unit tests on the files as they're being committed. That, of course, doesn't apply in all environments.
If the reason you're leaving some parts uncommitted is because they're local-only changes you always in in place (passwords, paths, etc.) they're a good candidate for a Mercurial Queues "patch". Then you'd be able to 'pop' them off, commit the whole file, and then 'push' them back on.

Mercurial: what are the consequences of changing a phase?

In Mercurial, the phase of a revision can be changed arbitrarily. What are the consequences of a phase change for all possible transitions (public, draft, secret) x (public, draft, secret)? Which phase changes are safe? Which may cause troubles and which kind of troubles? Which are more or less no-ops?
The default phase for a commit is draft, that's how they were treated when the phases didn't exist. When pushing a draft changeset, mercurial automatically changes its phase to public. You can use it to know which changesets you have already published or not.
But the real issue is that when the changeset is in public phase, mercurial won't let you change them with history editing extensions (like mq, rebase, etc). That's really important, because the history editing happens only in the local repository, they don't propagate with pull/push operations. So, once a changeset is published, it's out of control, it's dangerous to change it.
You can change from any phase to any other phase. The "normal flow" is to move to a higher phase (secret->draft->public), but Mercurial allows the change to a lower phase with the --force option. A phase change alone is harmless. For example, the only thing that happens when moving from public to draft or secret is that the protection of history editing is dropped, nothing else, pull and push will still work normally, Mercurial could never be confused about the changesets because they have unique identifiers. The history editing action that takes place after a phase change like this is what can cause problems. And that's why Mercurial gives the warning in the phase change and requires the --force option, as a confirmation that that's what you really want.
In general published commits shoudn't be modified, that's what the phases try to ensure. But maybe you do have control over all repositories. Or maybe you pushed something and you know that no one else pulled it yet. Whatever is the reason, you have the option of forcing the phase of the changesets back to draft and edit them. But this edition must be done in every repository that has the changesets.
A public revision can't be edited with history-editing tools (i.e. mq, rebase).
A secret revision can't be pushed to another repository (it will be ignored when you give the push command, or when another repository attempts to pull).
A draft revision allows both, but will automatically change to public if it gets pushed to another repository.
The purpose of the phase system is to prevent you from modifying a revision after you've pushed it to another repository, which is a bad idea unless you're able to delete the old version of the revision from all repositories that it's been pushed to.
All phase changes are more or less no-ops; it's just a marker to indicate what is or isn't safe to do with a revision.

Is it possible to add custom field to mercurial log?

we're moving from Subversion to Mercurial now. In Subversion there was possibility to add custom column into log (e.g. bug id) and force user to fill this column on every commit.
Is it possible to implement such feature in Mercurial?
Yes it's possible.
But before you go and do that, why isn't it enough to require bug fix commit messages to uphold to a certain pattern?
i.e. util: rename the util.localpath that uses url to urllocalpath (issue2875) (taken from Mercurial's repo)
Then you can install a hook on your central repository that scans incoming commit messages, and does whatever is needed when that pattern is found.
Furthermore, why would you want to force this on every commit? Is this for a QA team that should only commit bug fixes? If that's the case, a pre-commit hook that greps the commit message for the pattern sounds appropriate.
If you still want the extra field: when Mercurial commits something, it is possible to pass it a dictionary of strings, which you can fill with anything. See the transplant extension on how you might do that. You would also need to wrap the commit command and add a new command line option to it.
But I strongly suggest you think twice before doing this, because aside from the time consuming work involved in coding, testing (and maintaining this between Mercurial releases), you would also need to ensure that it is deployed on every environment where Mercurial is used.