Ensuring a merge between branches happens in one direction - version-control

This morning I discovered that my co-worker had merged the wrong way between two branches in mercurial --we have a ver5 and ver6 branch, with extra files in ver6. Is there any way (a serverside hook probably) to enforce that the children of any ver5 node be from ver5?

Whether you have ver5 merged into ver6 or ver6 merged into ver5 you're still ending up with a child of ver5 that has stuff from ver6 in it.
If, however, you want to avoid a changeset whose branch name is ver5 having ancestors that are ver6 you could do that pretty easily with a hook. Just where you put that hook is the tricky part. If you make it a pretxnchangegroup hook you can prevent people from pushing an offending merge into the server-side repo, but they will have already committed it, and maybe some more changes on top of it, and they'll have a hard time figuring out what to do to fix it. If you can control their local setups you can put in a pretxncommit hook that prevents them from committing the merge, but you can't make them run that hook using only Mercurial tools.
The actual hook, whichever type you make it, could use either of these strategies:
check if the branchname is ver5 and if so make sure no specific file/content from ver6 is presnet
or
check if branchname is ver6 and if so make sure neither p1 nor p2 has branchname ver5
TL;DR: It's probably more trouble than it's worth -- stick to shaming.

Rather than post twice, would my answer to "Mercurial: allow merge from a release branch to the default one, but not vice versa" help? https://stackoverflow.com/a/19926324/1025457

This should do it. It uses a revset query to find any merges into ver5 from ver6.
hg log -r 'children(p2(::ver5 and ::ver6 and merge()) and branch(ver6)) and branch(ver5)'
::ver5 and ::ver6 and merge() finds all merges that are ancestors of both ver5 and ver6 branches
p2(...) and branch(ver6) grabs the second parent (incoming changeset) that are on the ver6 branch.
children(...) and branch(ver5) then grabs the actual merge changeset that is on the ver5 branch.
I recently needed to figure this out myself, but also needed to ensure that default wasn't indirectly merged into my release branch, i.e. default -> feature -> release.

Related

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

How to copy a file from one branch to another branch using functionality on Eclipse

Usually, I would just copy the whole content of that file in the current branch and switch to another branch on Eclipse and paste it in the new branch but I am just asking if there is a way I could do this when checking out from Eclipse?
So, I have a branch called Mock branch and it has a file called a.java and I have modified the file. Now, I switch to another branch that also has a.java but different from that of the Mock branch because I have made changes to the a.java in the Mock branch.
Now, how do I push commit on the other branch showing the differences between the a.java in it and that of the Mock branch and applying the changes in Mock branch to the branch I am currently on?
Is this possible in Eclipse?
First of all we will consider that you have pushed the changes of the other branch (so they are HEAD) and you have switched to Mock branch (of course, Im not considering merge between branches because you didn't talk about it ). Starting from this point, let me describe two possible options:
You can do a cherry pick. Cherry pick is a process in which you take a commit from another branch (or even the same) and apply it in your checked out one. As example, if you modify the file of branch A and commit it, you can switch to branch B and do cherry-picking applying this commit from A to B.Of course, keep in mind that cherry pick applies ALL changes added in a commit so if you modify a.java and b.java, both modified files will be applied as a result of the cherry pick. You can get examples from here : https://wiki.eclipse.org/EGit/User_Guide#Cherry_Picking
My favorite and most simple. Do right click in a.java and select Compare with / Branch, tag or reference to get a view that compares the other branch's a.java version with your current Mock branch and use Eclipse editor to apply changes (You can also use Compare with / Commit in case the change you want to apply wasn't at the other branch's HEAD). You can use the arrows to pass changes from right (remote branch) to left (current branch) or even do manually copy- paste
If you want to replace the full content of that file, try and right click on it, and select:
Replace with -> Commit...
Then chose the commit from the other branch.
If you want to replace it with the latest revision from another branch, you can chose
Replace with -> Branch, Tag or Reference
(Here I select master because my current branch is not master, and I want to replace the content of the file with the content of the same file from master.)

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")