explaining git

ivo anjo

engineer-next-door @ talkdesk

...or (probably) (hopefully) (maybe)
the last presentation on git
you'll ever need!

explaining git

...or (probably) (hopefully) (maybe)
the last presentation on git
you'll ever need!

follow along @
http://tinyurl.com/eye-doctor-here-i-go

You only need to understand one thing to get what git is all about

repository ==

bunch of Directed Acyclic Graphs
of commits

Let's leave that in a background thread for a few slides

What's in a
git commit?

• repository state hash
• parent commit hashes
• commit message
• committer
• commit date
• author
• authoring date
• (extra metadata)

What's a
git commit hash?

sha1(           )

• repository state hash
• parent commit hashes
• commit message
• committer
• commit date
• author
• authoring date
• (extra metadata)

git commits are
*immutable*

You think you're editing commits?

You're not

So I promised we would go back to the DAG thingy

git operations are:

 

• operations on the DAG
• operations that change outside
    pointers to DAG nodes

 

What's a
branch?

Behold the magic .git/refs folder!

~/some-git-repo/.git/refs$ tree
.
├── bisect
├── heads
│   ├── master
│   └── feature-branch
├── remotes
│   ├── origin
│   │   ├── master
│   │   └── feature-branch
│   ├── production
│   │   └── master
│   ├── qa
│   │   └── master
│   └── staging
│       └── master
├── stash
└── tags
~/some-git-repo/.git/refs$ tree
.
├── bisect
├── heads
│   ├── master -> ccc
│   └── feature-branch -> ddd
├── remotes
│   ├── origin
│   │   ├── master -> bbb
│   │   └── feature-branch -> ddd
│   ├── production
│   │   └── master -> aaa
│   ├── qa
│   │   └── master -> aaa
│   └── staging
│       └── master -> aaa
├── stash
└── tags

Just a file containing the commit hash of the tip of the branch

What's "committing to a branch"?

• create new
   commit object

• hash it

• update branch file

Before

.git/refs/heads/master -> bbb

After

.git/refs/heads/master -> ccc

What's "amending a commit"?

A lie

You don't change the existing commit.

You create a new one.

• and then change the ref
file to point to from ccc to ddd

What's editing multiple commits (rebase, etc)?

rebase:
iterate over commit range & try to re-apply changes on top of new repo state

What's a
(*non fast forward)
merge?

Commit with several parents!

What's a fast-forward merge?

just changes the ref file to point to the new commit

What's a tag?

Just another ref

$ git tag bestest-release-ever master
$ ls .git/refs/tags/
bestest-release-ever
$ cat .git/refs/tags/bestest-release-ever 
c50f9ddda562e2777a68976ad7afbf83a72982f8

What's a
git stash push?

Just a commit that gets listed on .git/logs/refs

.git/logs?

Whazzat?

Do you remember I said nothing gets changed?

git keeps a log of all operations!

git reflog

~/ruby/ivo-pry-debugger$ git reflog
11b1e1b HEAD@{0}: commit: Fix missing link in README
0542fa3 HEAD@{1}: rebase -i (finish): returning to refs/heads/master
0542fa3 HEAD@{2}: rebase -i (pick): Bump major version due to breaking changes (ruby compatibility)
537b2fb HEAD@{3}: rebase -i (pick): Drop support for older ruby versions (< 2.2.0)
c817891 HEAD@{4}: rebase -i (pick): Modernize codebase
03677c0 HEAD@{5}: rebase -i (pick): Add missing banners to avoid warnings in Pry code
aa67887 HEAD@{6}: rebase -i (pick): Avoid circular require when being loaded by pry
123da12 HEAD@{7}: rebase -i (fixup): README cleanups and updates
a51fbe7 HEAD@{8}: rebase -i (start): checkout origin/master
ed2e349 HEAD@{9}: rebase -i (finish): returning to refs/heads/master
ed2e349 HEAD@{10}: rebase -i (start): checkout master
ed2e349 HEAD@{11}: commit: fixup
4cf6d29 HEAD@{12}: commit: Bump major version due to breaking changes (ruby compatibility)
f741c04 HEAD@{13}: commit: Drop support for older ruby versions (< 2.2.0)

You never lose anything

(*on your local machine)

If you're low on space, you can ask git to GC and recompress commits

(e.g. remove all commits not referenced in .git/refs or reachable via them)

Back to our regularly scheduled program

What's a push?

• upload commits
• change remote refs file
   to point to your latest
   commit
• execute hooks

That's it
Nothing more

What's a force push?

• upload commits
• change remote refs file
   to point to your latest
   commit
• execute hooks

that is not a child of the previous ref

git push

git push --force

It's **dangerous** because if someone else has pushed, you remove their changes from history

Don't use it

If you really need to
--force-with-lease

Basically only lets you push force if you previously fetched the branch

1. push

2. p --force-with-lease

1. push

2. your awesome colleague pushes

3. push --force-with-lease

It doesn't solve all problems
If you just run git fetch first then...

You've just erased your colleague's work from the repository history

What's
git log?

Just follow the commits from the tip of the branch and print their messages

And finally... Some useful things you may not have heard about

git diff --word-diff

git bisect

• This was working last deploy
• It's not working now

git bisect

• git bisect does a binary search of git commits, and each time you tell it yay or nay

• the final output is the commit which
   broke it
• can also run fully automated (e.g. run
   rspec, watch result)

The git "pickaxe"

git log -S foo

All commits that include the string foo

Great to make sure "Hmm this class seems unused. was its user removed?"

git filter-branch
Aka massive history rewriter
(check the docs! :)

Suggestions?
What's your kick-ass git command?

The End

Now stop asking me for help with git :)

Made with Slides.com