March 11, 2011, 7:32 a.m.
posted by geist
Editing Files Under Source Control
So far, we have examined the fundamentals of getting the client workspace set up and using both the Solution Explorer and the Source Control Explorer to retrieve files from the Team Foundation source server or add files to the server. Now let's get to the heart of the source control mechanism: change management.
Retrieving a File from the Source Repository
There are two ways to pull a file from the server source repository and place it into the local workspace: by using a Get Latest command or using the Check Out command. Get Latest, as you saw in the previous examples around workspace management, simply retrieves the current version of the file as it exists on the server and copies it down into your workspace. You use the Check Out command to tell the system that you not only want the latest version of the file, but that you also intend to make changes to the file. This can mean one of two things depending on whether the TFSC system has been configured for exclusive or shared access: If exclusive, a lock will be placed on the file and no one else will be able to make changes as long as it is checked out by you. If shared, then others are permitted to make changes to the file; these changes will later be merged with any changes that you make to generate a new version that will ultimately be the one stored in the source repository.
The exclusive versus shared access setting is actually dictated by the process template being used within your Team Project. For more information on process templates, consult Chapter 18, "Managing and Working with Team Projects," or the MSDN documentation for Team Foundation Server.
Checking in Your Changes
When you are done with your changes, it is time to check those changes back into the source server. There are three ways to do this: You can right-click on the file in the Solution Explorer, you can right-click on the file in the Source Control Explorer, or you can use the Pending Changes window.
Using the Solution Explorer window, you right-click on the file that you want to check in and select the Check In command from the context menu. The Check In dialog box, shown in Figure, is the place where the action happens. This dialog box contains a list of all the files currently available for check-in. Each file can be selected or deselected using a check box (the file that you previously selected will already have its selection check box checked for you). You simply select any of the files that you want included in the check-in process and then click on the Check In button. Notice that you can provide a comment as well (which is always a best practice to provide the check-in with some historical context on the reason for the change/check-in).
11. The Check In dialog box.
Buttons in the top toolbar allow you to control how the files are viewed, hide or show the comment area, or even filter the list of files based on the solution.
You can access this same window from the Source Control Explorer window: Select your file or files, right-click, and select the Check In command to view the Check In dialog box.
To the left side of the Check In dialog box are buttonsreferred to as channelsused to place the dialog box into different modes. Besides the Source Files channel (which is shown in Figure), you can select channels for working with Work Items, Check In Notes, and Policy Warnings. Before we get into these topics, let's examine the third way to check changes back into the source repository: through the Pending Changes window.
Checking Changes with the Pending Changes Window
The Pending Changes window is implemented as a tool window in Visual Studio. You open it by selecting View, Other Windows, Pending Changes. You can also launch the window by right-clicking on any item within the Solution Explorer and selecting View Pending Changes.
As its name implies, this window, shown in Figure, contains a list of all pending changes within your current workspace. Every file that you have checked out is visible in the window.
12. Viewing pending changes.
The Pending Changes window is structured identically to the Check In window and supports the same channels; there are just a few minor differences with the toolbar, which supports two new buttons: Shelve and Unshelve. We cover shelving later in this chapter.
Understanding Check-In Policies
Project teams will have different rules that users will need to follow in determining whether a check-in is appropriate. For instance, checking in a class file that doesn't compile probably isn't a good idea. Anyone else performing a Get Latest operation or Check Out on the file would have his or her project "broken" because of your changes. Team Foundation Source Control recognizes the importance of vetting check-ins and provides a way to enforce certain rules on check-in through the use of check-in policies.
Three check-in policies are available out of the box with TFS:
Check-in policies are typically set up and configured on a per-project basis by project administrators; a default set of selected policies is usually turned on by the TFS process template currently in use. To configure which policies are in effect for your current project, you would access the Team Foundation Server source control settings available by selecting Team, Team Project Settings, Source Control Settings. The Source Control Settings window (see Figure) has a Check-In Policy tab, which allows you to select the specific policies to be enforced for the current project.
13. Adding a check-in policy to the current project.
Each policy may require additional settings. For instance, adding the Code Analysis policy will spawn yet another dialog box used to specify the exact code analysis tests that should be required (see Figure).
14. Configuring the code analysis check-in policy.
If check-in policies are in effect, select the Policy Warnings channel (in either the Check-In or Pending Changes window), and you will see any policy violations. As an example, Figure shows the policy warnings that result from enabling the Code Analysis policy and then attempting to check in a VB class file without running the Code Analyzer.
15. Policy warnings.
If you were to try to check in these files, a Policy Failure dialog box would launch (see Figure). You can either choose to abort the check-in and satisfy the policy, or you can override and provide a comment that explains your decision to circumvent the policy.
16. Overriding a policy failure.
Adding a Check-In Note
Check-in notes are short pieces of text that you can attach to the check-in items during the check-in process. Check-in notes become a part of the file's historical metadata, are stored in the source repository, and can be viewed at a later date so that you can get a sense for an item's change history.
A check-in note consists of a category name or prompt and the actual note text. By default, there three note categories: security reviewer, code reviewer, and performance reviewer. When performing a check-in, you can click on the Notes channel button to enter notes. Each note prompt/category will appear with a corresponding text box that holds the text of the note (see Figure).
17. Adding notes to a check-in.
Check-in notes can be required for a project, and you can also add your own check-in note categories. These settings are managed from the Source Control Settings dialog box, which we covered during our discussion of check-in policy management. The Check-In Notes tab (see Figure) allows you to add or remove note categories.
18. Managing check-in notes for a project.
For example, you could add a new note prompt for a knowledgebase article number. Just click on the Add button, fill in the category/prompt text, and then select whether the note should be required (see Figure).
19. Adding a new check-in note category.
Using Work Items
The last check-in feature we'll cover is the concept of relating check-ins to work items. Work items, which we cover in depth in the next chapter, are used to represent tasks within the project from bug reports to traditional "to do" items. Work items can be linked to a variety of different artifacts within the Team Foundation system; check-ins are merely one of those items.
To associate a check-in with a work item, select the Work Items channel and then select from the list of available work items. By associating work items with a check-in, you help to integrate the various work sets from across the project into one cohesive representation of the project's progress. Consider, for example, a developer who has created a class library as part of her project tasks. After testing, she determines that one of her classes isn't responding as expected to one of the test cases. Instead of reporting an exception, the class is swallowing the exception. To fix this problem, the developer checks out the class file, fixes the bug, and then checks the file back in. During the check-in process, she would ensure that the bug work item that initially prompted the work was associated with the check-in, as shown in Figure.
20. Associating a work item.
The work items that appear in the list are actually returned from a query that is run against the work item database. You can change the query by using the drop-down at the top of the Work Items channel window, or you can even perform a search across all work items. As mentioned, work items, queries, and many more work item topics are covered in Chapter 20, "Work Item Tracking."
Understanding the Concept of Changesets
Until now, our discussion of the check-out/check-in process has been fairly simplistic, focusing on checking out a file, making changes, and then checking that file back in. In reality, what we have been talking about is the concept of changesets. A changeset is a compilation of all the information associated with a check-in operation.
To extend the prior bug fix example, you may check out three different files to fix a bug. When you perform a check-in, you will check in all three of these files at the same time and associate their check-in with the bug work item. This is where the changeset concept comes into play: The changeset bundles these three files into a single entity. In other words, the bug is, rightly, associated with the three files as a whole. It is associated with the changeset. Any related work items, notes, and metadata about the code change (date, time, user) are all associated to the changeset as a whole, and not to the individual files.
It is worth noting that check-ins and, by extension, changesets are atomic in nature. That is, Team Foundation Server guarantees that the entire changeset was committed in its entirety; you would never, for instance, attempt a check-in of three files and have only two of those files succeed in the transaction. All three of them go, or (in the case of an error) none of them go.
The diagram in Figure shows how changesets figure into the overall source control process.
Shelving Your Code
Sometimes, developers may need to set aside their current work or move on to other tasks before the files are ready for check-in. For instance, you may be in the middle of working on some code files when an urgent bug is logged that requires your attention. Or perhaps you haven't quite completed a required code change before leaving on vacation. In these scenarios, you don't want to check in your work because it is incomplete. You also don't want to leave the work checked out locally onto your box for what may be a lengthy time period. Shelving allows you to take some or all of your pending changes and store them back into the TFS source repository database without checking them in.
Shelving works in a similar way to the check-in process, and is handled by the Shelve window. To open the Shelve window, you can click on the Shelve button in the Pending Changes window, or you can click on the Shelve Pending Changes button in the Source Control Explorer. Alternatively, you can use the Solution Explorer: Right-click on a file and select Shelve Pending Changes.
When you shelve your code, you are creating a shelveset, which is identical to a changeset but applies to shelved code only. You will be prompted to name your shelveset so that it can be retrieved later. Figure shows code files being shelved from the Shelve window.
22. Shelving code changes.
After a shelveset has been created, you have the option to unshelve that shelveset at any point in time. This will return all the shelved files into your workspace. Click on the Unshelve button in the Pending Changes window to launch the Unshelve window.
All your previously created shelvesets will be visible; you simply select the one you want and click the Unshelve button (see Figure). Note that you can change the owner name field and initiate a new search for any shelvesets that belong to that user.
23. Unshelving code changes.
When we introduced the check-out process, we mentioned that check-outs can be exclusive or shared. In the case of shared check-outs, in which more than one person is actively changing the same file, Team Foundation provides a way to merge those changes into a new changeset that will replace the current file version on the server.
Let's examine a common scenario: Developer A checks out a class file and works on a method within the class. While the file is checked out, Developer B is assigned a bug and has to work on a different method contained in the same code file. Developer B then checks out the file and works on his method. Developer A checks in her changes and then a day later Developer B checks in his changes. At this point, a conflict exists: Because Developer B never had a copy of the source file in his workspace with Developer A's changes, something needs to be done to merge the two files. This situation is handled with the merge tool.
When Developer B starts to check in his file, Team Foundation source control will automatically detect a conflict. This will result in the Resolve Conflicts window being displayed (see Figure).
24. The Resolve Conflicts window.
To resolve the conflicts in the identified file, you click on the Resolve button, which launches yet another screenthe Resolve Version Conflict window, shown in Figurethat provides some more details on the file conflict and offers some options for rectifying the conflict.
25. The Resolve Version Conflict window.
There are four options available for proceeding:
In all but the simplest cases, you will need to use the merge tool to explicitly tell Visual Studio how to handle the conflict. To assist with understanding the nature of the conflict, you can also launch the File Comparison tool from this window.
Comparing File Differences
The File Comparison tool, shown in Figure, provides a simple side-by-side view of the two files, the server file and the local file, and visually highlights the textual differences between the two through a highlighting scheme. Blue represents changed text, green represents inserted text, and red represents deleted text.
26. Using the File Comparison tool.
You can't actually edit the files using this tool; that needs to take place with the merge tool.
Using the Merge Tool
The merge tool provides a similar view to the file comparison window: It highlights the textual differences between the two windows. But this tool shows a third view as well: the results of a merged file. See Figure for a look at the merge tool window.
27. Merging changes.
By moving the cursor in the merged file pane, you can move your current position and then insert changes from either of the two conflicting files. In this specific example, we wanted to add two methods to the merged file. One method exists in the server copy, and the other method exists in the local copy. To create the merged file, you would first select the change highlighted in the server copy (top-left pane). This will insert that block of changed text into the blank merged copy (bottom pane). You can then reposition the cursor location to some point after the newly added method text and then click on the highlighted, changed text in the local copy (top-right pane). The merge tool will add this text into the merged file as well, resulting in the desired outcome: a new version of the source file that combines the content of the server copy and the local copy.