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

    View Slide

  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

    View Slide

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

    View Slide

  4. 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.

    View Slide

  5. 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

    View Slide

  6. 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

    View Slide

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

    View Slide

  8. 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

    View Slide

  9. 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...

    View Slide

  10. 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

    View Slide

  11. 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

    View Slide

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

    View Slide

  13. 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)

    View Slide

  14. 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

    View Slide

  15. 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

    View Slide

  16. 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.

    View Slide

  17. View Slide

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

    View Slide

  19. 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 [email protected]{/$*} -p; }; f"
    SHELL ALIASES
    SHELL ALIASES

    View Slide

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

    View Slide

  21. 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

    View Slide

  22. 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.

    View Slide

  23. 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)
    %Creset' --abbrev-commit
    Example:

    View Slide

  24. g lg

    View Slide

  25. g lg

    View Slide

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

    View Slide

  27. g details

    View Slide

  28. 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"

    View Slide

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

    View Slide

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

    View Slide

  31. 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)

    View Slide

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

    View Slide

  33. 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?

    View Slide

  34. 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

    View Slide

  35. 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

    View Slide

  36. 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

    View Slide

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

    View Slide

  38. 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.

    View Slide

  39. 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

    View Slide

  40. 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")

    View Slide

  41. BUT...
    BUT...

    View Slide

  42. 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 [email protected]{2}
    Indexes by themselves are unintuitive

    View Slide

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

    View Slide

  44. 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:
    [email protected]{2}: On master: Fix sync bug from yesterday

    View Slide

  45. 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

    View Slide

  46. 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

    View Slide

  47. 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 [email protected]{$choice}; else git stash show -p [email protected]{$1}; fi; }; f"
    spop = "!f() { if [ -z "$1" ]; then git stash list | cat; printf \"Index to pop: \"; read choice; git
    stash pop [email protected]{$choice}; else git stash pop [email protected]{$1}; fi; }; f"
    sapply = "!f() { if [ -z "$1" ]; then git stash list | cat; printf \"Index to apply: \"; read choice; git
    stash apply [email protected]{$choice}; else git stash apply [email protected]{$1}; fi; }; f"
    sdrop = "!f() { if [ -z "$1" ]; then git stash list | cat; printf \"Index to drop: \"; read choice; git
    stash drop [email protected]{$choice}; else git stash drop [email protected]{$1}; fi; }; f"

    View Slide

  48. View Slide

  49. 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

    View Slide

  50. [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"

    View Slide

  51. View Slide

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

    View Slide

  53. 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.

    View Slide

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

    View Slide