Why does mercurial warn me about divergent renames? - version-control

I have been using Mercurial version control system for some time already and several times I have seen the system warn me about divergent renames.
What I do is make two different descendants of one larger file. Like for example I've had one class named HttpRequest that was a wrapper for CGI.pm. Later, when I decided to move to the PSGI protocol, I have made two copies of this file, namely Cgi.pm and Psgi.pm. The original class remains and becomes abstract with new ones inheriting from it.
I always thought that it is the preferred way to deal with such situations because each file retains the history of the file that it was based on. But when I push my changes to the remote server, it tells me this:
remote: adding changesets
remote: adding manifests
remote: adding file changes
remote: added 2 changesets with 2 changes to 2 files (+1 heads)
remote: warning: detected divergent renames of lib/HttpRequest.pm to:
remote: lib/HttpRequest/Cgi.pm
remote: lib/HttpRequest/Psgi.pm
Is this bad? Should I do it some other way?

It looks like the problem is not that you made versioned copies of the same source file, but that there are two changesets in which the file was renamed to a different name each time and these changesets are not in the same line of development. This observation is based on the fact that your pull created a new head.
So in this instance, Mercurial is warning you that the pull has created a new head and as a result your repo has two heads inside each of which CGI.pm has been renamed to a different file. Therefore, if you attempt to merge these into one you will have to decide which change should stick.
The simplest way to have prevented this would be to copy the original file instead of renaming it. More precisely, the first time you can rename it but on all subsequent occasions you have to copy it instead (obviously if you do this on the same line of development, and necessary if you do not but intend to merge divergent lines later).
You might also want to look at the relevant section of Mercurial: The Definitive Guide.

Related

Exclude a file or directory from CODEOWNERS

I have a file structure like so:
foo/file1.c
foo/file2.c
foo/freeforall.c
My foogroup on GitHub needs to review changes to everything in foo except freeforall.c which is a file that anyone can touch without restriction, so it should not automatically add anybody as a reviewer when changes are made to it.
(In reality, whoever modifies freeforall.c just asks someone else on their own team to review their change.)
The Question
How can I do this with GitHub CODEOWNERS? The file looks like this right now:
foo #MyOrg/foogroup
What I Tried
GitHub explicitly says that the ! syntax is not supported, so that won't work:
foo #MyOrg/foogroup
!foo/freeforall.c
And there are too many files in the foo directory to explicitly include them individually. I could move freeforall.c into a different directory, but really I don't want to be having GitHub's CODEOWNER feature dictating how I organize my components. I want freeforall.c to be in the foo directory, that's where it belongs!
I also considered creating an emptygroup to assign that file to, but soon realized that now I'd be requiring that a group with zero members must approve PRs to that file which obviously would cause problems. 😂
foo #MyOrg/foogroup
foo/freeforall.c #MyOrg/emptygroup
The CODEOWNERS file takes the last matching line into account. You can make definitions with empty owners to specify paths/files without an owner.
Consequently, you can use the following lines to have all files in the foo directory owned by #MyOrg/foogroup except foo/freeforall.c:
foo #MyOrg/foogroup
foo/freeforall.c

Can I stop mercurial from auto-merging a specific line of code?

