Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Git Unleashed

Chris Arcand
September 11, 2014

Git Unleashed

Enhancing your Git workflow by bypassing some of its verbose and archaic syntax and customizing it to do more for you.

Chris Arcand

September 11, 2014
Tweet

More Decks by Chris Arcand

Other Decks in Programming

Transcript

  1. 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
  2. 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
  3. 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.
  4. 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
  5. 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
  6. 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
  7. 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...
  8. 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
  9. 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
  10. 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)
  11. 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
  12. 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
  13. 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.
  14. 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
  15. WHAT ARE ALIASES, REALLY? WHAT ARE ALIASES, REALLY? Not just

    time savers, but unlockers of phenomenal cosmic power
  16. 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
  17. 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.
  18. 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:
  19. 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"
  20. More complex examples col = "!select choice in $(git branch

    | grep -v '*'); do echo checking out $choice; git checkout $choice; break; done"
  21. More complex examples aliases = "!git config --list | grep

    'alias\\.' | sed 's/alias\\.\\ ([^=]*\\)=\\(.*\\)/\\1\\\t => \\2/' | sort"
  22. 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)
  23. ZOMG! So many possibilities! We could sit here for hours

    doing nothing but looking at various individual aliases. ...but we won't.
  24. 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?
  25. 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
  26. 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
  27. 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
  28. 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.
  29. GIT STASH GIT STASH git stash [save] Save your local

    modifications to a new stash git stash pop [<stash>] 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 [<stash>] Like pop, but do not remove the state from the stash list
  30. 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")
  31. 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
  32. 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}
  33. GIT STASH BY NAME? GIT STASH BY NAME? You can

    use reflog syntax with regex: git stash apply stash^{/<regex>} 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
  34. 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
  35. 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
  36. 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"
  37. 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
  38. [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"
  39. 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.