How to cherry pick after having merged several changesets into one - tfs

We are using TFS 2010 with the Basic Branch Plan outlined in the Branching Guide on codeplex
for an internal web application. We have just the 3 basic branches = Dev, Main (QA/Testing), and Release (Production).
Because the app is an internal web application, we only support the single production release.
We basically develop locally and once we complete a task (a bug fix or enhancement), we commit it to Dev. We also generally do a Get Latest from Dev every day when we start work to pull down anything checked in by the other developers. After some period of time (usually a week or two), we'll decide we have enough changes to justify updating the QA site and do a Merge All from Dev to Main and then deploy the merged Main branch to a QA server for testing.
QA will then start testing the site, and after they're satisfied, we'll do a Merge All from Main to Release and deploy the merged Release branch to our production server. Sometimes we even wind up doing multiple Dev-to-Main merges before actually merging everything on up to Release.
Anyway, we've been using this strategy for a couple of months now and until recently everything was looking great. We were able to hotfix Release if we ran into some critical problem in production and then just merge it backwards. All was looking good.
Then we ran into something we didn't know how to deal with. We were given the directive of merging ONLY a single code fix on up from Main to Release (without merging everything else in Main). Now since we didn't know this was coming, when the original changeset was merged from Dev to Main, it was merged along with several other changesets. So when I went to merge from Main to Release, the only option I had was for the entire merged changset. I couldn't "drill-down" into the merged changeset and pick just the one original changeset from Dev that I really wanted.
I wound up manually applying the change like a hotfix in Release just to get it out there. But now I'm trying to understand how you prevent a situation like this.
I've read several articles on merging strategy and everything seems to recommend NOT cherry-picking changesets when you go to merge - to simple merge everything available... which makes sense.. but if you always merge multiple changesets (and they become one changeset in the destination branch), then how do you potentially merge only one of the original changesets on up to production if the need arises?
For example, if merging Dev (C1, C2, C3) to Main (becomes C4) - then how to merge only C1 from 'within' C4 on up to Release?
It makes me think we'd be better off merging every single changeset individually from Dev to Main instead of doing several at once. At least then we could easily just take one on up from Main to Release if the need arises.
Any recommendations/life lessons/etc. on handling branching/merging for this specific scenario would be greatly appreciated.

In your scenario you could have done the following:
Rollback C4 in Main (becomes C5, because rollbacks are changesets themselves, which apply inverse changes)
Merge from Dev to Main again, but this time select only C1 (becomes C6 in Main).
Now rollback changesets C5 and C6 again, so you have all changes in Main like before. (becomes C7 in Main).
After this you have the same code base in Main as before and you can now merge C6 (which has only the changes from C1) from Main to Release.
However, to prevent such trouble in future you should really consider merging every single changeset from dev to main separately.

I would not recommend merging every single change-set from dev to main; That would be a bad idea with much additional risk!
but if you always merge multiple changesets (and they become one
changeset in the destination branch), then how do you potentially
merge only one of the original changesets on up to production if the
need arises?
You don't and should not let the need arise.
This is probably not the easy answer that you are looking for, but there really is no easy answer. Merging every single change-set is creating a massive amount of effort to prepare for something that should not be happening anyway. Indeed the process of merging individual change-sets introduces yet more complexity that will, in the end, bit you in the ass when you can't figure out why your software is not working... "dam, I missed change-set 43 out of 50"...
If the result of a bug:
In your scenario it may have been better if you manually re-applied the "fix" to either a "hotfix" branch off of Release or directly to the Release line.
That is just the cost of having bugs slip through to production and I would spend a little time figuring out why this problem got passed QA and how to prevent it in the future.
If the result of an enhancement:
Did your financial (CFO) guys authorise the reduction in quality in production that is a direct result of shipping untested code? I hope that they did as they effectively own the balance statements upon which that software is listed as an organisational asset!
It is not viable to ship only one feature, built and tested with other features, to production without completing your entire regression cycle again.
Conclusion
I would not recommend merging every single change-set or feature from dev to main; That would be a bad idea with much additional risk that should be hi-lighted to the appropriate people!

Related

TFS Merge Discard Command

I'd like to discard a large number of non-continuous changesets that are currently eligible for merging between two branches.
Assuming that C100,C103 and C105 are the three changesets pending a merge, can I use the following command to discard them all, without any unpleasant side effects? i.e. affecting / including changesets C102, C104 on other branches?
tf merge $/sourceBranch $/targetBranch /discard /recursive /version:C100~C105
It seems highly unlikely that they would be affected, but I'd appreciate any confirmation possible, as I'm quite keen not to trash my new company's source control!
I finally plucked up the courage to run the tf merge command using a non-continuous range of changesets via /version:Cx~Cz (rather than discard 100+ changesets individually), and as expected it worked perfectly, so my paranoia about breaking the company's source control was unfounded (And of course I could have un-done the pending merge discards anyway).
Hopefully this may reassure someone doing some scary merging in the future!

