Understanding Source Control in Xcode

Session 414 WWDC 2013

Learn how Xcode’s source control features can help you work more efficiently with your team, juggle numerous development branches, find and fix bugs, and better understand the history of your code with the Version editor.

[ Silence ]

[ Applause ]

Kevin Lindeman: Good morning everyone.

Welcome to understanding Source Control in Xcode.

My name's Kevin Lindeman, I'm an Xcode Software Engineer.

So first off we have so much new stuff in Xcode 5 that we want you to take a look at our session from last year, Source Control Management in Xcode, to learn about some of the more basic integration of Source Control in Xcode.

It's all the same in Xcode 5.

And that session in conjunction with this year's session will give you the full picture of how to use Source Control in Xcode.

So I'm going to start off talking about the three C's in Source Control.

The first one is Confidence.

Using Source Control in Xcode gives you the confidence that you're committing the right code.

It also gives you the confidence that when you're using branching, you're committing to the right branch.

Now using Source Control also allows you to commit your changes in smaller chunks so that you can go back in history using the version editor or blame and see exactly why a change happened, when it happened and by who and maybe go back and run that version of the code instead to try to find regressions.

It also helps with compartmentalization.

Xcode has excellent branch management so when you're working on a potentially large feature, you can branch off of your main code and iterate on that branch over time until you're ready to make that your main branch and merge all of that code into your main line.

The third C is Collaboration.

Now especially with our integration with OS X server, Source Control becomes an easy two-way street of pushing changes back and forth to your coworkers so that when you make a change you can give those changes easily to your coworkers so that you're all always building the latest stuff in your project.

So we've added a lot to Source Control in Xcode 5.

And the first thing is we're now shipping the latest Subversion client, Subversion 1.7.

We also have a much improved checkout workflow that I think you'll really love.

We've also got brand new workspace centric workflows so there's no more running back and forth between the workspace and the repository organizer.

We also have deep integration with the Xcode service on OS X server making really easy so that when you start off with a new project, putting that project under Git and automatically pushing that project to your OS X server.

We also have greater customization using a new Source Control preference pane allowing you to make Source Control work with you.

So let's talk about Subversion 1.7.

One of the key differences compared to Subversion 1.6 which we shipped in Xcode 4, is that when you have a project like you see here every folder inside of that project has a .svn folder in it.

Now if you're looking at that project in Terminal or something that really clutters up your folder structure.

Subversion 1.7 when you upgrade to it, it takes all of the .svn folders lower down your file system and puts them up into the top level .svn folder for your project.

This makes it much more similar to how a Git works.

Now the first time you open a project in Xcode 5 you'll see this dialogue.

It's asking you to upgrade your project to Subversion 1.7.

Now this will be handled entirely by Xcode, you don't have to do anything.

It's also entirely client side.

It doesn't change anything on your server.

And each individual team member can opt into upgrading to Subversion 1.7.

Now this is an important distinction because Xcode 4 only supports Subversion 1.6.

So when you're going back and forth during the developer previews of Xcode 5, you'll need to be using Subversion 1.6 if you want to use Source Control in Xcode 4.

But we really do urge you to try to upgrade because there's a lot of really great enhancements in Xcode 5 when you use Subversion 1.7.

The first of those is improved performance.

Operations such as SV and up are a lot faster.

We've also added support for blame for modified files.

I'm sure you've been working in Xcode, modified a file, haven't yet committed it yet but then wondered, well who changed this line over there and noticed that you couldn't look at your locally modified version of that file in blame.

Well now you can with Subversion 1.7.

That also has always worked with Git.

We also have this great new feature called blame for line.

It's a shortcut in the standard editor.

You don't even have to go to the Version Editor into the blame submode to see blame for your whole file.

You can just say I'm curious about what this line is, right click it in Git and a great popover a view of who changed that line, when it was changed, why, with quick shortcuts for opening it in the full blame editor or into the comparison editor so you can see all the changes in that file.

It also highlights all of the other lines in that source file that were modified with the same commit.

And also the command line integration.

When you install the Xcode 5 version of command line tools, all you will have access to is Subversion 1.7.

Subversion 1.7 cannot talk to a Subversion 1.6 working copy until you upgrade and vice versa, 1.6 cannot talk to a 1.7 working copy.

