Lab 0: Install Party and Git Intro

Posted on October 2, 2019

NOTE. You do not have to submit anything for this lab. That said, you should at least complete the parts that explain how to set up Haskell and Git.

For this course, you will want four things on your computer:

  1. A terminal for compiling and running code.
  2. A good text editor for writing code.
  3. The latest version of Haskell.
  4. Git for tracking changes in your code and submitting assignments.

Terminal

Compiling and running Haskell programs generally happens on the command line, so you’ll need to have a terminal application.

All macOS machines come with an app called “Terminal” installed.

On Windows, if you don’t have a terminal you’ll get one for free when you install git below (it will be called “Git Bash”).

Terminal Basics

You will want to develop some comfort on the command line. Here’s the bare essentials:

See where you are (“print working directory”):

$ pwd

(The $ above is just an indication that you’re on a command line. All you have to type is pwd.)

List what’s in this folder:

$ ls

List “all” files (files that begin with . are usually hidden), with “long” information:

$ ls -al

Learn about any command by looking at its man page (manual page):

$ man ls

(Hit q to quit.)

Enter a folder (“change directory”):

$ cd some_folder

Go up one folder:

$ cd ..

The “root” folder is /, and your home directory is ~.

Make a folder:

$ mkdir new_directory

Move (or rename!) a file or folder:

$ mv old_name new_name

Copy:

$ cp old_file new_file

Copy a folder (“recursive” copy):

$ cp -r old_folder new_folder

Log on to a remote machine:

$ ssh username@computername.cs.uchicago.edu

Each computer’s name is written on the side of the machine. Or, there are a few machines for shared use. You can leave SSH with ctrl-d.

Copy a file to another machine:

$ scp some_file username@computername.cs.uchicago.edu:~/some/path/on/other/machine

If you use a terminal text editor like emacs or vim, you can use ssh to do your homework remotely.

If some app is running in a terminal and you want it to stop, hit ctrl-c. If some app in the terminal is asking you for input and you don’t want to give it any, hit ctrl-d (end of input). ctrl-d is also a way to end your terminal session.

Text Editor

Microsoft Word ain’t gonna cut it. You want a text editor that makes your code colorful and automatically indents every new line you type.

Two popular free GUI text editors are Atom and Visual Studio Code. The lab machines have Sublime Text installed; you can try it for free on your own machine and if you like it then it is a tool worth purchasing. If you use Atom, at least install the language-haskell package from within Atom. Similarly for VS Code: install at least the Haskell Syntax Highlighting extension from inside VS Code.

On the command line, the popular options are vim and emacs. Both these editors are pre-installed on the lab computers. Using a command-line editor takes some practice, but an experienced user can learn to rapidly perform complicated edits. Another advantage is that these editors can be used on remote machines over SSH. The main disadvantage is you can’t use your mouse.

Haskell

You can install the Haskell Platform (which includes some other tools you will need later in the course) onto your own machine using these instructions. Mac users may need to first install the XCode command line tools, which can be done with:

$ xcode-select --install

To see if you have Haskell installed correctly, open up a Terminal and run:

$ ghci --version
The Glorious Glasgow Haskell Compilation System, version 8.6.5

If your version of GHCi is not 8.6.5, then you may have to troubleshoot. For Mac users, run the command

echo $PATH

and check that ~/.ghc/bin and ~/.cabal/bin. If not, you might have to add these to your path. If you have the file ~/.profile or ~/.bash_profile, you can run the following:

$ echo 'PATH=~/.ghcup/bin:~/.cabal/bin:$PATH' >> ~/.bash_profile

Restart the terminal and try again. Then test GHCi with a couple arithmetic commands:

$ ghci
Prelude> 2 + 2
4
Prelude> 8 ^ 10
1073741824

Usually on a terminal you stop a program by typing ctrl-c, but in GHCi ctrl-c will only stop a long-running line of code. Instead, you leave GHCi by typing ctrl-d, which means “End of Input”. You can also leave GHCi by typing :q and hitting return.

(For non-Mac users (especially Windows users) you may have to consult stack overflow and help each other for troubleshooting. None of the instructors/TAs are particularly familiar with Windows, but we can try to help the best we can!)

Git

Git (pronounced like “get”) is a version control system. Git lets you take snapshots of an entire folder and stores the snapshots as “commits”. With git you can:

To use technical terms, Git is a distributed version control system. Because of its speed and flexibility, it has become the leading tool for managing source code. For example, Github is the world’s largest storehouse of open source projects. However, Github did not make Git—that honor goes to Linus Torvalds, who you may recognize as the creator of Linux.

If you’re looking for a version control system to learn in 2019, Git is the one. You won’t be using many of its features (for example, you won’t be collaborating with each other), but you will use Git to submit code and that will give you a taste of what you can do.

You can download git here. Mac OS X computers may already have git installed.

Verify Git Installation

To check if you have git installed, run this command on the command line:

$ which git

You should see a path, like:

/usr/local/bin/git

If you do, you’re good to set up git.

A Bit Of Git Setup

