p1-stats

Setting Up Version Control

This how-to will walk you through setting up a Git repository and using it to collaborate with a partner.

Prerequisites

We’re assuming that you already have a folder with starter source code in it, e.g., p1-stats/. You’ve created new files and added function stubs to make the code base compile, e.g., stats.cpp and main.cpp. You’ve already set up your visual debugger.

$ pwd
/Users/awdeorio/src/eecs280/p1-stats
$ ls -A
Makefile      main_test.out.correct  p1_library.h  stats_public_test.cpp
main.cpp      main_test_data.tsv     stats.cpp     stats_tests.cpp
main_test.in  p1_library.cpp         stats.h

You have installed git. Your version might be different.

$ git --version
git version 2.15.1

Restarting this tutorial

If you tried using this tutorial in the past and want to start over, here’s how to delete the files created by git and how to remove your repository from GitLab.

First, remove your GitLab repository. Browse to your repository’s project page from https://gitlab.eecs.umich.edu/. Select “Settings” -> “Advanced Settings” -> “Remove Project”.

Next, remove the hidden files created by git. Remember, hidden files start with a dot (.).

$ pwd
/Users/awdeorio/src/eecs280/p1-stats
$ rm -rf .git/ .gitignore
$ ls -A
Makefile      main_test.out.correct  p1_library.h  stats_public_test.cpp
main.cpp      main_test_data.tsv     stats.cpp     stats_tests.cpp
main_test.in  p1_library.cpp         stats.h

Confirm that this is no longer a git repository.

$ git status
fatal: Not a git repository (or any of the parent directories): .git

Install

You should already have git installed after completing the Command line tools tutorial. Verify that git is installed. Your version might be different.

$ git --version
git version 2.15.1

Configure your name and email

This sets the git preferences for your local machine. These settings apply to all repos on your computer. You only have to do this once, but repeating these commands won’t hurt anything. Be sure to use your own uniqname and email address

$ git config --global user.name "awdeorio"              # Your uniqname
$ git config --global user.email "awdeorio@umich.edu"   # Your email

Create a local repository

Navigate to your project directory and clean up any binary files using make clean. You should see the files we created earlier in the Starter files tutorial.

$ pwd
/Users/awdeorio/src/eecs280/p1-stats
$ make clean
$ ls
Makefile      main_test.out.correct  p1_library.h  stats_public_test.cpp
main.cpp      main_test_data.tsv     stats.cpp     stats_tests.cpp
main_test.in  p1_library.cpp         stats.h

Next, add a .gitignore file. This will prevent Git from controlling files like compiled binaries. We have a sample for you to download. It’s a hidden file (starts with a dot .), so you’ll need to use ls -A to see it. This sample is pre-configured to work with most C++ projects, so use the same sample file for all EECS 280 projects.

$ wget https://eecs280staff.github.io/p1-stats/dot_gitignore_sample -O .gitignore
.gitignore          100%[===================>]   6.23K  --.-KB/s    in 0s      

2018-01-12 15:15:30 (53.4 MB/s) - ‘.gitignore’ saved [6381/6381]
$ ls -A
.gitignore  main_test.in           p1_library.cpp  stats.h
Makefile    main_test.out.correct  p1_library.h    stats_public_test.cpp
main.cpp    main_test_data.tsv     stats.cpp       stats_tests.cpp

Initialize the repo. You’ll see that all the files in our directory are currently untracked.

$ git init
Initialized empty Git repository in /Users/awdeorio/src/eecs280/p1-stats/.git/
$ git status
On branch master

No commits yet

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

	.gitignore
	Makefile
	main.cpp
	main_test.in
	main_test.out.correct
	main_test_data.tsv
	p1_library.cpp
	p1_library.h
	stats.cpp
	stats.h
	stats_public_test.cpp
	stats_tests.cpp

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

Add existing files to version control

Add all the files in this directory. See that they are ready to be committed.

$ git add .
$ git status
On branch master

No commits yet

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

	new file:   .gitignore
	new file:   Makefile
	new file:   main.cpp
	new file:   main_test.in
	new file:   main_test.out.correct
	new file:   main_test_data.tsv
	new file:   p1_library.cpp
	new file:   p1_library.h
	new file:   stats.cpp
	new file:   stats.h
	new file:   stats_public_test.cpp
	new file:   stats_tests.cpp

Commit the added files to the local repo with the commit message “Initial commit. Starter files with function stubs.”.

