Restore a removed branch in CVS - tags

By mistake I removed the branch name of a file using TortoiseCVS.
I think this can be reproduced using the standard cvs client with this command :
cvs tag -d -B <mybranch> <myfile>
How do I restore it ?
I tried the following things :
Add the branch to the last revision
Add the branch to the last tag (in my case this is also the last revision)
In either way, a new branch is started and the revision numbering is changed (6 numbers instead of 4). This is not acceptable.

Suppose the revision numbering of the file is of the form 1.1.2.x
Then use this command (you don't need to do a checkout beforehand)
cvs rtag -r 1.1.2 <mybranch> <module/path/to/my/file>

Related

How to switch to an old revision of the entire project?

For what I know, CVS is not like git and svn that you can switch back to an older version of an entire repo code.
The best I tried is I checkout a date (some days ago), using Eclipse. But it checked out a very old version. I'm sure to have inserted the correct date.
You can return to an old version of the entire repo code by running the following command from the root directory of your repo:
cvs update -r <TAG name>
where TAG name is the name of a TAG which was previously created on the entire repo using:
cvs tag -F <TAG name>
In cvs, a TAG is a list of files and their cvs revision. So using the tag command creates that list, and using the update command (with -r switch) is asking to return to the same file revisions which existed when tag was created.
One more important note, to return to the latest revision (head) of all files in you repo, use:
cvs update -A

How to solve a Mercurial case-folding collision with branches involved?

Today I went to merge a branch back into an old branch and got told that I couldn't update to the original branch due to a case-folding collision.
My repo looks a bit like this:
default branch, revision 1: add most files.
default branch, revision 2: adds files xyz and XYZ. Presumably was done on Linux machine. This was back in 2008.
default branch revisions 3-35: various other changes, no problems
revision 36: new feature branch added
feature branch, revision 71: notice on Windows that Sourcetree is reporting that xyz is deleted, so I commit that, which becomes...
feature branch, revision 72: this is the change that explicitly removes BOTH xyz and XYZ
At this point, I wanted to merge the feature branch back into the default, but it will not let me update back to version 71, or any other version except revision 1 when xyz was not in the repo at all. Obviously every changeset from 2 through to 71 is 'polluted' with these 2 files that I could only ever check out as 1 on my Windows and Mac machines.
The usual suggested solution - https://www.mercurial-scm.org/wiki/FixingCaseCollisions - does not work: it says "hg status should show the troublesome file in state 'R' and all other files in state '!'", but when I follow the steps, it actually shows all other files in state 'M', which is obviously not what I want and implies some data loss would occur if I proceeded.
Additionally, I would suspect I can never perform the desired merge on Windows or MacOS, because I need revision 35 to be in a usable state before I can pull anything into it.
Is there anything I can do here to fix it? All my files are safe, and I am also willing to lose all data and revisions in the xyz files to get this repo working again, but I would really prefer not to lose the repo and the changelog entirely.
I couldn't find a proper fix for this, so I had to borrow a Linux box to get a case-sensitive filesystem. Then the fix was:
Copy the entire repository to a Linux machine with Mercurial installed.
Revert/update to the latest revision on the default branch that had the 2 files with clashing names in the working copy, and hg rename them to names that didn't clash. Reapply any other changes since then.
Update to the revision on the other branch, do the same thing.
Perform the merge as normal.
Copy the repo and working directory back to Windows.
Remove/rename/modify the 2 renamed files so that only 1 remains, with whatever name is desired.
Steps 4 and 5 could probably have been done in either order.
I haven't done this in a while, but I've used the convert extension in the past to clean up case folding on Windows.
Note: I'm making the assumption that this is an essentially private repository to which you have exclusive access. If that is the case then this approach would work. (Even if that is not the case, this would still work technically but you'd have to publish it to other people as a new repo since the conversion described below would generate all new changeset IDs.)
You can do this using the convert extension to Mercurial, and the filemap option.
Convert can ... rename files during conversion, when you
supply it a mapping via the --filemap option.
The filemap is a file that specifies which files are to be included,
renamed, or omitted.
Each line can contain one of the following directives:
...
rename from/file to/file
...
The rename directive renames a file or directory. To rename from a
subdirectory into the root of the repository, use . as the path to
rename to.
The command line to do this would be something like:
hg convert --filehmap filemap.txt path\to\source\repo path\to\converted\repo
Where filemap.txt has to include something like:
rename path\to\XYZ path\to\xyz_which_was_uppercase
The conversion process should rename ALL "instances" of XYZ on all branches, so the fact that branches are involved I think becomes irrelevant.
Documentation.
As noted by the OP, the primary resource for guidance on managing case conflicts of the type described is https://www.mercurial-scm.org/wiki/FixingCaseCollisions
The directions given there are perhaps not as clear as they could be, so here is an annotated transcript based on one of the procedures given there.
We start with a repository named "repo", which has two files: a.txt and A.txt. On a remote machine:
REMOTE_MACHINE $ hg files
A.txt
a.txt
Now let's assume that repo has somehow been cloned onto the local machine (the computer on which the case-folding problem occurs). This might have been done using a command such as:
$ hg clone --noupdate "ssh://REMOTE/DIRECTORY/repo" # illustrative
If you don't want to alter repo on the local machine, then you could (for example) clone it, as by:
$ hg clone --noupdate repo xrepo # illustrative and optional
Now cd into the directory of the repository to be modified, e.g.
$ cd repo # or perhaps: cd xrepo
You might want to verify the integrity of the repository:
$ hg verify
Next come the two lines of black magic:
$ hg debugsetparents tip
$ hg debugrebuildstate
At this point, Mercurial will think you have the tip checked out,
and that all the files are missing (status '!'). In our case:
$ hg st -dram
! A.txt
! a.txt
Now we will run some ordinary hg commands to address the case-folding problem. Let's begin by extracting the files of interest manually:
$ hg cat a.txt > lc.a.txt
$ hg cat A.txt > uc.A.txt
Now remove the two problematic files from the repo:
$ hg -v remove --after a.txt A.txt
removing A.txt
removing a.txt
(The --after option above in effect instructs Mercurial to handle the fact that the files being removed (from the repository) are not on disk.)
Now we're back to normal. We might want to check in our renamed files:
$ hg -v add lc.a.txt uc.A.txt
adding lc.a.txt
adding uc.A.txt
$ hg st -dram
A lc.a.txt
A uc.A.txt
R A.txt
R a.txt
$ hg commit --message "renamed a.txt to lc.a.txt and A.txt to uc.A.txt"
$ hg files
lc.a.txt
uc.A.txt
$ cat lc.a.txt
lowercase a
$ cat uc.A.txt
uppercase A
$
# Verify that the original files are still there:
$ hg files --rev 0
A.txt
a.txt
At this point, to checkout all the other files, you could run: hg revert --all