I currently have a repo with a default branch and a named branch.
There process is I make changes in default, then merge to the named branch.
The named branch is where I compile and release my code, but then I merge back to default so I have only one head and no floating heads in my repo.
My issue is there's one value, var, in foo.c that I want to track differently in default than in the named branch and the auto-merge keeps overwriting the current value and brining in the other value.
Initially var is set to 1 in the named branch and A in default.
When I merge in new good stuff from default to named branch I see foo.c updates var from 1 to A.
I change the value back to 1, compile and release my code, and then merge back to default, which changes the value of var in default from 1 to A.
My question is, is there any way to stop mercurial from auto-merging and updating just this one line in the file? This is creating thrash in the form of multiple changesets where I'm simply putting the value back to what it used to be and because it's not a merge conflict can easily be overlooked during the merge (this is a shared repository with sometimes very green developers) and cause some major issues in my program.
Thanks.
If you were only merging in one direction, it would be simple, just make the change in one branch, but you are merging in both directions. One option might be into looking into the Mq extension for Mercurial and using that to apply and remove a patch, but that probably adds more complication than it's worth. The better option would be to have a build system that selected the correct value of the variable at build time based on the name of the current branch. That can be retrieved by running the command hg id --branch. You mentioned using C code, but didn't mention an operating system. I'm going assume GNU Make with a minimal UNIX environment. In your Makefile, you would add something like as follows:
BRANCH := $(shell hg id --branch)
VAR_VALUE := $(shell if [ "$(BRANCH)" = "named" ]; then echo A; else echo 1; fi)
CFLAGS += -DVAR_VALUE=$(VAR_VALUE)
Then, in your C code, you could use this to reference the value:
#define VAR_VALUE_STR #VAR_VALUE
const char var[] = VAR_VALUE_STR;
The first define converts the defined value to a regular C string and then it's provided as the value to initialize the string var to.
Pure Mercurial-way
In your case you have to apply specific permanent change each time after merging into specific branch. In Mercurial such patches can be created once and used forever: see at MQ Extension.
In common: you'll have two independent patches in patch-queue (one per branch), in each branch after merge and before build you have to have only one branch-specific patch be applied. The latter task inside MQ can be solved by 3 slightly different ways:
Two patches in single queue, needed patch moved in queue (patch-queue is stack) and applied in pre-build event with some hand-made business-logic (credits to penguin359)
if $BRANCH = "..." then hg qpush --move PATCH-OF-BRANCH
Two queues with single patch in it (the same if, different command-set hg qqueue QUEUE-OF-BRANCH; hg qpop)
In single queue protect each branch-specific patch with guards, in order to have for hg qpush --all only needed patch applied for each target
From my POV, solutions 2 and 3 have better scalability and protection from monkey with grenade

Mercurial: Branching for releases?

