Skip to content

Instantly share code, notes, and snippets.

@rokroskar
Last active August 29, 2015 14:07
Show Gist options
  • Save rokroskar/25c65c8a2e9a2d556907 to your computer and use it in GitHub Desktop.
Save rokroskar/25c65c8a2e9a2d556907 to your computer and use it in GitHub Desktop.
Display the source blob
Display the rendered blob
Raw
{
"metadata": {
"celltoolbar": "Slideshow",
"name": "",
"signature": "sha256:b26e0cd5b3011b7cd0f6a71640fb3c5e23a820cb3a8da6ed0883e7f31fe8b37d"
},
"nbformat": 3,
"nbformat_minor": 0,
"worksheets": [
{
"cells": [
{
"cell_type": "code",
"collapsed": false,
"input": [
"# THE LINES BELOW ARE JUST FOR FORMATTING THE INSTRUCTIONS ABOVE !\n",
"from IPython import utils\n",
"from IPython.core.display import HTML\n",
"import os\n",
"def css_styling():\n",
" \"\"\"Load default custom.css file from ipython profile\"\"\"\n",
" base = utils.path.get_ipython_dir()\n",
" styles = \"\"\"<style>\n",
" div.prompt { /* remove In/Out prompt */\n",
" display: none;\n",
" }\n",
" </style>\"\"\"\n",
" return HTML(styles)\n",
"css_styling()"
],
"language": "python",
"metadata": {
"slideshow": {
"slide_type": "skip"
}
},
"outputs": [
{
"html": [
"<style>\n",
" div.prompt { /* remove In/Out prompt */\n",
" display: none;\n",
" }\n",
" </style>"
],
"metadata": {},
"output_type": "pyout",
"prompt_number": 2,
"text": [
"<IPython.core.display.HTML at 0x10b87fb90>"
]
}
],
"prompt_number": 2
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"#Version control for scientists\n",
"###Rok Ro\u0161kar, ETH Z\u00fcrich\n",
"\n",
"SIB Best Practices in Programming Course, October 21, 2014\n",
"\n",
"(see these slides at: http://bit.ly/1sbXp1m)"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"Sound familiar?\n",
"<p>\n",
"<img src=http://www.phdcomics.com/comics/archive/phd101212s.gif width=450>"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"\"version control\" is just a fancy name for tools that simplify tracking changes"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"source": [
"* cvs\n",
"\n",
"* svn (subversion)\n",
"\n",
"* hg (mercurial)\n",
"\n",
"* git -- this is currently most widely used"
]
},
{
"cell_type": "heading",
"level": 3,
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"Why do version control? (it seems like a lot of extra work)"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"source": [
"Selfish reasons: \n",
"\n",
"1. keeps you (and your code, and your papers) organized\n",
"\n",
"2. motivates you to write comments as you make changes (see 1.)\n",
"\n",
"3. helps you keep your research reproducible"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"source": [
"Altruistic reasons:\n",
"\n",
"1. makes it much easier to collaborate on projects with others\n",
"\n",
"2. sets you up to share results/code publicly (forces documentation of some sort -- also see 3. above)"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"Here I will walk you through a toy example, but you can repeat the same procedure on your own project to put it under version control. \n",
"\n",
"The [git documentation](http://git-scm.com/doc) can offer a lot more detail on what I will describe and I strongly recommend at least skimming the [basics](http://git-scm.com/book/en/Git-Basics) and [branching](http://git-scm.com/book/en/Git-Branching) sections. \n",
"\n",
"I loosely base these slides on [\"Git for scientists\"](http://nyuccl.org/pages/GitTutorial/) and the [Software Carpentry Git tutorial](http://software-carpentry.org/v5/novice/git/index.html)\n",
"\n",
"__note__: you will need to do [basic git installation](http://git-scm.com/book/en/Getting-Started-Installing-Git) before trying out the steps on the following slides"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"cd ~/"
],
"language": "python",
"metadata": {
"slideshow": {
"slide_type": "skip"
}
},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"/Users/rokstar\n"
]
}
],
"prompt_number": 1
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"%%bash\n",
"\n",
"cd \n",
"rm -rf test_project"
],
"language": "python",
"metadata": {
"slideshow": {
"slide_type": "skip"
}
},
"outputs": [],
"prompt_number": 2
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"## Trying it out\n",
"Let's have a look at how you can start using ``git`` right away... \n"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"source": [
"First we need a project with some files: "
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"%%bash\n",
"\n",
"cd ~\n",
"mkdir test_project\n",
"cd test_project\n",
"echo \"This is the start of our paper\" >> paper1\n",
"echo \"This is the script that generates results\" >> project_script"
],
"language": "python",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [],
"prompt_number": 3
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"cd test_project"
],
"language": "python",
"metadata": {
"slideshow": {
"slide_type": "skip"
}
},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"/Users/rokstar/test_project\n"
]
}
],
"prompt_number": 4
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"All that is needed to put this directory (and its subdirectories, should there be any) under version control is: "
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"%%bash\n",
"\n",
"git init"
],
"language": "python",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"Initialized empty Git repository in /Users/rokstar/test_project/.git/\n"
]
}
],
"prompt_number": 5
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"source": [
"This doesn't touch the project files: "
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"%%bash\n",
"cat paper1"
],
"language": "python",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"This is the start of our paper\n"
]
}
],
"prompt_number": 6
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"source": [
"But a repository database is created and hidden from view:"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"%%bash\n",
"\n",
"ls -la"
],
"language": "python",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"total 16\n",
"drwxr-xr-x 5 rokstar rokstar 170 Oct 22 15:10 .\n",
"drwxr-xr-x+ 293 rokstar rokstar 9962 Oct 22 15:10 ..\n",
"drwxr-xr-x 10 rokstar rokstar 340 Oct 22 15:10 .git\n",
"-rw-r--r-- 1 rokstar rokstar 31 Oct 22 15:10 paper1\n",
"-rw-r--r-- 1 rokstar rokstar 42 Oct 22 15:10 project_script\n"
]
}
],
"prompt_number": 7
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"We have made a repository -- a new world of possibilities has opened up: "
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"%%bash\n",
"\n",
"git status"
],
"language": "python",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"On branch master\n",
"\n",
"Initial commit\n",
"\n",
"Untracked files:\n",
" (use \"git add <file>...\" to include in what will be committed)\n",
"\n",
"\tpaper1\n",
"\tproject_script\n",
"\n",
"nothing added to commit but untracked files present (use \"git add\" to track)\n"
]
}
],
"prompt_number": 8
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"Lets take the advice of ``git`` and **add** our files to the repo. \n",
"\n",
"\"Adding\" a file means letting ``git`` know about it. "
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"%%bash\n",
"\n",
"git add paper1\n",
"git add project_script"
],
"language": "python",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [],
"prompt_number": 9
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"Lets check what we have done: "
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"%%bash\n",
"\n",
"git status"
],
"language": "python",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"On branch master\n",
"\n",
"Initial commit\n",
"\n",
"Changes to be committed:\n",
" (use \"git rm --cached <file>...\" to unstage)\n",
"\n",
"\tnew file: paper1\n",
"\tnew file: project_script\n",
"\n"
]
}
],
"prompt_number": 10
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"The two files are \"staged\" to be \"commited\" into the repository. \n",
"\n",
"Commiting them means adding them to the repository permanently. \n",
"\n",
"Lets do this now, so we can track their changes in the future: "
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"%%bash\n",
"\n",
"git commit -m \"first commit of our project\""
],
"language": "python",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"[master (root-commit) ce6bc05] first commit of our project\n",
" 2 files changed, 2 insertions(+)\n",
" create mode 100644 paper1\n",
" create mode 100644 project_script\n"
]
}
],
"prompt_number": 11
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"%%bash\n",
"\n",
"git status"
],
"language": "python",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"On branch master\n",
"nothing to commit, working directory clean\n"
]
}
],
"prompt_number": 12
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"source": [
"All changes in the local directory have been committed -- nothing else to do until more changes are made, all our valuable data is safe!"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"Now we change one of the files: "
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"%%bash\n",
"\n",
"echo \"this paper is going to be awesome\" >> paper1"
],
"language": "python",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [],
"prompt_number": 13
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"%%bash\n",
"\n",
"git status"
],
"language": "python",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"On branch master\n",
"Changes not staged for commit:\n",
" (use \"git add <file>...\" to update what will be committed)\n",
" (use \"git checkout -- <file>...\" to discard changes in working directory)\n",
"\n",
"\tmodified: paper1\n",
"\n",
"no changes added to commit (use \"git add\" and/or \"git commit -a\")\n"
]
}
],
"prompt_number": 14
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"What has changed? (using ``git diff``)"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"%%bash\n",
"\n",
"git diff"
],
"language": "python",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"diff --git a/paper1 b/paper1\n",
"index b34fc3c..45aa068 100644\n",
"--- a/paper1\n",
"+++ b/paper1\n",
"@@ -1 +1,2 @@\n",
" This is the start of our paper\n",
"+this paper is going to be awesome\n"
]
}
],
"prompt_number": 15
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"We can add (stage) the changes and commit to the repo: "
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"%%bash\n",
"\n",
"git add paper1\n",
"git commit -m 'new line in the paper'"
],
"language": "python",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"[master e6883f7] new line in the paper\n",
" 1 file changed, 1 insertion(+)\n"
]
}
],
"prompt_number": 16
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"``git``-controlled file cycle:\n",
"\n",
"do work --> stage --> commit --> do work... \n",
"\n",
"<img src='http://www.software-carpentry.org/v5/novice/git/img/git-staging-area.svg' width=800>"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"## ``git`` commits and repositories -- what do they mean\n",
"\n",
"``git`` stores snapshots of the project with metadata (author, parent etc), as well as the relationships between those snapshots:\n",
"\n",
"<img src='http://git-scm.com/book/en/v2/book/03-git-branching/images/commits-and-parents.png' width=700>\n",
"\n",
"The __repository__ is simply a collection of these interlinked snapshots. "
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"What does this look like for our current repository: "
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"%%bash \n",
"\n",
"git log --graph"
],
"language": "python",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"* commit e6883f79090bf44e026679a307cdc4b5f0ed1e0b\n",
"| Author: Rok Roskar <[email protected]>\n",
"| Date: Wed Oct 22 15:10:40 2014 +0200\n",
"| \n",
"| new line in the paper\n",
"| \n",
"* commit ce6bc056b8ec1226b48d01cbb47182b23405c11f\n",
" Author: Rok Roskar <[email protected]>\n",
" Date: Wed Oct 22 15:10:33 2014 +0200\n",
" \n",
" first commit of our project\n"
]
}
],
"prompt_number": 17
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"Now lets say we want to see what has changed since the first commit:"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"%%bash\n",
"\n",
"git diff ce6bc05"
],
"language": "python",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"diff --git a/paper1 b/paper1\n",
"index b34fc3c..45aa068 100644\n",
"--- a/paper1\n",
"+++ b/paper1\n",
"@@ -1 +1,2 @@\n",
" This is the start of our paper\n",
"+this paper is going to be awesome\n"
]
}
],
"prompt_number": 19
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"source": [
"Note that a subset of the commit \"hash\" is enough to identify it uniquely... other identifiers can be used (e.g. branch names) as we'll see in a second."
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"source": [
"Brief summary of basics:\n",
"\n",
"```\n",
"git init -- initialize a brand new repository in a new or existing project\n",
"git status -- show the current status of the repository\n",
"git add -- stage a file for committing to the repository\n",
"git commit -- permanently add the staged files to the repository\n",
"git diff -- compare two snapshots of the repository\n",
"git log -- show the log of the repository activity \n",
"```"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"## Branches\n",
"\n",
"``git`` allows for very fast and easy \"branching\". Think of branches as alternative realizations of your project -- they share some common origin but develop in slightly different ways. \n",
"\n",
"This is ideal for risk-taking and experimentation: how many times have you said \"I want to try this but I just got everything working and don't want it to break!\" This is one of the principal advantages of version-controlled code. \n",
"\n",
"In ``git`` lingo, a branch is just a label for a given commit (\"master\" is the default branch name): \n",
"\n",
"<img src=\"http://git-scm.com/book/en/v2/book/03-git-branching/images/two-branches.png\" width=500>"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"%%bash \n",
"\n",
"git branch"
],
"language": "python",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"* master\n"
]
}
],
"prompt_number": 20
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"source": [
"Now we want to add a new feature (or refactor code), but we don't want to cause permanent damage... \n",
"\n",
"Use a __branch__!"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"%%bash\n",
"\n",
"git branch testing \n",
"git branch"
],
"language": "python",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"* master\n",
" testing\n"
]
}
],
"prompt_number": 21
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"source": [
"This created a new branch \"testing\", which is just a new tag for the current commit. \n",
"\n",
"<img src='http://git-scm.com/book/en/v2/book/03-git-branching/images/head-to-master.png' width=500>\n",
"\n"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"To actually work on the new branch, we need to switch the \"HEAD\" or current working state, to the new branch:"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"%%bash\n",
"\n",
"git checkout testing"
],
"language": "python",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [
{
"output_type": "stream",
"stream": "stderr",
"text": [
"Switched to branch 'testing'\n"
]
}
],
"prompt_number": 22
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"source": [
"<img src='http://git-scm.com/book/en/v2/book/03-git-branching/images/head-to-testing.png' width=500>"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"Now we can make our experimental changes in the \"testing\" branch and leave the working version of the code untouched."
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"%%bash\n",
"\n",
"echo \"new features and functions galore\" >> project_script\n",
"git diff"
],
"language": "python",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"diff --git a/project_script b/project_script\n",
"index fec6e77..02d642c 100644\n",
"--- a/project_script\n",
"+++ b/project_script\n",
"@@ -1 +1,2 @@\n",
" This is the script that generates results\n",
"+new features and functions galore\n"
]
}
],
"prompt_number": 23
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"%%bash\n",
"\n",
"git commit -am \"adding new experimental features\""
],
"language": "python",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"[testing 3c41ea1] adding new experimental features\n",
" 1 file changed, 1 insertion(+)\n"
]
}
],
"prompt_number": 24
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"With the previous commit, we have moved the ``HEAD`` and ``testing`` branch tags forward, but the ``master`` branch tag remains on the previous commit:\n",
"\n",
"<img src='http://git-scm.com/book/en/v2/book/03-git-branching/images/advance-testing.png' width=500>"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"Now we want to go back to the \"safe\" master branch and make some changes without dire consequences:"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"%%bash\n",
"\n",
"git checkout master\n",
"echo \"written more in the paper\" >> paper1\n",
"git commit -am 'more paper edits'"
],
"language": "python",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"[master 7072b3c] more paper edits\n",
" 1 file changed, 1 insertion(+)\n"
]
},
{
"output_type": "stream",
"stream": "stderr",
"text": [
"Switched to branch 'master'\n"
]
}
],
"prompt_number": 25
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"source": [
"Note that checking out the ``master`` branch automatically changed back the ``project_script`` file:"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"%%bash\n",
"\n",
"cat project_script"
],
"language": "python",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"This is the script that generates results\n"
]
}
],
"prompt_number": 26
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"And finally we decide that the experimental features are stable enough to __merge__ back into the master branch:"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"%%bash \n",
"git merge testing"
],
"language": "python",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"Merge made by the 'recursive' strategy.\n",
" project_script | 1 +\n",
" 1 file changed, 1 insertion(+)\n"
]
}
],
"prompt_number": 27
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"source": [
"We can see the branching in the logs:"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"%%bash\n",
"git log --graph --oneline"
],
"language": "python",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"* 9645614 Merge branch 'testing'\n",
"|\\ \n",
"| * 3c41ea1 adding new experimental features\n",
"* | 7072b3c more paper edits\n",
"|/ \n",
"* e6883f7 new line in the paper\n",
"* ce6bc05 first commit of our project\n"
]
}
],
"prompt_number": 28
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"I was careful in the previous merging example to modify different files in ``master`` and ``testing``. Now what if we had made changes that conflict with each other? "
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"%%bash\n",
"git checkout -b testing2\n",
"echo 'made changes to paper' >> paper1\n",
"git commit -am 'changes to paper on testing2'"
],
"language": "python",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"[testing2 99b2030] changes to paper on testing2\n",
" 1 file changed, 1 insertion(+)\n"
]
},
{
"output_type": "stream",
"stream": "stderr",
"text": [
"Switched to a new branch 'testing2'\n"
]
}
],
"prompt_number": 29
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"%%bash \n",
"git checkout master\n",
"echo 'also made changes to paper' >> paper1\n",
"git commit -am 'changes to paper on master'\n",
"git merge testing2"
],
"language": "python",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"[master fd29d93] changes to paper on master\n",
" 1 file changed, 1 insertion(+)\n",
"Auto-merging paper1\n",
"CONFLICT (content): Merge conflict in paper1\n",
"Automatic merge failed; fix conflicts and then commit the result.\n"
]
},
{
"output_type": "stream",
"stream": "stderr",
"text": [
"Switched to branch 'master'\n"
]
}
],
"prompt_number": 30
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"Now our commits and branches look something like this: \n",
"\n",
"<img src='http://git-scm.com/book/en/v2/book/03-git-branching/images/advance-master.png' width=500>"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"%%bash\n",
"cat paper1"
],
"language": "python",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"This is the start of our paper\n",
"this paper is going to be awesome\n",
"written more in the paper\n",
"<<<<<<< HEAD\n",
"also made changes to paper\n",
"=======\n",
"made changes to paper\n",
">>>>>>> testing2\n"
]
}
],
"prompt_number": 31
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"source": [
"Edit the file in a text editor and save... (make sure to remove the \"<<<<<\")"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"%%bash \n",
"cat paper1"
],
"language": "python",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"This is the start of our paper\n",
"this paper is going to be awesome\n",
"written more in the paper\n",
"made changes to paper\n"
]
}
],
"prompt_number": 34
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"%%bash \n",
"git commit -am 'merged changes'"
],
"language": "python",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"[master 9c83a79] merged changes\n"
]
}
],
"prompt_number": 35
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"Sum-up: \n",
"\n",
"```\n",
"git branch -- create new branches, see a listing of branches\n",
"git checkout -- move the HEAD to a different branch\n",
"git merge -- merge another branch into the current one\n",
"```\n",
"\n",
"Branching is ideal for collaboration and experimentation! Use it often. \n",
"\n",
"* co-investigators can work on simultaneously in different branches\n",
"* this does not compromise the stable version \n",
"* when merging branches, changes can be __reviewed__ and consequences discussed \n",
"* to fix conflicts, just find \"<<<<\" and \">>>>\", edit, and re-commit"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"## Using tagging in the academic workflow\n",
"\n",
"Tags are basically just handy names for certain commits. However, they are statically assigned to a given commit and can be used to reference that commit at a later stage. \n",
"\n",
"They can be used very conveniently at certain logical points during a project: \n",
"\n",
"* mark the successful implementation of a major new feature\n",
"* record a version of the code or paper that was sent to collaborators\n",
"* preserve any other milestone, e.g. paper submission so analysis and figures can be reproduced later"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"Tagging is really straigtforward:"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"%%bash\n",
"\n",
"git tag -a v1 -m 'version shared with collaborators'"
],
"language": "python",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [],
"prompt_number": 36
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"%%bash\n",
"\n",
"git tag"
],
"language": "python",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"v1\n"
]
}
],
"prompt_number": 37
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"%%bash\n",
"\n",
"git show v1"
],
"language": "python",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"tag v1\n",
"Tagger: Rok Roskar <[email protected]>\n",
"Date: Tue Oct 21 10:00:39 2014 +0200\n",
"\n",
"version shared with collaborators\n",
"\n",
"commit 9c83a79f3c00a1c4e38d734aaf8ff199acb21ae9\n",
"Merge: 219bf3b 79d8550\n",
"Author: Rok Roskar <[email protected]>\n",
"Date: Tue Oct 21 10:00:37 2014 +0200\n",
"\n",
" merged changes\n",
"\n"
]
}
],
"prompt_number": 38
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"Now if we add new changes and commit:"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"%%bash \n",
"\n",
"echo \"new work beyond the stable point\" >> project_script\n",
"git commit -am 'added more stuff'"
],
"language": "python",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"[master 0093134] added more stuff\n",
" 1 file changed, 1 insertion(+)\n"
]
}
],
"prompt_number": 39
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"%%bash \n",
"cat project_script"
],
"language": "python",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"This is the script that generates results\n",
"new features and functions galore\n",
"new work beyond the stable point\n"
]
}
],
"prompt_number": 40
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"We can recover the previous stable commit by retrieving tag ``v1``"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"%%bash\n",
"git checkout v1 -b previous_stable\n",
"git log --oneline"
],
"language": "python",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"9c83a79 merged changes\n",
"219bf3b changes to paper on master\n",
"79d8550 changes to paper on testing2\n",
"eb7e9b1 Merge branch 'testing'\n",
"25d1600 more paper edits\n",
"abfb16f adding new experimental features\n",
"7a08209 new line in the paper\n",
"a838b13 first commit of our project\n"
]
},
{
"output_type": "stream",
"stream": "stderr",
"text": [
"Switched to a new branch 'previous_stable'\n"
]
}
],
"prompt_number": 41
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"%%bash\n",
"cat project_script"
],
"language": "python",
"metadata": {
"slideshow": {
"slide_type": "fragment"
}
},
"outputs": [
{
"output_type": "stream",
"stream": "stdout",
"text": [
"This is the script that generates results\n",
"new features and functions galore\n"
]
}
],
"prompt_number": 42
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"An overview of what the relationship between a tag, a commit, and a branch looks like: \n",
"\n",
"<img src='http://git-scm.com/book/en/v2/book/03-git-branching/images/branch-and-history.png' width=500>"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "slide"
}
},
"source": [
"## Remote repositories -- alternative backup and great collaboration tool\n",
"\n",
"A local ``git`` repository can be synced with a remote, which can serve as a way of backing up off-site or sharing your code with others. \n",
"\n",
"<img src='http://git-scm.com/book/en/v2/book/05-distributed-git/images/centralized.png' width=500>\n",
"\n",
"This is just the simplest possible model -- other workflows are possible for bigger teams, see the <a href=\"http://git-scm.com/book/en/v2/Distributed-Git-Distributed-Workflows\">Git documentation on distributed workflows</a>"
]
},
{
"cell_type": "markdown",
"metadata": {
"slideshow": {
"slide_type": "subslide"
}
},
"source": [
"Many free repository-hosting services exist, most popular are: \n",
"\n",
"<a href='http://www.github.com'><img src='https://assets-cdn.github.com/images/modules/logos_page/GitHub-Logo.png' width=200></a>\n",
"<p>\n",
"<a href='http://www.bitbucket.org'><img src='http://www.atlassian.com/dms/wac/images/press/Atlassian-logos/logoBitBucketPNG.png' width=200></a>\n",
"\n",
"Other benefits besides code hosting: \n",
"\n",
"* web site creation within the repository (github)\n",
"\n",
"* interface with continuous integration services to keep your code bug-free\n",
"\n",
"* wiki and documentation space\n",
"\n",
"* bug reporting and tracking -- also useful for single-person projects!"
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [],
"language": "python",
"metadata": {},
"outputs": []
}
],
"metadata": {}
}
]
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment