How to Guard your Secrets Using Git

July 15, 2017


Depending on how long you've been programming this might seem obvious, or odd. Recently, I've been playing with a few APIs and chose GitHub for version control. The problem is on GitHub (because I don't pay) the code I push is public so how do I keep those API keys secret? The Swift community has a few answers to this question but if you're new to the issue it could be difficult to figure out. I'll show you how I've solved the problem and how you can keep your sensitive info safe too.

Just to be clear, this isn't the only solution. In fact, I modeled my solution very close to how Rails does it by creating a specific file to hold the info that I don't want to be shared. Other people have used .plist or resorted to run-time HTTP request to grab the keys from a server but this seemed like the most straightforward.

For this tutorial, I'll be taking you through the following steps.

  1. Setup (Creating .gitignore)
  2. Creating our Secret.swift file
  3. Adding the Secret.swift file to .gitignore
  4. Making sure it's not checked into version control

That's the basic layout. I'll assume you have some knowledge of Git and the terminal.

Setup

This whole tutorial hinges on using Git as version control. It is the default choice when setting up projects in Xcode. Here you can see the check box signifying we'd like Xcode to setup Git to manage our project under version control.

If you're unsure if you had that box checked then I'll show you how to find out. Navigate to the root of your project in the terminal and type in ls -a and you'll see something like this.

The .git file indicates we're using Git. If you don't see that then type in git init and that should create the .git file for you. Just check again to make sure. After that, we need to create a .gitignore file. If you're curious what that is you can find out here. To create the file just type touch .gitignore and then press Enter. Your new file structure should look like this from the terminal.

If your project name is different that's fine. We'll move onto creating the file for holding our secret information.

Creating the Secret.swift file

First, you need to add a file to your project called Secret.swift. Technically speaking you could name it anything but for this example, we'll call it that. This file will hold info we don't want to be checked into version control. Inside the file, I added the following code.

struct Secret {
  let secretAPIKey = "someSecretKeyYouDontWantKnown"
}

If you committed and pushed this code right now you'd be sharing that key. In the next step, we'll be looking at how to keep it private.

Adding Secret.swift to .gitignore

Hopefully, you've read up on what the .gitignore file is used for. If not, the gist is it's used to tell Git what files we don't want to be included in version control. To edit the file we'll be using the nano text editor built into Linux. Type nano .gitignore into the terminal and you'll get a nifty text editor inside of the terminal window.

The file should be empty. Inside of the file type <yourProjectName>/Secrets.swift on the top line. Mine looks like this now.

If you're wondering how to save to the text file just exit (control-x), save (y), and then you can press Enter. We're close to being done but not quite there yet. Our Secrets.swift file is still being tracked by version control because Xcode auto checks them in when we create new files. I'll show you next how to check what's being tracked and then remove it.

Getting out of Version Control

If you ever want to see a list of files being tracked all you need to do is type git ls-files into the terminal and you'll get a list like this.

You can see the Secrets.swift file is still being tracked. Let's change that real quick. If you type git rm --cached <file> it'll remove all history of a file being tracked and take it off the list. For my example, I'll type this.

git rm --cached SecretsExample/Secrets.swift

If you get the response error: the following file has staged content different from both the file and the HEAD: don't worry. Since we don't need these changes tracked we'll go ahead and force the removal as it suggests just below that.

git rm --cached -f SecretsExample/Secrets.swift

Hopefully, you didn't get an error this time. Let's check to see if the file is still on our list of files being tracked (git ls-files). It should no longer be there. To double check, you can type git status and see all the files staged for commit and if Secrets.swift isn't there then we successfully removed it.

You can now be sure all of the info inside of Secrets.swift will only be available to you locally. If you found this helpful or have questions please leave a quick comment or find me on twitter @josh_qn.

Thanks again! Auf wiedersehen!