In this tutorial, you'll learn how to use git source control with Xcode 8; whether committing or reverting, branching or merging, this tutorial has you covered.
I was just wondering is it possible to switch between git source control? So that if you’ve started git versioning within xcode but later decide to want to use the command line and then maybe even later revert back to xcode, is that possible?
Absolutely! Git is git, and you can use the integrated capabilities in Xcode and the command at a terminal prompt together. That’s my normal way of working, in fact. I do some things in Xcode and some in the terminal window. There’s nothing special at all that you need to do.
First of all great article, and I have been successfully using git with Xcode and Bitbucket for the last few months, and I have recently published my app to the app store, and have begun working on version 1.1 of my app (version 1.0) is in the app store.
I have made significant changes since the release as it has been live fore a couple of weeks now. Today I have a customer calling with a problem with the 1.0 version they have from the app store. I feel sure if I still had the 1.0 version loaded on my machine, I could connect my test iPhone and debug the problem an find it in just a few minutes.
Here’s my question. How would I go about downloading a copy of the 1.0 version ( I can see it listed in my commits in both Xcode and on Bitbucket.com). and being able to compile that and load on my test device with out losing or corrupting my current work on version 1.1.
It seems to me that this should be a pretty simple task. Is that true or am I asking way to much from git.
Thanks in advance you or anyone who comments can give, I surely will appreciated it.
Nope, you’re not asking too much at all; it’s easy to do.
If you’re looking at the commits in the Source Control navigator, find the commit that is your V1.0 release, right-click and select Branch from “xxx”…. That assumes you’re going to need to make changes to the V1.0 source code. Once you’ve fixed the problem, you can merge that branch with the fix back into your development. If you only need to look at it and not make changes, you can choose Checkout “xxx”… instead. (These instructions are for Xcode 9. Xcode 8 can do the same thing but you get to them differently. You can also use the command line.)
One thing I do with my apps is to tag my release versions with their release number. That makes it trivial for me to go back to an earlier version. There is a Tag “xxx”…" option in that right-click menu, though I typically do it from the command line.
Lets say I have set up a branch locally, and then I pushed that branch so that it is also on the remote repository. I have been working on the local repository branch, and have pushed all commits to the remote.
Now I am ready to merge my working branch into the master. If I merge locally, what will happen to the remote? Conversely, If I handle the merge directly at GitHub, what will happen to my local repository?
The answer in both cases is “nothing happens unless you make it happen.” :] That’s not really helpful, though, so let’s look a little deeper:
Merge to master locally
You now need to push your master branch to the remote to reflect your changes. Your working branch is now no longer needed and can be deleted. After deleting it locally, you delete it on the remote as well. You can do that in the Source Control navigator by twirling down the Remotes to find the remote branch, right-clicking and selecting Delete…*. You can also do it in the terminal with git push -d origin <your branch name>.
Merge directly on the remote (e.g. merge a GitHub pull request)
The master branch on the remote now has the most current view of the world. Switch to master locally and select Source Control\Pull… to fetch those changes. Again, your branch is no longer needed and you can delete it both places.
Neither of these is particularly specific to using git inside Xcode; they are normal day-to-day git operations for any kind of project. If you haven’t seen them, let me highly recommend Sam Davies’ “Beginning Git” and “Mastering Git” video courses here on the site. They are excellent and truly helpful, even for folks who use source control all the time.
Hope that helps. Let me know if you have further questions.
I’ve never used Xcode server so I’m not sure what or how it was doing remotes. If I’m understanding what you want correctly, you can achieve it fairly simply from the command line. There is certainly no automated way to do it within Xcode.
In Terminal:
> mkdir my-repo.git
> cd my-repo.git
> git init --bare
> cd /path/to/local/repo
> git remote add origin user@host:/path/to/my-repo.git
You’ll then be able to push to origin from within Xcode.
Thanks rcritz for the solution. Also confirming this feature has been deprecated in Xcode 9 .(image snipet from Xcode 9 release note on this issue below).
Hi, thanks for the article! I have a question about checking out branches.
Let’s say I start with “master”, then create “branch1” with some changes, and then “branch2” with some changes. All branches have local commits (of course) and have been fully pushed to the remote repository. (I’m using BitBucket, although that shouldn’t matter, I assume, since it implements git.)
Let’s say I’m working on “branch2” and I want to switch to “branch1”. Using the Source Control Navigator, I can choose “Checkout…” on “branch1” under the local (“Branches”) part of the tree. I’ll get a warning stating that "All files in the working copy will switch from the current branch (“branch2”) to “branch1”. This makes perfect sense, so I confirm it by clicking the “Checkout” button. My working copy files are switched to the branch1 files as expected. So far so good.
Now here’s the problem. In the Navigator, under the “Remotes” section, I control-click on “branch1” and choose “Checkout…” I get the exact same warning about working files being updated; this is what I want, so I click “Checkout” to confirm and proceed. But then I get an error, stating “The branch could not be created because one named “branch1” already exists.”
I don’t understand why this happens. Of course branch1 already exists – the Navigator is already showing it in the local (“Branches”) subtree.
I’ll also say that I’m assuming that “Checkout” under “Branches” should work exactly the same as “Checkout” under “Remotes.” My gut instinct tells me it should also do a pull, since that is what would be required if I tried to checkout a branch shown only under “Remotes” but not under “Branches.”
Hi Ken! I’m glad you enjoyed the tutorial and found it useful.
The short answer is that your gut instinct is exactly correct: you must do a pull.
You can’t checkout a remote branch using git because you can’t edit the files on the remote directly. Instead, if you try to checkout a remote branch, git will create a local branch and pull the files over. If that local branch already exists, it can’t do that.
If you want to work on the files on a remote branch, you have to pull them to your local branch and work on them locally. If your local branch and the remote branch are out of sync with each other, then you have to merge them (locally) in order to work on the files. Then you push your local files to the remote to bring everything back into sync.
Thanks for the reply! That makes sense, I’m just surprised that Xcode offers a “Checkout” option under “Remotes” when it knows there is already the same branch locally and it’s just going to immediately give an error. (Would it ever not give an error if the same local branch already exists?)
Thanks for guide. For anyone not familiar using Git on the command line, I wanted to mention that you can easily use a remote repository other than Github even though Xcode appears to only have support for Github.
After you create your remote repository (for example on Gitlab), take your repository’s .git url, cd into the root of your project directory using the terminal, and use
git remote add origin <your .git url>
And allow keychain to save your credentials, if asked.
Now in Xcode, when you go to Source Control > Push it will push to that repository.
Okay, after I hit Source Control>Commit, I actually have to choose one of the files on the left, then the version editor will show me the diff.
I’ve been playing around some more with Source Control>Commit, and I am seeing inconsistent behavior: sometimes I see the Version Editor and a diff without choosing a file on the left, and other times I see No Version Editor, and I have to choose a file on the left.
This is a great article. I had started with the xCode 9 + github talk from WWDC video WWDC17 - Videos - Apple Developer but your article was much more helpful.
Please can you offer two pro tips?
Tip 1 - should I commit my project / workspace settings?
you used a manually created .gitignore file from a web template. I am writing C command line apps and I don’t like to add my xCode workspace settings. My goal was to keep my github code tidy. Am I setting myself up for a fall if I ever need to clone on a completely new machine?
Tip 2 - even though a file may be inside my .gitignore file, it seems I also have to manually de-select files I don’t want sent to my remote repo when using xCode / Source Control / Commit ?
There seems to be 3 masters of gitignore.
the local, project specific .gitignore file(s)
xCode / Preferences / source Control / GIT / has a git ignore section
when you select xCode / Source Control / Commit you can select to add a file should be ignored…
I’m glad the tutorial was helpful. That’s always nice to hear!
Tip 1:
If you look at the .gitignore that we create, you’ll see it excludes the xcuserdata directory. That’s good to exclude because it is truly your personal settings and those can be recreated. You still want to keep your .xcodeproj file itself or you’re definitely setting yourself up for some pain in the future. Likewise for any other Xcode-related files/directories that aren’t stored in xcuserdata. If you have particularly complicated build schemes, I would also advise making them shared so that they can be stored in the git repo.
Tip 2:
You may be running into a situation where the file was committed to the repo before the .gitignore was created. In my experience, files excluded by .gitignore that are not already in the repo don’t appear in Xcode’s commit dialog. While I know Xcode has its own preferences for doing ignores, I prefer to use git’s native mechanism: the .gitignore file. I find that’s more natural and what most git users are expecting.