How to find all branches merged to particular branch - version-control

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.

Related

Mercurial merge results in files labelled modified but which are binary equal

I'm in the process of doing a merge, and I'm ready to commit at this point but my commit dialog in TortoiseHg is showing many files as modified but when I diff to parents it says all files are binary equal.
I do not have and have never had the eol extension enabled.
Revert changes nothing, the file is still registering as modified.
hg parents shows two parents for the file.
hg stat shows the file as modified, e.g.
c:\Projects\MyProject>hg stat Authorization\AuthorityGroups.cs
M Authorization\AuthorityGroups.cs
hg diff --git shows nothing, e.g.
c:\Projects\MyProject>hg diff --git Authorization\AuthorityGroups.cs
c:\Projects\MyProject>
I've tried this on two different machines on two separate clones and I'm seeing the same thing.
Any other thoughts for how I could diagnose or fix this?
Clearly something has changed but if it's not showing in hg diff --git how can I establish what that might be?
Update 2014/12/10:
I've done a bit more checking on the history of the two parent revisions and I think I see why it's getting confused.
We've got the original parent file added in revision 1 on default.
On the Apple branch the file has been renamed to move it to a new location.
On the Orange branch the file has been added to move it to the same new location.
So the file on both branches is binary identical and at the same location, but presumably Mercurial is flagging it as a difference to be merged because they arrived there by apparently different means.
So the question then becomes:
Is there any way to retrospectively repair the move being treated as an add and delete on a long committed changeset (a new commit would be fine, but I can't edit the history) , or do I just need to let it go through in the merge?
Is there any way to retrospectively repair the move being treated as an add and delete on a long committed changeset (a new commit would be fine, but I can't edit the history)
Well... sort of. Update to the most recent Orange commit in which the files had their old names (you can use hg bisect to find it if you're not sure exactly when it happened), do hg rename to the new names, commit, and then merge this into the current Orange head. Mercurial should be smart enough to register the files as properly renamed, and it won't cause conflicts (we know this because the more complex Apple/Orange merge didn't).
or do I just need to let it go through in the merge?
This is easier. Mercurial's merging algorithm is quite smart. It can deal with situations like this just fine.
Unless you have a third branch in which the files were never moved, the second option is unlikely to cause a problem. If you do have such a branch, you should be fine as long as you merge it into a descendant of the Apple rename (or merge from such a descendant). The major difficulty would be with merges to or from the Orange branch.

In the RCS file format in a CVS repo, what does x.y.0.2 as a revision indicate?

Background
I am trying to salvage code from a CVS repo. I am using reposurgeon for the purpose, and I have tried the following tools to get myself a git-fast-import stream:
cvs-fast-export, which errors out (alleged cyclic branch, but doesn't provide details)
cvs2git followed by git-fast-export, which mashes up things beyond comprehension
git-cvsimport followed by git-fast-export, which creates the best results so far, but also ends up throwing stuff on branches that they don't belong on.
This CVS repo has been run on a variety of CVS versions and tags and branches have been forcibly moved. I know that this means I cannot salvage those branches and tags anymore. But so be it.
Nevertheless I have half a dozen branches (out of many many more), plus MAIN, which I am interested in retaining during converion into a git-fast-import stream. My target VCS is not Git, but the point is that reposurgeon handles its input this way and outputs this way, too.
In order to make sense of the artifacts and clean as much of the old stuff (including orphaned revisions) out in a pre-processing stage by means of rcs -o<rev> (of course on a copy of my repo ;)), I need to understand how the innards of the rcsfile format work.
Parsing is a piece of cake after modifying the rcsfile.py module from rcsgrep. But that doesn't yet provide me with any information about what the revision numbers, especially those without a corresponding delta+log, mean.
What I see
According to the RCS files man page, there shouldn't be a case where the third segment of a revision ID is 0. Yet I see exactly that condition.
Here is what I did (as an experiment).
On MAIN: commit a file (1.1)
From MAIN: branch to BranchX (1.1)
On BranchX: change the file (1.1.2.1)
On BranchX: change the file again (1.1.2.2)
On MAIN: change the file (1.2)
On MAIN: tag the file foobar (1.2)
From MAIN: branch to BranchX, moving the branch tag (1.2), effectively orphaning the previous branch at 1.1.2.x
On BranchX: delete the file (1.2.2.1)
On MAIN: change the file (1.3)
On MAIN: forcibly tag the file foobar (1.3)
On MAIN: change the file (1.4)
On MAIN: tag the file foobarbaz (1.4)
As you can see in the list above and also in the fully reproduced file below, there is no revision 1.2.0.2 in the form of delta with log.
Now my questions
If I branch off revision x.y freshly (no file changes!), the resulting revision ID is x.y.0.2. That is similar to the mysterious revision ID I am seeing and asking about.
Does the 0 indicate that the file doesn't have deltas, such that I have to go back to its ancestor for the actual contents?
Or does the 0 simply indicate the "root" of that branch, with the fourth segment being the latest revision on that branch?
Can anyone shed light on these questions or point to more comprehensive material than the above linked man page?
Below is the full RCS file:
head 1.4;
access;
symbols
foobarbaz:1.3
foobar:1.4
BranchX:1.2.0.2;
locks; strict;
comment ## #;
1.4
date 2014.12.11.13.46.46; author username; state Exp;
branches;
next 1.3;
1.3
date 2014.12.11.13.44.49; author username; state Exp;
branches;
next 1.2;
1.2
date 2014.12.11.13.39.31; author username; state Exp;
branches
1.2.2.1;
next 1.1;
1.1
date 2014.12.11.13.31.41; author username; state Exp;
branches
1.1.2.1;
next ;
1.1.2.1
date 2014.12.11.13.34.36; author username; state Exp;
branches;
next 1.1.2.2;
1.1.2.2
date 2014.12.11.13.35.08; author username; state Exp;
branches;
next ;
1.2.2.1
date 2014.12.11.13.42.32; author username; state dead;
branches;
next ;
desc
##
1.4
log
#Change on MAIN
#
text
#NOTE: this file will be removed!
Another change on MAIN#
1.3
log
#Change on MAIN
#
text
#d3 1
a3 1
ANother change on MAIN#
1.2
log
#Change on MAIN
#
text
#d3 1
a3 1
File on MAIN will be forcibly tagged X again ... how does this affect the rev ID?#
1.2.2.1
log
#Removing the two files from X
#
text
##
1.1
log
#Adding the experiment file
#
text
#d3 1
a3 1
Introducing file on MAIN#
1.1.2.1
log
#Changing the file on the X branch
#
text
#d3 1
a3 1
Changing on X branch#
1.1.2.2
log
#Another change on the X branch
#
text
#d3 1
a3 1
Another change on the X branch#
Okay, turns out the answer to this is buried deep down in the CVS source code.
For starters here are the important files if you are looking at the CVS source tree:
src/rcs.c
src/rcs.h
doc/RCSFILES
In addition to that you have the rcsfile(5) man page. And don't forget to use grep to the utmost extend (unless you have something more sophisticated at your disposal, that is).
The gist:
A branch revision is defined by the first three ( or bigger odd number) segments, i.e. x.y.z, e.g. 1.1.2, which is a branch off of revision 1.1.
The symbol for such branch will point to revision x.y.0.z, or 1.1.0.2. Where 0 is a magic value defined as RCS_MAGIC_BRANCH in the CVS code. Note that no delta will ever have the third segment set to 0, as these are "virtual revision numbers".
In stock CVS z (third segment of a branch revision, fourth of a virtual revision number) will ever only be an even number equal or bigger than two
assert((z >= 2) && (z % 2 == 0))
A branch number 1 is also reserved for vendor branches as per the comment in rcs.h (see below).
To check for a branch, simply look in the symbols list in the admin section of the RCS file (e.g. via rlog -h <file>, if you don't want to parse it) for revisions which have the second-to-last segment set to 0. That is, you have a revision that would match the (PCRE) regular expression (?:\d+\.\d+\.)+0\.\d+ (hope I got that right).
From a comment in rcs.h
CVS reserves all even-numbered branches for its own use. "magic"
branches (see rcs.c) are contained as virtual revision numbers
(within symbolic tags only) off the RCS_MAGIC_BRANCH, which is 0.
CVS also reserves the ".1" branch for vendor revisions. So, if you
do your own branching, you should limit your use to odd branch numbers
starting at 3.
Interesting functions using RCS_MAGIC_BRANCH are RCS_tag2rev() and RCS_gettag.
From comments in rcs.c
Comment on RCS_magicrev():
Return a "magic" revision as a virtual branch off of REV for the RCS
file. A "magic" revision is one which is unique in the RCS file. By
unique, I mean we return a revision which:
has a branch of 0 (see rcs.h RCS_MAGIC_BRANCH)
has a revision component which is not an existing branch off REV
has a revision component which is not an existing magic revision
is an even-numbered revision, to avoid conflicts with vendor branches The first point is what makes it "magic".
As an example, if we pass in 1.37 as REV, we will look for an
existing branch called 1.37.2. If it did not exist, we would look
for an existing symbolic tag with a numeric part equal to 1.37.0.2.
If that didn't exist, then we know that the 1.37.2 branch can be
reserved by creating a symbolic tag with 1.37.0.2 as the numeric
part.
[...]
Note: We assume that REV is an RCS revision and not a branch number.
The answers
Does the 0 indicate that the file doesn't have deltas, such that I have to go back to its ancestor for the actual contents?
Basically yes. When the second-to-last segment is 0, the revision number is a virtual revision number used to make a "reservation" for a branch number.
Or does the 0 simply indicate the "root" of that branch, with the fourth segment being the latest revision on that branch?
No, see above.

Fossil SCM - Revert to a specific revision like Mercurial

While using Mercurial if I want to change the current working copy with a specific revision I just do:
$> hg revert good_revision
$> hg commit -m "Now I'm in the good revision"
Then I can see that all my files are int the good_revision state and can start working on it.
So far on fossil I can do a revert but only on specific files, not the entire repository, and update or checkout don't seem to work as I would expect.
How can fossil revert my entire repository to a certain revision?
I'm not sure I quite follow but I think what you want is to be able to create a "multiple heads on one branch" sutuation in Fossil. If yes, then Fossil does support this, just it calls branch's heads "leaves", and this process is called "forking".
To do that, you
fossil update good_revision
and then
fossil commit --allow-fork
You may now spawn fossil ui, navigate to your branch and see it having two leaves.
You now may close the then-current leaf.
Note that, while supported, this does not appear to be a recommended practice. Instead, Fossil recommends a rather peculiar approach for throwing away changes:
Rename the branch at the "bad" leaf to "mistake" (or create that branch if it doesn't yet exist). By doing this you effectively "mark" the resulting subleaf as a mistake.
Note that the name "mistake" name is just a convention; this branch does not exist in a freshly created repository.
Close the "bad" leaf.
Return to the last-good state using fossil update, continue hacking.
Since that "last-good" commit still inherits the branch tag of its parent commit, the next commit you record will also inherit it and won't be on the branch "mistake".
For an example, see how it looks in the SQLite repo—there's a bunch of assorted short chains of commits on this branch. See also this.
My slightly different solution to what I think I understand the question to be (paraphrased: how to work on an older "good_revision" than current leaf of this branch/trunk that I'll call bad_leaf, and treat changes since "good_revision" as bad), which is sort of equivalent to applying diffs between the two versions but in reverse from/to order:
Merge in a (empty) fork from the good_revision, using the baseline from the bad_leaf instead of the default, last common commit; hence the diffs that will be applied are the original branch's differences back to a good_revision fork you create as it won't see they've already been applied. Using the latest as baseline "hides" those which would otherwise make it ignore all changes as they're already applied.
fossil update good_revision
fossil commit --allow-fork --allow-empty
# note the uuid from that commit (for use as forked_basis below)
fossil merge -f --integrate --baseline bad_leaf forked_basis
Then of course once happy,
fossil commit
It doesn't create any branches that should be called "mistake", it just applies the reverse diffs from good_revision to bad_leaf into bad_leaf to put you back where you were and you can continue committing to that same (new) leaf that used to be at bad_leaf.
A diff (straight gnu, not fossil diff) against a checkout at the original good_revision compared to a checkout after the above commands matched. Except for empty directories that had lost their files, but fossil doesn't track/tidy-up dead directories anyway.
caveat: I haven't been using fossil that long and its different in several ways to the common ways I've been used to with cvs/svn/git/hg/ perforce/clearcase.
Reason for adding this answer: I found the existing answers harder to understand and wasn't sure I trusted myself to do them correctly as a result.
If I understand your question correctly, there was a problem somewhere along the development cycle and you would now like to go back one or more revisions to a known good revision and start using that. Furthermore, you'd like that revision to become your trunk. The approach in Fossil is similar to that of Mercurial:
fossil revert -r good_revision
fossil commit -m "Now I'm in the good revision"
This will replace the files in the working directory with the ones from the specified revision. The commit will commit them to whatever branch you're working on (I am assuming that it is the trunk in this example). If you don't specify the revision number, it will use the last committed version.
One of the more common usages of the revert command is to roll back a single file:
fossil revert -r good_revision my_file
(or)
fossil revert my_file_from_the_last_commit
However, as shown in the first example, leaving out the file name causes all files to be reverted. For further information please see https://www.fossil-scm.org/index.html/help?cmd=revert
Sorry for the latest response, but I just came across the question while looking for something else. I post this in case someone else is looking into how to revert to a previously committed version stored in Fossil.

How to prevent divergent mercurial branches from merging?

I have a project stored in mercurial which has grown well beyond its original remit, and now I want to split the repository into two separate projects. Say the file tree looks something like this:
src/
a/
a.h
a.c
b/
b.h
b.c
Say I've hg cloned this repository twice, and in the first clone I've performed an hg rm src/b/*, and in the second I've performed an hg rm src/a/*. This gives me the two separate source trees I want, with history and revision numbering preserved in each branch.
The problem I now have is what happens if, in the future, I ever accidentally pull from the a/ clone into the b/ clone. What I'd like is for mercurial to simply refuse to pull from, or push to, the other branch, if I ever try to do so, as if the two had never shared history.
Is this possible? If not, is there a canonical way to create two parallel projects from one original which preserves history and revision numbering?
The canonical way would be to use hg convert with a filemap like this:
exclude b
rename a .
(and afterwards with the roles of a and b reversed to create the second repository)
This way you end up with two unrelated repositories (which Mercurial will refuse to push/pull without the use of force) only containing the history of a single directory.
Also see this question for reference.

vimdiff as a merge tool

vimdiff helps in showing the diff of two files graphically and allows us to pick the changes from left to right/right to left.
The files I am dealing with are huge files and most of the differences vimdiff reports can be auto-merged except a few.As it takes lot of time to go diff by diff in vimdiff and take the action.
I would like to know if there is an option available in vimdiff that automerges the differences in left and right files as long as there is no ambiguity and leaving the conflicted resolutions similar to the tools svn merge and cvs merge tools does?
Its not possible to auto-merge the changes in two files unless we have a base copy where these two files branched and changes done separately. If an item is on one side and not on the other,it can't judge whether this item was newly added or an existing item was deleted. As there is a base copy exists while merging files in a repository, cvs merge,svn merge can auto-merge the changes.
If you use no version control, you can try diff and patch this way:
Before changing your file (say, file.txt), make a backup of the original version (file.orig).
When changed are made, make a patch-file: diff file.orig file.txt >patch.txt
Get a file which you want to merge changes to (say, file2.txt).
Use patch: patch file2.txt patch.txt
Changes will be merged, conflicted rows will be placed in a separate file.
Looks like vimdiff does not allow that. Man page says
"vimdiff - edit two or three versions of a file with Vim and show differences"
But you can have a look at Kdiff3 which lets you compare and merge.