How to filter for named branches with a partial name match in mercurial? - version-control

I use the following search expression to find all the heads which aren't closed in our mercurial repository:
head() and not closed() and not branch('default')
However, I have a convention to name feature branches as fb-(target-release)-(feature-name) and I'd also like to filter for the named branches which contain fb at the beginning of their name. Is this possible without piping the output to another application?

You can use regular expressions in the branch expression. From hg help revset:
"branch(string or set)"
All changesets belonging to the given branch or the branches of the
given changesets.
If "string" starts with "re:", the remainder of the name is treated as a
regular expression. To match a branch that actually starts with "re:",
use the prefix "literal:".
So to match fb- at the beginning of the name:
head() and not closed() and not branch('default') and branch('re:^fb-')

Related

How to find all branches merged to particular branch

I need to list all branches merged to branch of a particular name. Is it possible in Clearcase?
ClearCase does not reason in term of branch alone, always in term of file.
You could list branches merged to a particular branch for a given file.
The only way to generalize that to a group of files would be in UCM with UCM components (group of files) and their baselines (UCM labels), which can be delivered (merged) to an UCM stream (branch)
But in base CC, you would need to:
list each version of a file (see "ClearCase: How do I find which version I branched off from?", with cleartool lsvtree.
The last segment in the extended path would be the name of the branch (just before the version number).
See:
"ClearCase View and Branch explained" for definition,
"Is ClearCase path is a standard one — '##' and string after that" for illustration.
and then look for an hyperlink (ahlink) as I did in "Find merge arrows pointing to a version in ClearCase" in order to detect a merge back to the current branch.

When undoing a git rebase with reflog, does it matter which commit you choose?

I know what the commit was (b7104e0) for my feature branch (GL18) before I attempted a rebase, which went poorly. I'm looking through Git Reflog in Eclipse and it lists the commit b7104e0 several times. I want to reset the head of GL18 back to b7104e0. Does it matter which b7104e0 commit I choose in reflog on which to reset, or it is all the same?
A git hash is computed using the commit message, commit author, commit date, the tree hash, and all parent commit hashes, see this blog post on the anatomy of a Git commit for details.
This means every commit you see with the same hash is the exact same commit. You can use any of these. In fact, if you reset, you reset to the commit hash: git reset --hard b7104e0.
No–but just for clarity, since the headline and body text seem at first to ask different questions, let's spell it out explicitly here:
The "true name" of any commit (or indeed any repository object in git) is its SHA-1, which in this case starts with b7104e0 (but goes on for another 33 characters). This true-name uniquely identifies the object. It can be abbreviated to something shorter, as in this case, as long as the shorter version remains unique.
All other names, such as branch names, tags, the very special ref HEAD, the slightly less special (but still special) ORIG_HEAD, MERGE_HEAD, CHERRY_PICK_HEAD, and so on, and (finally :-) ) reflog entries like HEAD#{3} or branchname#{1}, are just ways to express the "true name" SHA-1 ID. There's a special exemption to this rule when using git checkout or a command that rewrites a reference name, but in general, a name or reflog entry just resolves to the ID. Many names may resolve to a single ID, or perhaps only one name resolves to the ID, but the names do resolve to IDs, in general.1
Once you have the correct ID, it does not matter how you got it.
1Just for completeness: it's obvious that if we're going to change the target SHA-1 ID of a name, e.g., to move a branch or write a new value into CHERRY_PICK_HEAD, we need the name, not its current ID. The other place we need a name is when using an indirect ("symbolic") reference, such as when HEAD names ref: refs/heads/master so that you're on branch master as git status will put it.
We also have one special case where a name does not resolve to any SHA-1 ID, and that's the "branch yet to be born" one, which is most common in a new repository with no commits at all: in this case, you're on branch master, but refs/heads/master cannot resolve to a commit ID as there are no commits yet. This special case can recur later if you use git checkout --orphan to create a new branch that does not (yet) point to any SHA-1 (it will acquire its initial SHA-1 on the next commit). In these two oddball cases, the HEAD reference exists but names a branch that literally does not exist (yet).

Is there a way to search ALL mercurial commits for a specific string?

We have a situation where we know a keyword used in one particular mercurial commit in a repository. But we don't know what commit that is in. Obviously I can go through each committed file and eventually find the keyword and how it was used, but that would be a lot of tedious work.
Is there a way in mercurial to search for a string across ALL committed code in the repository?
hg grep does exactly that.
hg grep [OPTION]... PATTERN [FILE]...
search for a pattern in specified files and revisions
Search revisions of files for a regular expression.
This command behaves differently than Unix grep. It only accepts
Python/Perl regexps. It searches repository history, not the working
directory. It always prints the revision number in which a match
appears.
By default, grep only prints output for the first revision of a file
in which it finds a match. To get it to print every revision that
contains a change in match status ("-" for a match that becomes a
non-match, or "+" for a non-match that becomes a match), use the
--all flag.
Returns 0 if a match is found, 1 otherwise.