But like I said, this is entirely client side so you don't have to upgrade all of your working copies right now.

So moving onto this new workspace Source Control.

There's three things that that takes into account.

First is the new accounts preference pane.

Instead of setting up a repository on the organizer, you can go to the accounts preference pane and set up any of your accounts that would have login credentials that Xcode will talk to.

And there's also the new Source Control menu.

We've taken a lot of the new features of Xcode 5 and all the old ones and put them into a top level menu for you.

We've also got the new checkout workflow.

And so let's talk about the accounts preferences.

As I said this is the single place for doing all of your credential management.

You can set up Apple IDs for setting up provisioning of your devices.

You can also set up Subversion servers and any of the credentials used for those, Git remotes and OS X server accounts so that you can get the OS X server integration in Xcode.

Now let's talk about the Source Control menu.

This is great because we've taken all the working copies that are part of your workspace and put them at the top of the menu because we know you want to know what Source Control working copies you're using in your project.

We've also added the ability to show the current branch for each of those working copies right there so you know what you are committing to and what you're building.

Under each of those working copies is our branch management tools.

You can also do on demand upgrades here if you opted not to upgrade on workspace open.

Then there's some of more top level items like checkout for getting new Source Code, commit, push, pull and update and a new workspace wide history view which will take all of the working copies in your project, show you the logs all in one list that is also searchable.

So now let's talk about Checkout.

As I said brand new look, a lot easier to use as well.

But it's also a lot more powerful.

We show recent projects that you have open or checked out as well as recent repositories that you have checked out from right there.

We also have favorites.

You can now star a repository or project and have it always show up under the favorites tab.

There's also the repositories tab which will take all of the repositories you have set up in the accounts preferences and list them here as well as any repository that is hosted on your OS X server using its Git integration.

It will also show you browsing a subversion repository when necessary.

Xcode 5's checkout is way smart so it actually does subversion branch auto discovery.

So if you type in the URL the Xcode can figure out what you might be checking out, whether it's a branch or it knows that there's a bunch of branches in there, it will just show you that, you don't even need to browse your repository.

But if you put in a URL that's a little ambiguous such as sometimes if you have a multiple projects hosted in a single repository and you just give it the root URL to your repository, we can't really tell exactly what you wanted to checkout just yet so it will allow you to browse.

Let's take a quick look at this in the demo.

So we have here the Welcome window Xcode 5.

First I wanted to show how to easily create a new project or a new repository account in Xcode.

So I'm going to click the Xcode menu and click preferences.

And we see here I already have a number of repositories set up as well as my OS X server.

But I'm going to add a new repository so I'm going to hit the plus button and say add repository.

It's asking me for the address, I have a snippet that has a Git hub account in it and so I'm going to click next.

And now Xcode is verifying my credentials to this repository and is now added as a repository that I can checkout from.

Now when I go back to the Welcome window and select checkout an existing project, we see that that repository has now been added.

I can also star any of these repositories and have them show up in the favorite section.

For now, I'm going to check out a copy of WebKit.

Now this is the root URL to the repository but since there's only one project on here it was able to automatically discover the chunk folder, the branches folder and the tags folder and just showed me the list of branches I can checkout from.

So I want to check out chunk.

So I'm going to click next and check that out to my desktop.

So now Xcode is checking out that working copy and when it's done it will search through the Checkout and find automatically any Xcode projects or workspaces and opens them.

If there are more than one, it'll let you choose which one you want to open.

So since there's only one it just showed me the workspace.

And now we can take a look at the brand new Source Control menu at the top here.

When I click Source Control we see the one working copy that is part of this workspace and that I just checked out chunk and so the current branch is chunk.

All of our branching operations such as new branch, switching to branches, merging branches are all in here.

You can also configure a couple of options on a working copy.

I'll talk about that later.

There's also a way to get to checkout from in here as well as the workspace wide operations like commit, push, update, refreshing status.

You can discard all of the changes and all of the working copies in your workspace using Xcode 5.

You can do file, specific operations like adding, discarding changes in a specific file or marking files as resolved here.

Let's take a look at this new history option now.

So I click that and Xcode has now loaded all the history for this workspace.

There's only one working copy in this workspace so this is a very simple view of just that one.

Eric will show you a more complex example later.

So you can scroll through all these.

