Everyone makes mistakes, it’s part of being human. I’m sure everyone reading this has one time or another made a huge mistake in their code and wished they could revert their project to the way it was an hour earlier. It’s mistakes like these which is why every programmer should use source control for all of their projects. Not using source control is just as bad as not backing up your computer. One mishap or event of data loss and your whole project could be compromised.
Source control helps you go back to older versions of your project so you can either recover lost data or see the progression of your code over time. It is also significantly easier to collaborate with others on your project while using source control. Many people would agree that Git is the best form of source control and lucky for us, it’s built right into Xcode!
A common misconception is GitHub and Git are the same thing. This is NOT true. Git is a source control system that runs locally on your computer. GitHub is an online service which lets your store your Git repositories in the cloud. Think iCloud Drive, but for code, and with way more power.
With the introduction of Xcode 9, Apple collaborated with GitHub to make it easy for developers to use source control with their apps. Use of the command line is no longer required to use Git and GitHub with your iOS projects. Everything is built right into Xcode!
In this tutorial, I’m going to show you the basics of Git and how to set it up and use it in Xcode 9. I will also go through how to connect your GitHub account so you can store your code in the cloud.
Let’s Git Started!
Since we’re learning about GitHub here and not as much Swift, the Xcode project I use will be very simple. Just enough to show you how GitHub works. You can follow along as I make the project, or feel free to use your own project. If you’re using your own Xcode project, skip to the How Git Works section.
Creating a Project
Let’s get a project started! Open up Xcode and click File and New Project. Choose Single View App and give your project a name. I’ll be calling mine simply Git Tutorial. Set the language to Swift and we will not be needing Core Data, Unit or UI Tests for this project.
Now this part is important! On the next screen make sure you have Create Git Repository on my Mac checked. This will initialize Git for your project directory. After this, click Create and you’re good to go!
How Git Works
So before we go and jump in to using GitHub and Xcode, let’s talk about how Git works.
This diagram shows the different states that a file in your Git repository can be in and what commands you can use on them.
The working directory is where files you are currently editing will be. The staging area is where files are added to before a commit. Files here are considered “staged for commit”. When you commit these files, they are then added to your local repository. When you do a push, you are syncing your local repository with your remote repository which in our case today will be on GitHub. Doing a push takes any changes you have made locally and adds them to the remote repository. Similarly, doing a pull will take any changes on your remote repository and add them to your local one.
So let’s say you and some friends are working on a simple to-do list application. It has three pages: to-do, completed, and settings. Let’s say that you just want to work on the settings page today. First, you would pull from your remote repository to make sure that you have any changes your teammates made. Now, when you start working on the code for the settings page, it is in your working directory. After you finish a function for the settings page, or another significant part, you git add
it to staging. If you added any new files or images, you would add them to staging as well. Now you are ready go do a commit. When you make a commit, you add a comment about what you changed. Finally, you sync your local repository with the remote one with git push
. You would want your teammates to do a pull so they have the changes you made to the settings page.
It might seem confusing, but it’s actually really simple! The rest of this tutorial will make it much more understandable.
So let’s talk about some of the Git commands:
git init
: This initializes Git for a project directory. Xcode will do this for you. However, if you ever use Git in the command line, you will need to use this.git status
: This, as you would guess, shows you the status of your git repo. In your command line, files that are not tracked (not in staging) will show up red while files that are tracked (in staging) will show up green. Xcode shows the status of your files in the Project Navigator which we will get into later.git add
: This adds your files to staging. In Xcode, all you need to do to add files to a commit is check them off which we will get into later.git commit
: This commits your files in staging to your local repository.git push
: This pushes your changes to the remote repository (GitHub).git pull
: This pulls changes from the remote repository. If you are working on a project with teammates, you will use pull to sync their changes with your repository.
Those are the basics. Let’s get into it!
Your First Commit
So if you clicked the Create Git Repository box when creating your project, then Xcode has already made your initial commit for you! If you didn’t check the box, click source control in your menu bar and then click create git repositories to initialize a repository for your project. Your source control tab in your menu bar should look like this:
Now let’s change something so we can make another commit! Go to your ViewController.swift
in your project navigator and add any valid code! I’ve added a string constant and printed it in the ViewDidLoad
method.
class ViewController: UIViewController {
let message = "Hello Git!"
override func viewDidLoad() {
super.viewDidLoad()
print(message)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
As you can see above, I have made two changes to the original boilerplate code that was created with the project. I added a constant and a print statement. However, it’s not always so easy to recognize everything you have changed in one session of programming, so let’s let Xcode make it obvious for us.
Xcode has a neat tool called the version editor. Open it by clicking the button with the two arrows going left and right, next to the assistant editor.
After opening the version editor, you will see two columns of code with highlights showing the differences between them. The left column is the current file you are working on. The right one is the same file but when it was last committed to your local git repository. This is really powerful! This way you can see every line you changed since your last commit. If something has since stopped working correctly, you can easily track it down.
You can see here exactly what I have added and removed. There is also another way that we can see what files have changed since our last commit. Take a look in your project navigator:
See that little M next to the ViewController.swift
file? That stands for modified which means the ViewController file has been changed since my last commit. If you see an A, that means the file has been added. This is another great way to keep track of your files and repository.
Now since we know what has changed, let’s commit our changes. In your menu bar, click Source Control and then Commit. You should now see this:
This is the commit window and it lets you add files to staging and commit them all at once. As you can see, the version editor is here too showing you your local revision on the left and the file’s state at the last commit.
Now take a look at the list of files on the left. These are all the files you have changed since your last commit. You can click through these and see what’s new to help you come up with a good commit message. You will also notice all the files have a check box next to them. This is Xcode’s version of git add. Only files that are checked off will be committed.
Speaking of commit messages, look at the text box at the bottom of the window. This is where that is written. A good commit message is short, sweet, and to the point about the changes that have been made. You write this so 1) your teammates know what you are committing, and 2) you can look back in your log and see what changes you have made overtime. If you find a bug, good commit messages make it easy to track down when it was created and where it is.
Now, type a message about what you changed and click commit # file(s).
Creating a Branch
Let’s branch out and talk about branches. So what is a branch? It’s basically an independent mini repository that usually focuses on one feature. What’s nice is that it’s independent from all of your teammate’s work. This means, if you mess something up in a branch, it won’t mess up all the other code in the project.
Let’s go back to our to-do list app example from before. Say, you want to add a new feature which allows users to sync tasks to their iCloud calendar. You could create a branch called “calendar” from the master branch. The master branch is the default that we have been committing to throughout this tutorial.
The new “calendar” branch has all the code from the project, but you can work on it independently. When you commit changes, you commit to the calendar branch instead of the master branch. Once you are done programming the calendar sync feature and it works well, you can merge it back to the master branch. But say your team decided to forgo the calendar feature, you can just remove the branch and no harm is done. Using branches is a much more organized way to add features to your app and it’s much safer also since it’s harder to mess up your whole project by accident.
For demonstration, let’s add a new function to our little practice app that simply takes in a string in a parameter, reverses it, and returns it. We’re going to create the function in a different branch.
First, go to the Source Control Navigator. We’re going to be spending a lot of time in here. It’s the tab next to the project navigator in the upper left.
If you expand the folder, you will see three more folders: Branches, Tags, and Remote. Expand the Branches folder and you will see the master branch. Right click on the master branch and click Branch From Master.
Now it’s time to give your new branch a name. I will be naming mine “reverse” since I am using it to add the reverse function.
Now you will see your new branch in the branches folder. It will also have the (current) next to it. This is there because you have switched to this new branch. All your commits will be to the new branch unless you checkout another one.
Now let’s add the reverse
function and place it after viewDidLoad
:
func reverse(text: String) -> String {
return String(text.reversed())
}
On top of that, add this to the viewDidLoad
function:
print(reverse(text: "stressed"))
Now go into your Source Control tab and click commit again. You will see your changes but look closer to the file paths under the code:
You will notice that it now shows that we are currently working in the reverse branch. Write a commit message and commit.
Now we have finished adding our new feature and it works well. It’s time to merge it back into the master branch! Go back to the Source Control Navigator and into the branches directory. Right click on the master branch.
Let me explain a few of the options here:
- Checkout, the third option from the top: In Git, checking out means to switch branches. Let’s say, I want to work on another feature in the master branch. I will then checkout master and do what I needed to do. When I want to keep working on reverse, I checkout the reverse branch and keep working.
- Merge “master” into “reverse”: This will merge the master branch into the reverse branch. We do not want to do that! This will take all the code from “master” and put it into “reverse”. It generally a bad idea to merge master with another branch.
- Merge “reverse” into “master”: This is what we are going to do. This will take all the code from “reverse” and put it into “master” therefore adding the reverse feature to the project. Click on this option and then click merge.
You will now see the version editor showing you your local revision and last commit of master. Click merge in the lower left one more time.
You will now see that the merge is listed in the log of commits, and master is the current branch. Congratulations! You created your first branch added a feature, and merged it!
Connecting to GitHub
Now let’s get into the really good stuff: Connecting to your GitHub account! Therefore, make sure you have a GitHub account set up before continuing.
First, let’s get your account connected. Go to your Xcode preferences (Menubar > Xcode > Preferences) and then go to the accounts tab. Click the plus in the lower left, then select the GitHub option and continue. Enter your GitHub username and password and viola! You have successfully connected your GitHub account!
Now let’s create a repository in GitHub for the project. In the Source Control Navigator, right click on the folder with your project name and click “Create GitTutorial remote on GitHub”.
Now you should see a window that lets you set up your repository. Make sure that your account is selected. Set a name for your repository (the default is your project name) and add an optional description of your project. Here you can also select if your repository is public or private (private repos are only available for paying GitHub members or students.) When all of your settings are good, click create.
Now head to your GitHub account and go to your repositories (Click your profile pic in the upper right > your profile > repositories). You should see your project listed on the top.
Click on it and you can now see your repository page. You can also see your project’s description, the number of commits you have, and of course all of the project’s files. Pretty cool you were able to do all of that right from Xcode right?
Pushing to Remote
So now let’s make another change, but this time push the changes to GitHub after we commit.
I’m going to add a label to the storyboard, and an outlet for that label in the ViewController. After I use the reverse function, I will also print that string to the label.
Here is what I have now:
This is the first time we made changes on the storyboard for this project. Notice that the ViewController.swift
file and the storyboard file both have an M next to them. Also, open the version editor and click on the storyboard. Storyboard files are actually XML files, so the version editor works with storyboard files too, showing you the changes.
Now, go to the source control tab and do another commit. This time on the commit window, you will see both the ViewController file and the storyboard file. Make sure both of them are checked so they both get committed.
Now that you have committed the changes, let’s push them to GitHub! Go to the Source Control tab again, but this time click push. Choose the master branch in the pop-up and click push once again.
After your push is completed, a green check should show up with Push Successful. Now go to your GitHub account and look at your repository. You should see your commit message next to the files that were affected with an updated time.
Congratulations! You have completed your first push through Xcode!
How to pull
If you’re working on a project with teammates, you will need to know how to pull. So let’s say one of your teammates who cloned your repository made a change to the ViewController. They would have made the change, committed it, and pushed it to the repository. Now, of course, you will want to have these changes in your local repository. Thus, you will need to pull.
For demonstration purpose, I created a new file called FileToPull in my GitHub repo. Of course, you would most likely be pulling a new or updated code file.
To do a pull, go into the Source Control tab in your menu bar and click pull. For this case, choose the master branch and click pull once again.
Since I was pulling a new file, the pull was successful and the file is now in my project navigator:
However, let’s say you are pulling an updated version of a file you already have. This is where Xcode’s built in source control features really come in handy. In this case, the version editor will show up showing your version of the file and the one you are about to pull. This way you can see all the changes your teammate made before pulling. You can accept the pull and sync all the changes into your file, or you can even select certain changes to pull.
Recap
I hope this tutorial helped you get into the amazing world of Git and GitHub. Version Control is such an important and helpful tool to use with your projects and I can assure you that any programming job you have will use it heavily.
If you find any part of this tutorial confusing or have any questions, feel free to leave a comment below and I will help you out! For more information on how to use GitHub, check out the GitHub Guides.
Have fun with GitHub, and remember, in case of fire, git commit, git push, git out!