\(\newcommand{L}[1]{\| #1 \|}\newcommand{VL}[1]{\L{ \vec{#1} }}\newcommand{R}[1]{\operatorname{Re}\,(#1)}\newcommand{I}[1]{\operatorname{Im}\, (#1)}\)

Git walk-through

Basic configuration

We need to tell git about us before we start. This stuff will go into the commit information by default.

$ git config --global user.name "Matthew Brett"
$ git config --global user.email "matthew.brett@gmail.com"

git often needs to call up a text editor. We will use Atom as our text editor (see associating text editors with git):

$ git config --global core.editor "atom --wait"

We also turn on the use of color, which is very helpful in making the output of git easier to read:

$ git config --global color.ui "auto"

Getting help

$ git
usage: git [--version] [--help] [-C <path>] [-c <name>=<value>]
           [--exec-path[=<path>]] [--html-path] [--man-path] [--info-path]
           [-p | --paginate | --no-pager] [--no-replace-objects] [--bare]
           [--git-dir=<path>] [--work-tree=<path>] [--namespace=<name>]
           <command> [<args>]

These are common Git commands used in various situations:

start a working area (see also: git help tutorial)
   clone      Clone a repository into a new directory
   init       Create an empty Git repository or reinitialize an existing one

work on the current change (see also: git help everyday)
   add        Add file contents to the index
   mv         Move or rename a file, a directory, or a symlink
   reset      Reset current HEAD to the specified state
   rm         Remove files from the working tree and from the index

examine the history and state (see also: git help revisions)
   bisect     Use binary search to find the commit that introduced a bug
   grep       Print lines matching a pattern
   log        Show commit logs
   show       Show various types of objects
   status     Show the working tree status

grow, mark and tweak your common history
   branch     List, create, or delete branches
   checkout   Switch branches or restore working tree files
   commit     Record changes to the repository
   diff       Show changes between commits, commit and working tree, etc
   merge      Join two or more development histories together
   rebase     Reapply commits on top of another base tip
   tag        Create, list, delete or verify a tag object signed with GPG

collaborate (see also: git help workflows)
   fetch      Download objects and refs from another repository
   pull       Fetch from and integrate with another repository or a local branch
   push       Update remote refs along with associated objects

'git help -a' and 'git help -g' list available subcommands and some
concept guides. See 'git help <command>' or 'git help <concept>'
to read about a specific subcommand or concept.

Try git help add for an example.

Initializing the repository

We first make a new empty directory that will be version controlled with git.

Create the git repository:

$ cd our_work
$ git init
Initialized empty Git repository in /Users/brettmz-admin/dev_trees/psych-214-fall-2016/working/our_work/.git/

Show the new .git directory:

$ ls .git
HEAD
config
description
hooks
info
objects
refs

There are only a couple of empty sub-directories in the .git/objects directory:

$ ls .git/objects/*
.git/objects/info:

.git/objects/pack:

git add - put stuff into the staging area

Type this file in Atom and save:

Contents of our_paper.txt
This is the first sentence of the new paper.

Add to the staging area:

$ git add our_paper.txt

Check we added the file to the staging area:

$ git status
On branch master

No commits yet

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

	new file:   our_paper.txt

Show yourself there is a new sub-directory and file in .git/objects:

$ ls .git/objects/*

Looking at real git objects

Now we’re going to read the new object in Python, and find the hash of its contents. You don’t need to do this kind of thing to use git. This is to practice some Python, and to show you how git stores its files.

To read the new object, you’ll need a few new bits of Python.

Here’s how to read the binary contents of a whole file into memory:

>>> # Open a file in Read Binary mode to read bytes
>>> fobj = open('our_paper.txt', 'rb')
>>> # Read contents as bytes
>>> contents = fobj.read()  # Read the whole file
>>> fobj.close()
>>> type(contents)
<class 'bytes'>

Here’s how to calculate the SHA1 hash value for the file contents:

>>> # Import the Python module that calculates hash values
>>> import hashlib
>>> # Generate the SHA1 hash string for these bytes
>>> hashlib.sha1(contents).hexdigest()
'cb083f8092a8bfbe55a215e1b45e9f33b9dec86f'

This is the same value as the terminal command shasum calculates on a file:

$ shasum our_paper.txt
cb083f8092a8bfbe55a215e1b45e9f33b9dec86f  our_paper.txt

The new file in .git/objects is compressed using a program called zlib. To un-compress some bytes that have been compressed with zlib, use the decompress function in the Python zlib module:

>>> import zlib
>>> zlib.decompress
<built-in function decompress>

Now – what is the decompressed contents of the new .git/objects file? Do you recognize it? What is the SHA1 hash of the decompressed contents? Do you recognize that?

You should start with something like:

>>> fobj = open('.git/objects/d6/05b79accc16319ffe95fdc0a7992e830695c1c', 'rb')

where .git/objects/d6/05b79accc16319ffe95fdc0a7992e830695c1c is the new file that appeared in your .git/objects directory when you staged our_paper.txt.

When you are done, have a look at the solution in: reading git objects.

Make a first commit

Remember what will go into this commit:

$ git status
On branch master

No commits yet

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

	new file:   our_paper.txt

Make the commit:

$ git commit

Review what you have so far in your history:

$ git log

Show what branch you are on, with the hash of the current commit:

$ git branch -v

Edit again, check and commit

Edit the paper file again to add some text:

Contents of our_paper.txt
This is the first sentence of the new paper.

Crucially, this is the second sentence.

Check the difference between what you had before and what you have now:

$ git diff

Add the changes to the staging area:

# What goes here?

Our customary check:

$ git status

Make the commit:

$ git commit

Look at the project history again:

Check the parent hashes recorded in each commit. How?:

# Check the parents

Check which hash the default branch is pointing to now:

$ git branch -v

A new file

Make a new file like this:

Contents of our_analysis.py
# An analysis of our data
# Details to be confirmed

print("Tada!")

Check the status of the file.

Add the file to the staging area.

Make a commit.

A prettier log command

$ git config --global alias.slog "log --oneline --graph"
$ git slog
* 73f471c Add analysis
* cece131 Second version of the paper
* 8d1e37f First version of the paper

Thinking about objects again

See if you can guess how many files there are now in .git/objects.

What do these objects store?

If you have the hash of an object, you can check the contents with git cat-file -p followed by the first 7 digits of the hash value – e.g.

$ git cat-file -p d605b79
This is the first sentence of the new paper.

See if you can find the hash of the object corresponding to the directory listing for our most recent commit, and display its contents. Hint: Find the hash for the current commit message. Try displaying the contents for the current commit message.

Moving files

Try moving a file (renaming) using git mv:

$ git mv our_analysis.py our_first_analysis.py

Check the status. Do you need to add anything to the staging area?

Make a commit.

Now you have made a commit, check the new directory listing for our latest commit. What changed?

Making a new branch

Make a new branch with:

$ git branch work-from-home

Use git branch -v to check the hash that this new branch points to.

Have a look at the file .git/HEAD. What is it telling us?

Tell git to start working on the new branch instead of our previous branch:

$ git checkout work-from-home
Switched to branch 'work-from-home'

Have a look at git branch -v again. What changed? How about the file .git/HEAD?

Now see if you can replicate the following changes to our_paper.txt:

diff --git a/our_paper.txt b/our_paper.txt
index d18df62..75fe792 100644
--- a/our_paper.txt
+++ b/our_paper.txt
@@ -1,3 +1,5 @@
 This is the first sentence of the new paper.
 
 Crucially, this is the second sentence.
+
+The third sentence starts the crescendo.

Your job is to make the output from git diff look the same as the output above.

When you’ve finished, add the changes to the staging area and then commit.

Check where you are with git slog, and git branch -v.

Now go back to your previous branch, called master:

$ git checkout master
Switched to branch 'master'

Create this data file, add it to the staging area and commit.

Contents of our_data.csv
0,210,32
1,212,30
2,220,29

Merging

Now we want to merge the work from the work-from-home branch. Put another way, we want to merge the work-from-home branch into our current branch, master. What git command would do this action? Scan the output of git help for clues, then git help <command> when you’ve found the command you need.

Do the merge.

Check the output of git branch -v again.

Have a look at the output of git slog.

What do you see with git log --parents?

Conflicts

The merge that you just did should have been simple, with no conflicts.

Conflicts can occur when you have made changes to the same file on two different branches, and you try and merge them. If the changes are on or near the same lines in the file, git will complain and ask you to work out which changes you want to keep.

Make and checkout a new branch asking-for-trouble.

Edit our_paper.txt and add a sentence like “Fourth sentence gets to the point.” Add to the staging area and then commit.

Checkout the master branch again.

Edit our_paper.txt and add a sentence like “Fourth sentence is still warm-up.” Add to the staging area and commit.

Now try merging the asking-for-trouble branch into our current (master) branch. What do you see?

When the merge failed, git wrote some text into the file where the changes clash. our_paper.txt might look like this:

This is the first sentence of the new paper.

Crucially, this is the second sentence.

The third sentence starts the crescendo.

<<<<<<< HEAD
Fourth sentence is still warm-up.
=======
Fourth sentence gets to the point.
>>>>>>> asking-for-trouble

The lines between <<<<<<< HEAD and ======= are the changed lines from the branch we are merging into (master in our case). The lines between ======= and >>>>>>> asking-for-trouble are the changes from the branch we are merging (asking-for-trouble in our case).

Open the our_paper.txt file and remove the new marker lines in the text. Choose how you’d like to combine your two different changes to the file. When the file is ready, save it, then add it to the staging area and do a commit.

Check all is well with git slog.

The end

Congratulations! You now know the basics of working with a single git repository.