Slide 1

Slide 1 text

GIT UNLEASHED GIT UNLEASHED ENHANCING YOUR GIT WORKFLOW BY BYPASSING SOME OF ITS ENHANCING YOUR GIT WORKFLOW BY BYPASSING SOME OF ITS VERBOSE SYNTAX AND CUSTOMIZING IT TO DO MORE FOR YOU. VERBOSE SYNTAX AND CUSTOMIZING IT TO DO MORE FOR YOU. Chris Arcand / @chrisarcand www.chrisarcand.com Follow along online at http://slides.com/chrisarcand/git_unleashed/live

Slide 2

Slide 2 text

BEFORE WE BEGIN... BEFORE WE BEGIN... Chris Arcand Software Engineer at Sport Ngin Web applications in Ruby and Node.js for amateur and professional sports organizations

Slide 3

Slide 3 text

Minneapolis, MN Washington, D.C. BEFORE WE BEGIN... BEFORE WE BEGIN...

Slide 4

Slide 4 text

THIS TALK IS ABOUT: THIS TALK IS ABOUT: Enhancing your Git workflow by bypassing some of its verbose syntax and customizing it to do more for you™ THIS TALK IS NOT ABOUT: THIS TALK IS NOT ABOUT: How to use Git in the first place Replacing every Git interaction you can think of with aliases How to do anything in the left column on Windows (Sorry...kinda) BEFORE WE BEGIN... BEFORE WE BEGIN... Just kidding, I'm not.

Slide 5

Slide 5 text

INSPIRED BY "ENHANCED ASS KICKING WITH GIT" BY PATRICK BYRNE INSPIRED BY "ENHANCED ASS KICKING WITH GIT" BY PATRICK BYRNE BEFORE WE BEGIN... BEFORE WE BEGIN... pbyrne @pbyrne http://patrickbyrne.net/presentations/enhanced-ass-kicking-with-git

Slide 6

Slide 6 text

BEFORE WE BEGIN... BEFORE WE BEGIN... Slides are purposely quite verbose to be useful as a stand-alone resource online, not just a talk. Don't sweat the details. Slides available online at www.chrisarcand.com/talks

Slide 7

Slide 7 text

CONFIGURATION AND SETUP CONFIGURATION AND SETUP ALIASES ALIASES ENHANCE YOUR OWN GIT ENHANCE YOUR OWN GIT

Slide 8

Slide 8 text

SAVE YOUR WORK SAVE YOUR WORK ~/.gitconfig ~/.gitignore ~/.zshrc or ~/.bashrc or ~/.profile, etc. As with all of your customized dotfiles, it's a good idea to share them amongst your computers It is highly recommended you keep all of your dotfiles in a Git project - but that's a topic for another day. http://www.github.com/chrisarcand/dotfiles

Slide 9

Slide 9 text

SAVE YOUR FINGERS SAVE YOUR FINGERS You're going to type git a lot throughout the day. Why not make it a little easier? alias g=git NOT JUST GIT, EITHER NOT JUST GIT, EITHER be for bundle exec psg for ps aux | grep nrw for npm run-script watch etc, etc...

Slide 10

Slide 10 text

SAVE YOUR FINGERS SAVE YOUR FINGERS Some very unscientific musings g * vs. git * saves two keystrokes (oh the humanity) From .zsh_history, ~300 git commands on a busy work day = 600 extra keystrokes per day ~260 work days per year = 156,000 extra keystrokes per year 50 words per minute (modest generalization) = 15,000 keystrokes per hour *300 keystrokes might be a bit high for every single workday in a year; 260 days doesn't include vacation; average typing speeds are very​ spread. The point is that it's on the order of hours. = Over 10 hours wasted typing the letters 'i' and 't' in a year

Slide 11

Slide 11 text

CONFIGURATION CONFIGURATION ~/.gitconfig for global settings .git/config for local settings in any Git project WHAT'S THERE NOW? WHAT'S THERE NOW? g config --list to see all of the current settings Add --global to see just the global settings (~/.gitconfig) Add --local to see just the local settings (.git/config) TO CHANGE A CONFIGURATION VALUE TO CHANGE A CONFIGURATION VALUE g config --global foo.bar baz to set foo.bar to baz Or just edit the configuration file directly

Slide 12

Slide 12 text

g help config GOODBYE, AFTERNOON... GOODBYE, AFTERNOON... (Exhaustive documentation on all available configuration options)

