How to make Mercurial auto-commit on merge without conflicts? - mercurial

I was surprised when coming back to Mercurial after using Git for quite a few years when I did an hg pull -u: Mercurial fetched the new patches, did a merge without conflict, but still asked for a commit.
Is there a way to automatically commit when a hg pull -u did not create any conflict?
Currently, the revlog is polluted with many "Merge..." commit messages, and I'd really prefer to not see them (although the merge itself should be kept in history in case the automated process makes the wrong decisions).

Nope, I don't think so. This is a fundamental difference between git and hg. Mercurial wants you to make sure the merge was correct, possibly by running your test suite, before committing.
If you don't like merge commits, maybe you should be rebasing your work instead of merging? It's common practice to keep history linear by rebasing feature branches instead of merging.
If you are rebasing a lot, it helps if you make use of the phase system by pushing WIP work to a non-publishing repository and then once code passes review and gets accepted, it gets rebased and then pushed to a publishing repository. You might also find the evolve extension useful, especially if you are working collaboratively with a team, as that will propagate the history editing operations between developers.

you could use an alias for that:
alias hg_pull='hg pull -u && hg commit -m "No Merge Conflict"'
Running hg_pull from your repo should do more or less what you wish.
If anything goes wrong at "hg pull -u" step, the commit is not triggered.
Let me know if something is unclear!

Related

Edit commits in HG repo & mark as "closed"

