Video hosted by Apple at devstreaming-cdn.apple.com

Configure player

Close

WWDC Index does not host video files

If you have access to video files, you can configure a URL pattern to be used in a video player.

URL pattern

preview

Use any of these variables in your URL pattern, the pattern is stored in your browsers' local storage.

$id
ID of session: wwdc2012-411
$eventId
ID of event: wwdc2012
$eventContentId
ID of session without event part: 411
$eventShortId
Shortened ID of event: wwdc12
$year
Year of session: 2012
$extension
Extension of original filename: mov
$filenameAlmostEvery
Filename from "(Almost) Every..." gist: [2012] [Session 411] Source Cont...

WWDC12 • Session 411

Source Control Management in Xcode

Developer Tools • iOS, OS X • 51:46

Xcode provides powerful ways to work directly with Git and Subversion repositories. Learn how Xcode's SCM 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.

Speakers: Eric Dudiak, Kevin Lindeman

Unlisted on Apple Developer site

Downloads from Apple

HD Video (711.5 MB)

Transcript

This transcript was generated using Whisper, it has known transcription errors. We are working on an improved version.

Good morning. I'm Eric Dudiak. I am a Source Control Engineer on Xcode. And today we're going to talk about Source Control Management in Xcode. So just to give you a brief agenda of what we're going to talk about today, we're going to give you a brief overview of the fundamentals of source control management. Then we're going to talk about committing in Xcode and how you get your code committed into your source control repository.

and finally we're going to talk about sharing your code, whether that's around the world or just around your office. So first off, what is Source Control Management? Source Control Management, or SCM for short, is all about two different things: collaboration and backup. So collaboration means that you can work around the world with your code and share it with other users that need your code as well.

And backup, in that you have the ability to go back in time and see previous commits you've made to your code and find out how your code has changed over time. This is a great way to fix any bugs that might come up in your code when you know that you have a working version already in Source Control.

So that's SCM. So in Xcode, we support two different source control management systems. These are Subversion and Git. is a source control management system that is based on a client-server model. In this case, you have a server, your repository, that stores all of your code. Locally on your system, you have a working copy. This stores what code you're working on right now.

Whenever you want to see a past piece of code, something that you've done in the past, you're going to have to talk to the server and pull that copy down from the server whenever you do a log operation or anything like that. This means that every client who is using your code is connected to the same server. Now, Git works a little bit differently.

Under Git, Git is a distributed source control system. This means that your local copy of your code is actually a full repository. The advantage of this is that when you're on an airplane or otherwise out of network access, you actually can pull up every revision of the file that you've locally stored without ever needing to go to a server.

Now, of course, if you want to keep your code on another machine, such as a server, Git has this concept of remotes. A remote is basically another Git source code repository that is not locally on your machine. This could be on one of your coworkers' machines, it could be on a server, or it could be somewhere else on the web, such as GitHub. It's very flexible this way. So, source control in Xcode has a few great features that we're going to talk about today. And there's a lot of ways to use source control in Xcode just in your day-to-day workflows, such as when you're editing code.

We're also going to show you how you can use Source Control Management in Xcode to view the history of your file. This can help you quickly find bugs and squash them. And finally, we're going to talk about managing repositories in Xcode and how you can set up your repositories and add any settings you might need to for Xcode to work most efficiently with your repository.

So this is the Xcode workspace window. Here we see on the left that some of these files have been modified. We know that because if we look at the screen, On the left-hand side, we see the workspace view, which shows us several files with M status icons. These M status icons indicate that the file has been modified. and David We have several source control status icons. These indicate whether a file is added, deleted, or any number of other source control statuses that we might need to show you in Xcode.

Now, if we want to look at the history of your file, we're going to use Xcode's Version editor. If we go to the toolbar in Xcode, there are several editor modes at the top. This is currently showing the normal editor. To get to the Version editor, is the editor of the Xcode team. He's the editor of the Xcode team. Eric Dudiak is the editor of the Xcode team.

He's the editor of the Xcode team. Now, when we're in the Version editor, we have three different views to see our code. The first is the Comparison view. The Comparison view shows you two pieces of source code side by side. In this case, we're looking at the local revision, on the left side, and the historic revision on the right.