Previous history: The last couple of years I used SVN. Releasing a new version of a software project included following steps:
creating a branch for the new release: /repo/branches/0.1
getting the code into a release-worthy state there
creating a tag for a release candidate: /repo/tags/0.1-RC1
creating branch for RC1 to fix bugs: /repo/branches/0.1-RC1
creating tag for a new release candidate: /repo/tags/0.1-RC2
{...}
creating a tag for v0.1 from the last RC: /repo/tags/0.1
merging 0.1 into trunk
As far as I got Mercurial sees branches and tags slightly different than SVN and this finally leads to my question:
Do I create branches (and tags) for releases? And if not: What else wants Mercurial me doing to archive something similar to the described development pattern/cycle?
You can easily keep using this method. I'm not sure what you'd need a separate RC1 branch for, but I guess there are good reasons.
There is a bit of an annoyance in the way tags are stored in Mercurial, which is a versioned file listing them one by one. As a result tag creation constitutes a changeset. You should strive to keep all such tag-creating changesets on one branch, or you will get merge conflicts (which are easily resolved, but annoying nonetheless).
You can use old workflow, but:
Branch per release really needed (in any SCM) only if you have to maintain some amount (>1) of releases in production at the same time, gor single maintained release branches-tree not needed
I see a lot of (rather complex) projects, which use two-branches method ("Stable" with mergesets only and tags + "Devel" for every-day development (short-term branch-per-task are also possible, but it's more question of tastes and habits, than "a must")

Why is the "source" version given so much importance in Perforce while merging (resolving conflicts to be verbose)?

I don't think I even want to see it. Why do others find it so important ?
Isn't Base, Target enough for the "resolving conflicts" aka Merge tool window. What am I missing ? Are people really that bothered about the version before Base i.e. Source ?
It seems you have a fundamental misunderstanding about what each of the versions are. When you merge two branches, almost always you want to keep changes from both branches. Base is the latest common ancestor of the two branches. Base->Source shows what was changed in the branch you're merging from, and Base->Target shows what was changed in the branch you're merging to. To properly resolve a conflict, you need to know what was changed in each branch.
(Some documentation for p4merge at p4 docs - Merging Files)
When working with a merge conflict, there are four parts to it:
The common ancestor that both branches changed
Their changes (source)
Your changes (target)
The final result
(You may have an old version of p4merge - the docs show a different wording that may clear up the confusion)
The 'source' is not the revision before, but rather the incoming changes from the merge that someone else made.
Ignoring either your changes or their changes is a possible conflict resolution - many have that as a default "merge, handle conflicts by use mine." However, this has the distinct possibility of causing regressions of functionality introduced by the other branch (or worse, removing code the other branch is expecting).
For a given code block with a conflict, both your changes and their changes are important, and the ancestor of the two gives the appropriate context for what the change was.

Find all unmerged files/elements in ClearCase

We use ClearCase where I work and I'm trying to figure out how to find any files that have been modified but not merged up. We have a main branch at the very top level in ClearCase, and this is where the final source code changes are merged to and where we do our formal release builds from. We then have an integration branch under main where integration issues are worked out. When we get everything working and tested in the integration branch, we merge the integration branch up to main. For individual feature implementations and bug fixes, we create a new branch (usually named after an action, feature, or bugfix) off of the integration branch and work the issue. When we are done with it, we merge that change up to the integration branch.
I was wondering if anybody knew of a command or a way to see what files are modified in the feature/bug fix branches but were not merged back up to the integration branch. I've been looking around but I can't seem to find a way to do it. I would like to be able to run the command and have it tell me all files that have been modified on all of the sub-branches but not merged up. Thanks.
Normally, you use ct findmerge to find files to merge from one branch or view into the current view (assuming ct is an alias for cleartool).
I think you would have to identify all the branches you are interested in and do a separate ct findmerge operation for each branch - for each destination branch. That's complex. You'd also want to be able to eliminate many branches which are known to be fully merged. You can annotate a branch to indicate that it is fully merged.
So, I don't think there is a simple, single command to do this job.
You need to decide which branches are targets that you're concerned about. These would be your integration branch(es). Presumably, you have a fairly small list of these.
For each of those target branches, you need to decide which work branches are relevant to that integration branch. This is the tricky part; there is no easy way to determine whether a particular bug fix or feature branch is relevant to that integration branch using information in the VOBs; it is really only known by the users.
You then need a script that does (in outline):
for int_branch in $(list_relevant_integration_branches)
do
...create view with tag $tag for $int_branch...
ct setcs -f $(cspec_for_integration_branch $int_branch) $tag
ct setview -exec "find_outstanding_merges_for_integration_branch $int_branch" $tag
done
where find_outstanding_merges_for_integration_branch looks a bit like:
vob_list=$(list_relevant_vobs)
for mrg_branch in $(list_relevant_merge_branches $int_branch)
do
echo
echo "Merges from $mrg_branch to $int_branch"
ct findmerge $vob_list -fversion .../$mrg_branch/LATEST -print
done
Note that this command assumes (a) the current view is appropriate for the target, and (b) the integration branch name is passed as an argument.
You can get fancy and decide how to handle automatic or graphical merges instead of -print. The hard part is still the unwritten commands such as list_relevant_integration_branches and list_relevant_vobs. These might be simple:
# list_relevant_integration_branches
cat <<EOF
integration_branch_version_3_0
integration_branch_version_3_1
integration_branch_version_4_0
EOF
# list_relevant_vobs
cat <<EOF
/vobs/mainproject
/vobs/altproject
/vobs/universal
EOF
Or they might be considerably more complex. (If you only have one VOB, then your life is much simpler; the systems we work with have 20-odd VOBs visible in the cspec.)
The other unwritten script is list_relevant_merge_branches. I don't know whether there's a simple way to write that. If you define and apply appropriate attribute types (ct mkattype, ct mkattr) when the development branches are created (perhaps a 'target integration branch' attribute type, an enumeration type), you could use that to guide you. That leaves you with a retrofit problem; how to get the correct attribute onto each existing working branch. You also need a separate attribute to identify branches that no longer need merge scrutiny, unless you decide that the absence of a 'target integration branch' attribute means 'no need to scrutinize any more'. That reduces the retrofit problem to adding the target integration branch to those branches that still need merging; by default, all existing branches will be deemed fully merged.
If you know the source and destination branches (topic detailed in Jonathan's answer, which I have upvoted), then don't forget the query primitive merge:
merge (from-location , to-location)
In all cases, TRUE if the element to which the object belongs has a merge hyperlink (default name: Merge) connecting the from-location and to-location.
You can specify either or both locations with a branch pathname or a version selector.
Specifying a branch produces TRUE if the merge hyperlink involves any version on that branch.
The branch pathname must be complete (for example, /main/rel2_bugfix, not rel2_bugfix).
This thread illustrates that query in action:
How is it possible to find all the elements on a specific branch that are checked in and not merged away?
cleartool find \\view\administration\ProjectVOB \
-branch "brtype(HNH-372452) && \
!merge(...\HNH-372452\LATEST,...\main-372452\LATEST)" -print
\\view\administration\ProjectVOB\Com-API\Dll\COMFrontendDll\Mmi.cpp##\main\HNH-372452
\\view\administration\ProjectVOB\geometry\geochain\geocutterloc.cpp##\main\HNH-372452
That "merge hyperlink" is the red arrow you see in version tree:
(see article "Versioning and parallel development of requirements")