$ git commit -m "Initial commit.  Starter files with function stubs."
[master (root-commit) c19cc98] Initial commit.  Starter files with function stubs.
 12 files changed, 776 insertions(+)
 create mode 100644 .gitignore
 create mode 100644 Makefile
 create mode 100644 main.cpp
 create mode 100644 main_test.in
 create mode 100644 main_test.out.correct
 create mode 100644 main_test_data.tsv
 create mode 100644 p1_library.cpp
 create mode 100644 p1_library.h
 create mode 100644 stats.cpp
 create mode 100644 stats.h
 create mode 100644 stats_public_test.cpp
 create mode 100644 stats_tests.cpp
$ git status
On branch master
nothing to commit, working tree clean

View the commit log and see our first commit.

$ git log
commit a13e2521fab6488458c912f598d6d5f89d429484 (HEAD -> master)
Author: Andrew DeOrio <awdeorio@umich.edu>
Date:   Fri Jan 12 15:59:25 2018 -0500

    Initial commit.  Starter files with function stubs.

Create a remote repository

First, log in to https://gitlab.eecs.umich.edu/. It’s a Git server run by the EECS department and all UM students should have a login.

Create a new project

Call the new project p1-stats, mark it as “private”. Click “Create”.

Double check that you have selected “private”. Making your project code or test cases publicly available online is a violation of the honor code.

You now have a project page page for your remote repo. In this example, awdeorio’s project page is https://gitlab.eecs.umich.edu/awdeorio/p1-stats. You won’t have access to it because it’s private, but your page should look similar.

Connect local repo to remote repo

Browse to your repository’s project page from https://gitlab.eecs.umich.edu/. Select “HTTPS”, then “Copy URL to clip board”.

Pro-tip: If you want avoid typing a username and password all the time, you can use SSH keys and an SSH URL (instead of HTTPS). Check out the GitHub tutorial on SSH keys. Don’t forget to add your key to GitLab (not GitHub).

Connect your local repo to your remote repo.

$ pwd
/Users/awdeorio/src/eecs280/p1-stats
$ git remote add origin https://gitlab.eecs.umich.edu/awdeorio/p1-stats.git  # use your URL

Double-check that your local repo is connected to your remote repo. You’ll see the URL you copied from your remote repo appear.

$ git remote -v
origin	https://gitlab.eecs.umich.edu/awdeorio/p1-stats.git (fetch)
origin	https://gitlab.eecs.umich.edu/awdeorio/p1-stats.git (push)

Push commits already committed on the local repo to the remote repo.

$ git push -u origin master
Username for 'https://gitlab.eecs.umich.edu': awdeorio
Password for 'https://awdeorio@gitlab.eecs.umich.edu': 
Counting objects: 14, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (12/12), done.
Writing objects: 100% (14/14), 6.97 KiB | 3.48 MiB/s, done.
Total 14 (delta 0), reused 0 (delta 0)
To https://gitlab.eecs.umich.edu/awdeorio/p1-stats.git
 * [new branch]      master -> master
Branch 'master' set up to track remote branch 'master' from 'origin'.

Verify that your local repo is up to date with the remote the repo (AKA origin/master).

$ git status
On branch master
Your branch is up to date with 'origin/master'.

nothing to commit, working tree clean

Verify the commit log.

$ git log
commit a13e2521fab6488458c912f598d6d5f89d429484 (HEAD -> master, origin/master)
Author: Andrew DeOrio <awdeorio@umich.edu>
Date:   Fri Jan 12 15:59:25 2018 -0500

    Initial commit.  Starter files with function stubs.

See the commit log on your GitLab project page. Click “History”. (You may need to refresh the page to see this.)

You should see your first commit show up.

Add a new file to version control

Next we’ll add a README, which will show up on the front page of our GitLab repository web page.

$ pwd
/Users/awdeorio/src/eecs280/p1-stats
$ ls
Makefile      main_test.out.correct  p1_library.h  stats_public_test.cpp
main.cpp      main_test_data.tsv     stats.cpp     stats_tests.cpp
main_test.in  p1_library.cpp         stats.h

We have no modified files and our code is in sync with the code stored on GitLab. In other words, we haven’t changed anything since the last git commit, and no changes have happened on the GitLab server.

$ git fetch
$ git status
On branch master
Your branch is up to date with 'origin/master'.

nothing to commit, working tree clean

Add an empty file called README.md using the command line.