Now, we can throw any two arbitrary revisions. In this case, we've selected one that we've made modifications to locally and the current top of trunk on the repository. Now, if we wanted to look at a different version, such as one more in the past, and compare it to a version after it, we could. We can see any number of versions of a file next to each other and see all the changes between them.

If we want to see more information about when lines of a file were last changed, we can use the Blame view. Now the blame view allows you to basically blame someone for a particular line of code because you can see who was the last person to touch it.

In this case, we show the blame items next to each line of code on the right, as well as an indicator that darkens to show that that was the most recent commit. So the more recent a commit, the darker the line. So if you know a bug was introduced really recently, you're going to look for the darkest lines next to each line of code.

And then you can find the person who actually committed that code that you found is actually a bug. Finally, in the Version editor, we have the Log view. Now, the Log view shows you the history of the file with every commit, one after the other, shows you the commit message, as well as some other information that we'll see in a minute during the demo.

Now, when it comes to managing repositories, we also have a great tool in Xcode to facilitate this. And we find it in the Organizer. The Xcode Organizer can be accessed from the toolbar of Xcode using the Organizer button. In this case, we'll bring up the organizer, and one of the organizer views that we have is the repository view.

In this case, we see the WebKit repository, and we can see several parts of it. If we want to see the top level of the repository, we can go to the root folder seen on the left, We can also see the trunk. Now, in Subversion, the trunk is basically your main line of code. So if we want to see just the current main line of code in the repository, we can use the trunk view.

We also support branches and tags. We're going to talk a little bit more about branches in a minute. And then any local copies of that code are shown with blue folders in the sidebar. So in this case, we have a checkout of WebKit locally on this machine, as well as some information about the repository.

Now in this case, we are looking at the main view of the repository. We see the location of it, and it's a Subversion repository. If we needed a username or password, this is where we would go to enter it, although Xcode will also prompt you if you need to do a source control operation that requires a username or password.

For Subversion repositories, it is also necessary to set up tags, branches, and trunk folders and their relative locations from the root of the repository. You may not necessarily need to do this for your repository if you only want to check out and commit to a trunk. However, if you want branching support in Xcode, for Subversion, we are going to need the relative path to the branches folder.

Now, what does that necessarily mean? Well, in Subversion, there are several different common setups, and we're going to show you two of them right now. So one of the most common is that at the top level of your repository, you have three folders: trunk, branches, tags. So that's what we saw in the WebKit repository on the last screen. Three folders, so all the relative paths are just trunk, branches, and tags.

But if you have several projects in your repository, you may actually have a slightly different setup. In this case, you might have more than one project, and each one has its own trunk, branches, and tags folders. So if we had checked out project one from the second repository, we would have put in project one/trunk, project one/branches, and project one/tags as our trunk, branches, and tags folders.

You may, of course, have a completely different Subversion repository setup. That's perfectly acceptable. Your mileage may vary from these two common setups. So let's go in and do a quick demo of some of the source control features of Xcode. Okay, so here we see a workspace. This happens to again be the WebKit workspace. And I can see that I have modified a couple of files. In this case, I can see three. Now, I might have modified a few more. So if I want to see every file that I've modified, I might go down to the bottom here.

And we see the filter bar. We can, of course, filter by name, but in this case, I want to filter and see just files that have source control status icons next to them. If I click the repository icon, shown here as a safe, I can show only files with source control status. So clicking that shows that, indeed, I have only modified three files locally.

So this is great when working with a few files, and you know that you're working on the same files a lot in a larger repository, and they've all been modified on disk. Let's undo that because we're going to look at a few files. So I want to see the whole workspace.

So if I want to see some of these changes I've been making to the WebKit project, because I don't want to break anyone's iPhone's web browser, let's see what kind of fun I've been having in the Canvas support of WebKit. So let's look at the Canvas rendering context 2D.

So in this case, I see the file, and I'm not really sure what I've been messing around with. So if I want to see what edits I've made, I could, of course, go to Commit, but I want to see them right here in the Xcode editor. So I'm going to go up to the toolbar and select the Version editor.

Now, in this case, I see all the changes that I've made. On the right side, we see the current version on the repository. We know it's the current version because if you're not familiar with Subversion terminology, this one is called the base and head. Base is going to be the local version on disk that's the newest since I've updated, and head is going to be the top version -- or the latest version on the repository.

