Skip to content

Instantly share code, notes, and snippets.

@dunvi
Last active December 14, 2015 11:39
Show Gist options
  • Save dunvi/5080965 to your computer and use it in GitHub Desktop.
Save dunvi/5080965 to your computer and use it in GitHub Desktop.
Some tips for you guys

Getting started with a new project (for xcode)

1. Initialize the github repository FIRST

Go to GitHub and click the new repository button. Do this before creating an xcode project, hell, before even opening xcode. Trust me. No, seriously.

2. Clone the repository to the local computer

If you want to manually set up the repository (such as because you've already created the xcode project), this entire step is wrong.

On the command line (in terminal), traverse to where you want the repository and type
?> git clone https://[username]@github.com/[team name here]/[repository name here].git

This command will create a new folder named the name of the repository, so don't precreate the folder unless you like unnecessary nesting. This command should also automatically set the alias "origin" for you, and the branch "master".

This would be a good place to discuss what it means to use a "distributed" version control system, but suffice it to say for now that the way it works is that you keep copies of the repository wherever you wish to work, and sync across a network. So in order to work on a local computer, you need to "clone" the repository to said computer.

3. Create the .gitignore and the .gitattributes

Copy this file to the repository on the local computer. Name the file .gitignore. It should go at the root of the git repository - if you're unsure whether you're in the right place, ?> ls -a should reveal a .git directory.

Then create a new file named .gitattributes and put this line in it:
*.pbxproj -crlf -diff -merge

4. Now create your xcode project

I recommend doing any general config stuff by now.

5. Add, commit, and upload all of the starter files

Time to make your first commit! On the command line, type
?> git add .

So this is why you need that .gitignore. If you skipped that step, you will see lots of xcode's silly extraneous files appear here. You really don't want those uploaded, it'll give you a headache, so I recommend double checking what's being added. But when you're satisfied, type
?> git commit -m "[commit message here]"

For this kind of commit, a message like "setting up the repository" is fine. But later on, when you start writing complicated code, longer commit messages are a good thing, and can easily be written by skipping the -m flag and message argument.

Now your code is now committed to the local repository, but it's not synced to the central github repository. To do this, type
?> git push origin

Now you should be good to start writing real code.

Getting stuff done

A note about the github gui.

So github has made a gui for Macs and Windows. If you are working on Windows, I recommend installing it. I'm not so convinced by the mac version, at least partially since Mac has a proper commandline. However, feel free to use it if you wish, just make sure to go to preferences and log in as the correct person.

Getting the code on a different computer

Hopefully this is pretty simple. Just open a terminal and go to where you want to put the repository and type
?> git clone https://[username]@github.com/[team name here]/[repository name here].git
just like above.

This can be performed from the github gui, but I don't know how to use it.

Always work in a new branch

Consider the branch called master to be the "official" version of the code. A good way to think of it is "This branch should always compile", or "This version of the code could be submitted to Prof Z at any time", or "I could happily demo this code to the customer".

This means that if you want to work on the code, you should create a branch to work in. A few general words about branching:

  • The branch you start in is the one that's "copied", so make sure you're in the right one to start off. Usually it's best to start with a new copy of master. Type ?> git branch to check which branch you're in right now.
  • Make sure master is up to date first! It's good to get into the habit of always pulling before branching.
  • Don't have multiple people working in the same branch on different computers. This will prevent massive merging disasters, and besides the whole point is to have a different branch for each bugfix or new feature.
  • Okay, so the whole "working in a new branch" isn't always followed in the wild, but you should consider that on par with "doing your homework an hour before class". If you're going to do work on the master branch, you better be doing a really, really high priority emergency hotfix. It costs nothing extra to make a new branch, so just do it.
    • The more people there are working on the same code, the more seriously you should take this advice.
  • Branches don't have to be stored on the central server. A small branch that's merged back into master before the end of the day? Definitely no need. However, if you want your branch on github for whatever reason, type ?> git push origin [branch name here].

Soooo... how do I work in a new branch?

All of this can be performed from the github gui, but I don't know how to use it.

1. Create your new branch
  • To create a new branch, type
    ?> git branch [new branch name here]
  • To switch branches, type
    ?> git checkout [branch name here]
  • Shortcut to create a new branch and automatically switch to it:
    ?> git checkout -b [new branch name here]
2. Now make your changes in the new branch!
3. Commit your changes locally often!

About committing. Git has a two-step commit process. First you "stage" your files, then you commit. This allows you to be very specific about what files you're submitting (technically I think you can even commit just certain lines, but I don't know how to do that).

  • To stage, type
    ?> git add [files to be committed]
  • To commit, type ?> git commit [-m "[commit message here]"]