But I know that I have a specific commit message that I'm looking for.

So there's now a search field up here at the top.

I'm curious about searching for stuff that touched the CSS support.

So I type in CSS and now Xcode searched the subversion repository for commit messages referencing CSS.

So there's a particular commit down here that I was interested in.

So let's take a look at this one.

We see who committed it, when it was committed, the revision number, the commit message for this particular commit and there's also this option to show the modified files for this commit.

So when I click that, we now see a sheet that has all the files that were changed as part of that commit and allows me to look at the changes.

On the right side here we have the version of this file prior to the commit and then on the left what was actually changed.

So you can just go through all of these files and see exactly what changed in a commit.

So we just took a look at how to set up an account as well as a little preview of the Source Control menu, checkout and how it can auto discover branches for a subversion repository.

And also when you go to set up in Checkout a new URL that you've never checked out from, it'll automatically set up the account for you, asking credentials if needed.

But that was a really simple case for checking out.

Let's talk about more advanced setups, multiple working copies.

Many projects aggregate multiple working copies into a single workspace.

You'll have a repository for your main app and you may be using some Open Source tools as part of your app and those come from different repositories.

Well we want to make it really easy to set up new developers on your team.

And we also want to help you move away from things like subversion externals and Git submodules.

Now those work great when you're always using Git or always using Subversion but you might be trying to mix those and it's hard to have one talk to the other automatically.

So Xcode's in this unique position where it knows all this information and can package it all up for you.

So how's this work?

So when you first open your project, it contains all of the working copies into this metadata that Xcode will use.

You can manage this via the Source Control menu telling it to include certain working copies or not and whether those are required to build your project.

So this metadata is called Source Control data when committing.

It lives in your workspace in your shared data folder as your project name .xccheckout.

You're going to want to be committing this so that all of your other developers can take advantage of this new functionality in Xcode 5.

You can access this new functionality from the recents on checking out a particular project that you've checkout recently or when you open a workspace it sees that there are missing working copies and gives you a dialogue asking you to checkout other working copies.

So let's take a quick look at this.

All right, so let's go back to Xcode and we're going to click checkout an existing project again.

Now I have a project that's hosted on our OS X server and I'm going to check that out.

This particular project only had one branch so it didn't even ask me which branch I wanted to checkout.

I'm going to check that out to the desktop.

And we see Xcode has now opened the workspace for this and we can see over here on the left, there's another project reference that is read.

We won't be able to build unless we have that.

So since I committed the Source Control data, Xcode is asking me if I want to checkout additional working copies that are required for this project.

So I'll click checkout and it found exactly one that I was missing.

That's the one that contains this missing project.

So it tells me the name of the working copy, where to get it from, allows me to uncheck it if I decide that I don't want to actually check this out right now and lets me see all of the branches, this one only has one so I'm going to keep Master.

When I click next, it checks it out.

But if we see here on the finder we have this JogR application which you may have seen in some of the other tools sessions, and now there is this libraries folder next to it that appeared after I checked out additional working copies.

So if I look in there, there's that working copy.

Xcode knew that as part of the workspace the other project was relative to the main project inside of a library folder and recreated that file system structure for me.

I didn't have to tell it where to check it out from or where to check it out to.

So now if I go back to Xcode, I know that I'm going to be adding some more functionality to this Jogging application particularly I want to add swimming support.

I'm not sure why you would want to go swimming with your phone but maybe someone will.

So I'm going to go into my documents folder where I have this new SwimKit library.

I'm going to drag it into the libraries folder, look at the project and add that project into Xcode.

Now Xcode's asking me if I want to share this working copy.

It realizes that this is a new working copy that I didn't have before in my workspace and wants to know if I want to add it to my Source Control data.

I do, so I'm going to click yes.

Now if I look in the Source Control menu there's now yet another working copy and it also says what branch it's on.

Now I want to configure a couple of options on this working copy so I'm going to click configure.

Now we see here a sheet that has a path to the local working copy, where it is on my disc, as well as where it came from, now that's the information that we're going to use as part of the Source Control data to tell other developers where to check this out from.

And we have a checkbox to include this working copy in that new checkout workflow.

Currently it's set to optional but I know that we're going to soon require this to build.

So I'm going to select required.

There's also a couple of other options in here such as configuring remotes for my Git repository as well as branches where I can add and remove branches.

It also shows all of the remote branches in the remotes.

So now since I just changed that Source Control data file, I know that I need to commit the changes that I did to it so that all of my coworkers can take advantage of this.

So I'm going to go to Source Control, commit and we see that indeed I did change that file and I also changed the workspace settings file because I added a new project to the workspace.

So I'm going to drag [inaudible] commit message and we can also push to remotes automatically since I'm using Git.

So I'm going to select push to remotes and then when I commit two files in push, it asks me which remotes I want to push to.

Now pushing it to the remote makes it so that all of my coworkers can get access to it when they update their local working copies.

So I'm going to commit and push and now that that Source Control data file is updated so other developers will be able to automatically checkout that SwimKit from within Xcode.

First though, I know that since we're going to be doing a lot of work on the SwimKit, I'm going to be adding a new branch to JogR so that I don't impact the main line of my code.

So I'm going to select new branch, and it asks me what I want to name my branch.

Since we're adding swimming support to this, I think I'll call it Surf and Turf.

Now when you create a new branch it automatically branches from your current branch.

So I'll click create.

So it created the branch and also as part of creating it, it automatically switched to it which I can see here in the Source Control menu.

Now since I just created this branch locally in Git, I know that all my coworkers are going to be wanting to make changes to it as well so I'm going to push this new branch.

When I go to push we see that the JogR working copy now has a new branch that does not exist on the remote and gives me the option to create it.

So I want to do that and I'll push that new branch.

Now, since I just added yet another working copy to this workspace I know that any new developers on our team might want to be checking that out as well.

So I'm going to actually switch to my bosses account.

I happen to have his password although that's not very secure.

So I'll switch to his account and Xcode's launched and so I'm going to click checkout.

He has his OS X server set up and so it shows all of the repositories hosted on his OS X server automatically.

I'm going to click the JogR repository and check that out.

Now we see because I have two branches that asks me which one I want to check out.

He's not working on any new features just yet so I'm just going to checkout Master.

It asks me to where I want to check it out and I'm going to check it out to my desktop and it has checked it out.

And it as well has now asked me to check out additional working copies because now there are two read references to projects that aren't part of this workspace just yet.

So I'm going to click checkout and now it found those working copies.

And we see here because I made SwimKit required, I actually don't have the option to uncheck it.

When I click next it created that library folder next to JogR and has all of those files ready to go.

All right, so we just saw the brand new Checkout workflow and how it's much more streamlined.

We also saw the branch integration in the new checkout workflow including our multiple working copy support.

We also talked about the single point to manage accounts in the accounts preferences.

And the great new Source Control menu which takes all of your working copies and puts them right at the top of that menu so that you can easily see them and all of the branching workflows as part of those working copies are up there as well.

And also showing the current branch which I think is really great.

We also showed the new history with search and the new Subversion 1.7 support.

So now I'd like to invite Eric Dudiak up to talk about collaborating with OS X server.

[ Applause ]

Eric Dudiak: My name is Eric Dudiak and I'm going to talk about some of the great new features we've added to Xcode 5 and OS X server.

So the Xcode service on OS X server is a great end-to-end collaboration tool.

We've added one of the most requested features to Xcode which is the hosting of Git remote repositories.

It has never been easier to set up a new project and have both the Git repository created locally for your project as well as up on the server.

This is a great way to make sure your codes always backed up so there's no single point of failure where if you lost a machine, all your code would be gone.

One of the other great features of OS X server and the Xcode service on it is automated testing.

I'm sure you've seen a lot about this earlier this week, is a great feature where you can see all your unit tests run continuously on the server.

This gives you a great way to see when code might regress and you can use Source Control to then figure out what change might have actually caused that regression.

So every bot when it's run and does an integration will show you a list of the commits that were part of that integration.

You can then, since we're integrated into the ID see exactly what source changes were made in the version editor as part of those commits.

Finally one of the other great features of the OS X server is the archive of releases.

We highly recommend doing this as a nightly build bot.

And what that will give you is a great history of your application as it's been developed.

Every morning when you come into work you'll have a newly built version of your application that shows you what's been worked on in the past day.

This also allows you to easily track regressions.

You can go back and see previous versions of your application, run it on a device and figure out when a regression was introduced.