$ touch README.md
$ ls
Makefile   main_test.in           p1_library.cpp  stats.h
README.md  main_test.out.correct  p1_library.h    stats_public_test.cpp
main.cpp   main_test_data.tsv     stats.cpp       stats_tests.cpp

Add the existing file using your visual debugger.

Now, edit README.md to look like the following example. Be sure to change the name :)

EECS 280 Project 1 Solution
===========================
Statistics

By Andrew DeOrio <awdeorio@umich.edu>

You can see that the new file shows up as untracked.

$ git status
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)

	README.md

We want to track README.md, so git add it.

$ git add README.md
$ git status
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:   README.md

Commit, and you’ll see that the repo has a clean status again.

$ git commit -m "Added README"
[master e016bfa] Added README
 1 file changed, 5 insertions(+)
 create mode 100644 README.md
$ git status
On branch master
Your branch is ahead of 'origin/master' by 1 commit.
  (use "git push" to publish your local commits)

From the previous git status command, we see that we have added code on our local computer that hasn’t yet been pushed to the remote GitLab server (Your branch is ahead of 'origin/master' by 1 commit.). Let’s push it now.

NOTE: if you get a rejected error, see Fixing rejected pushes, below.

$ git push 
Counting objects: 3, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (3/3), done.
Writing objects: 100% (3/3), 361 bytes | 361.00 KiB/s, done.
Total 3 (delta 1), reused 0 (delta 0)
To gitlab.eecs.umich.edu:awdeorio/p1-stats.git
   350f38e..7fa8093  master -> master
$ git status
On branch master
Your branch is up-to-date with 'origin/master'.

nothing to commit, working tree clean

Browse to your repo’s project page on GitLab and you’ll see a fancy formatted version of your README.

Modify a version controlled file

Let’s practice modifying an existing file. We’ll add to the README. Check that our version controlled files are clean and up to date with the remote repo.

$ pwd
/Users/awdeorio/src/eecs280/p1-stats
$ git fetch
$ git status
On branch master
Your branch is up-to-date with 'origin/master'.

nothing to commit, working tree clean

Edit README.md to add quick start instructions. We’re using Markdown formatting. It should look this when you’re done:

EECS 280 Project 1 Solution
===========================
Statistics

By Andrew DeOrio <awdeorio@umich.edu>

# Quick start
```console
$ make main.exe
$ ./main.exe
```

We can see that our files are no longer clean.

$ git status
On branch master
Your branch is up-to-date with 'origin/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:   README.md

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

See what’s different. You can see lines added (+) compared to the last clean committed version of the file.

$ git diff README.md
diff --git a/README.md b/README.md
index 4641b12..b1dde51 100644
--- a/README.md
+++ b/README.md
@@ -3,3 +3,9 @@ EECS 280 Project 1 Solution
 Statistics
 
 By Andrew DeOrio <awdeorio@umich.edu>
+
+# Quick start
+```console
+$ make main.exe
+$ ./main.exe
+```

NOTE: On Windows, you may see lines that end with the ^M character. This is normal; Windows uses a different convention for line endings than other operating systems.

Add, commit, and push.

NOTE: if get a rejected error, see Fixing rejected pushes, below.

$ git add README.md
$ git commit -m "Added quick start to README"
[master 2fac8d1] Added quick start to README
 1 file changed, 6 insertions(+)
$ git push
Counting objects: 3, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (3/3), done.
Writing objects: 100% (3/3), 348 bytes | 348.00 KiB/s, done.
Total 3 (delta 2), reused 0 (delta 0)
To https://gitlab.eecs.umich.edu/awdeorio/p1-stats.git
   a80db0b..2fac8d1  master -> master

View the commit history from the command line.

$ git log
commit 4d375b45357b4b39822ad48c62c6988910258370 (HEAD -> master, origin/master)
Author: Andrew DeOrio <awdeorio@umich.edu>
Date:   Fri Jan 12 16:14:02 2018 -0500

    Added quick start to README

commit e016bfad5a6371097ea00380aedd3e22ee63f754
Author: Andrew DeOrio <awdeorio@umich.edu>
Date:   Fri Jan 12 16:07:36 2018 -0500

    Added README

commit a13e2521fab6488458c912f598d6d5f89d429484
Author: Andrew DeOrio <awdeorio@umich.edu>
Date:   Fri Jan 12 15:59:25 2018 -0500

    Initial commit.  Starter files with function stubs.

View the commit history on GitLab. Click a commit message to see a graphical diff.

View the diff on GitLab.

Daily work flow with version control

This section describes the work flow for a coding session with git.

Start with clean files.

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

