Version Control Branching - version-control

I'm using TFS version control and am very new to version control in general. The project I'm working on needs a new feature added. Would I branch the entire project or would I only branch those individual files or folders as I work on them? It seems easier to just copy the solution folder and work on an entire new copy but then if I have to go back and fix bugs in the original version I'll have to do them again in the new version. I'm a bit nervous because I've never used branching before and I don't want to screw my project up.

it's personal preference but check out the Rangers Guide to branching here http://blogs.msdn.com/b/visualstudioalm/archive/2012/10/17/alm-rangers-ship-the-new-branching-and-merging-guide-v2-1.aspx
for your situation, i would branch the whole solution, it makes it easier to develop if you have the whole solution, when you are happy you can then merge in your 'feature' branch back to the original branch. If changes have occured on the original branch in the mean time you may have to manualy merge files during the merge operation.

Related

Eclipse switching branch from branch to trunk

I don't understand something that is happening on my Eclipse and I am wondering if this is my Eclipse problem or if this is actually a feature. I have a trunk and a branch. On the repository they are the same so no changes have been commited since I created the branch. After making the branch I switch on my workspace the project from trunk to branch. Then I started working and changing on the branch. Suddenly I wanted to see something on the trunk because I got lost in my changes. So I switch to the trunk. I was surprised when Eclipse did not remove my changes and it was as if no switch was made. The changes continued being there.
Is this normal?
Can someone explain?
Thanks,
David
This is perfectly normal, and the way the svn switch is suppose to work.
Here's a common scenario. You're working on trunk, and realize that your changes should be applied to a branch instead. You simply do switch and you are now on a new branch and your changes are now applied to the new branch. Many times, I'll be working on one stream (a branch or trunk), and realize that my changes are too experimental and big to go into the current development stream. I'll create a new branch and switch to it.
There is no reason with gigabyte fast disks, and gigabyte networks to be skimping on working directories. I tell developers to dedicate a working directory for each project and branch. Otherwise, if they keep switching back and forth between various development streams, they're going to forget and do development in the wrong place.
With almost any svn client you can:
check out a project
make some changes
switch back and forth to any truck/branch
preserve your changes along the way
In other words, nothing specific to eclipse here.
see: svn switch
I prefer to have separate eclipse projects per branch and also change the project name to something like myProject-24 so when the branch is checked out again down the road, the default project name has some branch identifier on it.
This also enables you to make changes on a per branch level and do single commits across the branches; even if they're in discreet eclipse projects.
The functionality you are looking for can be reached by doing the following
Right Click on the folder that should be replaced
Click on "Replace With ..." from the context menu
Click on "Branch ..."
Select the branch you want to take a look at from the dropdown box
ATTENTION: This is replacing your local changes. It is not possible to reverse this.
Greetings
Tobi

Subversion in Eclipse - Switching branch with uncommitted work in repository

Suppose I have the following senario:
Trunk is my main development line where programmers commit to when done.
Branch V1.0 is a branch I created when releasing version 1.0.
The programmer is working on the trunk but needs to switch to the branch in order to fix bugs.
When switching back to the trunk Subversion will give me the latest in the SVN repository which does not include the recent changes.
So, in order to switch he will have to commit what he has because otherwise the changes are "lost". I know they are still kept in the local repository but it would still mean restoring them one by one once he switchesback.
Am I missing something here?
Edit:
Now I am thinking down these lines:
Each programmer would have his own "private" development branch off of the trunch. He could commit to there whenever he wants. When he has finished what he has written he can them merge it into the trunk. He starts again for the next assignment.
If at any point he is required to fix a bug in some other release he can just commit to his own private branch, fetch the odl release and fix it. Then, after committing the changes to the fix, he can easily switch back to his own development branch.
Would that work?
I think that subversion is not thought for switching as you described. A solution would be to have two workspaces, one for the branch and another one the trunk, so you can switch from one to another without problems. I know it is not a nice one.
Consider switching to a version control tool that is better suited for your approach. My own suggestion is Mercurial, coupled with MercurialEclipse. The only drawbacks I'm aware of are that Subversion is better suited to store binary files and that Mercurial's subrepositories don't work so well as Subversion's externals.
In Mercurial your programmers would be able to commit their changes to their private repositories, merge and commit locally again, and then push the resulting changes to an official repository, from which other programmers would pull them into their own private repositories.
The best solution for such purposes is to have two separate working copies. One for working with trunk and one working with the branch.