So it's both. That means it is actually the most up-to-date version that has been committed. On the left, we see my local revision. My local revision is the changes that I have made that have not been committed yet. And given that it's code I've just been messing with, probably shouldn't be committed to WebKit.

So we can see a few changes. If I want to find all the changes in the file, I can simply use the scroll bar, and we see that they're indicated with red lines in the scroll bar, and I can jump right to them. One of the great things about the Version editor is that in addition to allowing me to see the changes, it's actually a full functioning editor. So I can start typing code right here in the editor.

And we see that as I was editing code, a difference actually appeared in real time. And if I add a bunch of white space, that all appears as I'm typing. This is a great way that if you're editing code, you can see exactly what you've edited recently in a file that hasn't yet been committed.

So I'm going to look at another file. Let's look at the Canvas Gradient file. Now, I haven't touched any of this code yet. We see that there's no M status icon. But I think that there might be something going on here that's changed recently. So I can see that this is the last version that was committed on September 12th, last year.

If I want to see what was committed on September 12th, I'm going to go to the blame view. Now we change views of the Version editor down here on the right, and I click the blame icon. Now this is going to go out to our Subversion repository and get the status of every line of the file and when it was last committed.

Here I see a few different commits, and I can see exactly when each line was changed. So if I was interested in this #if enable dashboard support, I could see that that was committed. That was actually the commit from September 12th. Now, if I click on the info icon, I can actually get more information about this commit.

We see that it highlights the line I was interested in, as well as other lines in the file that were part of that same commit. So if we scroll through, we see that it wasn't just a single line commit, of course. Several other things in this file changed.

This is a great way, if I'm fixing a bug, to find out not only the area of code that I'm interested in that I think is directly relevant to the bug, but also other code that I may need to look at because it was committed at the same time and may be related and also need some tweaks.

Now, of course, this is going to show us some more information. Here we see there was the username that committed it. In this case, it was just part of the commit queue from WebKit. the date it was committed, the revision number, as well as the full commit message of that commit.

Now, if you're working on a bug and you find it on a single line in a project or a few lines, and you find the commit that it was committed as part of, you may not just need to look at that particular file. The bug may span multiple files, but it's most likely in one or a few commits.

So I may be interested in other files that were also part of this commit. In this case, we see that three files changed during this commit. If I expand this disclosure triangle, I can see that the header file, a change log, and this particular file were all part of that commit. So if I'm editing an implementation file, I probably also want to see what changed in the header file.

If I click the file, we see a sheet come down that shows us exactly what the view was when this commit was made. In this case, the file before the commit on the right and the file immediately after the commit on the left. as well as each change highlighted, and a commit message at the bottom.

So, okay, I can see what was changed. I can see what was changed in the header, as well as the implementation file, if I was interested in undoing the enable dashboard support. So now let's look at how we set up this WebKit repository. So I'm going to now go to the organizer. In this case, I have a few repositories set up that I've been working with recently.

And in this case, one of them is the WebKit repository. I can go and look at the root level of the WebKit repository, in this case, as trunk, branches, tags. I can see trunk, branches, tags. It would seem that the WebKit repository might be being a little slow this morning.

Well, we can look at one of our other repositories. So if I look at the engineering repo, part of a repository that we're going to see a little bit later, and we can see a few commits have been made to it. In the case of the WebKit one, we'd see several commits, of course. We can also set up the username and password. Trunk, branches, tags, folders, as I was saying before.

We can view the root. So in this case, I actually haven't set up trunk, branches, and tags. So in order to set it up, I'm just going to type trunk. Light turns green, and I see that I have a trunk folder here. I can jump right to the trunk. And I'm just going to add branches and tags.

So in that case, my repository is now set up, and I can actually do branching with the engineer's repo. In addition, I can look through the logs. Just like in the blame view, if I expand the triangle, I can see what files were committed as part of that commit, as well as the commit message.

And again, clicking on a file will show me that file committed as well as all the others as it looked during the commit phase. Now, if I wanted to view a particular revision, I didn't want to scroll through the list. Let's see if we can get the WebKit one to work.