As a shortcut for both of these, you can add the -a flag: ?> git commit -a -m "[commit message here]". This automatically stages everything for you. I don't like using it, because I'm a control freak. I also don't know if -a automatically adds new files, so be sure to check if you use it.

This step can be performed from the github gui.

3a. If you are storing your branch on github, sync your files

To push your commits to github, type
?> git push origin [branch name here] Yup, the same syntax as ever. Technically, you might be able to leave out the branch name as long as it's the branch you have checked out, but I wouldn't trust it. Funky things can happen (it also might just yell at you) if your remotes aren't set up properly.

This step can be performed from the github gui.

3b. Keeping up to date

If you've been working in a branch for a long time, your branch might start to fall behind master as your team continues to add more features and bugfixes. You probably want those changes, especially because including updates from master often means that merging the branch back into master will be significantly easier.

The canonical way of doing this is with a rebase. rebasing and merging aren't all that different at first glance, but rebasing turns out to be a much, much, much more powerful tool. Here, we're just gonna use the command
?> git rebase master
from inside the outdated branch. Same as merging, this may involve merge conflicts which you solve the same as ever.

4. When you're done with your changes, merge them back into master

Make sure all of your changes are committed in your branch before you start! I have totally not done this before. When you're ready:

  1. Switch back to master with
    ?> git checkout master
  2. Double check for recent changes to master with
    ?> git pull origin master
  • You can leave out master since you're in the right branch already if your remotes are set up properly, but it's safer to specify it.
  • Why do we do this? Remember in cs70, that one time you tried working on 2 machines at the same time and SVN yelled at you? Yeah. Let's not have that.
  • If git yells at you here, good luck. It really shouldn't, if it does it means you changed files in master when you shouldn't have.
  1. Now we merge your branch into master. Type
    ?> git merge [branch name here]
  • If you see fast-forward, that's a really awesome thing. Be happy.
  • If you see recursive, that's a really good thing. Be happy.
  • If you get a conflict, merge pauses and waits for you to fix it. You perhaps should have looked at 3b.
  1. Time to push master to github! Type
    ?> git push origin
5. Cleaning up

You can always just leave the branch lying around just in case. I like to do this if I anticipate more debugging down the line.

If you pushed the branch to origin and don't want to keep the branch around, type
?> git push origin :[branch name here]
The colon tells git to delete the branch you just specified. There's a logic behind this, I promise; if you're curious, look up the full syntax of the push command.

Then to delete the branch locally, type
?> git branch -d [branch name here]

There's like 5 different ways to do this branch deletion stuff, just so you're not surprised if you google this and get some really different answers.

How to solve merging conflicts

When you get a merge conflict, the merge process pauses and lets you finish it. If you type ?> git status it will tell you the conflicting files "needs merge", and then list them again under "unmerged".

To fix this, open that file. Git will have left some kludge at the conflict, with the old code above the break and the new code below the break. Manually make your changes so it looks like what you want (make sure you take out the <<<<<<<, =======, and >>>>>>>!), save your files, run ?> git add [file name here] on the resolved file, and then recommit.

If you have to resolve a merge conflict, I strongly recommend leaving a good commit message explaining the changes that you made to solve it, because when you find you accidentally removed a curly-brace or something it's much easier to figure out what happened.

FAQ

"Git won't let me push!"

Check your internet connection.

If you're on CINE it won't work. You need to be on the WPA or the LAN.

Check your remotes.
  • Type ?> git remote -v
  • If origin points to git://github.com/foo/bar.git that's probably the source of your error
    • this syntax is read only - it's good for cloning, not so good for committing.
  • To fix this, type ?> git remote set-url origin https://github.com/[team name here]/[repository name here].gi
If the remote is set correctly, check your ssh access.

Don't use ssh, use https. This is a lot easier than setting ssh keys.

"What's the difference between 'pull' and 'fetch/merge'?"

The short answer? Nothing.

The long answer? pull combines fetch and merge into a single command. pull is great when you have a fast-forward-able merge.

So what does this mean? It means that if you suspect there's any chance of a conflict, use fetch and then merge. Merge will tell you if there's a conflict and where, and you can repair it with the instructions above.

"I have an outdated branch. Merge or rebase?"

The short answer? ... no there's no short answer for this one.

The shortest long answer? Rebasing involves applying merges.

The best answer? ... google.

"What's a good commit message?"

Something useful and descriptive. If you're interested in good formatting, I believe the standard is 54 characters for a short message. For a longer one, again 54 characters for the first line, then an empty line and then go ahead and type whatever you want at that point. But don't quote me on that.