Managing code in Mercurial: how to revert individual files, "tag" it and be able to maintain it

Update: We ended up using a process very much like this schema (thanks to neuro for the link). We massaged out repository into a state where default is stable (and has the same code as our production environment), we have a dev branch, feature branches for new stuff and use release branches for releases. All seems to be working perfectly.
Backstory
Our team has recently switched from using SVN (using ToroiseSVN Windows client) to Mercurial (using TortoiseHg Windows client) for version control. We have successfully exported our SVN repository and imported it into a Mercurial repository.
We now have a Mercurial repository where we can see the entire history of revisions (changesets in Mercurial).
How we did it in the old days
Life was simpler in the old days; our development process was not really multi-stream like it is now. The trunk was used to hold all code - even changes that were still in-flight (as long as it didn't break the trunk). When it came to managing releases with SVN, we would checkout the trunk (which holds all code), revert the individual changes we didn't want as part of the release, and create a tag for it.
Cherrypicking the code we want with SVN was easy. Bug-fixing previous releases and ensuring it was part of the trunk was simple too.
What we are doing now
In Mercurial, we need to be able to get a snapshot of the "trunk" (default in Mercurial) with individual changes reverted out. We can do this using hg revert.
To snapshot this, we have created a "named branch" - let's call it Build-4.0.1 for now.
Where the challenge arises
Development continues on default as normal when a bug is found in Build-4.0.1. Let's assume the bug is in one of the reverted files. We change the code from the branch for Build-4.0.1, create a new "named branch" (Build-4.0.2) and want to merge it back into default without pushing the reverted code over the top of newer code. How can we accomplish this?
Alternatively, is there a better workflow for managing the releases and our code in Mercurial? I quite like the look of this wonderful SO answer on managing release branches, although I am not sure how we can transition to it from the state we are in now (with in-flight stuff in default).
Note: I have looked at the Transplant extension, but haven't used it yet - could it be part of the solution to this challenge?
Well, to begin with, your use of revert seems strange to me. Usually it is used to revert modifications done to the working copy back to the version of the repository.
The usual way to get the working copy to some point backward is to update :
hg update -r 1234
from there, you can tag, modify, commit, etc.
To merge back you only have to merge your release branch to the default branch. It will work like a charm, unless it is to different/old a release.
Transplant works fine, but do something a bit different from merge : it take your changeset as a "diff" and apply it as a new modification.
To manage your releases, you can look this other answer (by me) :
How to use mercurial for release management?
What we use is a clone / main branch that holds the most stable version, which is released at some points. On this clone : branch, we can fix critical bugs (hotfix). In parallel, we use a dev clone / branch to develop. The hotfixes are merge as soon as completed from stable to dev. When the current development is done, we merge the dev on stable / default.
This schema is pretty good to understand things :)
Good luck !
Going through all the changes and taking out the ones you don't want is not a common way of creating a release, to put it mildly. The Common Branching Patterns section in the SVN book suggest some more popular work flows:
release branches: create release branch from unstable trunk, fix bugs to stabilize it, cherry pick bug fixes between them while the branch is in maintenance mode.
feature branches: keep the trunk stable and ready for release by only merging in the feature branches that you want
The second one is probably the best fit here, because it gives you a place to put experimental or risky changes until you feel confident about them - these are the changes you would have reverted before a release in your old workflow.
Both of these branching patterns should carry over just fine to mercurial. In case you go for the first approach, note that mercurial (since 2.0) now has a graft command, you no longer need the transplant extension.

SVN Branching in Eclipse (Conceptual)