Slide 13

Slide 13 text

Colored output (diffs, file status, etc.) color.ui auto Push to upstream branch by default push.default upstream Don't write Windows linefeeds to repo core.autocrlf input Reuse Recorded Resolution rerere.enabled true Autocorrect help.autocorrect 1 Disable repetitive advice messages advice.detachedHead false SOME USEFUL EXAMPLES... SOME USEFUL EXAMPLES... (Windows users, use true instead) (Default pre Git2.0 is matching, pushes all branches) (Many different advice.* options available)

Slide 14

Slide 14 text

SOME USEFUL EXAMPLES... SOME USEFUL EXAMPLES... Use an outside tool for diffs/merges (Example: Filemerge via Xcode) diff.tool opendiff merge.tool opendiff difftool.prompt false mergetool.prompt false Set editor for Git to use (commit messages, etc) core.editor vim (Default is $EDITOR) The list goes on and on... g help config

Slide 15

Slide 15 text

ADD-ONS | ADD-ONS | AUTO COMPLETION AUTO COMPLETION # Install bash-completion brew install bash-completion # Add this to your bash config to load # completion scripts from Homebrew packages [ -f `brew --prefix`/etc/bash_completion ] && . `brew -- prefix`/etc/bash_completion # Lastly, enable completion for # your `g` alias in addition to `git` complete -o default -o nospace -F _git g Note that much of this is usually done for you if you use Z shell (zsh) and plugins like oh-my-zsh

Slide 16

Slide 16 text

Note that much of this is usually done for you if you use other shells/tools like Z shell (zsh) and oh-my-zsh ADD-ONS | ADD-ONS | $PS1 FOR GIT $PS1 FOR GIT # The __git_ps1 function is incredibly useful for customizing $PS1 \w $(rvm-prompt i v 2> /dev/null)\[\e[1m\] $(__git_ps1 2> /dev/null)\[\e[0m\] \n$ # Configurable with environment variables such as: GIT_PS1_SHOWDIRTYSTATE=1 # show * if there are unstaged changes and + if staged # and uncommitted changes. GIT_PS1_SHOWSTASHSTATE=1 # show $ if there are stashed changes. GIT_PS1_SHOWUNTRACKEDFILES=1 # to show % if there are untracked files. GIT_PS1_SHOWUPSTREAM=1 # show < if there are unpulled changes, > if there are # unpushed changes, <> if there are both, or = if everything’s synced.

Slide 17

Slide 17 text

No content

Slide 18

Slide 18 text

CONFIGURATION AND SETUP CONFIGURATION AND SETUP ALIASES ALIASES ENHANCE YOUR OWN GIT ENHANCE YOUR OWN GIT

Slide 19

Slide 19 text

WHAT'S AN ALIAS? (SIMPLISTIC) WHAT'S AN ALIAS? (SIMPLISTIC) “ Shortcuts for Git commands “ Custom Git commands “ Customization to avoid repeating yourself all the time STANDARD ALIASES STANDARD ALIASES s = status br = branch co = checkout cnf = "!git ls-files -u | cut -f 2 | sort -u" stashdrop = "!f() { git stash drop stash@{/$*} -p; }; f" SHELL ALIASES SHELL ALIASES

Slide 20

Slide 20 text

WHAT ARE ALIASES, REALLY? WHAT ARE ALIASES, REALLY? Not just time savers, but unlockers of phenomenal cosmic power

Slide 21

Slide 21 text

Frequent commands Small, 1-2 character shortcuts for basic commands Highly configurable commands Long, verbose commands you'd never type out regularly or remember every option for it Complex functionality not available with Git itself In essence, the addition of the shell to do complex things specific to your workflow The two types of aliases (Standard, Shell) can be broken down further: THE THREE ROLES OF ALIASES THE THREE ROLES OF ALIASES

Slide 22

Slide 22 text

FREQUENT COMMANDS FREQUENT COMMANDS s = status cm = commit br = branch co = checkout df = diff dc = diff --cached ls = ls-files Some of my own... And some I don't use... p = push u = pull tgif = git push --force origin master Why don't I use the commands on the right? Explanation forthcoming.

Slide 23

Slide 23 text

HIGHLY CONFIGURABLE COMMANDS HIGHLY CONFIGURABLE COMMANDS lg = log --color --graph --pretty=format:'%Cred%h%Creset - %C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue) <%an>%Creset' --abbrev-commit Example:

