CS61C Fall 2012 Lab 1

Registering your Account

Your TA will give you a sheet of paper with your class login (cs61c-XX) and initial password.

Log into one of the lab machines.

Add a shortcut to the Terminal program to the dock on the left hand side of the screen (bottom if you are in 200 SDH)

* Click on "Dash home" (the icon at the top of the dock)
* Type "Terminal" into the search field.
* Drag the Terminal icon onto the Dock.

Now start a Terminal session and change your password by typing ssh update and following the on-screen prompts.

Once you've changed your password type register and answer the following questions to associate your class account with your name and student ID number.

Initializing your working repository

Execute the following commands, where it is assumed that you will be developing your projects and homeworks in subdirectories of work (the name is inconsequential, name it something else if you like).

mkdir work
cd work
git init
echo "This is the top level of cs61c-XX's working directory" > README
git add -A
git commit -m "First commit."

Now let's walk through what we just did. The first two commands just made a work directory and moved us into it.
The third command, git init, places the current working directory under version control by placing the hidden directory .git inside of it. Now that work is version controlled you'll be able to return to pervious versions of your work if you muck something up while developing, among other things.
The fifth command, git add -A tells git that you think all of the changes to the repository since the last commit are worth tracking (git only tracks the files you tell it to). The jargon for the set of files whose changes are worth tracking is the index. So another way of expressing what git add -A did is to say that it placed everything in the directory in the index.
The final command you executed, git commit -m "First commit.", told git that this was a version of your code that you want to be able to get back to. The -m option told git to associate the message "First commit." with this version. On a side note, git will refuse to make a commit if there are no indexed changes, which is why we have the fourth command creating a README.

Pitfall Prevention: DO NOT RUN git init OR git clone FROM INSIDE A VERSION CONTROLLED DIRECTORY, INCLUDING ONE OF ITS SUBDIRECTORIES. This will cause "git in git" problems, which will almost definitely make someone's head hurt before they are resolved.

Pulling from another repository

Git provides the capacity for source materials to be shared between repositories. There are two main ways of doing this, the first of which is git pull, the other being git push, which we will cover later. git pull goes to the repository specified, at the specified branch or tag (line of development or labeled commit, respectively), and merges it into your repository. Basically it takes the code at the remote repository and sticks it in yours. Let's try it. We've placed the files for this lab in a git repository at ~cs61c/labs/fa12/01/. You can pull the files into your repository with these commands:

git remote add lab01 ~cs61c/labs/fa12/01
git pull lab01 master

So what does that do? The first instruction tell git to add ~cs61c/labs/fa12/01 to its list of remote repositories under the alias lab01. The second line goes to the lab01 repository, and merges its master branch into your currently checked out branch. Of course, you have no idea what all this business with branches is, which is why we're covering that next.

Branching and Merging

OK, so this is going to get a little complicated, but the bare bones of it are pretty simple. If you find yourself getting lost, try to make sure you don't forget these two things. First, branches represent lines of development, like trains of thought. Second, a merge takes two of these lines of thought, and incorporates one into the other.

You can think of version control as being a bit like a singly linked list. Every time you make a commit a new version of your code gets prepended to your list, and has as its child the next most recent version. That way if you want to back track to an old version you just look back through the list until you get to the version you want. What branches do is allow for your list to take on a more general graph structure, with nodes having multiple parents (ie, spawning multiple newer versions of code). When we give a node(version) more parents(successors) we call it branching, because we are splitting, or branching, the code into separate development paths. Merging is a little bit more complicated than just spawning a single parent for two children. It would be a more accurate depiction to say that we copy the nodes that the mergee (branch being merged into) doesn't have, but the merger (branch merging into the mergee) does, and inject those into the mergee. After we do that we look at the differences between the head of the merger and the head of the mergee before we injected the nodes from the merger. If these differences are "good" we'll combine the two automatically and make a new commit to the mergee. Otherwise we'll ask the user to perform conflict resolution manually, and then commit the changes.

Now that you have some idea of how branching and merging works at a high level, you're going to try using it on this lab. You'll notice that the code you've pulled in has a Makefile and a hello world program, but that the code doesn't compile. There are two ways of getting the program working. Either you can change the Makefile to make the compiler less picky, or you can fix the C code to be compliant with stricter standards. You're going to do both. First you'll make a branch for each.

git branch lab01c
git branch lab01make

Next you'll switch to the lab01c branch (ie, you will checkout lab01c) and fix the C code. Be sure to commit all your changes when you finish.

git checkout lab01c
/* Whatever you need to do to make the C code work. */
git commit -a -m "You should write a more meaningful commit message than this."

Then the same idea with the Makefile.

git checkout lab01make
/* Whatever you need to do to make the Makefile code work. */
git commit -a -m "You should write a more meaningful commit message than this."

Last merge in the improvements of both branches into master.

git checkout master
git merge lab01c
git merge lab01make

And that's it, you've used branches to explore different lines of development. This example may seem contrived (it was), but for more complicated problems this approach can make your life a lot easier.

Tagging important commits

git tag, in essence, applies a label to a given commit. In the real world you may want to tag the versions of the code which were used as releases, or perhaps just mark a commit which made a major difference in the way the code behaved. Of more immediate concern to you is the fact that we'll be using tags to determine which version of your code to grade for homeworks and projects. Apply the tag "lab01" to your most recent commit using the following command.

git tag lab01

Pushing to another repository

Pushing is the opposite of pulling. Where git pull took code from another repository and stuck it in yours git push takes your code and sticks it in another repository. In the real world it's not uncommon for teams to share work by pushing to a master repository which everybody else then pulls from. In this class it's how you'll be submitting all of your homeworks and projects (this is the only lab for which you will be making use of this submission process). The remote repository to which you'll be pushing your submissions is in ~cs61c/git/repos/cs61c-XX, where cs61c-XX is your login. The following sequence of commands will take your work and push it into the submission repository.

git remote add origin ~cs61c/git/repos/cs61c-XX
git push --tags origin master

The --tags option tells git to send tags, which it doesn't do by default.

Confirming your Submission

Now that you've gone through an assignment you're going to confirm that the submission process didn't fail. There are two things that you need to check on a given submission. The first is that it is tagged correctly, and the second is that the commit to which the tag points contains what you expect it to. The following commands will help you do that for this assignment. For other assignments you will need to pull with the appropriate tag. DO NOT EXECUTE THESE COMMANDS INSIDE OF YOUR WORKING REPOSITORY.

mkdir tmp
cd tmp
git init
git remote add origin ~cs61c/git/repos/cs61c-XX
git pull origin lab01
/*Examine your code to make sure that everything is in order*/
cd ..
rm -rf tmp

Checkoff

Confirm your submission for your TA or Lab Assistant.

Show that in your working directory branch lab01c only modified hello.c.

Show that in your working directory branch lab01make only modified Makefile.

When Things Go Wrong

You've misentered a path when using git remote add alias path:
Use the command git remote rm alias and then re-add your alias.

You've version controlled a directory(let's call the directory oops) that you don't want to be version controlled:
Use the command rm -rf oops/.git

You've mangled a branch and just want to throw it out and start over.
Use the command git branch -D problemBranch
Where problemBranch is the branch you wanted to remove.