I'm going to try to view a particular revision on here. Let's say someone sent me an email, told me to look at this one revision, and I'm going to look at 13992. Now, I could just scroll through the list and find that, but if I know exactly what revision I want to go to, I can jump straight to it, and Xcode's going to load that revision and a comparison view for me of that revision, just like it would if I had gone to it through the log view.

But bear with it. Ah, here we are. So in this case... Let's make that a little bigger. So we see, just like before, a full comparison view of the code. We see on the right what was on the server before the commit, and on the left what was committed. So we can see this was a rather large commit, and we see that files were deleted. We can see files were added. So this was a great way to look through our commits and find out information and what the history of our repository is.

So that's the Repository Organizer. So what have we seen? So we've seen how you can edit code in the Version editor, just like a normal editor, and how you can use it to see the changes you've made recently or even changes you've made in the past. We see how you can view the history of a file.

This allows you to find bugs and make sure that you change everything, not just the bug you see immediately, but anything else that might have been part of that same commit that also needs to be updated as a result. And we've seen how you can manage repositories. This includes setting up tags, trunk, and branches folders for a Subversion repository. So now I'm going to let Kevin come up and talk about committing your changes.

Thanks, Eric. My name is Kevin Lindeman, and today I'm going to talk about committing your changes. So in order to use all the great features that Eric just showcased, as well as committing and the rest of the features we'll talk about today, You need to actually be managing your projects with source control. Now, if you create a new project inside of Xcode, we make this extremely easy to do, and I'll show you how to do that.

I'll also talk about what is new while committing. We've added a number of new features this year that will make your day-to-day commit workflows even better, especially if you're working on multiple tasks all at once. And then I'll talk about ignoring files. Now, you might ask, all of my files are under source control now. Why would I want to ignore any of them? Well, there's a number of file types that you might want to ignore, so I'll talk about those.

Let's dive right into source control for new projects. As I said, you need to manage your projects with source control in order to use these features. When you create a new project inside of Xcode, when you get to the save dialogue, you'll see this check box. Create local Git repository for this project. What this means is that Xcode will create an empty Git repository and then use the basis of your new project as your first commit. Once that's done, you can just go ahead, make your changes, and commit.

Now that you've got a Git repository, you might want to configure remotes. This can be done entirely inside of the organizer in Xcode. The remotes, as Eric said, represent remote Git repositories, maybe on the same machine, on a server somewhere, maybe like GitHub. And now that you've configured a remote, since in Git all of your commits are done locally, you need to push your local changes up to the remote so that all your coworkers can then fix the bugs you just committed. So let's take a look at how to do this. We see the welcome window in Xcode, and I'm going to create a new Xcode project.

I'm going to create an iOS master detail application and click next. I'm going to name it My Awesome Application. and click next. Now we see here we have the check box, create local Git repository for this project. And since I want to Git repository, I'm going to leave that enabled and click create.

And now Xcode has opened this new project, and all of my work is now under source control. I can confirm this by going into the organizer. We see that Xcode has automatically detected the Git repository that was created for this project. If I click it, we see the initial commit. And all of the files that are part of that new project.

So now that I have this Git repository, I want to set up a remote. So I'll click remotes. We see that I don't have any remotes set up yet. And so I'll go to Safari where I've already set up a Git repository on GitHub. Now I'll copy the URL of the remote and go back into Xcode and click add remote.

Now, a remote is included by a name and the location to that remote. So the name is really all what you -- really what you just want to call it. I'm going to call this one origin because that's what you tend to call the first remote in a Git repository.

And I'll paste in that URL and click create. And now Xcode has added the origin remote to my repository. So now let's go back to the workspace, because I want to push these changes up to GitHub, so that all my coworkers can start working on our project. So I will go to File, Source Control, Push.

And so we see that since I just created this repository and it has a master branch, but I haven't pushed yet to the remote, it doesn't exist there yet. So it will tell me that it will create this branch when I push. Since I want this, I will click push.

We see that the push was successful. And now, if I go back to Safari... reload this page, we see my project is now on GitHub. So what did we talk about again? We talked about placing your project under source control and how Xcode makes this extremely easy. I then talked about configuring remotes, in this case GitHub, so that you can now collaborate with all of your coworkers. I then talked about pushing changes and how when you commit locally, you need to push them to the remote so that everyone can then use those commits.