nothing to commit, working tree clean

Retrieve any changes from the server. For example, you might have pushed changes while working on another computer, like CAEN Linux.

$ git fetch
$ git rebase

Make changes to files. Add and commit when you’re ready. You can do this several times.

$ git add SOME_FILE
$ git commit -m "Short description goes here"

Push changes to GitLab server.

$ git push

If you get a rejected error, see Fixing rejected pushes, below.

Next steps

If you’re here from the project 1 tutorial, you can now return to the main set up tutorial.

Version control for a team

Skip this section for project 1, which is individual.

We’ll walk you through a centralized Git workflow. You can find a description with pictures here.

Version control is great for teams working on the same code base. This is an outline of the steps to get started. Do this set up on one partner’s computer.

  1. Create a folder for this project and add the starter files.

  2. Create a local repository.

  3. Add existing files to version control.

  4. Create a remote repository.

  5. Connect local repo to remote repo.

  6. Add your partner as a team member on the remote repo.

    GitLab sends a confirmation email to your partner. Your partner clicks accept.

  7. Your partner clones the remote repo on their own local machine.

    Your partner uses the same remote URL that you do. Notice that akamil uses a link that has awdeorio in it, that’s because akamil is a member of the repo that awdeorio created.

    $ whoami
    akamil
    $ pwd
    /Users/akamil/Documents/eecs280/
    $ git clone https://gitlab.eecs.umich.edu/awdeorio/p2-cv.git
    Cloning into 'p2-cv'...
    
  8. All team members set up their visual debugger.

    Remember, other team members don’t need to download the starter files again because those files were already added by the first team member.

  9. All team members use the daily work flow with version control.

  10. Be sure to read up on resolving conflicts

Resolving conflicts

Note: the following text is copied from https://help.github.com/articles/resolving-merge-conflicts-after-a-git-rebase/

When you perform a git rebase operation, you’re typically moving commits around. Because of this, you might get into a situation where a merge conflict is introduced. That means that two of your commits modified the same line in the same file, and Git doesn’t know which change to apply.

After you reorder and manipulate commits using git rebase, should a merge conflict occur, Git will tell you so with the following message printed to the terminal:

error: could not apply fa39187... something to add to patch A

When you have resolved this problem, run "git rebase --continue".
If you prefer to skip this patch, run "git rebase --skip" instead.
To check out the original branch and stop rebasing, run "git rebase --abort".
Could not apply fa39187f3c3dfd2ab5faa38ac01cf3de7ce2e841... Change fake file

Here, Git is telling you which commit is causing the conflict (fa39187).

If you did this by mistake, you can undo the git rebase with git rebase --abort.

To fix the conflict, follow this how-to https://help.github.com/articles/resolving-a-merge-conflict-using-the-command-line/

Fixing rejected pushes

If you get a rejected error when using git push, this probably means you (or your partner) changed your repo using another computer (or the GitLab web interface).

$ git push
To https://gitlab.eecs.umich.edu/awdeorio/p1-stats.git
 ! [rejected]        master -> master (fetch first)
error: failed to push some refs to 'https://gitlab.eecs.umich.edu/awdeorio/p1-stats.git'

Fetch changes from the remote repo.

$ git fetch
remote: Counting objects: 3, done.
remote: Compressing objects: 100% (3/3), done.
remote: Total 3 (delta 2), reused 0 (delta 0)
Unpacking objects: 100% (3/3), done.
From https://gitlab.eecs.umich.edu/awdeorio/p1-stats
   4d375b4..2b9bea7  master     -> origin/master

See that the local and remote repos have diverged.

$ git status
On branch master
Your branch and 'origin/master' have diverged,
and have 1 and 1 different commits each, respectively.
  (use "git pull" to merge the remote branch into yours)

nothing to commit, working tree clean

Reapply your local commits on top of your remote commits, combining them into one sequence of commits.

$ git rebase
First, rewinding head to replay your work on top of it...
Applying: Local update to README.

Divergence between local and remote is fixed. You’re good to push.

$ git status
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 tree clean
$ git push
Counting objects: 3, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (3/3), done.
Writing objects: 100% (3/3), 318 bytes | 318.00 KiB/s, done.
Total 3 (delta 2), reused 0 (delta 0)
To https://gitlab.eecs.umich.edu/awdeorio/p1-stats.git
   2b9bea7..63a5d0b  master -> master
$ git status
On branch master
Your branch is up to date with 'origin/master'.

nothing to commit, working tree clean