How did that happen?!
or, Navigating Your Git Repository
Gemma Lynn / @ellotheth
Do I have to care?
Storytime!
Storytime!
ellotheth @ pnwphp $ git show --no-patch
commit 6fbbac497a4f1d63a0b8a1982745b62e11835e30
Author: ellotheth <ellotheth@pnwphp>
Date: Sat Mar 14 22:03:33 2015 -0500
added another lne
Storytime!
Storytime!
Storytime!
ellotheth @ pnwphp $ git commit --amend -m "added another line"
ellotheth @ pnwphp $ git show --no-patch
commit afce570cf7c622660fd679bfbc0bac4447b5d619
Author: ellotheth <ellotheth@pnwphp>
Date: Sun Mar 15 08:24:53 2015 -0500
added another line
Storytime!
ellotheth @ pnwphp $ git push
To origin
! [rejected] main -> main (non-fast-forward)
error: failed to push some refs to 'origin'
hint: Updates were rejected because the tip of your current branch is behind
hint: its remote counterpart. Integrate the remote changes (e.g.
hint: 'git pull ...') before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.
Storytime!
Storytime!
ellotheth @ pnwphp $ git pull
ellotheth @ pnwphp $ git log --oneline --graph --decorate
* c1a184d (HEAD, main) Merge branch 'main' of origin
|\
| * 6fbbac4 (origin/main, origin/HEAD) added another lne
* | afce570 added another line
|/
* 72d4576 Merge branch 'foo'
Let’s talk about Subversion
Centralized access
File-based repository model
Delta commits
Let’s talk about Git
Git is similar...
$ git status
$ git log
$ git diff
$ git add
$ git commit
$ git rm
$ svn status
$ svn log |less
$ svn diff
$ svn add
$ svn commit
$ svn rm
...but not the same
$ git branch
$ git merge
$ git rebase
$ git pull
$ git push
$ svn copy?
$ svn it-hurts-me
$ svn wat?
$ svn sort-of-up-ish
$ svn nope
Distributed access
Graph-based repository model
DSA Detour!
This is a graph.
node
node
node
edge
edge
edge
This is a directed graph.
node
node
node
edge
edge
edge
Edges only go in one direction
This is a directed acyclic graph.
node
node
node
edge
edge
node
edge
edge
Following the edges won’t take you all the way around the graph
This is a Git repository.
a0f56
71c1f
b3fd8
commit
1b88f
commit
commit
commit
Subversion
Git
a0f56
71c1f
b3fd8
commit
1b88f
commit
commit
commit
Snapshot commits
A Git commit is a snapshot of repository content at a given point in time.
a0f56
commit
Snapshot commits
a0f56
b3fd8
commit
itself
where it came from (previous commit)
Snapshot commits
If every commit knows about itself and its parents...
...then you can trace a path from any commit back to the first.
a0f56
b3fd8
first ever!
commit
Snapshot commits
a0f56
71c1f
b3fd8
first commit ever!
1b88f
commit
commit
commit
knows about
knows about
knows about
knows about
Naming the graph
A branch is a dynamic name (reference) for a path through the repository graph
a0f56
71c1f
commit
1b88f
commit
commit
main
foo
Naming the graph
A tag is a static name (reference) for a specific commit
a0f56
71c1f
commit
1b88f
commit
commit
main
foo
v5.3
Naming the graph
a0f56
commit
main
c97ff
commit
v5.3
71c1f
1b88f
commit
commit
foo
Kent Beck nails it again (mostly)
Committing: Adding to the graph
$ git commit
a0f56
commit
main
Committing: Adding to the graph
$ git commit
$ git commit
a0f56
commit
c97ff
commit
main
main
Branching: Defining a new path
$ git branch foo a0f56
a0f56
commit
c97ff
commit
main
foo
Branching: Defining a new path
$ git branch foo a0f56
$ git checkout foo
$ git commit
$ git commit
a0f56
commit
c97ff
commit
main
1b88f
commit
commit
foo
71c1f
foo
Merging: Combining paths
$ git checkout main
$ git merge foo
a0f56
commit
c97ff
commit
main
1b88f
commit
commit
foo
71c1f
31f9c
commit
main
Rebasing: Redefining a path
$ git checkout foo
$ git rebase main
a0f56
commit
c97ff
commit
main
1b88’
commit
commit
foo
71c1’
1b88f
commit
commit
foo
71c1f
Rebasing: Redefining a path
$ git checkout foo
$ git rebase main
a0f56
commit
c97ff
commit
main
1b88’
commit
commit
foo
71c1’
Copies of the original commits, not the same!
Amending: Redefining a path
$ git commit
$ git commit --amend
a0f56
commit
c97ff
commit
main
commit
c97ff’
main
The original is still here!
Wait, where am I?
Navigating the repository
You can checkout any commit
into your working directory.
In other words,
You can visit any node
in the repository graph.
Navigating the repository
a0f56
commit
c97ff
commit
main
1b88f
commit
commit
foo
71c1f
HEAD
Navigating the repository
$ git checkout main
Switch your working directory to main
a0f56
commit
c97ff
commit
main
1b88f
commit
commit
foo
71c1f
HEAD
HEAD
Navigating the repository
$ git reset main
Switch your working directory to main, and bring your current branch along for the ride
a0f56
commit
c97ff
commit
main
1b88f
commit
commit
foo
71c1f
HEAD
HEAD
foo
Navigating the repository
This blue path looks awfully bare...
a0f56
commit
c97ff
commit
main
1b88f
commit
commit
71c1f
HEAD
foo
Navigating the repository
Commits are “reachable” if they have a name, or if they are in the same path as a commit that has a name.
a0f56
commit
c97ff
commit
main
1b88f
commit
commit
71c1f
HEAD
foo
Navigating the repository
Commits are “reachable” if they have a name, or if they are in the same path as a commit that has a name.
a0f56
commit
c97ff
commit
1b88f
commit
commit
71c1f
v5.3
foo
HEAD
main
Navigating the repository
Reachable commits
Unreachable commits
Navigating the repository
Resetting or rebasing or amending a branch will make its old location unreachable...
a0f56
commit
c97ff
commit
main
1b88f
commit
commit
foo
71c1f
HEAD
HEAD
foo
Navigating the repository
...but if you keep track of the SHA, you can get back to it
$ git checkout 1b88f
a0f56
commit
c97ff
commit
main
1b88f
commit
commit
71c1f
HEAD
foo
HEAD
Navigating the repository
Git keeps track of the SHA for you!
$ git reflog
72d4576 HEAD@{0}: checkout: moving from 3cf4a04307ab96f6364fe82baad993bbd7fcaea5 to main
3cf4a04 HEAD@{1}: checkout: moving from foo to HEAD~
181c484 HEAD@{2}: checkout: moving from main to foo
72d4576 HEAD@{3}: commit (merge): Merge branch 'foo'
13945ea HEAD@{4}: checkout: moving from foo to main
181c484 HEAD@{5}: commit: second on foo
Do. Not. Redefine. Shared. Branches.
It’s private until you push it
$ git commit
$ git push
...time passes…
$ git commit --amend
$ git commit
a0f56
commit
c97ff
commit
fred/main
commit
c97ff’
e1f4f
commit
2f811
origin/main
your/main
commit
Things I didn’t talk about
Places with more learning
These awesome slides!