<?xml version="1.0" encoding="utf-8"?>
<rss xmlns:atom="https://www.w3.org/2005/Atom" xmlns:sy="https://purl.org/rss/1.0/modules/syndication/" xmlns:dc="https://purl.org/dc/elements/1.1/" xmlns:content="https://purl.org/rss/1.0/modules/content/" xmlns:wfw="https://wellformedweb.org/CommentAPI/" xmlns:slash="https://purl.org/rss/1.0/modules/slash/"
  version="2.0">
  <channel>
    <title>Edward Thomson's Blog</title>
    <atom:link
      href="https://docs.microsoft.com/archive/blogs/ethomson/feed.xml"
      rel="self"
      type="application/rss+xml" />
    <link>https://docs.microsoft.com/archive/blogs/ethomson/feed.xml</link>
    <description>Discussions about Team Foundation Server in a cross-platform environment.</description>
    <lastBuildDate>Wed, 17 Apr 2019 03:41:30 GMT</lastBuildDate>
    <language>en-US</language>
    <sy:updatePeriod>hourly</sy:updatePeriod>
    <sy:updateFrequency>1</sy:updateFrequency>
    <item>
      <title>Locking and git-tf and... danger?</title>
      <link>https://docs.microsoft.com/archive/blogs/ethomson/locking-and-git-tf-and-danger</link>
      <pubDate>Tue, 28 Aug 2012 07:56:00 GMT</pubDate>
      <dc:creator><![CDATA[Edward Thomson]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/ethomson/2012/08/28/locking-and-git-tf-and-danger/</guid>
      <description><![CDATA[If you haven't yet seen or heard about the new git-tf tool from Microsoft, this blog post probably...]]></description>
      <content:encoded><![CDATA[<p>If you haven't yet seen or heard about the new git-tf tool from Microsoft, this blog post probably won't make any sense. &nbsp;So... &nbsp;go check it out over at <a href="https://gittf.codeplex.com/" target="_blank">gittf.codeplex.com</a>. &nbsp;It's okay, I'll wait.</p>
<p>Okay, got it? &nbsp;Yeah, I know, it's cool, right? &nbsp;Well, it is, but like any software project, there are a few problems. &nbsp;One of them is in the whole <code>git-tf checkin</code> process and how it needs to take a lock on your tree before it can continue. &nbsp;I mean, locks are annoying, right? &nbsp;If git-tf requires a lock to do a checkin, then that's going to fail if somebody else has already taken a lock somewhere in that folder. &nbsp;And, of course, the default in TFS is to take a lock on binaries, so if you've got some of those in your tree then git-tf is going to complain all the time when you try to checkin.</p>
<p>It's even worse when you run into this the first time and decide that we can't have been so obnoxious as <em>force</em> you to take a lock. &nbsp;Surely those developers put in some no lock option, maybe even called <code>--no-lock</code>, that will avoid locking. &nbsp;And we did! &nbsp;And with our appropriately scary warning in the checkin help:</p>
<pre class="codeblock">--no-lock Does not take a lock on the server path before committing (dangerous)</pre>
<p>...you can see why this is a problem. &nbsp;I mean, it's <strong><em>dangerous?!</em></strong> &nbsp;Who would want to use that!?</p>
<p>Okay, let's back up and explain why we decide to take this lock.</p>
<p>Team Foundation Server's version control model has good concurrency. &nbsp;Let's assume that you and I are both working on the latest version and we both edit some files. &nbsp;If we both hit the checkin button at the same time, this is a classic race condition, but one that's harmless. &nbsp;Our checkins get serialized and - assuming we haven't edited any of the same files to produce a conflict - it really doesn't matter all that much which one of us wins this race and which one loses. &nbsp;Both of our changesets got checked in and the next time we do a get latest, we get the other person's changes, too. &nbsp;Things get a little bit more complicated if we edit the same file, but not much. &nbsp;The winner of this race gets their changes checked in - the loser has to resolve a conflict and then checkin again. &nbsp;This is pretty classic version control behavior and a well-understood problem.</p>
<p>git, of course, also has good concurrency. &nbsp;Let's assume that you and I are both on HEAD and we both edit some files. &nbsp;If we both were to commit to our local git repository, now we both have new commits that share a common parent. &nbsp;At some point, we'll need to merge this branch in the graph, but this is no big deal. &nbsp;Again, a race condition that doesn't matter.</p>
<p>git-tf, on the other hand, can't cope well with this race condition. &nbsp;(It might be a bit much to have called it <em>dangerous</em>, but that little word scared you enough to read this blog post, so I think we'll stick with that term for a little while longer.) &nbsp;Here's how git-tf checkin works, in a nutshell:</p>
<ol>
<li>Finds the latest TFS changeset that you've fetched and merged into your graph. &nbsp;This is the "high water mark".</li>
<li>Takes a lock on the TFS path you're bridging. &nbsp;Unless, of course, you're living dangerously and using that crazy <code>--no-lock</code> flag.</li>
<li>Ensures that this high water mark is actually the latest TFS changeset. &nbsp;If not, you will be told to fetch that changeset and merge.</li>
<li>Pends the changes to TFS that are representative of the changes in your git commit and checks them in.</li>
<li>Updates the aforementioned "high water mark" to the changeset that I just checked in.</li>
</ol>
<p>Let's take another look at this race condition once git-tf gets in the picture. &nbsp;Imagine that I'm using git-tf and you're using some other TFS client like Visual Studio or the TFS plug-in for Eclipse. &nbsp;The latest version is changeset 3, and I've made a git commit on top of that. &nbsp;My git repository looks like this:</p>
<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/44/48/4377.locking-1.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-44-48/4377.locking_2D00_1.png"><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/44/48/4377.locking-1.png" original-url="https://blogs.msdn.com/resized-image.ashx/__size/500x0/__key/communityserver-blogs-components-weblogfiles/00-00-01-44-48/4377.locking_2D00_1.png" border="0" alt="" /></a></p>
<p>I'm ready to git-tf checkin these changes, and I'll do so without a lock. &nbsp;Meanwhile, you've also made some changes against TFS and you're going to check in at the same time. &nbsp;If you happen to sneak your changeset in between steps 3 and 4 (above), then I've updated my high-water mark to <em>my</em> changeset... &nbsp;but I never got <em>your</em> changeset.</p>
<p>In a perfect world, I would pull your changeset down as a git commit such that it has a parent of 3, and my git commit <code>4fac65...</code> has your changeset as a parent. &nbsp;This keeps the linear model of TFS changesets that git-tf strives so hard for. &nbsp;Except that if I do that, my commit can't be <code>4fac65...</code> anymore, it gets a completely new ID because those are computed based on their parents. &nbsp;Ouch.</p>
<p>The way it is, I'll never even see your changes until there's a new changeset and I can fetch that, since git-tf's high water mark already includes the latest changeset on the server. &nbsp;So it turns out that not locking can be dangerous after all.</p>
<p>Of course, most people don't have <em>that</em> much churn in their code tree that this is an issue. &nbsp;So you could just check the history in TFS to make sure that nobody else snuck with a new changeset in those few seconds. &nbsp;And if they did, of course, you could just stick a new dummy changeset in TFS so that you could pull the latest version that has the other changes, too. &nbsp;But this isn't exactly an ideal workflow.</p>
<p>So the question of course becomes: &nbsp;can we avoid taking a lock, but stay out of danger? &nbsp;We think so. &nbsp;We spun up <a href="https://gittf.codeplex.com/discussions/393372" target="_blank">a conversation over on our codeplex site</a> about this - so if you're interested in this topic, we'd love your feedback.</p>]]></content:encoded>
    </item>
    <item>
      <title>Team Foundation Server and Xcode projects with git-tf</title>
      <link>https://docs.microsoft.com/archive/blogs/ethomson/team-foundation-server-and-xcode-projects-with-git-tf</link>
      <pubDate>Tue, 28 Aug 2012 07:15:00 GMT</pubDate>
      <dc:creator><![CDATA[Edward Thomson]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/ethomson/2012/08/28/team-foundation-server-and-xcode-projects-with-git-tf/</guid>
      <description><![CDATA[Brian Harry announced the availability of git-tf&nbsp;last Monday, a new tool from Microsoft that...]]></description>
      <content:encoded><![CDATA[<p>Brian Harry <a href="https://blogs.msdn.com/b/bharry/archive/2012/08/13/announcing-git-integration-with-tfs.aspx" target="_blank">announced the availability of <code style="white-space: nowrap;">git-tf</code></a>&nbsp;last Monday, a new tool from Microsoft that allows you to create a local git repository from a path in Team Foundation Server, then check the changes in your repository back in to TFS. &nbsp;This tool is another piece in our cross-platform support, aimed at users of IDEs that don't have built-in TFS integration.</p>
<p>We hope that Xcode users will find this particularly useful, as Xcode sadly lacks a plug-in model that would allow us to build TFS support natively. &nbsp;Xcode does have git support, however, so once you've created your git repository with git-tf,&nbsp;you can use Xcode's source code integration directly.</p>
<p>This means that if you're writing mobile applications, you can now use Team Foundation Server as your ALM solution for the entire development team. &nbsp;Imagine you have your shared business logic in C, you have a Windows Phone 8 version being developed in Visual Studio, an Android version being developed in Eclipse and an iOS version being developed in Xcode. &nbsp;Now all your developers can take advantage of TFS Version Control - your Visual Studio users with Team Explorer, your Eclipse users with the TFS Plug-in for Eclipse and your Xcode users with git-tf.</p>
<p>I'm too hopelessly old-school to be hip to the new mobile apps, so I'm going to show how I work on a cross-platform command-line application that plays blackjack. &nbsp;I've got my source in TFS, with an Xcode project side-by-side with my Visual Studio solution:</p>
<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/44/48/8640.vstudio-vc.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-44-48/8640.vstudio_2D00_vc.png"><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/44/48/8640.vstudio-vc.png" original-url="https://blogs.msdn.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-01-44-48/8640.vstudio_2D00_vc.png" border="0" alt="" /></a></p>
<p>Once I have Xcode and git-tf installed on my Mac, I can download this project easily:</p>
<pre class="codeblock">ethomson@mbp:~/Demo% git tf clone --deep https://tfs2012:8080/tfs/DefaultCollection $/DefaultAgile/blackjack<br />Username: ethomson<br />Password: <br />Connecting to TFS...<br />Cloning $/DefaultAgile/blackjack into /Users/ethomson/Demo/blackjack: 100%, done.                   <br />Cloned 14 changesets. Cloned last changeset 19 as fb65c36<br />ethomson@mbp:~/Demo% </pre>
<p>Now I have a git repository that represents my TFS changesets, with full history. &nbsp;(That was the <code style="white-space: nowrap;">--deep</code> option, without that I would have a single git commit that represents my latest TFS changeset. &nbsp;This is quicker to compute and useful if you don't need full history.) &nbsp;You can see that my history in Visual Studio:</p>
<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/44/48/3441.vstudio-history.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-44-48/3441.vstudio_2D00_history.png"><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/44/48/3441.vstudio-history.png" original-url="https://blogs.msdn.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-01-44-48/3441.vstudio_2D00_history.png" border="0" alt="" /></a></p>
<p>is the same as the history in my local git repository:</p>
<pre class="codeblock">ethomson@mbp:~/Demo/blackjack% git log<br />commit f33b75c0190d76c417fd5d724236a9c3f731b185<br />Author: tfsuser &lt;tfs2012\tfsuser&gt;<br />Date:   Tue Aug 14 15:20:20 2012 -0500<br /><br />    This is a commit from Xcode.<br /><br />commit a88b3887f1998fac74beb8ee32b4d91e06d8e625<br />Author: ethomson &lt;tfs2012\ethomson&gt;<br />Date:   Tue Aug 14 15:16:16 2012 -0500<br /><br />    This is a change from Visual Studio.<br /><br />...etc...</pre>
<p>When I open up this project in Xcode, you'll notice that when I start making changes to files, they're automatically added to my git index, as denoted by the small <strong>M</strong>&nbsp;next to the filename in Project Navigator. &nbsp;Below, I've made some changes to my project's assertion logic, changing Assert.cpp and Assert.h.</p>
<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/44/48/6622.xcode-editing.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-44-48/6622.xcode_2D00_editing.png"><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/44/48/6622.xcode-editing.png" original-url="https://blogs.msdn.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-01-44-48/6622.xcode_2D00_editing.png" border="0" alt="" /></a></p>
<p>When Xcode's source control integration, I can commit these changes to my local git repository from right within my IDE. &nbsp;When committing, it will show a handy diff viewer for each file in my commit.</p>
<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/44/48/0474.xcode-committing.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-44-48/0474.xcode_2D00_committing.png"><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/44/48/0474.xcode-committing.png" original-url="https://blogs.msdn.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-01-44-48/0474.xcode_2D00_committing.png" border="0" alt="" /></a></p>
<p>You can see the two commits I've made in my Xcode project in my git log.</p>
<pre class="codeblock">ethomson@mbp:~/Demo/blackjack% git log<br />commit 6f9bbafa5482c77de5b97b2548320b78de6b82fe<br />Author: Edward Thomson &lt;ethomson@edwardthomson.com&gt;<br />Date:   Thu Aug 16 15:58:43 2012 -0500<br /><br />    Fixed some typos in the comments.<br /><br />commit 8dd92848b4ea0f6549d6f88d28e47c3e1201cd7c<br />Author: Edward Thomson &lt;ethomson@edwardthomson.com&gt;<br />Date:   Thu Aug 16 15:55:01 2012 -0500<br /><br />    A couple of minor changes in Xcode<br /><br />...etc...</pre>
<p>Once I'm done making changes locally and I want to integrate with the rest of the team, I can check them in to my TFS server using git-tf checkin. &nbsp;Just like when I cloned my project, I can use the <code style="white-space: nowrap;">--deep</code> option to preserve history.</p>
<pre class="codeblock">ethomson@mbp:~/Demo/blackjack% git tf checkin --deep<br />Username: ethomson<br />Password: <br />Connecting to TFS...<br />Checking in to $/DefaultAgile/blackjack: 100%, done.                            <br />Checked in 2 changesets, HEAD is changeset 21</pre>
<p>Back in Visual Studio, you can see both of these changesets in my TFS history.</p>
<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/44/48/6283.vstudio-aftercheckin.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-44-48/6283.vstudio_2D00_aftercheckin.png"><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/44/48/6283.vstudio-aftercheckin.png" original-url="https://blogs.msdn.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-01-44-48/6283.vstudio_2D00_aftercheckin.png" border="0" alt="" /></a></p>
<p>And, of course, since I'm doing Continuous Integration builds for this project, as soon as I checkin from git-tf, TFS queues up a build for me. &nbsp;In this case, I get two - one for each changeset, since I did a deep checkin from my two git commits.</p>
<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/44/48/7245.vstudio-builds.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-44-48/7245.vstudio_2D00_builds.png"><img src="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/44/48/7245.vstudio-builds.png" original-url="https://blogs.msdn.com/resized-image.ashx/__size/550x0/__key/communityserver-blogs-components-weblogfiles/00-00-01-44-48/7245.vstudio_2D00_builds.png" border="0" alt="" /></a></p>
<p><a href="https://msdnshared.blob.core.windows.net/media/MSDNBlogsFS/prod.evol.blogs.msdn.com/CommunityServer.Blogs.Components.WeblogFiles/00/00/01/44/48/7245.vstudio-builds.png" original-url="https://blogs.msdn.com/cfs-file.ashx/__key/communityserver-blogs-components-weblogfiles/00-00-01-44-48/7245.vstudio_2D00_builds.png"></a>So you can see that now I can easily use Xcode to take advantage of the ALM functionality of Team Foundation Server, providing every developer on a team with intuitive access to TFS Version Control.</p>
<p>git-tf is <a href="https://gittf.codeplex.com/" target="_blank">available now on CodePlex</a>, Microsoft's Project Hosting for Open Source Software and we're making git-tf available open source under the MIT license. &nbsp;We think this is a very useful tool right now, and we're looking forward to making it even better.</p>]]></content:encoded>
    </item>
    <item>
      <title>TFS Austin User Group</title>
      <link>https://docs.microsoft.com/archive/blogs/ethomson/tfs-austin-user-group</link>
      <pubDate>Mon, 04 Apr 2011 21:37:00 GMT</pubDate>
      <dc:creator><![CDATA[Edward Thomson]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/ethomson/2011/04/04/tfs-austin-user-group/</guid>
      <description><![CDATA[A very special thanks to the TFS Austin User Group&nbsp;for providing me time today to present on...]]></description>
      <content:encoded><![CDATA[<p>A very special thanks to the <a target="_blank" href="https://sites.google.com/site/tfsaustinusergroup/" title="TFS Austin User Group">TFS Austin User Group</a>&nbsp;for providing me time today to present on TFS for Heterogeneous Environments.&nbsp; My slide deck from the presentation is available here:</p>
<p>[View:https://blogs.msdn.com/cfs-file.ashx/__key/CommunityServer-Blogs-Components-WeblogFiles/00-00-01-44-48-AustinTFSUGDemo/6505.Heterogeneous_5F00_ALM.pptx]</p>]]></content:encoded>
    </item>
  </channel>
</rss>