So now I'm going to dive right into what is new. First off, this year we have better change detection. Xcode is now better at deciding which lines are different between your current version and the previous version. We also now have the ability to skip or discard individual changes. We see this little button here between the two files, one for each difference.

You may have known about this feature as part of the Git command line tools when you're doing an interactive commit. It gives you finer-grained control for deciding what you want to commit inside of a single file. We now also have the ability to commit to a new branch directly while committing.

This is great because if you're working on a large part of your project and you might be destabilizing your code base, you want all that work on a branch. But maybe you forgot to create a new branch before you started working. You get to the commit sheet and remember, oh, shoot, I forgot to create a branch. Well, now you can do that.

So let me talk really quick about what a branch is. So here we have a simple Git repository. We have our master branch. It has a couple of When I create a branch in order to work on the task that I'm about to start, it also has all the content of master at that point.

And now I can commit to the branch and master doesn't have any of that content, so I won't destabilize everyone else. But everyone else, including myself, can also still commit to master if we have small bug fixes. Now when I'm done with my branch and I know I'm not going to destabilize anything anymore, I get to then merge that back in to master, and now master has all that work as well. So let's take a look at this inside of Xcode. All right. So we've been working on this project. It's called My Best Friends. And let's run it to see what we've worked on already.

So what we have here is 16 different tiles. They look a little bit like WWDC badges. So what happens if I tap on one of these? Well, we see a picture of an Xcode engineer before they were an Xcode engineer. That kid's pretty cute. Now if I click around and it's not the same person, they flip back over.

The point of this game is to match up the same person But we see there's a couple of unimplemented features here. It's supposed to show the present-day picture of that engineer. So let's work on this a little bit. Now we see here that I've already been doing some work because of these M status icons on the left here. Now I know I'm ready to commit some of this work right now, so I'm going to go to File, Source Control, Commit.

The great part about committing inside of Xcode is that you get this view. It shows you all the files that have been changed. That way, you know exactly what you need to commit so that when you do commit, you don't end up breaking the build for everyone else.

So if I go over here to this file, now we see the previous version of this game was actually a dog matching game. Now, I don't really want the engineers to bark when I pair them up, so I deleted this code. That change looks good. And we also see here at the bottom a new feature. We have a number 8 down here. That says that there are 8 changes in this file.

It's also really easy to navigate through all these changes by using these arrows on either side of it. So if I click the right one, I go to the next change. And the next change. And if I click the back arrow, I go back. So the second change here is also part of making the engineers stop barking, so I want that change right now, too.

We see here a couple of NSLogs for debug information. I don't want to commit those right now, so I could simply just edit the left-hand side here to look like the right-hand side, and that change would go away. Or I could click here and say discard change. Now we see here that after the change is reverted, I can use undo to restore the change. So if I hit OK, the change disappears. If I hit Command Z, the change reappears.

I don't want that, so I'm going to redo that. And now I also don't want this change. So now if you have focus in the center split bar here and you have a difference selected as we can see by the blue outline, you can also simply hit delete and it will do the same thing.

Now, if we look down at this change, this looks like a lot of work. So I'm not ready to commit this, but I was ready to commit the code removal up at the top of this file. So since they're in the same file, I would like to disable just this difference. I would like to keep it around, however, so I don't want to revert it.

In order to do that, I can press this checkbox. Now it grays out. This means that this difference will not be committed when I hit commit, but it will still be there when I hit commit. after the commit is done. If I select this commit, I can also do it by hitting the space bar.

Now I don't want this one either, so I'm going to disable that. And now I'm done with this file. Now this is also removing some of the AV audio player code in order to make the engineers bark. I don't want that. So I'm going to leave that file checked. Now this was part of the code that I disabled, so I don't want any of this. Now I need to insert a commit message. Making the engineers stop barking.

And click Commit. And now we see the commit has completed, but I still have two files with M status badges next to them. This is because, as I said, I disabled those differences. Now I'm actually missing a couple of the photos down here of the engineers, so I'm going to insert those in. Even though there's eight engineers, I only have four photos. So Eric's going to put in some more later. But I'm going to drag these in.

And since I was writing them from outside of the project, I want copy items into destination groups folder checked because that will copy them into my Xcode project and also add them to source control. So when I click add, we see the A's next to them. This means that they're going to be added when I commit.