Alternatively, try this.

"I don't understand something"/"I need more information"/"You don't have information on [question here]"

Some config information

The general command for configuring git is ?> git config. There are three general configuration "environments" - generally, two of them, global (your global settings) and local (special settings per repository) are the configuration options you are interested in.

If you type in the command
?> git config -l
(-l asks git to list all of the variable sset) you might get an empty list because nothing is set. I recommend changing this. THe general format for changing variables is
?> git config --[global/local] [variable name] [value]
Even if you can leave out the --global or --local I don't recommend it. You probably could have guessed that by now, though.

Here are some good variables to make sure you have set:

  • ?> git config --global user.name "[name here]"
    Note, this is not related to your github username. This is the name that appears on your commits. If you want a different name to appear in a certain repository, make sure to also set it in --local. I use dunvi for my general projects, so for school-related projects I (am supposed to) run the command
    ?> git config --local user.name "Linnea Shin"
    so that my professors know who this "dunvi" person is...

  • ?> git config --global user.name [email here]
    Again, this is not related to your github username, this is simply the name that appears on your commits. I like to set this locally as well, because I use multiple emails to filter my projects, so for example, for school projects I (am supposed to) type
    ?> git config --local user.email lshin@hmc.edu

  • ?> git config --global core.editor [editor here]
    If you have an environment variable, git might already use your preferred editor, but it's probably good to be sure (eff you nano) so I recommend setting this one to your favorite commandline editor. For the basic operations I'm discussing here, it only comes into play for longer commit messages, but when stuff starts going wrong and you start researching what the command rebase does you definitely want your favorite editor.

  • ?> git config --global color.ui true
    Just set this one. Trust me.

  • ?> git config --global core.autocrlf [input/true]
    If you are on Windows, set this to true. Otherwise, set it to input. This means that git will handle those awful CR+LF issues for you. If you anticipate ever ever EVER making even a small change on a Windows machine, just set this. Seriously. There is also a way to do it per repository using a .gitattributes file, but you should have this set anyway so just do it.

  • ?> git config --global push.default [simple/matching]
    I recommend setting this to simple. This means that when you push, git will only push the current branch, and will make sure that the names match across repositories (I don't know what happens if they don't). If you set it to matching git will push all branches which match names between the two repositories, which can lead to some crazy, so don't do that unless you know what you're doing.

There are lots and lots of options you can set here, but this should get you comfortably started.

Good commands to remember how to use

  • add
  • branch
  • checkout
    • basic useage: git checkout [branch] [files]
    • most commonly used to switch branches
    • however, also can be used to retrieve certain versions of a file (including from previous commits, google is your friend)
    • if, for example, you have a new file in a branch that you need on master for a hotfix, instead of doing a complicated commit-stash-merge sequence, you can use this command to retrieve just the one file.
  • clone
  • commit
  • config
  • fetch
  • log
  • merge
  • pull
    • basic useage: git pull [remote] [remote branch]
    • if you have the proper config, you can type as little as git pull.
    • shorthand for fetch and then merge.
  • push
    • basic useage: git push [remote] [local branch]:[remote branch]
    • if you have the proper config, you can type as little as git push.
    • usually you can just provide the local branch.
      • I think this pushes to the remote branch with the same name, though don't quote me.
    • providing both allows you to do things like push hotfixes from a branch to master without merging the entire branch.
    • this also explains the "delete remote branch" syntax - you're pushing an empty branch to the remote branch, which removes it.
  • reset
    • used to "reset" the state of the working directory.
    • don't confuse this with revert, which is used to undo a commit, this is the command you want when you are undoing uncommitted changes.
    • following are the two version of this command you are likely to want, anything else you should start googling.
    • git reset HEAD
      • this will unstage all files
    • git reset --hard HEAD
      • this will undo all changes you've made since the last commit.
  • revert
    • revert undoes changes that you have committed.
    • for uncommitted changes, use reset.
    • this command will make another commit that reverses the specified commit (reverses the diff)
  • remote
  • stash
    • allows you to "stash" changes for later
    • basically, if you don't want to commit yet (or at all) but you need to switch branches, use stash.
    • to stash your changes: git stash
    • to reapply them later: git stash apply
    • your change get pushed to a stash stack. If you stash multiple sets of changes, you can apply them (in LIFO order) by repeatedly using the apply command, or by specifying which set of changes to apply (google time)
    • useful command: git stash branch
      • creates a new branch, then applies the changes that would have been stashed (changes since last commit)
      • very handy when you spend 5 hours working on something and then realize that you were working in master and it's completely borked now and you need a working version of the code in 20 minutes >.<
  • status

details to come

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment