CSCI 104 - Fall 2017 Data Structures and Object Oriented Design

Introduction to Git

[Git][git] is a distributed source code version control system. When you place your code under version control, you record the changes you make to your files over time and you can recall the history of each of your file changes at will. We will be using git extensively this semester in homework assignments.

[GitHub][github] is a development ecosystem based around git. In this course, we will be using GitHub to host our git repositories and we will take advantage of other GitHub features such as the issue tracker and wiki.

0 - Disclaimer

The instructions and discussion in this lab are for the git command line interface in course VM. GitHub and other software vendors have GUI-based applications to interact with repository. These tools are not will not be supported in this class. Git Bash is also not supported in this class.

1 - Install Course VM

Download and Install the Course VM. Instructions are available here.

[Note] We update course VMs often so you should not use any old VMs from previous classes or semesters. When you first open course VM, please verify that you have proper Internet access. If you see a two-arrow icon on the top right of your VM, you are connected to Internet. If you see a hollow fan shape instead, you are disconnected.

Connected Clone SSH

Disconnected Clone SSH

If you do not have Internet access from your VM despite having acccess on your laptop, try to reboot your VM (not your laptop). If that did not solve your problem, verify that you are using the correct VirtualBox version (5.1.26). If you need to update your VirtualBox, you will also need to update the extension pack and re-import your VM. You will lose ALL your files in the VM, so backup anything that you want to keep.

To re-import the course VM, first turn-off the VM. Open VirtualBox and right-click on the VM and select Remove. When prompted, select Delete all files. You can then follow the instructions on how to import course VM here.

[Hint] You will be copying and pasting a lot of commands into your VM terminal. To paste something to Terminal, you can use ctrl+shift+v or right-click in Terminal and choose Paste.

2 - Git Configuration: SSH Keys

One of the main features of using a distributed version control system such as git, is having a complete backup of your code and its history. Git uses the Secure Shell protocol (SSH) when contacting remote servers. To facilitate this communication, you need to generate a pair of encryption keys: one public and the other private.

In this step, we will generate the set of keys required to use SSH. This will be done manually through the command line. To start the configuration you would need to launch the Terminal.

Then, type the following command replacing Tommy Trojan's email with your own:

ssh-keygen -t rsa -b 2048 -C "ttrojan@usc.edu"

When prompted for a file location, use the default location [press Enter]:

# Creates a new ssh key, using the provided email as a label
Generating public/private rsa key pair.
Enter file in which to save the key (/home/student/.ssh/id_rsa):

