---
layout: bare
title: Sioux.nl Productive Git & GitHub Class
description: A full-day Git Intermediate class
tags: [notes, class, workshop]
path: classnotes/2013-01-23-sioux.nl-workshop-and-hotornot.md
eventdate: 2013-01-23
---

# Instructors
* Matthew McCullough ([Twitter](http://twitter.com/matthewmccull), [GitHub](https://github.com/matthewmccullough))
* Wynn Netherland ([Twitter](http://twitter.com/pengwynn), [GitHub](https://github.com/pengwynn))

# Resources
* [Free Office Hours](http://training.github.com/web/free-classes/)
* [Ask a Git or GitHub Question](https://github.com/githubtraining/feedback)
* [Hot or Not Slides](http://cl.ly/1z1C410S422a/content)
* [Workshop Slides](http://cl.ly/1l3d1Z1r3p3b/content)
* [Cheat Sheets](http://teach.github.com/articles/git-cheatsheets/)
* [Visual Merge Tools](http://www.youtube.com/watch?v=xfh13LcgqIU&feature=plcp)
* [Git & GitHub Public Videos](http://www.youtube.com/github)
* [Slides](http://teach.github.com/articles/course-slides/)
* [Slide PDF 1](http://githubtraining.s3.amazonaws.com/github-git-training-slides.pdf)
* [Slide PDF 2](http://githubtraining.s3.amazonaws.com/github-git-training-slides-advanced.pdf)
* [Open Source Git Ignores](https://github.com/github/gitignore)


# Hot or Not Session

## Title

Practical Git and GitHub

## Summary

Git is a version control system that prefers to more formally be called a "content tracker." But neither of these phrases points at the practical side of Git.

In this talk, we will explore how Git is more than the next flavor of Subversion and how it can culturally shift the very foundations of the way teams craft code, review code, search code, and even, collaborate. This talk offers newcomers to Git & GitHub a look at specific examples of how team member interactions are made easier and more frequent in the direction of a more continuous delivery development approach.

## Hot or Not Session – Command Line History

    git init testrepo1
    cd testrepo1
    ls -al
    git status
    mkdir source1
    mkdir source2
    echo HELLO > test1.txt
    echo HELLO > source1/test2.txt
    echo HELLO > source2/test3.txt
    git status
    git add .
    git commit -m"My first commit"
    open .
    mate test1.txt
    git status
    touch source1/test2.txt
    git status
    git add test1.txt
    git commit -m"Lots of content"
    git status
    git satus
    git status
    rm test1.txt
    mate source2/sioux9.txt
    git status
    git add .
    git status
    git add -A .
    git status
    git commit -m "Renamed some files with content changes"
    git log
    git l2
    git l2 | more
    
    git config --global color.ui auto
    cat ~/.gitconfig| more
    
    mate source2/sioux9.txt
    git status
    git diff
    git diff -w
    git diff --word-diff
    git add --patch .
    gitx
    git status
    git commit -m"Saving part of the changes"
    git status
    git stash
    git stash pop
    git diff
    git stash
    git add .
    git commit -m"Bug fix"
    git stash pop
    git stash
    git branch
    git branch is-this-a-fix-for-ticket-9071
    gitx
    git checkout is-this-a-fix-for-ticket-9071
    generaterandomchanges 5 sample txt
    git checkout master
    git checkout -b is-this-another-fix
    git checkout master
    
    git branch bigfeature1
    vim source2/sioux9.txt
    git add .
    git commit -m"Fix of a thing"
    git checkout bigfeature1
    mv source2 sourcebigfeature
    cd sourcebigfeature
    mv sioux9.txt newfeature.txt
    vim newfeature.txt
    cd ..
    git add -A .
    git status
    git commit -m"Big feature changes"
    git checkout master
    git merge bigfeature1
    
    cat sourcebigfeature/newfeature.txt
    cat sourcebigfeature/newfeature.txt | more
    echo $EDITOR
    git reset --hard HEAD@{1}
    export EDITOR=vim
    git merge bigfeature1
    git reset --hard HEAD@{1}
    git config --global core.editor vim
    git merge bigfeature1
    git reset --hard HEAD@{1}
    git merge bigfeature1
    
    git clone https://github.com/githubstudent/hellogitworld/ hellostudent
    cd hellostudent
    git checkout -b feature2
    ls
    vim README.txt
    git add .
    git commit -m"Added a line"
    git push -u origin feature2
    cd ..
    git clone https://github.com/githubtrainer/hellogitworld hellotrainer
    cd hellotrainer
    git pull https://github.com/githubstudent/hellogitworld.git feature2
    git push origin master
    git pull
    echo THIS >> new.txt
    git add .
    git commit -m"This fixes #5"
    git checkout -b feature4
    generaterandomchanges 5 sample txt
    gitx
    git rebase -i master

# One-day workshop
Wednesday, January 23rd, 09:00 to 17:00 with lunch break from 12:45 till 13:30.

## Conflict Resolution
* You are warned
* You choose or merge (right, left, blend)
    * --ours
    * --theirs
    * merge (by blending)
* Signal success of resolution with `git add FILE`
* Merge
    * git commit
* Rebase
    * git rebase --continue

## Git & GitHub Beyond the Foundations

## Summary

In this Git and GitHub.com course, we'll cover the full gamut of using Git effectively, including the syntax and the refactored thinking and capabilities that Git brings to the table. The general outline, which adapts to questions, is as follows:

### The Git Mindset

Once the new three stage thinking mindset of Git and DVCSes has been established, the power of Git's staging area and content tracking (not just file tracking) is fully revealed. The workflow changes of when to modify, add and commit files is contrasted to other version control systems. The speed, memory footpring, and other performance characteristics of Git versus Subversion are explored and put into perspective.

### Internals

Git's unique use of hashes as object identifiers and storage of objects in a hash tree on disk is made  through explanation. The treeish and commitish navigation vocabulary is introduced. The concepts behind Git's composed command architecture, similar to that of the Unix/Linux suite of OS-level utilities, are explored and leveraged to produce new shortcut commands called aliases.

### Rebasing

Git takes the idea of merging further with rebasing. Rebasing keeps volatile changes in a branch and guarantees that they will apply cleanly to the mainline when merged.

### Undo

Git provides unique capabilities to undo mistakes or alter previous commits. Leverage reset, revert, amend and clean to make the source code's history as perfect as possible.

### Refspecs

All Git interactions, whether transparently or opaquely, leverage a domain specific language in strings called Refspecs. Knowledge of this language lets you adeptly manipulate the contents of the packs that are sent to and from upstream hosts, and where those received items are stored on disk.

### Notes

You know that Git stores blobs, trees, commits, and tags, but did you know it can also store a parallel stream of notes? These notes can be written and adjusted again and again, categorized by namespace, and even rendered in the GitHub user interface. Notes are supported by automation tools like Jenkins and its Git plugins, and can be a powerful supplement of build results and deployment metadata on to an existing commit history.

### ReReRe

Git provides the power of being able to reset-away a less than plesant merge. But what about all that investment in the merge conflicts that you solved? The rerere option switch and command provides a means of preserving your merge conflict resolutions, even for discarded merges. These can be reused across branches; for example, in the scenario of delivering a common fix to more than one branch.

The `rerere` command (and configuration option) which stands for "reuse recorded resolution" memorizes the two sides of a conflict and can re-use your resolution next time the same conflict is seen.

Merge conflicts are an inevitable thing, but it certainly would be nice if you never had to deal with the same one more than once. What if you rolled back a commit, only later to have to merge it again? It would be fantastic if Git could remember how you resolved it last time. It can, with `rerere` turned on.

Rerere captures the left and right side of a merge conflict and if it sees those same two sides again, it will auto-resolve them, leaving them staged for your review and approval. The intelligence of a rerere data file can be incredible on a large and long-lived code base.

#### Testing Rerere
* Turn on rerere

         git config --global rerere.enabled 1
         #or
         git config --global rerere.enabled true

* Start a merge with a conflict.

        git checkout conflict1
        git merge conflict2
        
        Auto-merging src/Sum.groovy
        CONFLICT (content): Merge conflict in src/Sum.groovy
        Automatic merge failed; fix conflicts and then commit the result.

The merge failed, needing manual intervention. The rerere status and diff will tell us what it is watching for resolution:

        git rerere status
        
        src/Sum.groovy
        
The `git rerere diff` will show the contents of the conflicts known by the rerere cache.
        
        git rerere diff
        
        --- a/src/Sum.groovy
        +++ b/src/Sum.groovy
        @@ -1,7 +1,4 @@
         static int sum(int val1, val2) {
        -<<<<<<<
        -    return (val1 + val2)
        -=======
             val3 = val1 + val2
        ->>>>>>>
        +    return val3
        }

Next, we'll fix the conflict and then commit it.

        # Fix conflict in file
        
        git commit -a -m"Fixed conflict"
        Recorded resolution for 'src/Sum.groovy'.
        [conflict1 c062e45] Fixed conflict

Notice how the rerere indicated it was capturing the merge conflict resolution.

We don't like the merge result, so we'll roll it back.

        git reset --hard HEAD~1

Then try it again with a merge that will redo that merge plus some things:

    git merge conflict2
    Auto-merging src/Sum.groovy
    CONFLICT (content): Merge conflict in src/Sum.groovy
    Resolved 'src/Sum.groovy' using previous resolution.
    Automatic merge failed; fix conflicts and then commit the result.

The results of rerere are explicitly cleaned if the `git rerere gc` command is run. Rerere results are saved for 15 days for unresolved conflicts and for 60 days for resolved conflicts. These expirations can be set through the `gc.rerereunresolved` and `gc.rerereresolved` variables, which are set to integer date counts.

Specific resolutions can be forgotten via the rerere command. A rerere resolution set can be forgotten, but this technique is deprecated.

    git rerere forget
    
    warning: 'git rerere forget' without paths is deprecated

It is more appropriate to forget the rerere of a specific filespec.

    git rerere forget src/Sum.java
    
    Updated preimage for 'src/Sum.groovy'
    Forgot resolution for src/Sum.groovy

#### Rerere Cache Location
The most surprising fact is that the rerere cache is not machine-portable in the sense that it is not transported with `push` or `pull` operations. It saves resolved objects to the `.git/rr-cache` folder.

    .git
       |-- rr-cache
           |-- 810a8080b83381d1db72066593c8f01954be8bc3
           |   |-- preimage
           |-- c437466904eeeebfd1f406c0f7a0179db64382be
               |-- preimage

#### Expiration of Rerere Cache Entries
* Resolved expiration
    * 60 days?
    * Can be configured
* Unresolved expiration
    * 30 days?
    * Can be configured

### External merge and diff tools

Merging and diffing with the command line can be effective. But, when an ocean of < symbols is overwhelming, switch to using Git's integration with any visual diff and merge tool. We'll cover how to configure, invoke, and leverage Open Diff and Araxis and talk about how this can extent to Beyond Compare, VimDiff, P4Merge and other similar tools.

### The Reflog

Git's ability to re-write history may seem scary at first. But once you know that the reflog has a rolling 90 day history of your destructive and creative actions, you'll feel more at ease to use Git's advanced features.

### Interactive Rebase

Interactive rebasing gives you the ability to shape your commit history prior to sharing it with others. Combine commmits, reorder activities, and improve the commit messages with ease.

### Bisect

The bisect feature of Git is a powerful tool that can be used to search for a regression. It is best paired with a strong unit test suite for complete automated execution, but can also be used in support of a manual search for a difficult-to-automatedly-detect problem, such as a subtle shift in an image. We'll explore this feature using a repository that has a latent defect that is easily found using bisect run.

## Workshop Command Line History

    git init project1
    open .
    clear
    git config user.name
    git config --global user.name "Matthew McCullough"
    git config user.email
    git config --global user.email "matthew@github.com"
    head ~/.gitconfig
    cat ~/.gitconfig | more
    git config --global -e
    git clone https://github.com/githubstudent/hellogitworld.git
    cd hellogitworld
    git log
    git config --global color.ui auto
    git branch matthewm-feature1
    gitk --all
    clear
    git checkout matthewm-feature1
    vim matthewm-feature1.txt
    git add matthewm-feature1.txt
    git commit -m"My first feature commit"
    git rev-parse 1f56
    git rev-parse 1f5
    git push -u origin matthewm-feature1
    mate ~/.gitconfig
    gitk --all
    vim matthewm-feature1.txt
    git add matthewm-feature1.txt
    git commit -m"One more change"
    gitk --all
    history
    clear
    git status
    echo STUFF >> matthewm-feature1.txt
    git gui
    git status
    git reset --hard
    git push
    git remote add nicky https://github.com/nickyjaspers/hellogitworld.git
    git fetch nicky
    git branch -a
    git branch -a | more
    echo "Fetch retrieves, but does not merge them"
    git log nicky/nickyjaspers-feature1
    history
    while sleep 2; history | tail -10
    while sleep 2; history | tail -10 | tac
    brew install tac
    sudoi port install tac
    sudo port install tac
    while sleep 2; history | tail -10 ; done
    while sleep 2; history | tail -10 ; done;
    while sleep 2 do history | tail -10 ; done;
    while sleep 2 do history | tail -10 ; done
    while sleep 2; do history | tail -10 ; done
    while sleep 2; clear; do history | tail -10 ; done
    while sleep 2; do clear; history | tail -10 ; done
    echo test
    history
    tail -f ~/.zsh_history
    tail -f ~/.zsh_history| cut 9-
    tail -f ~/.zsh_history| cut -c 9-
    tail -f ~/.zsh_history| cut -c 13-
    tail -f ~/.zsh_history| cut -c 15-
    tail -f ~/.zsh_history| cut -c 16-
    echo test 2
    clear
    git branch
    git status
    git checkout master
    git checkout matthewm-feature1
    git branch 
    echo CHANGE1 >> matthewm-feature1.txt
    git commit -a -m"Change 1"
    echo CHANGE2 >> matthewm-feature1.txt
    git commit -a -m"Change 2"
    git checkout master
    echo MASTERFIX1 >> README.txt
    git commit -a -m"Master fix 1"
    echo MASTERFIX2 >> README.txt
    git commit -a -m"Master fix 2"
    gitk --all
    git checkout matthewm-feature1
    git rebase master
    git log
    gitk --all
    git log -2
    git reset --hard matthewm-feature1~1
    git reflog
    git reset --hard 6c11683
    git checkout master
    git branch -d matthewm-feature1
    git branch -D matthewm-feature1
    git branch matthewm-feature1 6c11683
    git orphank
    git branch -D matthewm-feature1
    git orphank
    git orphanl
    git reflog
    git branch -D matthewm-feature1
    git branch matthewm-feature1 6c11683
    git checkout master
    git checkout matthewm-feature1
    git reflog
    git reset --hard matthewm-feature1~1
    git reset --hard 6c11683
    git reset --hard matthewm-feature1~1
    git reset --hard 6c11683
    git reflog
    git log
    vim .git/refs/heads/handcrafted
    git branch
    git checkout handcrafted
    git reset --soft matthewm-feature1~3
    git status
    git reset --hard
    git checkout matthewm-feature1
    git checkout matthewm-feature1~1:matthew*
    ls
    git checkout matthewm-feature1~1:matthew-feature1.txt
    git checkout matthewm-feature1:matthew-feature1.txt
    git checkout matthewm-feature1:matthewm-feature1.txt
    git checkout master
    git log --stat
    git checkout master~2:README.txt
    git checkout master~2 -- README.txt fix.txt
    git status
    git show master~2:README.txt| mate
    git diff HEAD~1:README.txt HEAD~5:README.txt
    git checkout matthewm-feature1
    git reset --hard
    echo CHANGE >> matthewm-feature1.txt
    git commit -m"Thias sdlkfjs weprouiwer"
    git commit -a -m"Thias sdlkfjs weprouiwer"
    git commit --amend
    git orphank
    clear
    echo file1.txt
    echo HELLO > file1.txt
    echo HELLO > file2.txt
    echo HELLO > file3.txt
    git add file1.txt
    git commit -m"New feature. TADA"
    git status
    git add file2.txt
    git commit -m"New feature. TADA"
    git status
    git add file3.txt
    git commit --amend
    git rebase -i HEAD~2
    clear
    git --version
    git branch some-tyyypo
    git branch -m some-tyyypo some-typo
    git log -2
    echo CHANGE >> matthewm-feature1.txt
    git add .
    git commit -C ce26a9b4e
    clear
    git status
    echo CHANGE >> matthewm-feature1.txt; git commit -a -m"Change"
    git revert 2055790
    git status
    git diff
    vim matthewm-feature1.txt
    git status
    git add .
    git status
    git commit 
    ls
    vim src/Division.groovy
    git commit -a -m"Test method"
    vim src/Division.groovy
    git commit -a -m"Test 2"
    vim src/Division.groovy
    git commit -a -m"Return better"
    git l2
    git revert 31af57b
    git show HEAD
    cat src/Division.groovy
    git revert --no-commit  31af57b
    git reset --hard
    cat .git/config
    git ls-remote
    git ls-remote | more
    git ls-remote https://github.com/githubtrainer/hellogitworld
    git fetch https://github.com/githubtrainer/hellogitworld refs/pull/3/head
    git merge FETCH_HEAD
    git remote add githubtrainer https://github.com/githubtrainer/hellogitworld
    vim .git/config
    git fetch githubtrainer
    gitx
    vim .git/config
    git fetch origin-pulls
    git push origin matthewm-feature1:theothername
    git log -1
    git notes add 
    git log -1
    git push 
    git push -f
    git push origin 'refs/notes/*'
    head -5 .git/config
    head -15 .git/config
    vim .git/config
    git notes add HEAD~1
    git push 
    cd ..
    cp -r hellogitworld hgw2
    cd hgw2
    git pushnotes
    git pushnotes origin
    cd ..
    cd hellogitworld
    git pull
    vim .git/config
    git ls-remote
    vim .git/config
    git pull
    git pull originnotes
    git pushnotes origin
    mate .git/config
    git push 
    git pull
    git push -u origin matthewm-feature1
    git pull
    git help notes
    git config rerere.enabled true
    clear
    git checkout master
    git branch rererepractice
    vim src/Square.groovy
    git commit -a -m"Fix return on master"
    git checkout rererepractice
    vim src/Square.groovy
    git commit -a -m"White space on rerere"
    git branch rererepractice2 master
    git checkout master
    git merge rererepractice
    vim src/Square.groovy
    git commit -m"Solved it"
    git add .
    git commit -m"Solved it"
    git checkout rererepractice2
    git merge rererepractice
    cat src/Square.groovy
    git status
    git add .
    git commit 
    git reset --hard HEAD~1
    git difftool
    git mergetool
    git help difftool
    git log -1
    git merge rererepractice
    git mergetool
    git merge --abort
    git merge rererepractice
    git mergetool
    git mergetool -t myaraxis
    meld
    brew install meld
    sudo port install meld
    cd hellogitworld
    git config thing.otherthing.lastthing value
    cat .git/config
    clear
    git help difftool
    git mergetool -t vimdiff
    git mergetool -t opendiff
    git status
    mate ~/.gitconfig
    git config diff.tool "meld"
    git difftool
    git difftool HEAD~1
    git config diff.tool "opendiff"
    git difftool HEAD~1
    git status
    git reset --hard
    echo NEWFILE > newfile.txt
    git diff
    git add .
    git status
    git diff --staged
    git difftool --staged
    git status
    git reset --hard
    git checkout master
    echo CHANGE >> fix.txt; git add .; git commit -,
    echo CHANGE >> fix.txt; git add .; git commit -m"Step 1"
    echo CHANGE >> README.txt; git add .; git commit -m"Step 2"
    echo CHANGE >> tomonfeaturebranch1.txt; git add .; git commit -m"Step 3"
    echo CHANGE >> build.gradle; git add .; git commit -m"Step 4"
    gitk
    git log --oneline
    git rebase -i 90c96be
    git log --pretty=raw -3
    git reflog
    git reset --hard fd482bd
    git log --oneline
    git reflog
    git reset --hard 819fbf3
    git log --oneline
    git rebase -i 90c96be
    git log --oneline
    git reset --hard 819fbf3
    echo CHANGE5 >> timonthebranchfeature1
    git commit -a -m'fixup! Step 4"
    git commit -a -m'fixup! Step 4'
    git rebase --autosquash -i 90c96be
    git reflog
    git reset --hard 819fbf3
    git commit -a -m'fixup! Step 2'
    echo CHANGE5 >> timonthebranchfeature1
    git commit -a -m'fixup! Step 2'
    git rebase --autosquash -i 90c96be
    git log --oneline
    git rebase -i 5dbe845
    git log --oneline
    git checkout bisect
    git checkout origin/bisect
    git log --oneline
    git bisect start
    git bisect good 9de4cd3
    git bisect bad 245a19a
    tree
    open .
    git bisect good
    git bisect bad
    git bisect reset
    git bisect start
    git bisect good 9de4cd3
    git bisect bad 245a19a
    git bisect run mvn test
    git bisect visualize
    git bisect run for 5 times cd ..mvn test
    cd ..
    svn co https://github.com/revans/bash-it/trunk
    cd trunk
    svn log

## Workshop Chat History

    http://www.emoji-cheat-sheet.com/
    
    https://github.com/githubtrainer/
    
    git config --global color.ui auto
    
    sudo apt-get install gitk
    
    git push -u origin YOURBRANCHNAME
    
    what was the trick to store the password temporarily?
    git config --global credential.helper 'cache -- timeout=300'
    
    Dotfiles
    https://github.com/matthewmccullough/dotfiles

    terminator is a handy console. (sudo apt-get install terminator).
    You can enable color through your ~/.bashrc
    set or uncomment force_color_prompt=yes for colors

    for more dotfile goodness: http://dotfiles.github.com

    Matthew is using a fair number of `git log` shortcuts. You can see what they're doing here:
    https://github.com/matthewmccullough/dotfiles

    git ls-remote https://github.com/githubtrainer/hellogitworld

    http://caiustheory.com/evil-rb
    love the instance_eval hack

    http://developer.github.com
    http://teach.github.com/cheatsheets

    I like the visualization of this one http://ndpsoftware.com/git-cheatsheet.html
    
    Using the GitHub API is a great way to automate some batch activities for Git
    You can "get all the changes of all pull requests for a certain project"
    If you need a GitHub Foundations slide deck, we are
    working on (95% done) with a pure-web copy of the slides:
    
    http://teach.github.com/presentations/git-foundations.html
    http://dotfiles.github.com
    https://github.com/jch/html-pipeline
    https://github.com/vmg/redcarpet
    http://socrates.io/
    
