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 :)
explaining git
By Ivo Anjo
explaining git
An overview of how git works internally
- 1,558