I'm currently dealing with the fallout from BitBucket dropping HG support. We're going to be giving hg-git a try because, while my preference is self-hosting, my boss isn't quite mad enough at Atlassian to move away from BB yet. Taking this opportunity to clean up our existing HG repo before the conversion to GIT. Have used hg convert to remove some accidentally committed binaries to reduce size, etc.
One thing I've noticed is that we've got about two dozen old branches that are technically "open", but have been merged into default (no closing commit, but they're months to years old). Is there any way I can use a tool like hg histedit or during the hg convert to go back and specifically mark old branch heads with --close-branch?
Looking through docs I can find things about editing files, editing the contents of commits, or modifying commit messages, but nothing I can find mentions meta-data around whether a commit is "closed". I know this is just a flag on a given commit, but I don't know how to retroactively add it via any HG extension.
Edit: Just to add a bit more clarity, I recognise I can just update to each of these old branches & add a new commit that just closes the branch. There'll be a lot of dangling-looking, closed heads, but that'd work fine enough. However, I also then have to give each of them a bookmark in HG as well, or these additional "closing" commits are lost in the hg-git conversion. I'd rather avoid having to add ~30 additional branches to the git branch-list, just to have them show up as closed properly in HG without having to use revsets.
What I want to do isn't "essential" in the grand-scheme of the repo, but I'd be surprised if editing a commit's metadata to say --close-branch were impossible.
I tested out the rebase idea with a mock repository and it seemed to work.
Here was the starting repo:
And here was the state after rebase:
I think this example matches what the question was asking about. The original dangling close-branch changeset was moved to precede the merge.
I updated to default and ran the following command:
hg rebase --dest=4 --source=3 --keepbranches --config=ui.merge=internal:merge
I actually used Tortoise Workbench to execute the rebase and that is the command it used. So the final argument for ui.merge is probably not strictly necessary.
As you may have already noticed using hg convert its a really good idea to make new clones when you go to modify the repository. Thus if it gets messed up you have an easy undo option. I'd certainly recommend that approach for this operation as well.

What is the standard commit process for Hg?

Is it
pull
update
merge
commit
push
? Or can you do the commit first?
I don't like the idea of pulling and merging without having a version of my local code backed up somewhere in case the merge explodes, but presumably you have to do the merge before you can do a push, because you can't have conflicts in the central repo. Not quite understanding this whole process yet; used to my nice simple SVN.
I recommend to always commit before pulling in changes to your working directory, unless you are 100% sure that your changes and the changes to be merged into your working directory will not conflict.
If you do an updating pull (hg pull; hg update, or shorter hg -u pull) and have any outstanding non-committed changes, any changes coming from outside will be combined with your changes. When conflicts happen, it might be difficult to decide how the merge result should look like, because you can't easily distinguish between your changes and the changes merged in.
When you did commit first, it is much easier to decide how the merge result should look like, because you can always look at both parents of the merge.
So, in effect it is:
hg commit
hg pull -u (if no merge necessary, go to 5)
hg merge
hg commit
hg push
Update: As Martin Geisler has pointed out, it is possible to get at the "original" changed version of a file using:
hg resolve --unmark the-file
hg resolve --tool internal:local the-file
or for all files at the same time:
hg resolve --unmark --all
hg resolve --tool internal:local -all
Still, I find the "commit first" system nicer. At the end, it is personal preference...
I don't know as there's a standard per se, but one of the ideas behind Mercurial is that you can commit as often as you like since it goes to your local repository. So you can commit to your heart's content as much as you like before you pull updates.
I tend not to commit very often, saving up for when I'm preparing to push, but that's me. I can see the utility of committing early and often. I do pull updates frequently as I work to cut down on merge fun.
One other thing I do is to keep a parallel clone of my working repo (cloned from the same repository as my working repo, not cloned from my working repo) so that I can check the original state of a file easily, and if need-be check in an out-of-band emergency fix or what-have-you without complicating my current change set.
Do edits
Commit
Goto 1 until satisfied
Pull
Merge & commit
Push if you want to.
Definitely commit before trying to do something complex like a merge. I don't think mercurial will allow you to merge before committing, but even if it did, what if the merge goes wrong. You have no pre-merge revision to go back to.
Commit early, commit often.
If you don't, you are missing out on a huge benefit of a DVCS.
but presumably you have to do the merge before you can do a push, because you can't have conflicts in the central repo
Wrong statement and poor understanding of distributed workflow and parallel development.
You can merge heads before push, but not have or must. Push can put any data to repo, if it needed and intended to be so
By default, push will not allow creation of new heads at the destination,
since multiple heads would make it unclear which head to use. In this
situation, it is recommended to pull and merge before pushing.
(NB: "recommended to pull and merge before" statement)
You can use commit-pull-merge, stash-pull-unstash-merge, perform fetch with modified WC and merge on the fly, don't merge heads at all or sporadically and push --force with +1 heads - there are not common rule for everybody. And any and every such workflow doesn't produce "conflicts in the central repo", but only different DAG.
Each point of divergence, which appear in case of existing your and other changeset from commmon parent in your (or even central) repo is a point of starting anonymous branches in Hg, which (technically) are absolutely legal, applicable and usual way. How they handled is defined by policy and agreement between developers, PM, QA-team and others
I, personally, prefer finish my task (in one or more amount of commits), after it pull and maybe merge, when it approved by development-policy

How to retrieve an accidentally deleted patch in Mercurial with MQ

I had two patches in series, neither one applied, and I accidentally called qdelete on the wrong one. Is there any way to reverse this operation and get my patch back? I had a huge amount of work in this one!!!
The way to avoid this (and I know it's not helpful now, sorry) is to not just use Mercurial Queues, mq, but to use it with a patch repository. Mercurial/mq has great support for this.
When initially creating the queue you do:
hg qinit --create-repo
(instead of just hg qinit), which creates a new Mercurial repository in your .hg/patches directory. Then you can use:
hg commit --mq
to commit all your patch files, and bringing this back would be just a matter of:
hg revert --mq
The bottom line, and again I know it's not helping you now, but maybe it'll help the next guy or you later, is: if you're writing code and it isn't committed somewhere it doesn't exist -- commit and push early and often
Unfortunately, if you did not use the -k option when calling the qdelete command, the patch file also got deleted. Thus your only hope is either a backup or an tool that could perform some "undelete" operation.

Hg post-merge commit message, best practice?

I find myself doing the following a lot:
C:\Code>hg pull
pulling from http://server/FogBugz/kiln/Repo/Project/Rebuild/trunk
searching for changes
adding changesets
adding manifests
adding file changes
added 2 changesets with 4 changes to 4 files (+1 heads)
(run 'hg heads' to see heads, 'hg merge' to merge)
C:\Code>hg merge
4 files updated, 0 files merged, 0 files removed, 0 files unresolved
(branch merge, dont forget to commit)
C:\Code>hg commit -m "Merged"
C:\Code>hg push
pushing to http://server/FogBugz/kiln/Repo/Project/Rebuild/trunk
searching for changes
remote: kiln: successfully pushed 2 changesets
My question is, what is a better/more useful commit message to use after merging a pull from the repository. Are there any best practices that people use in distributed version control systems for this sort of thing?
If you use the fetch extension it automates the pull,merge step into one step, fetch. The message it auto-generates is something along the lines of "automatic merge". The hg developers seem to think this is reasonable as the extension is now distributed with the base.
Merge messages don't seem to be contain a particularly high amount of information. Your message seems reasonable.
[[ offtopic, we sometimes use them as an opportunity for a pun on the word merge]]
There is no one way so here is what I have tried to adhere to.
On commit messages:
Jus remember that those messages are the only strings that would connect you to some one who is try to decipher the reasons for the commit.
Key is to provide a description that is going to be a useful commentary on code development.
So when some one uses hg log , he has a nice commentary on how the software is being developed.
Some good practices:
Link it with your bug management system:
fixes #3456, new feature #2435 etc
or a more descriptive one of what changes it is bringing in the repo
Give credits
In fact, what I do mostly is. Look at
the current state of "hg log" and see
what useful message would mean a
logical progression in understanding the latest commit.
As long as "merg" is in the message somehow, we've had fun using the opportunity to fill our mercurial logs with hilarity. For example, we've used merge messages such as "real-estate mergage loans are at an all time low" or "a Merge Griffin television production."
You can collect all the newly added changesets' commit messages into a file by
$ hg log --rev 'reverse(p2():ancestor(p1(),p2())-ancestor(p1(),p2()))' \
--template '{desc}\n' \
> commit-message.txt
then manually edit commit-message.txt, and finally use it as the log message:
$ hg commit -l commit-message.txt
You could use the rebase extension, so hg pull --rebase would rebase your repo to the central repo's tip. This negates the need for merging after a pull.
I added an alias for it:
[alias]
pure = pull -u --rebase
Works well for us.
More details are at the RebaseProject page.
For mundane merges, where you're only working with one repository, I think just "merge" is fine. Usually you don't even know everything that got merged in because it's all other people's changes anyway.
The one time I would suggest being more verbose would be when you're working with more than one repository. If you have a devel repo and a stable repo, and you're pulling bug fixes in from stable, I would just mention that in the merge: "merging with stable". Those merges tend to be bigger, so it helps explain them to people who come along later.

commit-pull-merge-push or pull-merge-commit-push?

We started using Mercurial a several weeks ago. Most developers follow this workflow:
work on a feature
commit -m "Worked on feature ABC"
pull -u
If branch
merge
commit -m "Merge"
push
Today, one of our developer suggested that we do:
work on a feature
pull -u
if branch
merge
commit -m "Worked on feature ABC"
push
That way, we have a lot less "Merge" changesets in the log.
Some of us think it's just a matter preference. Some of us think one is better than the other. We don't have much experience and don't want to live the downsides of misusing the tool. So if one approach is more advisable then the other, please let me know why.
I like your original procedure more, but reasonable people can certainly disagree. I consider merging an actual piece of software development work and like having it be a first class citizen in our process.
In your second/suggested procedure the risk is that the pull does some stuff you really don't want and then you have a very hard time separating it from the work you've already done.
For people who just can't stand branchy history the usual preferred workflow is:
work on a feature
commit
pull --rebase
push
where the --rebase option appears on pull after you enable the rebase extension. I'm not a fan of rebase because it's technically rewriting history which is antithetical to how mercurial is supposed to work, but I'm in a rapidly shrinking minority on that point.
Bottom line, if you really don't want a branchy history use rebase -- don't update into uncommitted changes as it's hard to undo.
I would go with your first workflow. The main objection I have with the second option, is that if you try to merge before you commit, there's no easy way of backing out of the merge when things go wrong (which does happen from time to time) so you can start again.
This can be especially handy if you get a merge conflict with Feature A, and want to ask the developer that worked on Feature A something about it, but he's on his lunch break. With your first workflow, you can abort the merge and just carry on until that developer is back and you're ready to merge again. With the second workflow, you just kinda stuck and have to go find something else to do (or make another clone of the repository and work in that one until you can merge, but that seems worse to me).
This won't work:
work on a feature
pull -u
if branch
merge
commit -m "Worked on feature ABC"
push
If you have local changes, you may not merge. What you /can/ do is this:
work on a feature
pull -u
work on a feature
pull -u
work on a feature
pull -u
...
commit -m "Worked on feature ABC"
push
You might also want to investigate hg fetch, it's a shipped with mercurial optional plug-in that does the pull/merge in the same step. Which is good for if you forgot to pull before committing.