Jenkins to deploy on Gitlab merge into development, but ignore updates

I have Jenkins set up, connected with Gitlab, to do some deployment stuff whenever a merge request gets accepted into the development branch. It pulls the code, runs some incantations, increments the version number, and commits+pushes that new version number in. The only issue, that I just discovered, is that updating old, already merged MRs, even in trivial ways such as updating the milestone or title, will trigger the build. Because of this, when I just updated multiple old merge requests to have the milestone for this release, the version number got incremented ten times or so- not ideal.
My Gitlab triggers inside Jenkins are quite closed down (please note I'm not on EE):
My Gitlab integrations settings only fire on MR events (and I'm aware there's no way to say only on merging in, rather than editing):
I also have some custom build scripts that do bits and bobs, but the main part that bumps the version number checks that if [ "$GIT_COMMIT" != "$GIT_PREVIOUS_SUCCESSFUL_COMMIT" ]; then. However, even though this seemed logical at the time, it became apparent recently that old, stale merge requests will still be true for this when compared to the development HEAD.
There are many different aspects to this that could be the cause of the trouble, and it may be a very easy solution, but I'm not sure what that would be quite yet. Any help or suggestions greatly appreciated.

Database issue (orphaned migrations) when using git flow branches

Have a git flow question if anyone can help. I'm not really comfortable with using the git flow approach to things so this may be a very stupid question, but here goes:
The way my company handles things is by naming each feature after a specific issue code that relates to the GitHub "issues" page. So, for example, I finished feature/issue-3118 a short time ago. In that branch, I had to remove 2 columns from the user table and clear out (or change) anything that was trying to access it. This was completed, all tests passed etc so I pushed the branch. I then did a git checkout develop and started a new feature branch for the next task assigned to me (called feature/issue-3201).
The problem I have now is that the current branch is failing a bunch of tests that were fixed in the last branch. Running rake db:migrate:status shows my 2 previous migrations as now being orphaned so methods etc. trying to access them are failing tests.
The issue-3118 branch is still in review so I can not just update my master and be on my way. Rather than going through all the database changes again manually (or waiting for the master to be updated), is there an easy way to get over this issue? If I merge the branches, won't this cause conflict issues when I push the current branch?
(If this does indeed sound like a really stupid question, I am about as junior as junior devs get - started my first web development job on August 1st!)
One option, which is likely the way that I would do it, is to start the new feature branch from your feature/issue-3118 branch, rather than from the head of develop. This is not the standard approach, but it sounds as though your new feature is dependent on the completion of feature/issue-3118.
That way, the new feature, will already have those changes in it, and you can continue work there.
Then, once feature/issue-3118 is merged into develop, you can rebase your new feature branch on develop, and continue work.
This maintains the segregation of the work that needs to happen, but allows you to continue while issue-3118 is being reviewed.
Likely, you should get sign off from other people in your team prior to going down this route.

Crucible - Smart commits do not work for large repositories

Smart commits either do not work or works with lag with large repositories. Reviews are created sporadically. The smart commit works on certain branches and not others. Have you seen experienced such nuances, and if so, what would be an option to try?
Large repositories take a lot of time to index, especially if you have lot of feature branches. The lag is because it takes time for crucible to index all that data
You can try 2 things , You can force crucible to run a smart index on a large repository ahead of time
In case your repository is large because you have too many feature branches, try cleaning up your feature branches after a release . We ran into this issue where we had too many feature branches. Once we started cleaning this up , our indexing ran a lot faster and the lag time reduced significantly
I have not seen smart commits not working on branches. In case you have a specific branching scheme that crucible is monitoring and your new branch does not match that pattern crucible will not monitor it. For ex if your crucible is setup to monitor all branches whose name starts with "feature" and your branch name does not start with feature it will not be monitored, period

TFS 2010: Rolling CI Builds

I've been looking around online at ways of improving our build time (which is currently ~30-40 minutes, depending on which build agent gets the task), and one common theme I've seen is use CI builds.
I understand the logic behind this, and it makes sense that it would reduce the time each build takes. Our problem, however, is that building on every check-in is a pointless use of our resources, because in our development branch, we only keep the latest successful build. This means that if 2 people check-in in a short space of time, whoever checked-in last will be the one whose build is kept.
It's this reason (along with disk space limitations) that we changed to using Rolling Builds, so that we only built the development branch a maximum of once every 45 minutes (obviously we could manually trigger builds on otp of that).
What I want to know (and haven't been able to find anywhere) is whether there's a way of combining rolling builds AND continuous integration. So keep building only once every 45 minutes, but only get and build files that have changed.
I'm not even sure it's possible, and if not then I'll look into other ways, but this seems like something that should be possible.

Resources