You can then use Source Control to figure out exactly which commit caused that regression once you've found what day that roughly happened in.

So for more information about OS X server and Xcode 5, I highly recommend reviewing the Continuous integration with Xcode 5 session from earlier this week.

It provided a lot of information about how to create a bot, how to set up server and just a lot of things that we're not going to have time to talk about today.

We're going to talk mostly about the Source Control and interaction with the server.

So let's look back at those 3 C's of Source Control that Kevin was talking about earlier, confidence, compartmentalization and collaboration.

One of the key features of Source Control that really brings all these together is branching.

So I know we've all been in this position where maybe you've been working on your code for a while and you realize that this change is really, really big and you don't ever feel like you're ready to commit it into your mainline code.

And then you're in this situation where you have all these changes locally, either they're committed locally and you haven't pushed them to your remote or they're not even committed.

This is a really bad idea because now all those changes are in one place and you don't have any backup of them.

Branching is a great way to get around that.

You can create a branch and then it's not in your mainline code and you can work on it separately.

This gives you the confidence that your code is always backed up when you push it to a remote server or commit to subversion.

This is obviously a key feature of compartmentalization because now you can work on your branch separately from your mainline code.

Let's say you have an app already in the App Store and that's your Master branch now.

If you want to start working on version 2.0 of that app, you'd probably want to start creating or start by creating a branch for new features which aren't going to be committed to your mainline code.

So this way if you have to do a bot update while you're working on a big feature, you can quickly switch back to your mainline branch and make those small changes and submit it to the App Store, then go right back to your feature branch and start working on that again.

Finally, branching is a great way to collaborate with your coworkers.

It allows you to be insulated from all the changes that they're making while you're working on a feature.

So you're not constantly dealing with changes of your coworkers, you can focus on your feature and deal with their changes at the end when you want to merge it or if you decide to pull their changes in at specific points.

It also gives you a great way to do code reviews.

So if you do all this work on a branch, when it's time to merge it you can simply have one of your coworkers actually take a look at the code and do the merge.

Make sure that you're always checking each other's code and that everything works the way you expect it to.

So as I was saying branches are great for working in teams.

You don't always want to see every change your coworker is making as you're working on a big feature, you want to be somewhat insulated from that.

So we highly recommend in Xcode using branches for developing features.

This is going to keep your mainline code from ever getting impacted by feature development and so you can quickly release small updates as needed.

Also with OS X server, that automated testing I was talking about and you've heard about earlier this week is on a per branch basis.

This means that each bot is aware of which branch it's currently testing and you can create a new bot as you create new branches.

This way is unit test change, you can verify that each branch is in a good state.

This is a great way to make sure that before you merge, all your code is in the state that you expect it to be in and all your unit tests are running successfully.

So let's look at a high level concept of what exactly is a branch.

So if we have a single branch here, Master, represented by two dots, representing a few commits, this might be sort of the existing version of your app in the App Store.

Now the first thing we're going to do is create a new branch.

Right now that branch has nothing different from Master.

It has the exact same code, it's just essentially a different name right now.

But the big power to branching is that we can commit separately.

So as we start to make commits to this branch we see that those changes are only in orange, they're only on the branch, they're not in the Master branch.

And the other great part is we can still commit to the Master branch independently of our new branch.

So we can make features while still making those small updates.

And this goes on, we can continue to keep these branches separate up until the point that we're actually ready to integrate this great new feature into our mainline code.

And at that point we'll go ahead and merge it and now everything that was on that branch is now in the Master branch or our mainline code.

But let's take a look at this in a bigger picture.

Let's look at this with OS X server and working with a team.

So here on the left this represents sort of a normal user working on code on their machine.

They currently have the Master branch.

And one of their coworkers has made a branch on the server and pushed that up.

So let's talk about branching with Git.

Git has both local branches and remote branches.

So in this case the user on the left does not actually have that branch yet, it's only available on the server.

Actually they're also a little bit behind on even changes to the Master branch.

Now since Git is a distributed Source Control system, you have to push and pull in order to synchronize your local machine with the server.

So here we're going to do a pull and we see that what's happened is we got the changes on Master and are now up to date.

And we can continue to make changes to Master simply by making a commit locally.

Now committing locally in Git does not push that change up to the server unless you specifically tell us to in Xcode or later push separately.