Slide 24

Slide 24 text

g lg

Slide 25

Slide 25 text

g lg

Slide 26

Slide 26 text

details = log -n1 -p --format=fuller HIGHLY CONFIGURABLE COMMANDS HIGHLY CONFIGURABLE COMMANDS Another example:

Slide 27

Slide 27 text

g details

Slide 28

Slide 28 text

COMPLEX FUNCTIONALITY COMPLEX FUNCTIONALITY Combining the shell and other outside tools with Git Can be a trival combination of Git commands... u = "!git add -u && git status" ...or added functionality that Git, by itself, can't provide clear-local-branches = "!git branch | grep -v "master" | xargs git branch -D"

Slide 29

Slide 29 text

More complex examples col = "!select choice in $(git branch | grep -v '*'); do echo checking out $choice; git checkout $choice; break; done"

Slide 30

Slide 30 text

More complex examples aliases = "!git config --list | grep 'alias\\.' | sed 's/alias\\.\\ ([^=]*\\)=\\(.*\\)/\\1\\\t => \\2/' | sort"

Slide 31

Slide 31 text

More complex examples cnf = "!git ls-files -u | cut -f 2 | sort -u" "conflict" = Shows unmerged files in a merge conflict Now when you have a merge conflict, you can easily open all the files that require your attention: $ subl `g cnf` (Example using SublimeText)

Slide 32

Slide 32 text

ZOMG! So many possibilities! We could sit here for hours doing nothing but looking at various individual aliases. ...but we won't.

Slide 33

Slide 33 text