Why is a 3-way merge advantageous over a 2-way merge?

Wikipedia says a 3-way merge is less error-prone than a 2-way merge, and often times doesn't need user intervention. Why is this the case?
An example where a 3-way merge succeeds and a 2-way merge fails would be helpful.
Say you and your friend both checked out a file, and made some changes to it. You removed a line at the beginning, and your friend added a line at the end. Then he committed his file, and you need to merge his changes into your copy.
If you were doing a two-way merge (in other words, a diff), the tool could compare the two files, and see that the first and last lines are different. But how would it know what to do with the differences? Should the merged version include the first line? Should it include the last line?
With a three-way merge, it can compare the two files, but it can also compare each of them against the original copy (before either of you changed it). So it can see that you removed the first line, and that your friend added the last line. And it can use that information to produce the merged version.
This slide from a perforce presentation is interesting:
The essential logic of a three-way merge tool is simple:
Compare base, source, and target files
Identify the "chunks" in the source and target files file:
Chunks that don't match the base
Chunks that do match the base
Then, put together a merged result consisting of:
The chunks that match one another in all 3 files
The chunks that don't match the base in either the source or in the target but not in both
The chunks that don't match the base but that do match each other (i.e., they've been changed the same way in both the source and the target)
Placeholders for the chunks that conflict, to be resolved by the user.
Note that the "chunks" in this illustration are purely symbolic. Each could represent lines in a file, or nodes in a hierarchy, or even files in a directory. It all depends on what a particular merge tool is capable of.
You may be asking what advantage a 3-way merge offers over a 2-way merge. Actually, there is no such thing as a two-way merge, only tools that diff two files and allow you to "merge" by picking chunks from one file or the other.
Only a 3-way merge gives you the ability to know whether or not a chunk is a change from the origin and whether or not changes conflict.
A three-way merge is where two changesets to one base file are merged as they are applied, as opposed to applying one, then merging the result with the other.
For example, having two changes where a line is added in the same place could be interpreted as two additions, not a change of one line.
For example, file a has been modified by two people, one adding moose, one adding mouse.
#File a
dog
cat
#diff b, a
dog
+++ mouse
cat
#diff c, a
dog
+++ moose
cat
Now, if we merge the changesets as we apply them, we will get (3-way merge)
#diff b and c, a
dog
+++ mouse
+++ moose
cat
But if we apply b, then look at the change from b to c it will look like we are just changing a 'u' to an 'o' (2-way merge)
#diff b, c
dog
--- mouse
+++ moose
cat
Borrowed from AWS CodeCommit:
Developer Tools > CodeCommit > Repositories > RepositoryName >
Pull requests > Pull request name > Merge

Generating a list of which files changed between hg versions

I want to generate a list of which files changed between two revisions in a given directory in Mercurial.
In particular, I am not interested in what changed, but which files changed in that directory.
E.g., supposing that between then and otherthen, only 2 files changed:
>hg hypothetical-command -r then:otherthen
foo.baz
bar.baz
>
What's the hypothetical command? I've tried diff and log, but I can't see how to convince them to do it: either I get the patch(diff), or I get the whole repo(log).
hg status --rev x:y
where x and y are desired revision numbers (or tag or branch names).
If you are using the terminal in windows add hg status --rev x:y> your-file.txt to save the list to a file.
status is what you need.
But, depending what you mean by "between two revisions", you might also consider using the "x::y" (DAG - Directed Acyclic Graph) range.
Given parallel changesets,
1--2---4
\---3
hg status --rev 1:4 would return (1,2,3,4),
i.e. anything between and including the endpoints, according to the local, numerical rev. This might (and most probably will) return different results in other - though related - repositories!
hg status --rev 1::4 would return (1,2,4),
i.e. the endpoints, and all changesets which are descendants of '1' AND ancestors of '4'.
The latter case, x::y, is usually more useful in real-world applications. This is what you get via TortoiseHg\Visual Diff.
>hg help revsets:
"x::y"
A DAG range, meaning all changesets that are descendants of x and
ancestors of y, including x and y themselves. If the first endpoint is
left out, this is equivalent to "ancestors(y)", if the second is left
out it is equivalent to "descendants(x)".