This is an important distinction for anyone using Subversion.

But notice that even though we did a pull, we still don't have that branch locally.

In Xcode 5 we've introduced automatic tracking branches.

A tracking branch is simply a local branch that tracks a remote branch.

In this case when I switch to the branch in Xcode, I get an automatic local copy of the same name that I can start working with and can merge locally.

Now again all those changes because Git is distributed are just local.

And if I want to share all this work with my coworkers, I'm going to have to do a push.

A push takes all those changes and puts them up on the server.

And of course since we all have unit testing continuous integration running when the server sees new commits as part of a push, it will go ahead and run the integration and because I checked this beforehand, all those unit tests will succeed.

So let's take a look at this in a quick little demo.

So I'm going to login to my account and I'm also working on the JogR application.

Now let's open it up and just as we saw before since Kevin added a new project to it with a new working copy, I also need to check that out.

So let's get that taken care of real quick.

And we see that it's automatically used my user name instead of Kevin's to check it out.

So great and I have all the sources.

I can verify that.

I can totally build this project right now and have no problems.

But I made a deal with Kevin before we came up on stage here that if he came up first I would take a look at his branch and merge it in with the Master branch.

So I'm going to go ahead into the Source Control menu and look at JogR.

And I'm going to switch to a branch.

Now the only branch I have locally is Master and since I'm already on that I can't switch to it.

However, we see that there are two branches on the server, Master and Surf and Turf.

So I'm going to switch to Surf and Turf and take a look at Kevin's branch and do a quick code review of it.

This is creating an automatic tracking branch locally and switching to Surf and Turf.

If we go back into the Source Control menu we see that I'm now on the Surf and Turf branch.

So let's take a look and rather than doing a really, looking through all his code, I'm going to do something simple.

We wrote a few unit tests for JogR.

So I'm going to go to the test navigator and I see that JogR has four unit tests and I'm just going to run them.

Easy way to make sure that Kevin didn't break anything.

Set the build failed.

All right, well let's take a look at what's happened.

All right, so this is a normal failure in a unit test.

It looks like something is probably changed around here and we can no longer even build our unit test.

It looks like there's not this particular initialization method anymore.

So let's take a look at the run data class and see what's happen.

So I'm going to hold down command and select run data which is going to take me right to the run data header file where run data is declared.

And I'll take a look here at this initialization method.

Pretty sure it looks a little different than what I saw before in the test.

So let's open up the contextual menu and do show blame for line.

And here we see that it was indeed changed by Kevin recently and it seems to be adding support for Swimming so it's probably on this branch that he was playing around with things and changed this initialization method.

Now also importantly I can see that Kevin committed this at 3:30 a.m. so I'm going to want to take a little closer look at this.

I'm going to go ahead and show all the files that he modified this morning after the Bash.

So I can see that indeed he did change the initialization method to support Swimming and it looks like it now takes in an extra boolean that it didn't have before in our unit tests.

The rest of this looks like pretty normal changes.

So I'm going to go ahead and fix that unit test by just updating the use of the initializer.

So now I can go back to the testing navigator and run all those unit tests.

This time they succeed at building and we're running in the simulator.

Ah, but I still don't have green light to cross the board.

Looks like two of them are fine but two still need a little work and have changed as a result of the changes in Surf and Turf.

So looks like a lot of these are just the result of some of the assumptions we were making and some of our test data has changes involving Kevin adding new test data for the Surf and Turf branch.

Now I can go through and fix all these but luckily I have a great little snippet of code that just fixes all of them.

So let's rerun the two unit tests that were failing.

And I can of course with our new testing support run them one at a time.

So I can take a look at the two that failed, run the first one and now the second one, all four are green.

I have a lot of confidence that this is now in a much better state.

Now since I made a couple changes, I need to go ahead and commit those.

So I'm going to go to the Source Control menu and commit.

And we see these are just my updates to the unit tests.

Give it a commit message and commit the one file.

But now the whole point of this is I was supposed to merge Kevin's branch.

So let's go to the Source Control menu and where I'm on the Surf and Turf branch in JogR now, I want to merge that into the Master branch.

So I'm going to go to Surf and Turf and select merge into branch.

There's only one branch that I can possibly merge this into and we're discovered that that's Master.