I understand the basic concept of a branch and merge. All of the explanations I've found talk about branching your entire trunk to create a branch project and working on it and then merging it back. Is it possible to branch a subset of a project?
I think an example will help me explain best what I want to do. Suppose I have an application with ten files file0 through file10. All files are interdependent and to be able to test any one file all the others need to be included in the build. I want to work on file0 but don't need to make changes to file1 through file10. Can I branch file0 so changes committed to file0 will update something like myrepos/branches/a-branch/file0 but all the other files in my working copy will simply be from the trunk?
The reason I want to do this is that I'm working on a huge j2ee application with tens of thousands of files and it seems like branching the entire thing will take a really long time. Also, I'm using eclipse with subclipse (and I could be wrong about this) but it seem like if I branch a project in eclipse then I will have to set up a new eclipse project to point to the branch. Unfortunately importing this particular project from SVN to eclipse takes several hours due to the size of the application. It isn't realistic for me to spend this much time.
I suppose that I could have the concepts wrong. Perhaps branching an entire project doesn't require a new working copy at all?
Thanks for any light shed on this issue.
Branching an entire (even) very large tree in Subversion is a very cheap operation, which does lazy (O(1) time) file copying.
You don't necessarily have to change your entire working copy to work on just one changed file. You can use svn switch to switch one file or one directory in your working copy to be a checked out version of the file on the branch.
In Subversion, making a branch is simply making a copy of a hierarchy of directories. Therefore, you can branch a subset, but only if that subset can be defined by a hierarchy of directories.
Can I
branch file0 so changes committed to
file0 will update something like
myrepos/branches/a-branch/file0 but
all the other files in my working copy
will simply be from the trunk?
To answer this question: No, you can't branch a single file. However, what I think you want to do instead is to make a branch and work on file0 there. As you make changes to trunk files, you simply merge them into your branch where you're working on file0.
In this way, you'll always have the latest information from trunk, which will let you test the file0 changes independently of trunk. Then you can use svn switch to move your "file lens" between the trunk and the branch (but beware, Eclipse may complain about such shenanigans).
svn branching is based on lazy copy mechanism, so you can branch safely your all project: that would not take long.
As mentioned in the the question "How do I branch an individual file in SVN?", you could branch a subset, but I believe this would be dangerous with the svn:merginfo properties mechanism: it works better it that property is set from the root of the project.
Branching in SVN is an O(1) operation. Also, as SVN internally employs lazy copying, you only pay a space penalty for what you change.
So if you are unsure, why not go ahead and branch the whole project?
(As quark mentioned, one problem with branching big projects is that, if you checkout several branches/the trunk in parallel, this might take a lot of local disk space.)

When to use a Tag/Label and when to branch?

Using TFS, when would you label your code and when would you branch?
Is there a concept of mainline/trunk in TFS?
A label in TFS is a way of tagging a collection of files. The label contains a bunch of files and the version of the file. It is a very low cost way of marking which versions of files make up a build etc.
A branch can be thought of as a copy of the files (of a certain version) in a different directory in TFS (with TFS knowing that this is a branch and will remember what files and versions it was a branch of).
As Eric Sink says, a branch is like a puppy. It takes some care and feeding.
Personally, I label often but branch rarely. I create a label for every build, but only branch when I know that I need to work on a historical version or that I need to work in isolation from the main line of code. You can create a branch from any point in time (and also a label) so that works well and means that we don't have branches lying around that are not being used.
Hope that helps,
Martin.
In any VCS, one usually tags when you want a snapshot of the code, to be kept as reference for the future. You branch when you want to develop a new feature, without disturbing the current code.
Andrew claims that labeling is lazier than branching; it's actually more efficient in most cases, not lazy. Labeling can allow users to grab a project at any point in time, keep a history of files changed for a version or build, and branch off of/work with the code at any point and later merge back into the main branch. Instead of what Andrew said, you're advised to only branch when more than one set of binaries is desired- when QC and Dev development are going on simultaneously or when you need to apply a hotfix to an old version, for example.
I always see labels as the lazy man's branch. If you are going to do something so significant that it requires a full-source label then it is probably best to denote this with a branch so that all tasks associated with that effort are in an organized place with only the effected code.
Branching is very powerful however and something worth learning about. TFS is not the best source control but it is not the worst either. TFS does support the concept of a trunk from which all branches sprout as well.
I would recommend this as a good place to read up on best practices - at least as far as TFS is concerned.