\(\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:
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:
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:
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.
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.