Xcode will only ever show you valid branches for merging.

I can go ahead and select that and it's going to go ahead and determine all the potential conflicts and issues that may come up and it looks like we might actually have one.

What are the odds?

So actually this happened in a project file.

Now this is scary.

I don't want to have to deal with doing a merge in a project file, that can't possibly be done.

So it looks like it's actually not that bad.

It looks like what's happened is something that happens a lot which is something, a resource file was added on both the Master branch and Kevin's branch.

So we have a couple of ways we can resolve the conflict here and these are all displayed at the bottom.

I can either select left and then right.

So this is going to take all the changes on the left side which is the Master branch, take all those and then take the changes from Surf and Turf on the right side after them.

So in this case I'll end up with both resource files.

This is actually what I want but let's just look at the other merge options.

I could take just the left side which would only give me the resource file from the Master branch and discard the changes that were conflicting from the Surf and Turf branch.

I could also take just the Surf and Turf changes or I can take both changes in the opposite order.

Now in most cases for project files when dealing with multiple files being added, it doesn't matter which order they're in but we probably want both.

So I'm just going to go ahead and take both of those resource files and make sure they're in the project.

And it looks like that was the only conflict we had so I can go ahead and select merge.

And since I have Source Control turned on in a remote server, I'm not going to bother with a Snapshot right now.

So now we've done the merge and we can see that one of the other things I've set up for the Master branch is this JogR bot.

And this JogR bot will run integrations so since I already ran the unit test on the other branch, I'm reasonably confident that I can go ahead and just commit and push this.

So I'm going to go to commit and we see that I basically had to resolve that conflict in addition to the normal merge commit that was added.

So I resolved the conflict and now that I've made all the changes that I need to make to land Kevin's branch, I'm going to ahead and push that to the remote.

I'm pushing now to Master because I've merged onto Master.

So I'm going to do a commit and push.

It's going to take all my working copies and push them up to the remote server and I can now go ahead and fire off an integration to just double check that everything I did commit is good.

Now if we go to the Source Control menu as Kevin was saying, we have this history view.

And I can see that as a result of the changes that were made, I have now taken all the support for Swimming and the merge and it's now all in the Master branch.

And here we see an example of looking at the history sheet across several working copies.

I can look at all of them integrated together so we can get a full history of the project or I can see just one at a time.

And again, the search works across all of them or whichever ones are selected.

So that's Source Control in Xcode 5 with the Continuous integration Server.

So just to recap what we saw there since it can be a little confusing to follow what's happening in branching and merging, on the left side we see the JogR branch and we see Kevin's Surf and Turf branch committed before a couple changes were made on the JogR branch but it's all on the server.

So what I did was I went ahead and pulled it down and created a local tracking branch.

From there I then made a small commit in order to fix those unit tests.

This was all local still.

And then I merged it.

Now in order for everyone else to get the code and I went ahead and pushed it up to the server.

And then we saw that it fired a continuous integration and we can verify the code, it worked on the server.

So this is very powerful tool for making sure that your code's always in a great state.

So let's review some of the great new features of Source Control in Xcode 5 that we've seen today.

We've seen how the new workflow driven Source Control interaction is primarily now accessed through the top level Source Control menu where we have access to the every working copy that a project or workspace is currently using and what branch we're currently on in each one.

So this is a great easy way to quickly see what code you're working on and be sure that what you're working on is what you think you're working on.

We've also seen some of the great new server integration with OS X server and the Xcode service providing for the first time end-to-end solution for Xcode with one click, get remote repository creation with a new project.

And we've seen how we can automatically manage multiple working copies so we're not dealing with a mess of subversion externals or get submodules.

We can easily take all this data, put in a manifest file in Xcode and share it with our teammates to make sure that everyone knows exactly what they have to have checked out in order to build our projects.

This is a very powerful tool and it just makes getting setup with a new project for a new team member so much easier.

Or if you're working with a large team and someone adds something that you need and they didn't tell you, it's all automatic.

For more information about Xcode Source Control or OS X server, please contact Dave Delong, he's the app framework and developer tools evangelist or ask a question on the Apple Developer forums.

I'd like to thank you very much for coming today.

[ Applause ]

[ Silence ]

Apple, Inc. AAPL
1 Infinite Loop Cupertino CA 95014 US