In this episode I will show you how to make use of Tags in Git. This is not supported in Xcode or GitHub for Mac at the time of this recording (April 2014). I will also show you how to utilise the Tag/Release feature on GitHub.com.
Tags are a useful feature if you want to mark versions of your software before you add new features. With Tags you can always go back to the code of a release.
We’re using Xcode 5.1 and the Terminal utility for this. Enjoy!
Podcast: Download (Duration: 10:12 — 9.4MB)
Watch the full course in one convenient playlist:
Catch this episode on my iOS Dev Diary Podcast:
Sometimes Xcode gets confused with the intricacies of versioning. Frequently I find that I’m on a branch, everything is working fine, and for the life of me can’t merge it back into the Master branch. Often this happens because Xcode refuses NOT to make an change, such as update certain files I have already dealt with in the new branch.
That’s when the command line git tool can come in handy.
Suppose my new branch Mavericks is what I’d like to merge into master, but both Xcode and GitHub hang when trying to do so, citing “unrelolvable conflicts” and weird error messages. Rather than trying to understand them, it’s probably easier to just DELETE master and create a new copy from my Mavericks branch. Let’s do this.
First display what we have – cd into your working directory first, then issue
OK, we’re on the Mavericks branch, and master also exists. Let’s delete master:
Done and dusted – master is history. Let’s create a copy and call it master, then check it out:
git branch master
git checkout master
Switched to branch 'master'
Nice – looks like we’re all set here. You can also combine the “branch + checkout” command by typing “git checkout -b master”
Back in Xcode (and GitHub) everything seems fine too.
Like in Subversion, Git supports tags. Most developers use tags to “freeze” a bunch of files at a moment in time, much like a snapshot. Commonly this feature is used whenever a new release of your software is… well… released.
Xcode does not support this feature via the GUI, but of course Git does. Let’s see how to do this from the command line.
Tagging the current branch
You can create a tag from whatever you’ve just committed, no matter which branch this is on. Simply head over to your project and type the following:
git tag -a v1.1 -m 'Version 1.1'
This will create a tag called “v1.1” with the comment “Version 1.1”. To see a list of all your tags, type
Tagging a previous commit
If you’ve forgotten to create a tag from an earlier commit you can do that too. Simply specify part of that ugly long hash Git creates with every commit. They’re not easy to remember of course, so let’s list each commit to find the one you need:
git log --pretty=oneline
bd75bbfcee6de546c5c0dbb62387241b534481c8 added Season 1
a646c0bfd8c84087b6a37b77352761d84a6d57af added pictures
e9e2732cffe5ce81eb401e78e529f946ccdac226 wish I tagged this
152996254bee69fc3caf7e5c703e7ebaabd4afd4 Initial Commit
Say you wanted to create a tag from the second commit, the one that reads “wish I tagged this”. Tag it just like above, but add the first few hash digits like so:
git tag -a v1.2 -m 'Version 1.2' e9e273
Pushing Tags to a remote
Just like branches, your tags are not automatically pushed to a remote. You must specify this explicitly. You also need to know what your remote is called. Let’s assume it’s called “Remote”, here’s how you’d push the tag we’ve just created:
For a more detailed explanation, check out this excellent article from Git SCM.
Usually when you create a new Xcode Project you can choose to setup a new Git repository. This is the best and easiest way to track your changes. However if you have a project that is not under version control you can create a Git repository retrospectively.
This is fairly straightforward using the Terminal app on your Mac (under Applications / Utilities):
- cd into the directory where your project resides
- then initialize an empty repository (git init)
- and add the entire directory to it (git add .)
- commit your changes (git commit -m “initial commit)
So far so good. However Mac has a hidden directory called .DS_Store in every directory – we may not want to track that. Plus, every time you make a minor UI change in Xcode (such as open a group in the file explorer or something that is not relevant to your actual code) Xcode tracks this change in a file called UserInterfaceState.xcuserstate, and we definitely do NOT want to track that.
To tell Git that we don’t want those two things, we’ll amend our previous instructions a bit:
- cd into the directory where you project resides
- create a file called .gitignore
- add each file or directory on a new line
- then create, add and commit your files to Git
Let’s assume my project is called MyProject, then the steps are as follows:
(add the following lines to that file)
# ignore these files
(save and exit vi by pressing SHIFT-Z-Z)
git add .
git commit -m "initial commit, omitting several files"
If you have already committed all your files and forgot to setup the .gitignore file you must manually remove the files/directories you don’t want from being tracked. This is how you’d do that:
git rm --cached .DS_Store
git rm --cached # ignore these files
git commit -m "removing files I no longer want"
Replace myusername with your own system user name obviously, and MyProject with the actual folder in which your project resides.
Setting up a local GIT repository:
Open Terminal and change to the directory where your project is located (cd /path/to/your/project). Then use the following shell commands:
git add .
git commit -m "my initial commit (or any other comment you feel like)"
NOTE: as of Mountain Lion you need to install the Xcode Command Line Tools for this to work (under Xcode Preferences – Downloads – Components).
Setting up a local SUBVERSION repository:
This content is for members only.