So I'm going to go back to File, Source Control, Commit. Now we see here, because I added those files, the project file has changed. We see the file that I had completely unchecked. And we see all the differences that I had unchecked inside of the file. If I go through all of them, we see those.

Now, while you're committing and in the regular Version editor, you don't have to look at just source code. You can also look at binary files such as images. Hey, that looks like me. We also see on the right that the file is added, so there's no previous version. So I'm going to write in a commit message now. I am adding some new engineer photos. Thanks, autocorrect.

And now, since I think this code will destabilize our work, because I haven't tested it very much, I'm going to commit this to a branch. So I'll click Commit to Branch in the bottom left. And we see here that my Xcode project actually had two repositories associated with it. An engineer's repository, which housed all my photos. It's also Subversion, as we can see by it being named Trunk.

And then I have my best friend repository, which is Git. So since I don't really need to branch just for adding a couple of photos to the Subversion repository, I'm only going to branch to my best friend Git repository. So I'm going to click here and select new branch. I'm going to name it New Photos. And click Create Branch. Now when I click Commit 7 files, all of that work will be put onto the branch.

So now I've committed all that work into my branch, and Xcode also automatically switched us to this branch so that we could continue working on it. But I'm ready now for Eric to finish this work, so I'm going to push all this to our remote. So I'll go do file, source control, push. And now we see that since I just created that new photos branch locally, I need to create it on the remote when I push it. So I'll hit push.

and now we have pushed this branch to the remote so Eric can start working on it. But you may remember that I was also working a little bit on the master branch before I committed all that to the branch. So I need to switch back to my other branch so I can push it. So I can do that from the Now if I go down here to the My Best Friend working copy, the blue folder, we see here that the current branch is that new photos branch that I just created.

Now I can switch the branch. We also see here that the commit that I just did adding some new engineer photos is listed here in the log as well as the commit that I did on master branch before I even switched. That's because when I branched from that commit, it still had all that work as well. So now I'm going to switch back to master.

And we see that that commit that I did only to the branch is not there anymore. If I go back to branches and click new photos, we see it there, but not on master. So it looks good. So I'm going to push this work on master. up to the remote. And since we'd already pushed this before, it doesn't ask me to create it. It's just going to update the remote.

So I'll click push. And now we have pushed all this work up to the remote. So what did we just go over? We took a look at the Version editor inside of Xcode and its better change detection. as well as the ability to skip or discard individual changes. The best part about this feature is also that it works for Subversion as well.

And we also talked about how you can then commit to a new branch. So the last thing I'm going to be talking about is ignoring files. You're going to be asking why. All of my work is now under source control. Why do I need this certain file as ignored? Well, not every file that is part of your project is crucial to your work. It's not necessarily source files. So you don't want to always clutter up the window when you're committing. You might not also want them cluttering up your repository when you look at the files on the repository.

So what files might you want to ignore? I'll talk about which files we may want to ignore and how. I'll also talk about what if I committed those already, and how do I fix that? So what do we want to ignore? You may consider ignoring finder settings. These are stored in the .DS store files.

You may also consider ignoring window geometry. These are specific to Xcode and they are stored in the user interface to XC user state files. You may also consider ignoring private schemes and breakpoints. These are the ones personal to you. They're stored in your usernames.xc user data D files.

So in order to use -- ignore all these files, you're going to need to use the command line tools. Depending on your system configuration, you may not have them installed by default. But they are installed as part of Xcode in a private location. In order to access that version of Git and Subversion, you can use XCRUN to run those. You can also use those to run any of the other Xcode command line tools. We'll see an example of this in a moment.

So you have a few choices with ignoring files in Git. First is per repository. In order to ignore files per repository, you place a .gitignore file at the root of your working copy. It may look a little something like this. Here I'm ignoring the DS store file and the user interface state file. Just separated by new lines. You can then commit this file to the repository and push it, and now everyone that closes your -- clones your repository from the remote will take advantage of your gitignore file.

If you're like me, you work with a lot of Git repositories. You may want to set it up globally. This will affect every repository that you clone no matter where you got it from. In order to do this, you can create a .gitignore global file in your home folder and then you need to tell Git to use this one.