Check your Git config and see if you have a name and email set.

$ git config --list

If you don’t have a name and email set, choose the name and email that will appear on all your commits. You do not have to use your UChicago email.

$ git config --global user.name "Name"
$ git config --global user.email "email@example.com"

Enable color to be happier:

$ git config --global color.ui auto

Getting Your Repository

We created git repositories for all of you. You need to gain access to yours.

  1. Log in to https://mit.cs.uchicago.edu/. This is a web interface where you can view your repository.

  2. Find the settings.

  1. Go to manage your SSH Keys.

  1. If you don’t have an SSH key (usually they are stored in the ~/.ssh/ folder), follow the directions for generating one (I always skip the password step).

Public key encryption is one of the coolest things in computer science. Unfortunately, we don’t have time to discuss it. Just make sure you give Gitlab your public key not your private one.

  1. Copy/paste your public key into Gitlab.

There. Now, when you try to talk to the submission system from your computer, the submission system knows it’s your computer and not someone else. Let’s give it a go.

On the command line, navigate to your folder for this class. Now, clone the repository from the submission system onto your computer:

$ git clone git@mit.cs.uchicago.edu:cmsc16100-aut-19/yourcnetid.git
$ cd yourcnetid

Note: Some Mac users have reported trouble if they try to clone into an iCloud directory. Clone outside of iCloud.

You will asked about trusting a computer: say yes this first time.

Each of your labs will eventually be its own folder in this one big repository (e.g. folders named lab0, lab1, lab2, etc.). Well, it’s not a big repository yet. But it’s your one repository for this term.

Note: This is your lab repository. You can store your homework in it if you like—it will be ignored. But complete the labs in the lab0, lab1, lab2, etc. folders that will be provided and do not change their locations within the repository.

Some Git Practice

Let’s make sure Haskell is working and practice Git’s workflow.

Make a lab0 folder in your repository (either on the command line or in your operating system’s GUI). Using your text editor (not the mit.cs.uchicago.edu web interface), make a new file in the lab0 folder called Hello.hs. Paste in this program…

data Level
    = Undergraduate
    | Masters
    | PhD
    | Other
    deriving Show


name :: String
name = "Your Name Here"

level :: Level
level = Undergraduate

major :: String
major = "Your Major or Program Here"

why :: String
why = "A sentence about what inspired you to go into CS or why you are taking this class or what you hope to gain from this course."

distance :: Int -> Int -> Int
distance rate time = rate * time

…and put in your own answers for name, level, major, and why.

Make sure to save the file as Hello.hs in the lab0 folder.

On the command line, make sure you are in the lab0 folder and then start GHCi by typing:

$ ghci

You should see Prelude>. To load the file, use :l (the letter l)

Prelude> :l Hello

You should see:

Prelude> :l Hello
[1 of 1] Compiling Main             ( Hello.hs, interpreted )
Ok, 1 module loaded.
*Main>

You can now use the items you defined.

*Main> name
"Chuck Norris"
*Main> level
Other
*Main> distance 15 20
300

Let’s turn in this file. There’s a still another modification we’ll make below, but it’s a good idea to submit your changes as you work.

Exit GHCi by hitting ctrl-d. Then run:

$ git status

You should see something like:

On branch master

Starter code for lab0

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

	Hello.hs

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

Git is telling you that it’s not watching the Hello.hs file. Any changes to this file will be ignored.

Tell Git to track your file with git add.

$ git add Hello.hs

Now if you run git status you should see:

On branch master

Initial commit

Changes to be committed:
  (use "git rm --cached <file>..." to unstage)

	new file:   Hello.hs

We haven’t actually created a snapshot (a commit). We’re just telling Git what files we want to include in the commit. If we had more files, we could also add them to create a single big snapshot with multiple files.

Let’s just make a commit with this file.

$ git commit -m "Hello.hs with some personal info"

The string after -m is your message for the commit. It’s sort of a name for the snapshot. Use it to describe what you changed since the last commit.

You can see a log of commits with git log:

$ git log
commit 30a672d7a3b3f615080a7fd79eccaa831f5285dc
Author: Brian Hempel <brianhempel@uchicago.edu>
Date:   Mon Oct 31 22:46:35 2016 -0500

    Hello.hs with some personal info

The commit is still only on your own computer. To push this change to the remote repository (the mit.cs.uchicago.edu server that’s acting as our submission system), just type:

$ git push

(For your very first push, you may have to type git push -u origin master.)

You should see a message about pushing to master.

Okay, now it’s time to make a real change. Open Hello.hs and paste this code at the bottom:

main :: IO ()
main = do
    putStrLn "Hello, world!"
    putStrLn ""
    putStrLn ("My name is " ++ name ++ ".")
    putStrLn ("I am a " ++ show level ++ " student.")
    putStrLn ("I'm going into " ++ major ++ ".")
    putStrLn ("I'm in this class because " ++ why)
    putStrLn ""
    putStrLn ("If you travel for 15mph for 30 hours you will go " ++ show (distance 15 30) ++ " miles.")

Try compiling the file with:

