Git Stash

Before you can git pull, you need to have committed any changes you have made. If you find you want to pull, but you're not ready to commit, you have to temporarily "put aside" your uncommitted changes. For this, you can use the git stash command, like in the following example:

In [1]:
import os
top_dir = os.getcwd()
git_dir = os.path.join(top_dir, 'learning_git')
working_dir = os.path.join(git_dir, 'git_example')
In [2]:
%%writefile Wales.md
Mountains In Wales

* Pen y Fan
* Tryfan
* Snowdon
* Glyder Fawr
* Fan y Big
* Cadair Idris
Overwriting Wales.md
In [3]:
git pull
Already up to date.

By stashing your work first, your repository becomes clean, allowing you to pull. To restore your changes, use git stash apply.

In [4]:
git stash apply
No stash entries found.
CalledProcessError                        Traceback (most recent call last)
<ipython-input-4-c47375944a4e> in <module>
----> 1 get_ipython().run_cell_magic('bash', '', 'git stash apply\n')

~/virtualenv/python3.6.3/lib/python3.6/site-packages/IPython/core/interactiveshell.py in run_cell_magic(self, magic_name, line, cell)
   2321             magic_arg_s = self.var_expand(line, stack_depth)
   2322             with self.builtin_trap:
-> 2323                 result = fn(magic_arg_s, cell)
   2324             return result

~/virtualenv/python3.6.3/lib/python3.6/site-packages/IPython/core/magics/script.py in named_script_magic(line, cell)
    140             else:
    141                 line = script
--> 142             return self.shebang(line, cell)
    144         # write a basic docstring:

<decorator-gen-109> in shebang(self, line, cell)

~/virtualenv/python3.6.3/lib/python3.6/site-packages/IPython/core/magic.py in <lambda>(f, *a, **k)
    185     # but it's overkill for just that one bit of state.
    186     def magic_deco(arg):
--> 187         call = lambda f, *a, **k: f(*a, **k)
    189         if callable(arg):

~/virtualenv/python3.6.3/lib/python3.6/site-packages/IPython/core/magics/script.py in shebang(self, line, cell)
    243             sys.stderr.flush()
    244         if args.raise_error and p.returncode!=0:
--> 245             raise CalledProcessError(p.returncode, cell, output=out, stderr=err)
    247     def _run_script(self, p, cell, to_close):

CalledProcessError: Command 'b'git stash apply\n'' returned non-zero exit status 1.

The "Stash" is a way of temporarily saving your working area, and can help out in a pinch.


Tags are easy to read labels for revisions, and can be used anywhere we would name a commit.

Produce real results only with tagged revisions.

NB: we delete previous tags with the same name remotely and locally first, to avoid duplicates.

git tag -a v1.0 -m "Release 1.0"
git push --tags

You can also use tag names in the place of commmit hashes, such as to list the history between particular commits:

git log v1.0.. --graph --oneline

If .. is used without a following commit name, HEAD is assumed.

Working with generated files: gitignore

We often end up with files that are generated by our program. It is bad practice to keep these in Git; just keep the sources.

Examples include .o and .x files for compiled languages, .pyc files in Python.

In our example, we might want to make our .md files into a PDF with pandoc:

In [5]:
%%writefile Makefile

MDS=$(wildcard *.md)

default: $(PDFS)

%.pdf: %.md
	pandoc $< -o $@
Writing Makefile
In [6]:
make[1]: Entering directory `/home/travis/build/alan-turing-institute/rsd-engineeringcourse/ch02git/learning_git/git_example'
pandoc index.md -o index.pdf
pandoc lakeland.md -o lakeland.pdf
pandoc Scotland.md -o Scotland.pdf
pandoc Wales.md -o Wales.pdf
make[1]: Leaving directory `/home/travis/build/alan-turing-institute/rsd-engineeringcourse/ch02git/learning_git/git_example'

We now have a bunch of output .pdf files corresponding to each Markdown file.

But we don't want those to show up in git:

In [7]:
git status
On branch master
Your branch is ahead of 'origin/master' by 3 commits.
  (use "git push" to publish your local commits)

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


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

Use .gitignore files to tell Git not to pay attention to files with certain paths:

In [8]:
%%writefile .gitignore
Writing .gitignore
In [9]:
git status
On branch master
Your branch is ahead of 'origin/master' by 3 commits.
  (use "git push" to publish your local commits)

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


nothing added to commit but untracked files present (use "git add" to track)
In [10]:
git add Makefile
git add .gitignore
git commit -am "Add a makefile and ignore generated files"
git push
[master 2e75ece] Add a makefile and ignore generated files
 2 files changed, 9 insertions(+)
 create mode 100644 .gitignore
 create mode 100644 Makefile
To https://github.com/alan-turing-institute/github-example.git
   4a35412..2e75ece  master -> master

Git clean

Sometimes you end up creating various files that you do not want to include in version control. An easy way of deleting them (if that is what you want) is the git clean command, which will remove the files that git is not tracking.

In [11]:
git clean -fX
Removing Scotland.pdf
Removing Wales.pdf
Removing index.pdf
Removing lakeland.pdf
In [12]:
  • With -f: don't prompt
  • with -d: remove directories
  • with -x: Also remote .gitignored files
  • with -X: Only remove .gitignore files


Git Hunks

A "Hunk" is one git change. This changeset has three hunks:

+import matplotlib
+import numpy as np

 from matplotlib import pylab
 from matplotlib.backends.backend_pdf import PdfPages

+def increment_or_add(key,hash,weight=1):
+       if key not in hash:
+               hash[key]=0
+       hash[key]+=weight

Interactive add

git add and git reset can be used to stage/unstage a whole file, but you can use interactive mode to stage by hunk, choosing yes or no for each hunk.

git add -p myfile.py
+import matplotlib
+import numpy as np
#Stage this hunk [y,n,a,d,/,j,J,g,e,?]?

GitHub pages

Yaml Frontmatter

GitHub will publish repositories containing markdown as web pages, automatically.

You'll need to add this content:


A pair of lines with three dashes, to the top of each markdown file. This is how GitHub knows which markdown files to make into web pages. Here's why for the curious.

In [13]:
%%writefile index.md
title: Github Pages Example
Mountains and Lakes in the UK

Engerland is not very mountainous.
But has some tall hills, and maybe a mountain or two depending on your definition.
Overwriting index.md
In [14]:
git commit -am "Add github pages YAML frontmatter"
[master 6aca2a7] Add github pages YAML frontmatter
 1 file changed, 7 insertions(+), 4 deletions(-)

The gh-pages branch

GitHub creates github pages when you use a special named branch.

This is best used to create documentation for a program you write, but you can use it for anything.

In [15]:
In [16]:

git checkout -b gh-pages
git push -uf origin gh-pages
Branch 'gh-pages' set up to track remote branch 'gh-pages' from 'origin'.
Switched to a new branch 'gh-pages'
To https://github.com/alan-turing-institute/github-example.git
 + 7663bfb...6aca2a7 gh-pages -> gh-pages (forced update)

The first time you do this, GitHub takes a few minutes to generate your pages.

The website will appear at http://username.github.io/repositoryname, for example:


UCL layout for GitHub pages

You can use GitHub pages to make HTML layouts, here's an example of how to do it, and how it looks. We won't go into the detail of this now, but after the class, you might want to try this.