After that, you will be prompted for a passphrase to secure your private key. It is a good idea to secure your key with a passphrase, though it is optional. Note that your password will not show up in terminal as you type it. When you are done typing your password (don't enter anything if you do not wish to set a passphrase), press Enter. You will be promted to verify your passphrase. Re-enter your passphrase (or nothing if you did not set one) and press Enter.

Upon success, you should receive a confirmation such as:

Your identification has been saved in /home/student/.ssh/id_rsa.
Your public key has been saved in /home/student/.ssh/id_rsa.pub.
The key fingerprint is:
SHA256:vC+4OG2u1PIeE0OKX9jiFFHuLnkYCBSsvIW8ybD873H ttrojan@usc.edu
The key's randomart image is:
+---[RSA 2048]----+
|   ++o.          |
|    S+.o *.*     |
|   +.X. o        |
|    0. o +       |
|   ..o  E .      |
|  .=S. . + .0    |
| .*=* ...        |
|.+.=o*. ..  *o*  |
| .++*oo. ..      |
+----[SHA256]-----+

3 - Git Configuration: Developer Profile

The next step is to configure your git profile in your development environment. This is important because your profile information is used to annotate your contributions to a repository/project. Although this may not seem like a big deal when you are the only one committing to a repository, it is of the utmost importance once you work on a group project because this information is the basis used to calculate your contribution to a project.

You only need to do this configuration once and we will be setting-up the following information:

Configuration is performed manually through the command line. To start the configuration you would need to launch the Terminal.

Your Personal Information

Please use your actual first and last name when configuring your git user.name. For your email, you should use the email address you want to appear in the git commit log. You should not feel obligated to use your usc.edu account here unless you want to. Configure your information as follows:

# Set your name and email
git config --global user.name "Tommy Trojan"
git config --global user.email "ttrojan@usc.edu"

[Note] One of the cool features of the GitHub UI is linking your contributions to your GitHub profile. For that to work, you MUST register and verify your git user.email in the GitHub Email Settings. (Hint: you can have multiple emails registered with GitHub and you could control which ones are public and/or private).

Git CLI Interface

By default, git does not color its output. Pretty printing git messages makes it easy read the output and take proper actions. You can enable colors for interactive use of git by:

# Let's get pretty colored output!
git config --global color.ui auto
Git Message Text Editor

When committing code in git, the system requires a commit message. If a message is not provided via the commandline, git will launch the Operating System's default text editor prompting you for a message. You can customize this action using the following configuration directive:

# Pick your editor of choice to edit commit messages (not code)
# Note that you should pick an editor that is installed on your machine
git config --global core.editor "subl -n -w"

Here, git will automatically launch Sublime. You may want to change that to your editor of choice. Here are some examples (you only need one):

# emacs
git config --global core.editor emacs

# Sublime Text
git config --global core.editor "subl -n -w"

If you are not familiar with any of the editors and feel unsure which one to use, it is recommended that you use Sublime. It is similar to gedit and Notepad but with some additional features.

Let Git Handle New Lines

Operating Systems implement new lines differently. (Why is this a problem?) Here you will configure git to automatically normalize the line feed (LF) to properly match the platform:

# LF Normalization (Linux & MacOS)
git config --global core.autocrlf input
Update Deprecated Settings

Since Git 2.0, Git has updated its default push settings. To avoid getting a warning when you push (we will explain what push means soon), apply the following setting:

# Push Setting
git config --global push.default simple
Check Your Work
# List local git configuration options
git config --list

You should see something like this:

user.name=Tommy Trojan
user.email=ttrojan@usc.edu
color.ui=auto
core.editor=subl -n -w
core.autocrlf=input
push.default=simple

4 - Update Your Github Profile

You need to update your profile to include your name and SSH public key. There are also some optional settings you can change such as your avatar (profile picture) and email notifications.

In your Profile Settings:

In your SSH Key Settings:

cat ~/.ssh/id_rsa.pub

In your Notification Settings, apply the following settings:

Notifications
Email notification preferences

Homework grade reports are released through GitHub, and using the above settings will ensure that you receive email notifications when your grade report is available.

[Optional] You can add more emails to your GitHub account using the Email Settings page.

5 - Using Git

Now that all your settings are in place, you are (finally) ready to use Git!

5.1 - Create GitHub Repository

A repository is a place to host your code. You can think of it as a directory or folder in a cloud server (i.e. GitHub server). Just like a folder in your Google Drive or Dropbox, a repository can contain sub-directories and files. Unlike cloud drives, changes to your local copy of the repository are not automatically synced to GitHub servers (and for good reasons).

To create a new repository, go to GitHub's "Create a new repository" page and enter the following information:

Click Create Repository and you should be taken to the repository page.

Clone SSH

5.2 - Clone Your Repository

At this stage, we created a repository to host our code called a code. We now need to make a local version of the repository to work with it. The is called cloning the repository. To do that, you need to get the cloning URL by visiting the page of the repository you just created in GitHub and look for the SSH clone URL.

  1. Go to your repository page and look for the green Clone or download button. Clone SSH

  2. Click on Clone or download and select Clone with SSH. Click on the button to the right of your repository url to Copy to clipboard. You can use the botton at the top right to toggle between Use HTTPS and Use SSH. Clone SSH

  3. Go back to your course VM and open terminal. Using that URL, you can clone the repo using the following commands in the Terminal.

# Change directory to your home directory
cd

# Clone the repository. Replace the url with what you copied from GitHub in the previous step.
git clone git@github.com:TTrojan/cs104-git-practice.git

If promted with the following question, type yes and press Enter.

The authenticity of host 'github.com (192.30.255.112)' can't be established.
RSA key fingerprint is SHA256:nThbg6kXUpJWGl7E1IGOCspRomTxdCARLviKw6E5SY8.
Are you sure you want to continue connecting (yes/no)?

You should see something like this when git is done cloning:

remote: Counting objects: 4, done.
remote: Compressing objects: 100% (3/3), done.
remote: Total 4 (delta 0), reused 0 (delta 0), pack-reused 0
Receiving objects: 100% (4/4), done.
Checking connectivity... done.

Now you have clone the repository to your local machine, you can start working in it.

# Start working in the repository
cd cs104-git-practice

5.3 - HelloWorld.cpp

Use your favorite editor to write a HelloWorld program in a file called HelloWorld.cpp:

# include <iostream>

int main() 
{
  std::cout << "HelloWorld!" << std::endl;
}

Since we have made progress in our code, it is a good idea to commit that code to the repository and make part of our code history. To see what files changed, you run the following command:

git status

You will get something like:

On branch master
Your branch is up-to-date with 'origin/master'.

Untracked files:
  (use "git add <file>..." to include in what will be committed)

        HelloWorld.cpp

nothing added to commit but untracked files present (use "git add" to track)

In the above status message, git is telling you that you have one file that is not currently tracked by your repository and that file is called HelloWorld.cpp. If you want to add the file to your repository, you need to use the git add <file> command. Here is an explanation of the some of the terms:

5.4 - Commiting Changes

To track HelloWorld.cpp, we use the following command:

# Add HelloWorld.cpp
git add HelloWorld.cpp

Now, let's check the status of our repository:

git status

You notice we get:

On branch master
Your branch is up-to-date with 'origin/master'.

Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

        new file:   HelloWorld.cpp

This tells us that we just added a new file called HelloWorld.cpp and we are ready to commit. Technically, we moved this new file from being untracked to be staged for commit. You can continue working on other files and you can stage them too. Once you feel that you are ready to committed, i.e. be part of the repository history, you use the following command:

# Commit with a message
git commit -m "My first HelloWorld using git"

This will commit HelloWorld.cpp and make it part of repository history. Each commit must have a message associated with it. You can add the message as part of the commit command using the -m option (see code above) or git will prompt you for a message using the editor you configured in section 3.

To check the commit history for the repository, you use the log command:

# See the commit history of the repository
git log

Which will give us the following message

commit df7cd3feda8a856de9cb2dc4bc132f15f7842bb1
Author: Tommy Trojan <ttrojan@usc.edu>
Date:   Tue Jan 14 17:42:52 2014 -0800

    My first HelloWorld using git

commit 6d9fe80012ff9bf5b43120a87dc61bf196fec313
Author: Tommy Trojan <ttrojan@usc.edu>
Date:   Tue Jan 14 15:57:08 2014 -0800

    Initial commit

The commit history of this repository shows that we have two commits in reverse chronological order. For each commit, you see the commit id (which is a SHA1 checksum), the author, the time the commit was made and the commit message.

5.5 - Pushing to the Server

Now that we committed successfully, let's check the status of our repository

# Check status of repository
git status

You will notice something different about this message:

On branch master
Your branch is ahead of 'origin/master' by 1 commit.
  (use "git push" to publish your local commits)

nothing to commit, working directory clean

It says that we are: ahead of 'origin/master' by 1 commit. If you go back to your repository page in GitHub, you will find that it only has one commit as opposed to the two you have locally. Since git is distributed, it allows you to work "offline" by committing locally and only pushing to the server once you feel ready to do so.

[Hint] Commit often and commit early. Try to push to the server as soon as you have a good portion of your code complete so you have a backup of your code. Never leave your coding session before pushing to the server.

To push your changes to the server, you use the following command

# Push changes to remote
git push

Now, check the commits section of your code repository by clicking on the commits links in your repository's page

GitHub Commits Page link

5.6 - Keeping Your Repo Up to Date

Since git uses the distributed model, you can have multiple copies of the repository on multiple machines. This makes it important to make sure your local version is up to date. Here is a practical example of what could happen.

  1. Go to your repository on GitHub
  2. Click on the HelloWorld.cpp file
  3. Click on Edit to edit the file online
  4. Let's update HelloWorld.cpp:
    • Change HelloWorld! to FightOn!
    • In Commit changes type: School pride
  5. Click _Commit changes`

GitHub Commits Page link

Visit the commits page in your repository and note how many commits you have. Now, go to your local repository and check the status of your repository:

# Check status of repository
git status

You should get

On branch master
nothing to commit, working directory clean

If you check the commit history, how many commits will you see:

# Produce commit history with one line per commit
git log --pretty=oneline

Notice that despite that you have 3 commits in total, you can only see 2 on your local machine. Because git compares your local repository to the remote repository using the lastest update from the server, it may or may not be the server's latest state.

To get an update from the server and bring your local repository up to date, you need to pull from the server:

# Get the latest updates
git pull

You will get a response that looks like:

remote: Counting objects: 3, done.
remote: Compressing objects: 100% (3/3), done.
remote: Total 3 (delta 0), reused 0 (delta 0), pack-reused 0
Unpacking objects: 100% (3/3), done.
From github.com:TTrojan/cs104-git-practice
   df7cd3f..1ffe7e8  master     -> origin/master
Updating df7cd3f..1ffe7e8
Fast-forward
 HelloWorld.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

Here, git is telling you: + It is updating from git@github.com:ttrojan/HelloWorld.git + It updated master + The update was from commit df7cd3f to commit 1ffe7e8 - HelloWorld.cpp has two changes - one insertion and one deletion. - There was one file changed - There was one line inserted - There was one line deleted

If you want to see in detail what the changes in the last commit were, you issue this command:

git log -p -1

To see

commit 1ffe7e8b5e776395126fb6e06fc72f5af12ab063
Author: Tommy Trojan <ttrojan@usc.edu>
Date:   Tue Jan 14 18:53:08 2014 -0800

    School pride

diff --git a/HelloWorld.cpp b/HelloWorld.cpp
index 55818b8..b9a284d 100644
--- a/HelloWorld.cpp
+++ b/HelloWorld.cpp
@@ -1,5 +1,5 @@
 #include <iostream>

 int main() {
-       std::cout << "HelloWorld!" << std::endl;
+       std::cout << "FightOn!" << std::endl;
 }

5.7 - Ignoring Files

Code repositories are intended for just that, code. When working on a programming project, you may get a number of different files such as: object files, executables, log files and sometimes compiled header or library files. It is important to keep your repository clean of such unecessery files.

git uses a file named .gitignore to list all files or file extensions that git should not track or report when you do a git status. Your repository now has a list that was auto generated by GitHub. You can see that list by typing the following command from within your repository:

# List the contents of .gitignore
cat .gitignore

Let's compile our HelloWorld.cpp to get the executable helloworld:

# Compile HelloWorld.cpp
g++ -g -Wall HelloWorld.cpp -o helloworld
# Run the executable
./helloworld

Now, if we do a git status, we will get the following output:

On branch master
Untracked files:
  (use "git add <file>..." to include in what will be committed)

        helloworld

nothing added to commit but untracked files present (use "git add" to track)

Since helloworld is an executable, we don't want to add it to the repository and we definitly don't want git status to keep bugging us about it. So, append .gitignore to have helloworld.

Now, do a git status and examine the output:

On branch master
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

        modified:   .gitignore

no changes added to commit (use "git add" and/or "git commit -a")

As you can see, we are no longer prompted for helloworld. However, we now need to commit our changes to .gitignore.

# Add .gitignore after modifying it
git add .gitignore

# Commit the changes
git commit -m "added helloworld to the list of ignored files"

# Pushing the changes to the server
git push

[IMPORTANT] When you turn in your homework through GitHub, you should not add any binary files to your repository. This includes executables and object files (more on this later in the class). You will lose points for turning in these files. As a general rule of thumb, anything that you write should be included and anything that we can generate by running compiling commands should be excluded.

5.8 - Let's Git Going

To summarize, we learned the following git commands:

# Clone a repository
git clone git@github.com:TTrojan/cs104-git-practice.git

# Add an untracked or modified file
git add <file1> <file2> <...>

# Remove a file from your git repository AND your local repository
git rm <file1> <file2> <...>

# Commit files that are staged for commit
git commit -m "non-optional commit message"

# Push commits to the server
git push

# Check the status of the repo
git status

# Let's make sure our repository is up to date
git pull

# See the commit history
git log

# See the commit history by printing a summary of each commit in a line
git log --pretty=oneline

# See the log of the last commit (-1) showing diffs of all the files (-p)
git log -p -1

When you are working on your homework, you should ALWAYS use git pull before you start. As you progress, you should sync your changes to the server often, using git add, git commit, and git push.

6 - Important Repositories

You will need to be added to the usc-csci104-fall2017 in order to access all course-related repositories. To check whether you have access, open the organization page.

If you see a list of repositories, then you have joined the organization already and you may continue to section 6.1:

Clone SSH

If you are promted with a message that you've been invited to join the usc-csci104-fall2017 organization, go on to View Invitation:

Clone SSH

You should be taken the organization's invitation page and click on Join usc-csci104-fall2017:

Clone SSH

If you see something like this, then you are not added to the organization yet. See section "6.3 - Cannot access a course repository?" for instructions on how to get added to the course organization:

Clone SSH

6.1 - Homework Repository

We have created a private repository named hw-ttrojan for you (you'll see your USC ID instead of ttrojan). You can access it by going to https://github.com/usc-csci104-fall2017/hw-ttrojan (replace ttrojan with your USC username).

This will be your homework repository where you will be doing all your homework assignments. In order for us to grade you, all your work must be pushed to your homework repository.

6.2 - Homework Resources Repository

The homework-resources repository is where we post things related to your homework. This includes any skeleton code, sample test cases, and grading rubrics (after grades are released).

6.2 - Labs Repository

The labs repository is where we post things skeleton lab code. Starting from lab 2, you will need to use skeleton code from this repository to finish lab assignments.

6.3 - Cannot access a course repository?

If you cannot access the orgnization page or you get an error (i.e. 404 This is not the web page you are not looking for) when trying to access all of the repository links, you either filled out the Github Account Registration Form late, or you entered the wrong USC/GitHub username. Please fill out the form again at end of this lab.

If you can access some of the above links but not all of them, please let your lab instructor know. Give them your USC username, GitHub username, and the repositories that you cannot access.

If you joined the class late (i.e. missed first week of class/lab), or if you still cannot access your repository during the second week of class, please let your lab instructor know. Give them your USC username and GitHub username.

7 - Git Resources

For more on git and how to use it, see the following resources.

Git Resources

Git Official Website

GitHub

[CAUTION] Unless you are already familiar with Git, please avoid using any commands that you do not already know on course related repositories (i.e. labs, homework-resources, and hw-username). You are welcome to create your own repository and test out Git's various commands there.