$ ghc Hello.hs

GHC should produce an executable in the same folder called Hello.

Run it:

$ ./Hello

You should see output. You’ve just compiled your first working Haskell executable!

Now, let’s commit this change.

Use git diff see any changes that we haven’t told Git we want to commit. (Note, this shows changes in tracked files only; Hello.hs is tracked because we already committed it once).

$ git diff
diff --git a/lab0/Hello.hs b/lab0/Hello.hs
index c8f78bd..79cf6e1 100644
--- a/lab0/Hello.hs
+++ b/lab0/Hello.hs
@@ -11,3 +11,13 @@ why = "Want to make computing better."

 distance :: Int -> Int -> Int
 distance rate time = rate * time
+
+
+main :: IO ()
+main = do
+    putStrLn "Hello, world!"
+    putStrLn ""
+    putStrLn ("My name is " ++ name ++ ".")
+    putStrLn ("I am a " ++ show level ++ " student.")
+    putStrLn ("I'm going into " ++ major ++ ".")
+    putStrLn ("I'm in this class because " ++ why)
+    putStrLn ""
+    putStrLn ("If you travel for 15mph for 30 hours you will go " ++ show (distance 15 30) ++ " miles.")

Or, you can see a summary with git status:

$ git status
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:   Hello.hs

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

	Hello
	Hello.hi
	Hello.o

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

The Hello executable and a few intermediate files created by Haskell are untracked. Let’s let them be and not commit them.

But we do want to commit our change to Hello.hs. Tell Git to include our change in our next commit:

$ git add Hello.hs

Now, actually make the commit:

$ git commit -m "Print out my info"

If you run git log, you will now see two commits:

$ git log
commit 32133475e7e83c3ba4017787f4c0d56aab35f058
Author: Brian Hempel <brianhempel@uchicago.edu>
Date:   Mon Oct 31 23:01:02 2016 -0500

    Print out my info

commit 30a672d7a3b3f615080a7fd79eccaa831f5285dc
Author: Brian Hempel <brianhempel@uchicago.edu>
Date:   Mon Oct 31 22:46:35 2016 -0500

    Hello.hs with some personal info

The “Print out my info” commit is still only on your computer.

$ git push

There you go! If your Hello.hs file looks right on Gitlab, you’ve successfully pushed. Push early and push often.

There’s one more thing you should know. Your instructor or the graders may distribute grades by making changes to your remote repository. When there are more commits on the remote repository than on your local repository, Git will not let you push.

You have to first run:

$ git pull

This will pull any commits from the remote repository and automatically merge them with your local changes.

A vim session may open with a commit message saying “Merge … into master”. Save the message and exit vim by hitting :x (colon x).

Afterwards you can run:

$ git push

Below is a bit more miscellanea about Git.

Graphical Tools

For the git add and git commit part of the workflow, a GUI tool may help (I, Brian, use the Mac-only GitX). A GUI helps visualize changes much better. There are equivalent tools for other operating systems. Git comes with gitk, which you might try.

Documentation

There are man pages documenting the different git commands, e.g.:

$ man git-add
$ man git-diff
$ man git-commit
$ man git-pull
...

Or:

$ git help add
$ git help diff
...

These docs describe an interactive mode for git add that you might find useful:

$ git add -i

*** Commands ***
  1: status	  2: update	  3: revert	  4: add untracked
  5: patch	  6: diff	  7: quit	  8: help
What now>

Of course, you can also search online for tutorials, for example Learn Git Branching and Try Git. (Though we don’t recommend using branches during this course—you don’t want to accidentally forget to push master and fail your lab!)

More Git

The above commands are all you should need for this class, but in the future you may want to learn more about what you can do with Git.

Git gives you complete flexibility. You can grab old versions of files. You can undo entire commits. You can work on different branches to separate different features while you are working on them. You can reorder commits. You can go back in time and change history. (However, a rule of thumb is that you should not rewrite history after pushing.)

For what it’s worth, these are the commands I (Brian) use in my programming workflow. More advanced users may find these interesting. For this course, multiple branches or rewriting history is not recommended.

git add --patch     # Okay, really through GitX; but `git add -p` is close.
git rm              # Un-stage a change so it's not committed
git commit          # Again, through GitX
git commit --amend  # Change last commit; (GitX again)
git rebase --interactive HEAD^^^^^^ # Clean up history before pushing!
git commit -a -m "wip"  # WIP commits are better than stashing. Never stash.
git reset HEAD^         # Un-commit a WIP commit (but keep changes).
git checkout file_name  # Discard changes to file
git checkout -b branch_name # New branch
git branch -d branch_name   # Delete a branch
git pull --rebase      # Pull, then re-apply local commits
git rebase branch_name # Replay commits on top of branch
git cherry-pick        # Apply a single commit from a different branch
git reflog             # Recover deleted branches or mistaken hard resets

A Final Recommendation

If you haven’t already maximized your key-repeat rate yet in your keyboard settings, you’ll thank yourself later for doing it now.

You’ll quickly get used to it and it will save you days worth of time.

Happy coding!