You can combine this with the .gitignore file as well. So in order to tell Git to use this gitignore file, you use XCRUN git config to point to that file. And here we see XCRUN prepended to Git so that it will find the one that's used by Xcode and use that one. Now, the best way to ignore files for Subversion is globally. In order to do that, you'll edit the .subversion/config file in your home folder, and you need to find the global-ignore setting. It may be commented out.

And you make it look a little bit like this. Here we're ignoring the same two files, the DSStore and the userinterface.xcuserstate file. And they're just separated by spaces all in the same line. Once you do that, Subversion will ignore those files and you won't see them while committing.

But what if I already committed these files? How do I fix this? This is easiest in the terminal, where you'll CD to that working copy that you want to fix. and you use XCRUN to tell Git or Subversion to remove those files. and you'll need to do this for every file that you want to remove. Once you've done that, you need to actually commit that deletion. Otherwise, it didn't do anything. It just did the removal locally. So you commit the removal.

And then you set up the ignore files just as I showed. So in summary, I talked a little bit about source control for new projects and how Xcode makes it easy to create a Git repository instead of remotes. Talked about what's new while committing, especially the great new feature where you can disable individual differences in a single file. And also which files you may want to ignore and how. So Eric will come back up and talk about sharing your code.

So once we've made all these changes, we're going to want to share our code so that, say, if you're going to the beer bash this afternoon, one of your coworkers can take care of any bugs you've just introduced. So there are a few workflows that make it easy to work with other people or even just share code between multiple computers in your office.

The first step is getting all of your code locally up to date. Now, depending on whether you're using Git or Subversion, this is either a pull for Git or an update in Subversion. Doing this means that you have all the local code -- or all the code on the server is now locally up to date.

You may also need to merge some branches. So Kevin was showing earlier how to make a branch. And we're going to need to merge that in if we're ready to put that into our mainline code. Both this and the update operation may involve resolving a few conflicts. So if both Kevin and I, or any number of other people working on our code, touch the same file in roughly the same place, there may be a conflict where we both tried to change the same thing, and we need to resolve it. We're going to go over that. And finally, to make sure that everyone else has your code, you're going to need to do a push if you're using Git, because when you first commit, it's only locally stored on your local repository.

So let's go over what we were looking at before with Kevin's code. Now, Kevin finished pushing to the remote at the end of his work. So that means that our remote looks more or less like this on the right. It has a task branch as well as a master that has a few changes as well.

Now, locally, since I wasn't up to date with Kevin's code yet, I just had the master from before he was working on that. If I want to start working on some of the code he was just changing, I'm going to need to do a pull. That pull is going to get my master branch up to date with all the changes he made on the master branch.

But what if I'm interested in Kevin's task branch where he was adding those engineer photos? In that case, I'm going to need to begin tracking that branch. That's going to give me a local copy. I might also make a few changes to master. But I might also want to pull Kevin's branch.

and bring that in, and I need to track it to do that. That will require me tracking his branch, which will give me a local copy of his branch. Finally, to get all the changes that I made on master, as well as any changes that Kevin made in his branch, all into our mainline code, ready to submit to the App Store, we're going to need to do a merge. That may involve resolving some conflicts, and we'll see how to do that. Finally, since I want Kevin to finish working on the code later today, I have to do a push. That's going to put it back up on the server already merged.

So let's go over how we do that in Xcode. And I'm going to open up the same project that Kevin was working on. So here's the My Best Friends project. If we look at it, we see that under the engineers, I don't have the photos that Kevin added to the repository. And if we look at the controller, my engineers still bark. There's still an audio player here.

Now, I don't want that, and Kevin already did that work. So I'm going to go to File, Source Control, Update and Pull. Since we have both a Git and Subversion repository, we're actually going to be doing both operations to get our local code up to date. Here we see those two repositories, engineers, which was our resource repository, and My Best Friend, which was our code repository. I want all the updates possible, so I'm going to leave both checked and go ahead and press Choose.

Now, in this case, we didn't have to see any of those changes in a sheet like you may have been familiar with in previous versions of Xcode. This is because if there are no conflicts and you've already selected that you want to update and pull, we'll go ahead and make all those changes and locally keep you up to date. So there's no further interaction necessary. And if we go into the supporting files, under Resources and Engineers, we see that I still don't have those engineer photos because Kevin committed them on a branch.

