{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Basic Git Workflow\n",
    "\n",
    "\n",
    "## The git model\n",
    "\n",
    "The main components to consider when dealing with a simple git workflow are:\n",
    "\n",
    "- the working directory \n",
    "- the staging area\n",
    "- the repository\n",
    "- the .git directory\n",
    "\n",
    "We use the various ``git`` commmands to move data between these areas. In the image below (taken from the Software Carpentry's [Version Control with Git](http://swcarpentry.github.io/git-novice/) lesson, CC-BY-4.0) we see a file in the Working Directory that has some exisiting lines in black and a new addition in green. ``git add`` is used to move the change, the additional green bit, in to the staging area. Once all the changes that make up the logical change have been assembled they are stored in the repositrory with ``git commit``. \n",
    "\n",
    "![staging and repo](http://swcarpentry.github.io/git-novice/fig/git-staging-area.svg)\n",
    "\n",
    "## Setting up git\n",
    "\n",
    "In order for git to record who made changes we need to configure our name and email address.\n",
    "\n",
    "```\n",
    "$ git config --global user.name \"Alice Researcher\"\n",
    "$ git config --global user.email \"a.researcher@gw4.ac.uk\"\n",
    "```\n",
    "\n",
    "There are other configuration options, but these are the only ones we need to set for now.\n",
    "\n",
    "## git status\n",
    "\n",
    "``git status`` is a very handy command for figuring our where you are and what is going on.\n",
    "\n",
    "If you aren't in a working directory you'll get a message like\n",
    "\n",
    "```\n",
    "train31@myVM:~$ git status\n",
    "fatal: Not a git repository (or any of the parent directories): .git\n",
    "```\n",
    "\n",
    "Otherwise you'll see something like\n",
    "\n",
    "```\n",
    "train31@myVM1:~/git1/example-basic$ git status\n",
    "On branch master\n",
    "Your branch is up-to-date with 'origin/master'.\n",
    "nothing to commit, working directory clean\n",
    "```\n",
    "\n",
    "We'll cover branches in few minutes. The last line is what we are looking for.\n",
    "\n",
    "## git diff\n",
    "\n",
    "If we make a change to one of the tracked files in the working directory git will notice\n",
    "\n",
    "```\n",
    "train31@myVM1:~/git1/example-basic$ git status\n",
    "On branch master\n",
    "Your branch is up-to-date with 'origin/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:   README.md\n",
    "\n",
    "no changes added to commit (use \"git add\" and/or \"git commit -a\")\n",
    "```\n",
    "\n",
    "We can examine exactly what the modification was with ``git diff``\n",
    "\n",
    "```\n",
    "train31@myVM1:~/git1/example-basic$ git diff \n",
    "diff --git a/README.md b/README.md\n",
    "index cfebfd9..9708379 100644\n",
    "--- a/README.md\n",
    "+++ b/README.md\n",
    "@@ -3,7 +3,9 @@ ex-basic\n",
    " \n",
    " This repository has just 5 basic commits on master by three different coders, providing a basic commit structure for learning exploring Git commands.\n",
    " \n",
    "+Adding a new line in the README will be a new commit.\n",
    "+\n",
    " ## Usage\n",
    " \n",
    " * Using `git log` to review simple history\n",
    "-* Filtering `git log` with `--author` option\n",
    "\\ No newline at end of file\n",
    "+* Filtering `git log` with `--author` option\n",
    "```\n",
    "\n",
    "## git add\n",
    "\n",
    "The command ``git add`` takes the changes and moves them to the staging area\n",
    "\n",
    "```\n",
    "train31@myVM1:~/git1/example-basic$ git add README.md \n",
    "```\n",
    "\n",
    "Now the status is \n",
    "\n",
    "```\n",
    "train31@myVM1:~/git1/example-basic$ git status\n",
    "On branch master\n",
    "Your branch is up-to-date with 'origin/master'.\n",
    "Changes to be committed:\n",
    "  (use \"git reset HEAD <file>...\" to unstage)\n",
    "\n",
    "\tmodified:   README.md\n",
    "\n",
    "```\n",
    "\n",
    "## git commit\n",
    "\n",
    "Git already automatically records\n",
    "\n",
    "- who\n",
    "- when\n",
    "- what\n",
    "\n",
    "The only thing it can't determine is **why**. It is up to you do supply the thinking behind the change.\n",
    "\n",
    "![xkcd](https://imgs.xkcd.com/comics/git_commit.png)\n",
    "*CC-BY-NC 2.5 Randall Munroe*\n",
    "\n",
    "If it is a particularly simple change and the reasoning is so obvious that you can use a single line to describe it you can use the ``-m`` flag\n",
    "\n",
    "```\n",
    "git commit -m \"Short Message explaining the commit\"\n",
    "```\n",
    "\n",
    "Otherwise run\n",
    "\n",
    "```\n",
    "git commit\n",
    "```\n",
    "\n",
    "which will open up your editor (in the case of this workshop ``nano``, but this can be set with ``git config --global core.editor`` )\n",
    "\n",
    "Here's a screenshot of a commit message in the process of being edited\n",
    "\n",
    "```\n",
    "  GNU nano 2.5.3 File: .../train31/git1/example-basic/.git/COMMIT_EDITMSG Modified  \n",
    "\n",
    "Add a line as an example\n",
    "\n",
    "Here we have a longer description of the commit explaining the \n",
    "rationale.\n",
    "\n",
    "# Please enter the commit message for your changes. Lines starting\n",
    "# with '#' will be ignored, and an empty message aborts the commit.\n",
    "# On branch master\n",
    "# Your branch is up-to-date with 'origin/master'.\n",
    "#\n",
    "# Changes to be committed:\n",
    "#       modified:   README.md\n",
    "\n",
    "^G Get Help   ^O Write Out  ^W Where Is   ^K Cut Text   ^J Justify    ^C Cur Pos\n",
    "^X Exit       ^R Read File  ^\\ Replace    ^U Uncut Text ^T To Spell   ^_ Go To Line\n",
    "```\n",
    "\n",
    "## Commit Messsage Best Practice\n",
    "\n",
    "https://chris.beams.io/posts/git-commit/\n",
    "\n",
    "1. Separate subject from body with a blank line\n",
    "1. Limit the subject line to 50 characters\n",
    "1. Capitalize the subject line\n",
    "1. Do not end the subject line with a period\n",
    "1. Use the imperative mood in the subject line\n",
    "1. Wrap the body at 72 characters\n",
    "1. Use the body to explain what and why vs. how\n",
    "\n",
    "\n",
    "## git log\n",
    "\n",
    "```\n",
    "train31@myVM1:~/git1/example-basic$ git log -p -1\n",
    "commit f7a92c7db602425409a5bbb01c6f6d7c3cff9063\n",
    "Author: Alice Researcher <a.researcher@gw4.ac.uk>\n",
    "Date:   Wed Dec 6 14:39:29 2017 +0000\n",
    "\n",
    "    Add a line as an example\n",
    "    \n",
    "    Here we have a longer description of the commit explaining the\n",
    "    rationale.\n",
    "\n",
    "diff --git a/README.md b/README.md\n",
    "index cfebfd9..9708379 100644\n",
    "--- a/README.md\n",
    "+++ b/README.md\n",
    "@@ -3,7 +3,9 @@ ex-basic\n",
    " \n",
    " This repository has just 5 basic commits on master by three different coders, providing a basic commit structure for learning exploring Git commands.\n",
    " \n",
    "+Adding a new line in the README will be a new commit.\n",
    "+\n",
    " ## Usage\n",
    " \n",
    " * Using `git log` to review simple history\n",
    "-* Filtering `git log` with `--author` option\n",
    "\\ No newline at end of file\n",
    "+* Filtering `git log` with `--author` option\n",
    "```\n",
    "\n",
    "\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Exercises"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Exercise 1\n",
    "\n",
    "- Configure your git with your name and email address"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "```\n",
    "git config --global user.name \"Chris Edsall\"\n",
    "git config --global user.email \"chris.edsall@bristol.ac.uk\"\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Exercise 2\n",
    "\n",
    "- Make a change to a file\n",
    "\n",
    "```\n",
    "nano README.md\n",
    "```\n",
    "\n",
    "- see what effect this has had on the working directory\n",
    "\n",
    "```\n",
    "git status\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Exercise 3\n",
    "\n",
    "- examine the difference between the state of the repository and the working directory. Is the exactly and only what you wanted to change?"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "```\n",
    "git diff\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Exercise 4\n",
    "\n",
    "- Stage the change so that it is ready to be commited\n",
    "\n",
    "```\n",
    "git add README.md\n",
    "```\n",
    "\n",
    "- Examine the state now\n",
    "\n",
    "```\n",
    "git status\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Exercise 5\n",
    "\n",
    "- Commit your change"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "```\n",
    "git commit -m \"Add more context to the readme\"\n",
    "```\n",
    "\n",
    "Or, you could have used\n",
    "\n",
    "```\n",
    "git commit\n",
    "```\n",
    "\n",
    "And then used `nano` to write a full commit message."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Exercise 6\n",
    "\n",
    "- Look at the repository history and see how your commit is displayed"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "```\n",
    "git log -p -1\n",
    "```"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.0"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
