Your browser doesn't support the features required by impress.js, so you are presented with a simplified version of this presentation.

For the best experience please use the latest Chrome, Safari or Firefox browser.

Common 
Git
Scenarios
Hit esc. at any time for the table of contents.
Warning...
This presentation
is interactive.
(Interpretive dance encouraged but undertaken 
at the dancer's own risk.)
Questions will be asked.
... to provide the answers
Let's test this 
"interactive" thing...
Are you ready?
Hint: say "yes".
What if...
You're in the middle of a task. 
The future's uncertain, and 
you could really use a roll-back 
point.

What do you do?
You could...
Make a interim commit
and hope you remember 
to rebase it later...
or...
Take a snapshot
[alias]
      snapshot = !git stash save "snapshot: $(date)" \
                         && git stash apply "stash@{0}"


git stash save "snapshot: $(date)"
git stash apply "stash@{0}"
Better yet: make it an alias
Something has broken!
You don't know what broke it.
You don't know when it broke.
You don't who to beat
with a trout.
Now what?
git bisect
What does git bisect do?
...provides a guided binary
search across commits within
a specified range. 
git bisect
But...
Which is cool, 
You can automate it.
git bisect start HEAD HEAD~50
git bisect run <the thing to run>
All it has to do is return
a standard status code.
What do you call code
that "tests" other code
to expose failures?
I refuse to
believe 
any of you didn't 
know the answer to that.
Your tests return
status codes...
and... you were gonna write
a test to prevent that bug 
from coming back
anyway right?
git bisect run bundle exec \
rake test TEST=test/unit/some_test.rb
Test written.
Bug found.
There is however,
a "gotcha"...
Any guesses?
Git won't like that you've
modified a file (the test)
when it tries to move
through history.
Any solutions?
#1 temporarily shove it
in a new file.
#2 wrap your test in a shell
script that leverages
the stash.
    #!/bin/sh
    git stash apply stash@{0}
    bundle exec ruby -I"lib:test" test/unit/some_test.rb
    RESPONSE_CODE=$?
    git reset --hard HEAD
    exit RESPONSE_CODE
Something like this:
What else is git bisect
good for?
Finding when something
was removed.
Just grep for the text.
But I don't want everything...
Where would I put it all?
You want to pull code
from some commits in
one branch into another
branch without merging
everything. 
What do you use?
git cherry-pick you say?
However did you guess?
So señor(ita) smarty-pants,
what's the difference 
between a merged commit 
and a cherry-picked one?
Cherry-picked commits
are clones, torn from the pages 
of history.
...and we all know how well 
that worked out.
(psst. It went badly.)
Use them only
when merging
isn't an option.
It's not that they're bad, per se
but they can turn and shoot you 
in the butt from time to time.
How do you indicate that 
you're the one who did 
the cherry-picking?
Use the --signoff option.
How do you indicate 
where the cherry-pick
originated?
git cherry-pick -x <treeish>
-x used to be the default.
This is no longer the case.
Note:
Can you cherry-pick
multiple commits at once?
Oh yes...
git cherry-pick master
git cherry-pick ..master
git cherry-pick ^HEAD master
git cherry-pick maint next ^master
git cherry-pick maint master..next
git cherry-pick master~4 master~2
git cherry-pick -n master~1 next
git cherry-pick --ff ..next
git rev-list --reverse master -- README | \
    git cherry-pick -n --stdin

That last one?
Applies the changes introduced
by all commits on the master
branch that touched README
to the working tree and index,
so the result can be inspected
and made into a single new
commit if suitable.

git rev-list --reverse master -- README | \
    git cherry-pick -n --stdin
Cleaning up after yourself.
It took you a week and fourteen commits
to get that thing done. What strategies
can you employ to make your pull
request clean and easy to understand? 
git pull --rebase
Pulls down everyone
else's changes, and
moves yours on top
of them.
Why is this important?
In the beginning...
But then...
Until finally...
2 months later...
Is Bob's commit something 
feature X depends on, or should
I ignore it?
It could have been so clear:
The more interleaved commits 
there are in a pull request the harder 
it is to find the boundaries of the 
change set.

Make life easier for your reviewer, 
and future archaeologists.
git pull --rebase
is kinda limited
but there is another,
more powerful, option...
What does it do?
Allows you to rewrite history.

Edits commits, reorders 
commits, removes 
commits, edit 
commit messages.
Rewriting history is dangerous,
but Git will complain if you try and push
commits that alter known history.
Would you read a book 
where the author left random
junk sentences in every
other paragraph?
Question:
So why do so many of us 
do this?
Garbage commits pollute the
codebase & hamper understanding.
Unsurprisingly,
there's another way to
                skin this cat.
git merge --squash
What's it do?
...brings in all the commits
from a branch as if they
were one change and
doesn't log it as a merge.
git merge --squash
When should you
use this?
When merging two of
your own topic branches
and don't want to preserve
the history
When should you
not
use this?
When merging anything
written by anyone else,
as it removes credit.
Using words to
convey meaning.
Would you find this
a useful code comment?
"Does something"
How about this
commit message?
"further changes"
What about
"github"?
Maybe
"min or syntax fixes"
"updates"
"code review"
"changes"
"bug fix"
"fix"
Any of these?
(Yes, these are all real ones from our codebase.)
Some get close...
"syntax error fix"
...in?
"view and javascript"
… Are nice things to
have in a webapp?!
"model, migration,
and association"
... are fundamental concepts
when building a Rails app?
What should be in 
a commit message?
A short, descriptive subject line
A blank line
Any additional details
The linux kernel docs 
have this to say:
…the "summary" must be no more than 
70-75 characters, and it must describe 
both what the patch changes, as well as 
why the patch might be necessary.  
It is challenging to be both succinct and 
descriptive, but that is what a well-written 
summary should do.
What's the 50/72 rule?
Try and keep your subject around 
50 characters long.
Always wrap your content at or before 
72 characters.

Originates (probably) from 
Linux kernel commits:
No
fixed bug
Yes
fixed bug in authentication system
More Yes
<ticket num> Fixed bug preventing 
    logins from Harlem
Even More Yes
<ticket num> Enabled Harlemites to 
    log in: (bug is PR nightmare)
Why should I care?
git log doesn't handle wrapping
Because it's not all about you.
It's about us.
Also...
Some things about git log
Side note: this is the most powerful
and underutilized piece of git.
How do I find all the commits 
that mention elephants?
git log --grep elephants
Yes, that's a regexp.
How do you search while
in the git log.
Yes, that's a regexp too.
Slash + search string
/elephants
What common thing will
render these searches
useless?
Crappy commit messages
How do I see all the commits
made 2 days ago?
git log --since=3.days.ago \
    --until=2.day.ago
git log --since="3 days ago" \
    --until="2 days ago"
or
Shouldn't that be?
git log --since=2.days.ago \
    --until=1.day.ago
No.
Don't ask me why.
How do you see who 
did what in a branch
last week?
git shortlog --since=8.days.ago
Can you see that
across all branches?
Not without getting 
your geek on.
Yes, I "[have] my geek on."
Git log can give you 
everything from this...
To this...
Do not underestimate it.
Commit(ish) things.
How do you un-add a file?
git reset HEAD <file>
or
git add -i
or
git checkout HEAD <file>
or...
Better yet, add this alias:
git config --global alias.unadd \
    "reset HEAD"
then 
git unadd <file 1> <file2> <etc…>
How do you add only
part of a file?
git add --patch <file>
or
git add -i
When should you use 
git add .
?
When importing a new 
repo for the first time.

When running from within 
a new subdirectory.
What about all the
other times?
git add -u .
adds all tracked files.
or
git add -A .
adds all tracked files 
including deleted ones.
What if you've professed
your undying love for  
git add .   ?
How do you avoid adding 
temp files and other cruft?
git clean
git clean -e <pattern>
git clean --exclude=<pattern>

Now, what do those do?
git clean removes untracked
and unignored files
from the working tree
How do you make sure 
it doesn't remove too much?
git clean --dry-run
What's the difference?
How do you compare the
working tree and the index?
git diff
How do you compare 
the index to HEAD?
git diff --cached
How do you compare
the working tree and 
the index to HEAD?
git diff HEAD
How do you compare 
two versions of a file?
git diff <treeish 1> <treeish 2> \
    path/to/file
What about 2 consecutive
versions of a file?
git diff <newer treeish>^ \
    <newer treeish> path/to/file
Only need to copy-paste
one treeish.
Credits
This presentation was
put together by masukomi.
The source of these images is a mystery to me.
Seriously. Most of them appear to have been reshared so 
many times that any hope of finding the original author 
is long since gone.
However, if one of them is yours and you'd like it removed,
It's distributed under the CC By 3.0 license.

Use a spacebar or arrow keys to navigate