And I also want to add a few myself. So I have a few images here, the other four engineers of our eight. and I'm going to add them to my project as well. This way when we merge, we'll have all eight images. So I've added those, and I'm going to go ahead and commit that.

I'm on master, but that's all right. I'm just adding images. I'm not touching any of our code, so I don't need to commit to a new branch. So I'm going to add some engineer. Photos. And I'm just going to commit those five files. Of course, I've modified my project file because I added photos to it.

So I've committed that. Now I want to start looking at some of Kevin's work. So if we go to the organizer, to the My Best Friend repository, and to branches, we see I only have master. Just like we were looking before on the slide, since I only have a master branch locally, I don't have any of Kevin's changes.

If we look at the remotes, though, since Kevin finished pushing his branch up to the origin and created it there, if we expand the origin remote, we see that it actually has two branches, master and new photos. Now, I already have a local copy of master, but I want this new photos branch as well. So with it selected, I'm going to press track branch.

I'm going to give it a name and a starting point, in this case, new photos, and I'm going to keep the name the same locally. I don't want to switch to this branch, since I don't want to do work on it. I want to merge it into the master branch to get it ready for our App Store submission. So I'm going to click Create. And now, if we go back to Branches, we see that I have two branches locally. I'm all ready to do the merge. So let's go back to my workspace and go to File, Source Control, Merge.

Now, in this case, we still have two repositories, the Engineer's and My Best Friend. Since we didn't make any changes in Engineer, we never created branches for it, since it's just our resources. So in this case, we only have branches in My Best Friend. It's checked, we want to merge it in, and we want to merge this new Photos branch. If we select it, we see that's actually the only branch I can merge in, because there's only two branches, and I'm already on master. So let's go ahead and start the merge.

Now here we see the changes that are going to happen during the merge. We actually haven't done the merge yet. I can simply push Cancel if I want to back out.

[Transcript missing]

Of course, I want all eight of these images. So I want to add Kevin's changes as well as my own.

And there's two different ways I can do this. I can either do a left and then right merge, in which case my changes, being the left, are placed on top of Kevin's. Or since Kevin committed first, I'll go ahead and put the changes that Kevin made before mine. So in this case, we see all the images are added. We have eight images.

And we don't have to worry about missing any of those images or doing all this work over again that we've already done. I still can't merge. There must be another conflict in this file. In this case, it's because we both added the engineers to the workspace, as well as set them up as resources for our application. So that's part of the build phase. So just like before, I'm going to select a right and then left merge.

Here we see I again have all eight images. Now, I know that this file is no longer in conflict because the C image here has changed to a blue icon instead of the red icon. This means that the file was in conflict, but those conflicts have been resolved. I can also now push the Merge button. It's no longer disabled. So let's go ahead and do that merge.

And now, if I open up My Best Friends, Supporting Files, Resources, Engineers, we see that I have eight images there. So we didn't have to throw out my work just because Kevin also made work that conflicted with it, even in a project file. So we don't even have to just worry -- so this can also happen in source files, but you can even resolve project files as non-binary files.

And I made a few changes to that project file to resolve the conflict, so I need to commit. So I'm just resolving a conflict here. If I commit that... The branch has been successfully merged in. If I go to File, Source Control Push, I can push all those changes of merging the branch in up to the server, and now our server has all the work for Kevin to do during the beer bash.

All right, well, that is our project. It has now got all the changes we want, so let's go ahead and run it. So just like before, it's a matching game. Let's try a few of these tiles. Nope. Anyone have any ideas of which tiles?

[Transcript missing]

There's Kerry, my manager. Can't believe that sweater still fits him.

There's Kevin. Let's see if we can find... Nope. Eight. Eight. There's Mike. So we've got Mike, again. So we have two more. Any ideas? And then last we have Mirzai. So there are our Xcode engineers. And you can see what working on Xcode does to you. So we saw how you can work with multiple repositories in Xcode, even if they're a mixture of Subversion and Git.

We've seen how you can resolve conflicts in project files and not necessarily treat them as binary files. This, of course, also works in your code files. This can, of course, happen during an update or a merge. And finally, we see now you push code so that when you're working under Git, that code is updated to whatever remote you're currently connected to. For more information, please feel free to contact Michael Jurwitz or use the Apple Developer Forums. Thank you.