#!/bin/sh

esc=$(printf '\033')
clear
cat << X0
${esc}[31m
           don't git good...   ██               ██   ██
                              ░██              ░░   ░██
        █████  ██████  ██████ ░██  ██    █████  ██ ██████
       ██░░░██░░██░░█ ██░░░░██░██ ██    ██░░░██░██░░░██░
      ░██  ░██ ░██ ░ ░██   ░██░████    ░██  ░██░██  ░██
      ░░██████ ░██   ░██   ░██░██░██   ░░██████░██  ░██
       ░░░░░██░███   ░░██████ ░██░░██   ░░░░░██░██  ░░██
        █████ ░░░     ░░░░░░  ░░  ░░     █████ ░░    ░░
       ░░░░░                            ░░░░░
${esc}[0m
                      ~ whois xero

                        * unix wizard
                        * devops sourcerer
                        * serial minimalist
                        * {h,cr,sl}acker
                        * ascii/ansi artist
                          * x0^67^imp!

                        * http://0w.nz
                        * http://xero.nu
                        * github.com/xero

X0

read -rsp $'' -n1 key

clear
cat << X0







  ${esc}[31m## getting a copy of the slides${esc}[0m


    * this presentation is actually a POSIX shell script
    * it will run on shells like ${esc}[35mbash${esc}[0m, ${esc}[35mdash${esc}[0m, ${esc}[35mzsh${esc}[0m, ${esc}[35mksh${esc}[0m, ${esc}[35mmksh,${esc}[0m etc
    * grab a copy of the script from ${esc}[33mgit.io/gitgrok${esc}[0m
    * or curl pipe it into your shell directly
      * ${esc}[33mcurl git.io/grokgit | sh${esc}[0m
        * if you trust me ;D





X0

read -rsp $'' -n1 key

clear
cat << X0




  ${esc}[31m## git good / git gud${esc}[0m

  * An expression used to heckle inexperienced
    players or newbies in online video games

  * Similar to the use of the phrase ${esc}[33m"lurk more"${esc}[0m
    often used on forums and image boards.


  ${esc}[31m## grok${esc}[0m

  * To fully understand.
    * Connotes intimate and exhaustive knowledge.
  * Coined by American writer Robert A. Heinlein
    * in his 1961 science fiction novel Stranger in a Strange Land.





X0

read -rsp $'' -n1 key

clear
cat << X0



${esc}[38;5;34m       xxx     ${esc}[0m   Git is fundamentally a content-addressable filesystem
${esc}[38;5;34m       xxx     ${esc}[0m   with a VCS UI (version control system user interface)
${esc}[38;5;34m  xxxxxxxxxxxxx${esc}[0m   written on top of it. From the original commandline
${esc}[38;5;34m  xxxxxxxxxxxxx${esc}[0m   interface to GUI applications and even implementations
${esc}[38;5;34m       xxx     ${esc}[0m   built into IDEs, they all build upon Git's core.
${esc}[38;5;34m       xxx     ${esc}[0m
${esc}[0m                  But because Git was initially a toolkit for a VCS
${esc}[38;5;124m  xxxxxxxxxxxxx${esc}[0m   rather than a full user-friendly one, it has a bunch
${esc}[38;5;124m  xxxxxxxxxxxxx${esc}[0m   of verbs that do low-level work that were designed
${esc}[0m                  to be chained together UNIX style {and,or} called from scripts.
${esc}[38;5;242m    xx   xxxxxx${esc}[0m
${esc}[38;5;242m   xx    xx xx ${esc}[0m   These are generally referred to as 'plumbing' commands,
${esc}[38;5;242m  xx     xx  xx${esc}[0m
${esc}[38;5;242m  xx         xx${esc}[0m   the more user-friendly are called 'porcelain' commands.
${esc}[38;5;242m   xx       xx ${esc}[0m
${esc}[38;5;242m    xxx   xxx  ${esc}[0m   let's review some of these verbs...
${esc}[38;5;242m      xxxxx    ${esc}[0m
${esc}[0m



X0
read -rsp $'' -n1 key

clear
cat << X0

${esc}[31m## porcelain${esc}[0m

git-add                 git-rebase              git-cherry
git-am                  git-reset               git-count-objects
git-archive             git-revert              git-difftool
git-bisect              git-rm                  git-fsck
git-branch              git-shortlog            git-get-tar-commit-id
git-bundle              git-show                git-help
git-checkout            git-stash               git-instaweb
git-cherry-pick         git-status              git-merge-tree
git-citool              git-submodule           git-rerere
git-clean               git-tag                 git-rev-parse
git-clone               git-worktree            git-show-branch
git-commit              git-verify-commit       git-blame
git-describe            git-config              git-verify-tag
git-diff                git-fast-export         git-whatchanged
git-fetch               git-fast-import         git-pull
git-format-patch        git-filter-branch       git-archimport
git-gc                  git-mergetool           git-cvsexportcommit
git-grep                git-pack-refs           git-cvsimport
git-gui                 git-prune               git-cvsserver
git-init                git-reflog              git-imap-send
git-log                 git-relink              git-push
git-merge               git-remote              git-quiltimport
git-mv                  git-repack              git-request-pull
git-notes               git-replace             git-send-email
X0

read -rsp $'' -n1 key

clear
cat << X0

${esc}[31m## plumbing${esc}[0m

git-apply               git-for-each-ref        git-receive-pack
git-checkout-index      git-ls-files            git-shell
git-commit-tree         git-ls-remote           git-upload-archive
git-hash-object         git-ls-tree             git-upload-pack
git-index-pack          git-merge-base          git-check-attr
git-merge-file          git-name-rev            git-check-ignore
git-merge-index         git-pack-redundant      git-check-mailmap
git-mktag               git-rev-list            git-check-ref-format
git-mktree              git-show-index          git-column
git-pack-objects        git-show-ref            git-credential
git-prune-packed        git-unpack-file         git-credential-cache
git-read-tree           git-var                 git-credential-store
git-symbolic-ref        git-verify-pack         git-fmt-merge-msg
git-unpack-objects      git-daemon              git-interpret-trailers
git-update-index        git-fetch-pack          git-mailinfo
git-update-ref          git-http-backend        git-mailsplit
git-write-tree          git-send-pack           git-merge-one-file
git-cat-file            git-update-server-info  git-patch-id
git-diff-files          git-http-fetch          git-sh-i18n
git-diff-index          git-http-push           git-sh-setup
git-diff-tree           git-parse-remote        git-stripspace

X0
read -rsp $'' -n1 key

[ -d ./.git ] && rm -rf .git
printf 'x\ngit.md' > .gitignore; git init; rm .git/hooks/*; git add .gitignore; git commit -m 'init'

clear
cat << X0


${esc}[31m#Git internals${esc}[0m

${esc}[31m## Objects${esc}[0m
  * Same content, never duplicated

${esc}[31m## Trees${esc}[0m
  * Points to (hashed) objects by name
  * A root tree object is a snapshot

${esc}[31m## Commits${esc}[0m
  * Explains metadata (who/when/what/why)
  * Points to a tree object
  * Is a pointer, not a delta

${esc}[31m## References${esc}[0m
  * Human alternatives to SHA1 hashes
  * Stored in .git/refs



X0

read -rsp $'' -n1 key

clear

printf "\n\n${esc}[31m## parse an object ${esc}[0m\necho \"test\" | git hash-object -w --stdin\n"
echo "test" | git hash-object -w --stdin | sed "s/^...../${esc}[41m&${esc}[0m/"

printf '\necho "testing testing" | git hash-object -w --stdin\n'
echo "testing testing" | git hash-object -w --stdin | sed "s/^...../${esc}[43m&${esc}[0m/"

printf "\n${esc}[31m## find them${esc}[0m\nfind .git/objects -type f\n\n"
find .git/objects -type f | grep 'objects\/46\|objects\/9d' | sed "s!46/c2e!${esc}[43m&${esc}[0m!;s!9d/aea!${esc}[41m&${esc}[0m!"

printf "\n${esc}[31m## view content${esc}[0m\ngit cat-file -p ${esc}[43m46c2e${esc}[0m\n"
git cat-file -p 46c2e

printf "\n${esc}[31m## view type${esc}[0m\ngit cat-file -t ${esc}[43m46c2e${esc}[0m\n"
git cat-file -t 46c2e
printf "\n\n"

read -rsp $'' -n1 key

clear
cat << X0


${esc}[31m## hash-object - what's happening?${esc}[0m


${esc}[0mcontent  = "test"
${esc}[0mheader   = "blob %d\0", length_of(content)
${esc}[0mstore    = header + content
${esc}[0msha1     = sha1_of(store)
${esc}[0mdir      = ".git/objects/" + sha1[0:2] + "/"
${esc}[0mfilename = sha1[2:]

${esc}[0mwrite(dir + filename, store)
${esc}[31m> saves compressed header + content
${esc}[0m

e.g.

X0

find .git/objects -type f | grep 'objects\/46\|objects\/9d' | sed "s!46/c2e!${esc}[43m&${esc}[0m!;s!9d/aea!${esc}[43m&${esc}[0m!" | tail -1
printf "\n\n\n\n"

read -rsp $'' -n1 key

clear
printf "\n\n${esc}[31m## file example ${esc}[0m\necho \"xero\" > test.txt\ngit hash-object -w test.txt\n"
echo "xero" > test.txt
git hash-object -w test.txt| sed "s/^...../${esc}[43m&${esc}[0m/"

printf "\n\necho \"rulez\" > test.txt\ngit hash-object -w test.txt\n"
echo "rulez" > test.txt
git hash-object -w test.txt | sed "s/^...../${esc}[45m&${esc}[0m/"

printf "\n\n${esc}[31m## display tracked file contents${esc}[0m\ngit cat-file -p ${esc}[43m885e1${esc}[0m\n"
git cat-file -p 885e

printf "\n\n${esc}[31m## display local file contents${esc}[0m\ncat test.txt\n"
cat test.txt
printf "\n\n"

read -rsp $'' -n1 key

clear
printf "\n\n${esc}[31m## tree objects${esc}[0m\n\nmkdir favs; echo \"converge\" > favs/band\ngit update-index --add favs/band\ngit write-tree\n"
[ -d favs ] && rm -rf favs
mkdir favs; echo "converge" > favs/band
git update-index --add favs/band
git write-tree | sed "s/^...../${esc}[43m&${esc}[0m/"

printf "\n\ngit cat-file -p ${esc}[43mcad00${esc}[0m\n"
git cat-file -p cad00| grep -v ".gitignore\|test.txt" | sed "s/71c51/${esc}[45m71c51${esc}[0m/"

printf "\n\ngit cat-file -p ${esc}[45meb41f${esc}[0m\n"
git cat-file -p eb41f
printf "\n\n\n\n\n"

read -rsp $'' -n1 key

clear
printf "\n\n${esc}[31m## commit objects${esc}[0m\necho 'test commit' | git commit-tree ${esc}[45meb41f${esc}[0m\n"
id1=`echo 'test commit' | git commit-tree eb41f`
echo $id1| sed "s/^...../${esc}[43m&${esc}[0m/"

printf "\ngit cat-file -p ${esc}[43m`echo ${id1} | cut -c1-5`${esc}[0m\n"
git cat-file -p ${id1} | sed "s/9e730/${esc}[45m&${esc}[0m/" | sed "s/eb41f/${esc}[45m&${esc}[0m/"

printf "\necho \"leviathan\" > favs/band\ngit update-index --add favs/band; git write-tree\n"
echo "leviathan" > favs/band
git update-index --add favs/band
tree=`git write-tree`
echo $tree | sed "s/^...../${esc}[41m&${esc}[0m/"


printf "\necho 'another commit' | git commit-tree ${esc}[41m9e730${esc}[0m -p ${esc}[43m`echo ${id1} | cut -c1-5`${esc}[0m\n"
id2=`echo 'another commit' | git commit-tree 9e730 -p ${id1}`
echo $id2| sed "s/^...../${esc}[44m&${esc}[0m/"

printf "\ngit cat-file -p ${id2}\n"
git cat-file -p $id2 | sed "s/9e730/${esc}[41m&${esc}[0m/" | sed "s/`echo ${id1} | cut -c1-5`/${esc}[43m&${esc}[0m/"

read -rsp $'' -n1 key

clear
printf "\n\n${esc}[31m## create a branch${esc}[0m\n\necho '$id1' > ./.git/refs/heads/test-branch\n"
echo $id1 > ./.git/refs/heads/test-branch
printf "\n"
git branch
printf "\n\n${esc}[31m## update refs${esc}[0m\n\n"
printf "git update-ref refs/heads/master $id2\n"
git update-ref refs/heads/master $id2
printf "git log --graph\n\n"
git log --graph --color --pretty=format:"%C(yellow)%H%C(green)%d%C(reset)%n%x20%cd%n%x20%cn%C(blue)%x20(%ce)%x20%C(cyan)%C(reset)%n%x20%s%n"
printf "\n"

read -rsp $'' -n1 key

clear
printf "\n\n${esc}[31m## HEAD${esc}[0m\n\n * a reference to the currently checked out commit.\n\ncat ./.git/HEAD\n"
cat ./.git/HEAD

printf "\n\ngit symbolic-ref HEAD refs/heads/test-branch\ncat ./.git/HEAD\n"
git symbolic-ref HEAD refs/heads/test-branch
cat ./.git/HEAD

printf "\n\ngit branch\n"
git branch
printf "\n"

read -rsp $'' -n1 key

clear
printf "\n\n${esc}[31m## HEAD hunting${esc}[0m\n\n"

printf  "git checkout master\n"
git checkout master
printf  "\n\ngit log -1 --pretty=oneline\n"
git log -1 --pretty=oneline
printf  "\n\ngit reset HEAD~1\n"
git reset HEAD~1
printf  "\n\ngit log -1 --pretty=oneline\n"
git log -1 --pretty=oneline
printf  "\n\ngit reset ORIG_HEAD\n"
git reset ORIG_HEAD
printf  "\n\ngit log -1 --pretty=oneline\n"
git log -1 --pretty=oneline
printf "\n"

read -rsp $'' -n1 key
clear

printf "\n\n${esc}[31m## @ hunting${esc}[0m\n\n * @ is an alias for HEAD\n\ngit reflog\n\n"
git reflog

printf "\n\ncheckout your HEAD from 10 mins ago:\ngit checkout \"@{10 minutes ago}\"\n\ncheckout the 5th-last visited commit:\ngit checkout \"@{5}\"\n"

read -rsp $'' -n1 key
clear

cat << X0


${esc}[31m## from plumbing to porcelain${esc}[0m

git diff @
git ls-files -m

git cherry master upstream/master
git rev-parse master..upstream/master

git status
git ls-files --exclude-per-directory=.gitignore --exclude-from=.git/info/exclude --others --modified -t

git commit
git update-index --add && echo "message" | git commit-tree [SHA1] && git write-tree

X0
read -rsp $'' -n1 key
clear

cat << X0


  ${esc}[31m## git reset${esc}[0m

  ${esc}[33mgit reset [<mode>] [<commit>]${esc}[0m

  ${esc}[35m--soft${esc}[0m
    Reset the HEAD back to the first commit, but any other commits that happened since would have 
    their changes staged together in our git 'index' waiting to be committed.

  ${esc}[35m--mixed${esc}[0m
    Reset the HEAD back to the first commit, but any other commits that happened since would have 
    their changes applied to the working directory, ready for us to choose which changes to be added 
    to the index (i.e. staged) and then finally committed.

  ${esc}[35m--hard${esc}[0m
    Any of the changes that came after the commit being reset to, are lost. They're not sitting in 
    your staging index, nor are they available within your working directory either.

  So be careful whenever using the --hard flag.


X0


read -rsp $'' -n1 key
clear

cat << X0


  ${esc}[31m## git merge${esc}[0m


  Incorporates changes from the named commits (since the time their histories diverged from the 
  current branch) into the current branch. This command is used by git pull to incorporate changes 
  from another repository and can be used by hand to merge changes from one branch into another.

  ${esc}[33mgit merge --abort${esc}[0m
  * Abort the current conflict resolution process, and try to reconstruct the pre-merge state.

  ${esc}[33mgit merge --continue${esc}[0m
    * Continue mergeing after resolving merge conflicts

  ${esc}[33mgit merge --squash [ref]${esc}[0m
    * Squash all commits into one before merging


X0


read -rsp $'' -n1 key
clear

cat << X0




  ${esc}[31m## git rebase${esc}[0m

  Reapply all the commit from your branch to the tip of another branch.
  A rebase will sequentially take all the commit from the branch you’re 
  on, and then reapply them to the destination. 

  The golden rule of rebase:
  "No one shall rebase a shared branch" — Everyone

  ${esc}[33mgit rebase --interactive${esc}[0m

  * Make a list of the commits which are about to be rebased and lets the user
    edit that list before rebasing. This mode can also be used to split/squash commits.




X0


read -rsp $'' -n1 key
clear

cat << X0




 ██████████   █████  ██████  █████   █████
░░██░░██░░██ ██░░░██░░██░░█ ██░░░██ ██░░░██
 ░██ ░██ ░██░███████ ░██ ░ ░██  ░██░███████
 ░██ ░██ ░██░██░░░░  ░██   ░░██████░██░░░░
 ███ ░██ ░██░░██████░███    ░░░░░██░░██████
░░░  ░░  ░░  ░░░░░░ ░░░      █████  ░░░░░░
                            ░░░░░
      ██
     ░██
     ░██  █████  ██████████   ██████
  ██████ ██░░░██░░██░░██░░██ ██░░░░██
 ██░░░██░███████ ░██ ░██ ░██░██   ░██
░██  ░██░██░░░░  ░██ ░██ ░██░██   ░██
░░██████░░██████ ███ ░██ ░██░░██████
 ░░░░░░  ░░░░░░ ░░░  ░░  ░░  ░░░░░░



X0

read -rsp $'' -n1 key
clear

cat << X0



## citations

* http://catb.org/jargon/html/G/grok.html
* https://git-scm.com/book/en/v2
* https://www.slideshare.net/th507/git-an-intro-of-plumbing-and-porcelain-commands
* http://www-cs-students.stanford.edu/~blynn/gitmagic/ch07.html#_don_8217_t_lose_your_head
* http://vimcasts.org/episodes/fugitive-vim-resolving-merge-conflicts-with-vimdiff/



X0


read -rsp $'' -n1 key
clear

cat << X0







   ██   ██                                 ██
  ░██  ░██                                ░██
 ██████░██       ██████   ███████  ██   ██░██
░░░██░ ░██████  ░░░░░░██ ░░██░░░██░░██ ██ ░██
  ░██  ░██░░░██  ███████  ░██  ░██ ░░███  ░██
  ░██  ░██  ░██ ██░░░░██  ░██  ░██  ██░██ ░░
  ░░██ ░██  ░██░░████████ ███  ░██ ██ ░░██ ██
   ░░  ░░   ░░  ░░░░░░░░ ░░░   ░░ ░░   ░░ ░░








X0