It looks like tags and bookmarks can only be applied to a single revision. Is there a way to attach some sort of identifier to multiple revisions? I'm trying to query the repo to get all revision of a specific label name. Is there a way to attach some sort of label to multiple revisions to make this possible?
You could do this with bookmarks, although not necessarily in the most elegant fashion. For example, you could "label" a bunch of commits with bookmark names like mylabel-1, mylabel-2, mylabel-3, etc. You could then search for the commits that have bookmarks beginning with 'mylabel' using the following revset:
$ hg log -r "bookmark('re:^mylabel')"
See hg help revisions.patternmatching and hg help revsets for more information.
In principle the feature you're looking for could be added in a more elegant way using an extension. I'm not aware of an existing extension that implements commit labels.
Related
This question is not only technical. I want to get into the concept itself, too.
There is a foreign project on BitBucket (e.g. ObjectListView). And I need to work on two problems at the same time. In git I would just create to branches in my local repository after clonening.
But how would I does this with Mercurial?
When I create branches there I am not able to push my local commits back to the remote repository because of the missing '--allow-new-branch' option.
So it doesn't want me to branch.
In my current understanding I would just create a clone for each new feauter (branch). So this means I have to create two forks on BitBucket for one project when I want to work on two different problems.
How would you solve this?
There is some missing information here, so I'm not sure I know what your problem is. I'll try to take some educated guesses and cover a number of possibilities. Feel free to ask back if I failed to address your problem adequately.
First, you can definitely just create new branches if you wish to do that. You'll need to use hg push -f or hg push --new-branch (if you used a named rather than an anonymous branch) to make the remote server accept them (that's to prevent you from pushing new branches by accident). You will, of course, need write access to the repository (or fork the repository and work on that fork).
Second, if you just want to push the current revision/branch (and any associated revisions of a feature branch) and not sync the entire repository, then hg push -r . will do that (here, . denotes the current revision, you can also specify others). If you use that frequently, you may want to create an alias, e.g. submit = push -r ..
Third, if you actually need separate workspaces, it's probably more convenient to use hg share instead of cloning the repository. (Note that you'll first have to enable the share "extension" for that; the word "extension" is in quotes because it's actually a part of core Mercurial and not really an extension in the traditional sense.) hg share creates a separate directory that is still linked to the same repository, but has a separate checkout with separate files.
It is also important to understand that branches in Git and Mercurial are completely different things. Branches in Git, aside from naming specific commits, exist to keep revisions alive (so they don't get garbage-collected). In Mercurial, nothing ever gets garbage-collected, so you don't need Git-like branches for that purpose; instead, Mercurial has anonymous branches (which are sort of like detached HEADs in Git -- sort of) and named branches (which are used to label sets of revisions with a permanent name). Bookmarks can be used to put temporary labels on either type of branch (or specific revisions). Bookmarks + anonymous branches can be made to feel fairly Git-like if you desire that.
So, if you want a Git-like approach, you'd just create anonymous branches (and optionally put a bookmark on them for ease of reference, though having them as branch heads in two directories created with hg share can be the better choice if you wish to work on both concurrently without having to switch. You'd then use hg push -r . to push that specific branch to the remote repository (you may also need -f if you're creating a new head).
However, if it is not your repository, you may want to check with the owner what structure they prefer; for example, plenty of Mercurial users prefer named branches in order to be able to tell later which revisions belong together (sort of like a tag that spans multiple revisions).
I am trying to display the diff of each changed file in a changeset, using a template.
What I need is something very similar to "hg diff" command. I cannot find anything which might serve my purpose in the help here
To add context, I am trying to use this template in Bugzilla extension. I need to add the diff of the changes which went in to bugzilla ticket.
You can use diff() pattern
(extract from hg help templates - better than URL referenced by you)
- diff([includepattern [, excludepattern]])
You if you don't specify any patterns, it will simply give you the equivalent of hg log -p. If you want to print diff per file, you will need to pass explicit filenames as includepattern parameter, like
hg log -r tip --template "{diff('mercurial/bundlerepo.py')}"
Looping through the list of files (like "{files % '{file}'}" in templates help) seems broken in this case (well, I didn't manage to make it work). Probably it's a bug, so you can write to mercurial discussion list to get confirmation.
Anyways, to get more luxury support, better to write to mercurial discussion list, or join #mercurial IRC and ask :)
Also they will guide you on how to achieve what you are trying to do in better way - seems you are trying to reinvent something
I am going from git to mercurial. Trying to find the equivalent of git-branches, I run into mercurial-bookmarks.
Given that I have no bookmarks. The workflow I follow is:
hg bookmark test_bookmark
hg update test_bookmark
How can I merge that back to the head, since there is no main bookmark?
You can get a list of heads with hg heads. This will usually include the bookmarked head along with any other heads you may have created. If, after pulling, there is exactly one head, there is nothing to merge (your history is linear). You may want to delete the bookmark in this case with hg book -d name_of_bookmark.
On projects which make extensive use of bookmarks, it is common to bookmark the "canonical" head #. This bookmark is checked out automatically when cloning (unless the user passes the -u or -U flags), and is roughly analogous to git's master branch, except that it doesn't exist by default. It helps keep track of which head to merge with, but unlike git, you don't need to give every head a name if you don't want to.
If you want to do a fast-forward merge (i.e. you want to move a bookmark forward to a descendant changeset), update to the descendant and do hg book name_of_bookmark. It's somewhat common to fast-forward # in this fashion, if your repository is using it.
What I would like to do is something like this:
When I deliver my code, I would like to label my part of the source with “delivered”.
If other developers follow the same convention, it should be possible to extract from the scm all the code labelled delivered.
When I deliver code again, it should be possible to move or replace the label delivered on my source.
What is the closest thing you can do in Mercurial, or what is the best convention to follow to keep track of code in specific states as described above?
(I haven’t actually done a lot of this in VSS, I might actually be mistaken about how it works)
Appendix 1:
I would like that we work in one branch as far as possible, commit and pull/push as much as possible. Then we need something like labels to keep track of code in a certain state.
It sounds like you might want named branches. Each developer can work on their own branch and merge their branch to a "delivered" branch when ready. When all the developers have merged their branches, the release can be given a final check and tagged.
If I understand this right, you want to label individual files in more than one revision. E.g. in revision 1 you label all files in /lib1/ as "delivered", and in revision 2 you label all files in /src/ as "delivered". Now if somebody comes along and tells hg to give him all the code that is "delivered", you want in /lib1/ the files from revision 1, and in /src/ the files from revision 2.
If this is what you want, it is not possible in hg (and for a good reason: it is considered bad practice). In such a scenario, you could perhaps split the single repo into 2 subrepos "lib1" and "src", versioning both separately. You can then register a certain combination of these 2 sub-repositories by means of a commit in the super-repository, followed by a tag "delivered" in the super-repository.
If you do not want something like this, I don't understand the purpose of labeling only a subset of files in a revision. In this case standard tagging is sufficient, as you can move public tags in Mercurial, anyway (and with history!).
The closest thing in Mercurial is Tag.
hg tags always shows all tags, so how can I get only the tags that point to a specific revision and all its ancestors?
The real-world use case is that if I use local tags to designate features (or bug fixes) on changesets, and I need to find out the cumulative features/bugs up till a specific rev.
One solution would be adding a wrapper command that adds "-r" to tags. Then what's the best way to implement it? Use revsets to get all ancestral revs and filter the tags?
This should do the trick (requires mercurial 1.7):
hg log -r "ancestors(<rev>) and tag()"
where <rev> is the hash or local revision number. However, tagging every bugfix and feature seems overkill.
Instead of tagging, you can just follow a convention where you put "bugfix: xyz" or "feature: abc" in your commit messages. You can then extract all bugfixes and features like this:
hg log -r "ancestors(<rev>) and (keyword(bugfix) or keyword(feature))"
Keep tags for important milestones or other revisions that have some special significance.
If I understand you correctly, you want to:
Specify a revision
Filter the log to only that changeset + all its ancestors
Extract all tags that are in those changesets
You can do that if you can limit yourself to tag names:
hg log -r "ancestors(HASH)" --template "{tags}"