TWO QUESTIONS TWO QUESTIONS Where does it end? AKA: Where do you draw the line with aliases? (This is related to what I asked earlier; the ones I don't use) Copy/pasting aliases off of StackOverflow. Rummaging through people's dotfiles. How mind blowing. How can this really affect how I view my workflow?

Slide 34

Slide 34 text

WHERE DOES IT END? WHERE DOES IT END? Where to draw the line is obviously subjective CONS OF ALIASES CONS OF ALIASES Eventually become so terse they betray almost no meaning (Even the author of the alias can't remember what it all does again) User practically forgets how to use out-of-box Git

Slide 35

Slide 35 text

WHERE DOES IT END? WHERE DOES IT END? Avoid aliasing commands in a way that isn't intuitive from an outside viewpoint g u ? g pu ? = git push, duh! To me, this includes any sort of push action (mostly) Reminder: Once you push, you cannot completely revert something ...without pissing people off You don't need an alias for git diff $(git merge-base master HEAD) HEAD You need to know how to use git diff master... (which is git diff master...HEAD) Use aliases to circumvent Git's complexities, not its simplicities Don't alias extremely important actions

Slide 36

Slide 36 text

HOW DOES THIS AFFECT MY WORKFLOW? HOW DOES THIS AFFECT MY WORKFLOW? Aliases are great for stealing random functionality that didn't know you needed in your workflow Their true power lies in being able to customize Git to do what you need it to do in your own personal workflow BUT ALIASES - ALONG WITH THOUGHTFUL CONFIGURATION - ARE MORE BUT ALIASES - ALONG WITH THOUGHTFUL CONFIGURATION - ARE MORE THAN JUST COPY PASTA THAN JUST COPY PASTA

Slide 37

Slide 37 text

CONFIGURATION AND SETUP CONFIGURATION AND SETUP ALIASES ALIASES ENHANCE YOUR OWN GIT ENHANCE YOUR OWN GIT

Slide 38

Slide 38 text

CUSTOMIZATION EXAMPLE CUSTOMIZATION EXAMPLE On a normal day I... Constantly switch between environments on multiple services Constantly switch between tasks, many times in the middle of working on one.

Slide 39

Slide 39 text

GIT STASH GIT STASH git stash [save] Save your local modifications to a new stash git stash pop [] Remove a single stashed state from the stash list and apply it on top of the current working tree state git stash list List the stashes that you currently have git stash apply [] Like pop, but do not remove the state from the stash list

Slide 40

Slide 40 text

Solves my problem by stashing changes to quickly switch gears and attend to other things. GREAT! GREAT! $ git stash Saved working directory and index state \ "WIP on master: 049d078 added the index file" ​HEAD is now at 049d078 added the index file (To restore them type "git stash apply")

Slide 41

Slide 41 text

BUT... BUT...

Slide 42

Slide 42 text

list uses less; can't reference the list while I'm typing my next command pop/apply uses verbose, annoying reflog syntax git stash apply stash@{2} Indexes by themselves are unintuitive

Slide 43

Slide 43 text

FIRST, A SIMPLE FIX FIRST, A SIMPLE FIX [alias] sls = "!git stash list | cat" ~/workspace/cool_project(branch:master) » g sls stash@{0}: WIP on master: f5b42a9 Updating Changelog for 2014.09.05.14.10 stash@{1}: On master: another something ~/workspace/cool_project(branch:master) » g stash apply stash@{1}

Slide 44

Slide 44 text

GIT STASH BY NAME? GIT STASH BY NAME? You can use reflog syntax with regex: git stash apply stash^{/} Great! sapply = "!f() { git stash apply stash^{/$*}; }; f" sshow = "!f() { git stash show stash^{/$*}; }; f" g sshow sync bug applies stash with example description: stash@{2}: On master: Fix sync bug from yesterday

Slide 45

Slide 45 text

GIT STASH BY NAME? GIT STASH BY NAME? git stash drop requires index. Could fix through tricksy means, but more effort required Not actually that intuitive Useful only for a preset git stash apply, honestly

Slide 46

Slide 46 text

KEEP IT SIMPLE, STUPID KEEP IT SIMPLE, STUPID Keep regex alias as sapplyr for special circumstances and future reference Make indices suck less, because remembering what things are called sucks more

Slide 47

Slide 47 text

sls = "!git stash list | cat" ssave = stash save sclear = "stash clear" sshow = "!f() { if [ -z "$1" ]; then git stash list | cat; printf \"Index to show: \"; read choice; git stash show -p stash@{$choice}; else git stash show -p stash@{$1}; fi; }; f" spop = "!f() { if [ -z "$1" ]; then git stash list | cat; printf \"Index to pop: \"; read choice; git stash pop stash@{$choice}; else git stash pop stash@{$1}; fi; }; f" sapply = "!f() { if [ -z "$1" ]; then git stash list | cat; printf \"Index to apply: \"; read choice; git stash apply stash@{$choice}; else git stash apply stash@{$1}; fi; }; f" sdrop = "!f() { if [ -z "$1" ]; then git stash list | cat; printf \"Index to drop: \"; read choice; git stash drop stash@{$choice}; else git stash drop stash@{$1}; fi; }; f"

Slide 48

Slide 48 text

No content

Slide 49

Slide 49 text

DON'T TAKE MY WORD FOR IT... DON'T TAKE MY WORD FOR IT... Armin Ronacher needed an easier way to include pull requests against the master branch - while using a maintenance branch workflow

Slide 50

Slide 50 text

[aliases] slog = log --pretty=format:"%C(auto,yellow)%h%C(auto)%d\\ %C(auto,reset)%s\\ \\ [%C(auto,blue)%cn%C(auto,reset),\\ %C(auto,cyan)%ar%C(auto,reset)]" addprx = "!f() { b=`git symbolic-ref -q --short HEAD` && \ git fetch origin pull/$1/head:pr/$1 && \ git fetch -f origin pull/$1/merge:PR_MERGE_HEAD && \ git rebase --onto $b PR_MERGE_HEAD^ pr/$1 && \ git branch -D PR_MERGE_HEAD && \ git checkout $b && echo && \ git diff --stat $b..pr/$1 && echo && \ git slog $b..pr/$1; }; f"

Slide 51

Slide 51 text

No content

Slide 52

Slide 52 text

CONFIGURATION AND SETUP CONFIGURATION AND SETUP ALIASES ALIASES ENHANCE YOUR OWN GIT ENHANCE YOUR OWN GIT

Slide 53

Slide 53 text

GIT UNLEASHED GIT UNLEASHED Customize Git to fit your specific needs and do the heavy lifting in your preferred workflow Use aliases to... Make frequent commands faster Make highly configurable commands more accessible Unlock functionality Git doesn't provide by itself Don't let customization/aliases throw off your understanding and Git Fu Constantly reassess what is useful, what isn't, and what new things might make you more efficient. Keep in mind what is actually useful to you in your workflow.

Slide 54

Slide 54 text

QUESTIONS? QUESTIONS? ChrisArcand @chrisarcand www.chrisarcand.com Thanks for listening!