ClearCase merge not updating LATEST in a local branch

My question is related to this one. Basically, I checked out a file in my local branch and, later, I performed a merge from the main branch, which already had a newer version of this file. I find it weird that file##/main/branch/subbranch/LATEST still contains the older version of the file, from before performing the checkout. Shouldn't the merge operation also update this link?
For merging, I used this command:
cleartool findmerge /my_file_folder -nc -fver .../branch -merge
The cleartool findmerge will checkout and merge, but won't check in.
As long as you do not checkin, the extended path ##/main/branch/subbranch/LATEST won't reflect the result of that merge.

Get latest revision number of a file from cvs repository

Is there a way to know the latest revision number of a file in cvs repository without checking out that file.
The exact problem is, suppose I know the name of a file which is in cvs repo. Let's call it file1.text.
So, is there any command or any way by which I can search repo for that file and get the latest revision number of that file?
You can use CVS log and give a revision as "starting point":
$ cvs log -r{REVISION}:: file1.text
The -r{REVISION}:: will only search for revisions after {REVISION} (can be a number or tag).
If you don't have a working copy, you can use rls cvs command. With -l argument, it will print the version of files.
$ cvs rls -l MyModule/path/to/the/file
You can use -r to specify a branch.
Here's the command to use:
cvs history -a -c -l module/file1.text
This will display the version and the date the file was last modified. This doesn't require the module or file checked out.

Committing to a different branch with commit -r

Does CVS allow committing a file to a different branch than the one it was checked out from? The man page and some sites suggest that we can do a cvs ci -r branch-1 file.c but it gives the following error:
cvs commit: Up-to-date check failed for `file.c'
cvs [commit aborted]: correct above errors first!
I did a cvs diff -r branch-1 file.c to make sure that contents of file.c in my BASE and branch-1 are indeed the same.
I know that we can manually check out using cvs co -r branch-1, merge the main branch to it (and fix any merge issues) and then do a check in. The problem is that there are a number of branches and I would like to automate things using a script. This thread seems to suggest that -r has been removed. Can someone confirm that?
If ci -r is not supported, I am thinking of doing something like:
Make sure the branch versions and base version are the same with a cvs diff
Check in to the current branch
Keep a copy of the file in a temp file
For each branch:
Check out from branch with -r
replace the file with the temp file
Check in (it'll go the branch as -r is sticky)
Delete the temp file
The replacing part sounds like cheating to me - can you think of any potential issues that might occur? Anything I should be careful about? Is there any other way to automate this process?
Note that a file may not be up-to-date even if diff shows zero output. For example, if you add a line of text to a file in one commit and remove it in the next you have zero difference along the path of two revisions.
As for the commit -r -issue. To me it seems like an experimental feature, and actually one you are better off by just using:
cvs update -r <branch> <file>
cvs update -j <ver> -j <ver> <file>
cvs commit <file>
Besides, propagating a single commit to all other branches programatically like the way you suggested is slightly questionable business since you usually need a quite a bit of human brain to resolve the conflicts.