Slides
Slides
NINA ZAKHARENKO
@NNJA
frontendmasters.com/workshops/git-indepth/
git.io/advanced-git
1
HI
➤ who am I?
➤ @nnja
➤ [email protected]
2
REQUIREMENTS
➤ command line that supports unix style commands
➤ git version > 2.0
➤ github.com account
➤ clone git.io/advanced-git for slides and exercises
➤ (osx only) install homebrew - https://brew.sh/
3
4
WAT?
git-man-page-generator.lokaltog.net
5
PORCELAIN VS. PLUMBING
6
CLASS OVERVIEW - PART 1
➤ What is Git?
➤ Working Area, Staging Area, Repository
➤ Staging Area Deep Dive
➤ References, Commits, Branches
➤ Stashing
7
CLASS OVERVIEW - PART 2
➤ Merging + Rebasing
➤ History + Diffs
➤ Fixing Mistakes
➤ Rebase
➤ Forks, Remote Repositories
8
CLASS OVERVIEW - PART 3
➤ The Danger Zone
➤ Advanced Tools
➤ Customization - Config, Ignore, Hooks, Templates
➤ Social Git: Integrating GitHub with CI Tools
➤ Advanced GitHub: Working with the GitHub API
9
WHY USE
THE COMMAND LINE?
10
WHAT IS GIT?
Distributed Version Control System
11
HOW DOES GIT STORE INFORMATION?
➤ At its core, git is like a key value store.
12
THE KEY - SHA1
➤ Is a cryptographic hash function.
➤ Given a piece of data, it produces a 40-digit hexadecimal
number.
➤ This value should always be the same if the given input is the
same.
13
THE VALUE - BLOB
➤ git stores the compressed data in a blob, along with metadata in
a header:
➤ the identifier blob
14
UNDER THE HOOD - GIT HASH-OBJECT
Asking Git for the SHA1 of contents:
8ab686eafeb1f44702738c8b0f24f2567c36da6d
8ab686eafeb1f44702738c8b0f24f2567c36da6d
It’s a Match! 15
THE VALUE - BLOB
8ab68…
blob 14
\0
Hello World!
16
WHERE DOES GIT STORE ITS DATA?
~/projects/sample
❯ git init
Initialized empty Git repository in /Users/nina/projects/sample/.git/
17
WHERE ARE BLOBS STORED?
❯ echo 'Hello, World!' | git hash-object -w --stdin -w flag means write
8ab686eafeb1f44702738c8b0f24f2567c36da6d
18
WHERE ARE BLOBS STORED?
❯ echo 'Hello, World!' | git hash-object -w --stdin
8ab686eafeb1f44702738c8b0f24f2567c36da6d
19
WHERE ARE BLOBS STORED?
❯ echo 'Hello, World!' | git hash-object -w --stdin
8ab686eafeb1f44702738c8b0f24f2567c36da6d
❯ rm -rf .git/hooks
❯ tree .git
.git
├── HEAD
├── config
├── description
├── info
│ └── exclude
├── objects our blob is stored in objects
│ ├── 8a
│ │ └── b686eafeb1f44702738c8b0f24f2567c36da6d
│ ├── info
the directory starts with the
│ └── pack
first 2 chars of the hash.
└── refs
├── heads
└── tags
20
WE NEED SOMETHING ELSE
The blob is missing information!
➤ filenames
➤ directory structures
21
TREE
a tree contains pointers (using SHA1):
➤ to blobs
➤ to other trees
and metadata:
➤ type of pointer (blob or tree)
➤ filename or directory name
➤ mode (executable file, symbolic link, …)
22
TREE
4ad20…
.
├── copies tree <size>
│ └── hello-copy.txt
└── hello.txt \0
23
TREES POINT TO BLOBS & TREES
tree
blob blob
24
IDENTICAL CONTENT IS ONLY STORED ONCE!
Directory structure: root directory
.
├── copies tree size
│ └── hello-copy.txt
└── hello.txt
hello.txt blob 8ab68 hello.txt
1 directory, 2 files
tree a14ca copies
blob 14
copies/ directory
Hello World!
\n tree size
8ab68…
blob 8ab68 hello-copy.txt
hello-copy.txt
25
OTHER OPTIMIZATIONS - PACKFILES, DELTAS
➤ Git objects are compressed
➤ As files change, their contents remain mostly similar.
➤ Git optimizes for this by compressing these files together, into
a Packfile
➤ The Packfile stores the object, and “deltas”, or the differences
between one version of the file and the next.
26
COMMITS
27
COMMIT OBJECT
a commit points to:
➤ a tree
and contains metadata:
➤ author and committer
➤ date
➤ message
➤ parent commit (one or more)
28
COMMIT
fae12…
commit size
tree 8ab68
parent a14ca
author Nina
29
COMMITS POINT TO PARENT COMMITS AND TREES
Tree
“Snapshot of
ab29d the repository”.
Points at files
and directories.
fae12
Parent commit
30
A COMMIT IS A
CODE SNAPSHOT
31
COMMITS UNDER THE HOOD - MAKE A COMMIT
❯ echo 'Hello World!' > hello.txt
32
COMMITS UNDER THE HOOD - LOOK IN .GIT/OBJECTS
❯ tree .git/objects
.git/objects
├── 58
│ └── 1caa0fe56cf01dc028cc0b089d364993e046b6
├── 98
│ └── 0a0d5f19a64b4b30a87d4206aade58726b60e3
├── ad
│ └── f0e13658d9b4424efe03c3ac3281facf288c13
├── info
└── pack
33
COMMITS UNDER THE HOOD - LOOKING AT OBJECTS
❯ cat .git/objects/98/0a0d5f19a64b4b30a87d4206aade58726b60e3
xKOR04fH/IQHak%
oops!
remember, git objects are compressed.
34
GIT CAT-FILE -T (TYPE) AND -P (PRINT THE CONTENTS)
❯ git cat-file -t 980a0 -t
print the type
blob
35
GIT CAT-FILE -T (TYPE) AND -P (PRINT THE CONTENTS)
❯ git cat-file -t 581caa
tree
36
GIT CAT-FILE -T (TYPE) AND -P (PRINT THE CONTENTS)
❯ git cat-file -t adf0e1
commit
Initial commit
37
WHY CAN’T WE “CHANGE” COMMITS?
➤ If you change any data about the commit, the commit will have
a new SHA1 hash.
➤ Even if the files don’t change, the created date will.
38
REFERENCES - POINTERS TO COMMITS
➤ Tags
➤ Branches
➤ HEAD - a pointer to the current commit
ab29d
fae12
39
REFERENCES - UNDER THE HOOD
❯ tree .git
.git
├── HEAD
└── refs
├── heads
│ └── master refs/heads is where branches live
└── tags
40
REFERENCES - UNDER THE HOOD
❯ tree .git
.git
├── HEAD
└── refs
├── heads
│ └── master
└── tags
❯ cat .git/refs/heads/master
adf0e13658d9b4424efe03c3ac3281facf288c13
41
REFERENCES - UNDER THE HOOD
❯ tree .git
.git
├── HEAD
└── refs
├── heads
│ └── master
└── tags
❯ cat .git/refs/heads/master
adf0e13658d9b4424efe03c3ac3281facf288c13
❯ cat .git/HEAD
HEAD is usually a pointer to the current branch
ref: refs/heads/master
42
EXERCISE
1. Configure your editor
➤ git.io/config-editor
2. Complete exercise
➤ https://github.com/nnja/advanced-git/blob/master/
exercises/Exercise1-SimpleCommit.md
3. Check out cheat sheet for using less
➤ git.io/use-less
43
THREE AREAS WHERE
CODE LIVES
1. Working Area
2. Staging Area
3. Repository
44
THE WORKING AREA
➤ The files in your working area that are also not in the staging are
are not handled by git.
➤ Also called untracked files
45
THE STAGING AREA (A.K.A INDEX, CACHE)
➤ What files are going to be part of the next commit
➤ The staging area is how git knows what will change between
the current commit and the next commit.
46
THE REPOSITORY
➤ The files git knows about!
➤ Contains all of your commits
47
CLOSER LOOK:
THE STAGING AREA
48
THE STAGING AREA
➤ The staging area is how git knows what will change between
the current commit and the next commit.
❯ git ls-files -s
100644 b8b2583b242add97d513d8d8b85a46b9b5fb29cb 0 index.txt
100644 ed52afd72f64b1f8575e81bb4cb02ef1215739f6 0 posts/
welcome.txt
The plumbing command ls-files -s will show you
what’s in the staging area.
49
MOVING FILES IN & OUT OF THE STAGING AREA
➤ add a file to the next commit:
➤ git add <file>
50
GIT ADD -P
➤ one of my favorite tools
➤ allows you to stage commits in hunks
➤ interactively!
➤ It’s especially useful if you’ve done too much work for one
commit.
51
USING GIT ADD -P
❯ git add -p
.
.
.
diff displayed
.
.
.
52
“UNSTAGE” FILES FROM THE STAGING AREA
➤ Not removing the files.
➤ You’re replacing them with a copy that’s currently in the
repository.
53
BASICS: HOW CONTENT MOVES IN GIT
54
STASHING
55
GIT STASH
➤ Save un-committed work.
➤ The stash is safe from destructive operations.
56
GIT STASH - BASIC USE
➤ stash changes
➤ git stash
➤ list changes
➤ git stash list
➤ show the contents
➤ git stash show stash@{0}
➤ apply the last stash
➤ git stash apply
➤ apply a specific stash
➤ git stash apply stash@{0}
57
ADVANCED STASHING - KEEPING FILES
➤ Keep untracked files
➤ git stash --include-untracked
➤ Keep all files (even ignored ones!)
➤ git stash --all
58
ADVANCED STASHING - OPERATIONS
➤ Name stashes for easy reference
➤ git stash save "WIP: making progress on foo"
59
ADVANCED STASHING - CLEANING THE STASH
➤ Remove the last stash and applying changes:
➤ git stash pop
➤ tip: doesn’t remove if there’s a merge conflict
➤ Remove the last stash
➤ git stash drop
➤ Remove the nth stash
➤ git stash drop stash@{n}
➤ Remove all stashes
➤ git stash clear
60
EXAMINING STASH CONTENTS - GIT SHOW
❯ git stash list
stash@{0}: WIP on master: 9703ef3 example
stash@{1}: WIP on example3: 0be5e31 hello
stash@{2}: WIP on example3: 0be5e31 a commit
goodbye.txt | 1 +
hello.txt | 2 +-
2 files changed, 2 insertions(+), 1 deletion(-)
61
GIT STASH - WHAT I USE
➤ Keep untracked files
➤ git stash --include-untracked
62
EXERCISE
➤ https://github.com/nnja/advanced-git/blob/master/exercises/
Exercise2-StagingAndStashing.md
63
REFERENCES
(pointers to commits)
64
THREE TYPES OF GIT REFERENCES
➤ Tags & Annotated Tags
➤ Branches
➤ HEAD
65
WHAT’S A BRANCH?
➤ A branch is just a pointer to a particular commit.
➤ The pointer of the current branch changes as new commits are
made.
66
WHAT IS HEAD?
➤ HEAD is how git knows what branch you’re currently on, and
what the next parent will be.
➤ It’s a pointer.
➤ It usually points at the name of the current branch.
➤ But, it can point at a commit too (detached HEAD).
➤ It moves when:
➤ You make a commit in the currently active branch
➤ When you checkout a new branch
67
HEAD
❯ git checkout master
❯ cat .git/HEAD
ref: refs/heads/master
❯ cat .git/HEAD
ref: refs/heads/feature
68
SAMPLE REPO - A SIMPLE BLOG
➤ We’re working on a simple blog.
➤ index.txt contains links to our entries, and post titles
➤ the posts/ directory contains our blog entries.
❯ mkdir posts
69
CURRENT REPO STATE
❯ git init
❯ git add .
70
CURRENT REPO STATE
❯ git checkout -b tech_posts
Switched to a new branch 'tech_posts'
71
CURRENT REPO STATE
❯ git add posts/python.txt
❯ git commit -m "New blog post about python"
[tech_posts 2b0b3f2] New blog post about python
1 file changed, 0 insertions(+), 0 deletions(-)
create mode 100644 posts/python.txt
72
LIGHTWEIGHT TAGS
➤ Lightweight tags are just a simple pointer to a commit.
➤ When you create a tag with no arguments, it captures the value
in HEAD
73
ANNOTATED TAGS: GIT TAG -A
➤ Point to a commit, but store additional information.
➤ Author, message, date.
❯ git tag
my-first-commit
v1.0
74
WORKING WITH TAGS
➤ List all the tags in a repo
➤ git tag
➤ List all tags, and what commit they’re pointing to
➤ git show-ref --tags
➤ List all the tags pointing at a commit
➤ git tag --points-at <commit>
➤ Looking at the tag, or tagged contents:
➤ git show <tag-name>
75
TAGS & BRANCHES
➤ Branch
➤ The current branch pointer moves with every commit to the
repository
➤ Tag
➤ The commit that a tag points doesn’t change.
➤ It’s a snapshot!
76
HEAD-LESS / DETACHED HEAD
➤ Sometimes you need to checkout a specific commit (or tag)
instead of a branch.
➤ git moves the HEAD pointer to that commit
➤ as soon as you checkout a different branch or commit, the value
of HEAD will point to the new SHA
➤ There is no reference pointing to the commits you made in a
detached state.
77
HEAD-LESS / DETACHED HEAD
❯ git checkout cd0b57
Note: checking out 'cd0b57'.
78
HEAD-LESS / DETACHED HEAD
❯ git checkout cd0b57
Note: checking out 'cd0b57'.
79
HEAD-LESS / DETACHED HEAD
Save your work:
➤ Create a new branch that points to the last commit you made
in a detached state.
➤ git branch <new-branch-name> <commit>
➤ Why the last commit?
➤ Because the other commits point to their parents.
80
DANGLING COMMITS
Discard your work:
➤ If you don’t point a new branch at those commits, they will
no longer be referenced in git. (dangling commits)
➤ Eventually, they will be garbage collected.
81
EXERCISE
➤ https://github.com/nnja/advanced-git/blob/master/exercises/
Exercise3-References.md
82
MERGING
83
UNDER THE HOOD - MERGE COMMITS ARE JUST COMMITS
❯ git cat-file -p 649efc8c9
tree 8c90eb0e4af7e0b05f736c933dc55e14e45031f2
parent 14176d1d63b6a85308fd61a9a20c8aeed398043b
parent 1ea4e219580910921dce70e96e5da96f12f5066b
author Kenneth Reitz <[email protected]> 1499378257 -0400
committer Kenneth Reitz <[email protected]> 1499378257 -0400
84
FAST FORWARD
❯ git checkout master
❯ git merge feature
Updating 2733233..9703930
Fast-forward
index.txt | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
85
GIT MERGE --NO-FF (NO FAST FORWARD)
➤ To retain the history of a merge commit, even if there are no
changes to the base branch:
➤ use git merge --no-ff
➤ This will force a merge commit, even when one isn’t necessary.
86
MERGE CONFLICTS
➤ Attempt to merge, but files have diverged.
➤ Git stops until the conflicts are resolved.
87
GIT RERERE - REUSE RECORDED RESOLUTION
➤ git saves how you resolved a conflict
➤ next conflict: reuse the same resolution
➤ useful for:
➤ long lived feature branch (like a refactor)
➤ rebasing
88
GIT RERERE - REUSE RECORDED RESOLUTION
Turn it on:
➤ git config rerere.enabled true
➤ use --global flag to enable for all projects
91
HISTORY & DIFFS
92
BAD COMMIT MESSAGES
93
GOOD COMMITS ARE IMPORTANT
➤ Good commits help preserve the history of a code base.
➤ They help with:
➤ debugging & troubleshooting
➤ creating release notes
➤ code reviews
➤ rolling back
➤ associating the code with an issue or ticket
94
A GOOD COMMIT MESSAGE
Commit message is in future tense. ‘Fix’ vs ‘Fixed’
95
ANATOMY OF A GOOD COMMIT
➤ Good commit message
➤ Encapsulates one logical idea
➤ Doesn’t introduce breaking changes
➤ i.e. tests pass
96
GIT LOG
➤ git log - the basic command that shows you the history of your
repository
❯ git log
commit 25b3810089709394636412adf3d887cb55cb47eb (HEAD -> test)
Author: Nina Zakharenko <[email protected]>
Date: Wed Sep 27 22:46:38 2017 -0700
Initial commit
97
GIT LOG --SINCE
➤ The site is slow. What changed since yesterday?
➤ git log --since="yesterday"
➤ git log --since="2 weeks ago"
98
GIT LOG --FOLLOW
➤ Log files that have been moved or renamed
➤ git log --name-status --follow -- <file>
99
GIT LOG --GREP
➤ Search for commit messages that match a regular expression:
➤ git log —grep <regexp>
➤ Can be mixed & matched with other git flags.
➤ Example:
❯ git log --grep=mail --author=nina --since=2.weeks
100
GIT LOG DIFF-FILTER
➤ Selectively include or exclude files that have been:
➤ (A)dded, (D)eleted, (M)odified & more…
❯ git log --diff-filter=R --stat
➤ ~ or ~n
➤ no args: == ~1: the first commit back, following 1st parent
➤ n: number of commits back, following only 1st parent
102
REFERENCING COMMITS
* Both commit nodes B and C are parents of commit node A.
Parent commits are ordered left-to-right.
* A is the latest commit.
A = = A^0
B = A^ = A^1 = A~1
C = A^2
D = A^^ = A^1^1 = A~2
E = B^2 = A^^2
F = B^3 = A^^3 = A^2^1
104
DIFF
➤ Diff shows you changes:
➤ between commits
➤ between the staging area and the repository
➤ what’s in the working area
➤ unstaged changes
➤ git diff
➤ staged changes
➤ git diff --staged
105
DIFF COMMITS AND BRANCHES
106
“DIFF” BRANCHES
➤ Which branches are merged with master, and can be cleaned
up?
➤ git branch --merged master
107
EXERCISE
➤ https://github.com/nnja/advanced-git/blob/master/exercises/
Exercise5-HistoryAndDiffs.md
108
FIXING MISTAKES
checkout
reset
revert
clean
109
GIT CHECKOUT
➤ Restore working tree files or switch branches
110
WHAT HAPPENS WHEN YOU GIT CHECKOUT A BRANCH?
1. Change HEAD to point to the new branch
2. Copy the commit snapshot to the staging area
3. Update the working area with the branch contents
111
WHAT HAPPENS WHEN YOU GIT CHECKOUT - - FILE?
Replace the working area copy with the version from the current
staging area
Warning:
This operation overwrites
files in the working directory without warning!
112
GIT CHECKOUT: OVERWRITE FILES WITH STAGING AREA COPY
➤ Overwrite the working area file with the staging area version
from the last commit
➤ git checkout -- <file_path>
Warning:
This operation overwrites
files in the working directory without warning!
113
WHAT HAPPENS WHEN YOU GIT CHECKOUT <COMMIT> - - FILE?
1. Update the staging area to match the commit
2. Update the working area to match the staging area.
Warning:
This operation overwrites
files in the staging area and working directory without warning!
114
GIT CHECKOUT: FROM A SPECIFIC COMMIT
➤ Checkout a file from a specific commit
➤ copies to both working area & staging area
➤ git checkout <commit> -- <file_path>
Warning:
This operation will overwrite
files in the working directory and staging area with no warning!
115
GIT CLEAN
➤ Git clean will clear your working area by deleting untracked
files.
Warning: this operation cannot be undone!
116
GIT CLEAN
❯ git clean --dry-run
Would remove a-note.txt
❯ git clean -d -f
Removing a-note.txt
Removing scratch/
❯ git status
nothing to commit, working tree clean
117
GIT RESET
➤ Reset is another command that performs different actions
depending on the arguments.
➤ with a path
➤ without a path
➤ By default, git performs a git reset —mixed
➤ For commits:
➤ Moves the HEAD pointer, optionally modifies files
➤ For file paths:
➤ Does not move the HEAD pointer, modifies files
118
RESET --SOFT: MOVE HEAD
❯ git reset --soft HEAD~
119
RESET --SOFT: RESULT
120
RESET --MIXED: MOVE HEAD, COPY FILES TO STAGE
❯ git reset HEAD~
❯ git reset --mixed HEAD~
121
RESET --MIXED: RESULT
122
RESET --HARD: MOVE HEAD, COPY FILES TO STAGE & WORKING
Warning: this overwrites files
❯ git reset --hard HEAD~ and cannot be undone!
123
Warning: this overwrites files
RESET --HARD: RESULT and cannot be undone!
124
GIT RESET <COMMIT> CHEAT CHEAT
1. Move HEAD and current branch
2. Reset the staging area
3. Reset the working area
--soft = (1)
--mixed =(1) & (2) (default)
--hard = (1) & (2) & (3)
125
DANGER: GIT RESET CAN CHANGE HISTORY!
❯ git reset --soft HEAD~
❯ git commit -m “new commit”
126
GIT RESET -- <FILE>
❯ git reset <file>
127
GIT RESET -- <FILE>: RESULT
128
GIT RESET <COMMIT> -- <FILE>
❯ git reset <commit> -- <file>
129
GIT RESET <COMMIT> -- <FILE>: RESULT
130
GIT RESET <COMMIT> -- <FILE> CHEAT CHEAT
1. Move HEAD and current branch
2. Reset the staging area
3. Reset the working area
131
UNDO A GIT RESET WITH ORIG_HEAD
➤ In case of an accidental git reset -
➤ Git keeps the previous value of HEAD in variable called
ORIG_HEAD
➤ To go back to the way things were:
➤ git reset ORIG_HEAD
132
GIT REVERT - THE “SAFE” RESET
➤ Git revert creates a new commit that introduces the opposite
changes from the specified commit.
➤ The original commit stays in the repository.
➤ Tip:
➤ Use revert if you’re undoing a commit that has already been
shared.
➤ Revert does not change history.
133
GIT REVERT - PICK A COMMIT TO UNDO
❯ git log --oneline
2b0b3f2 (HEAD -> tech_posts) New blog post about python
cd0b57c (tag: v1.0, tag: my-first-commit, master) Initial commit
134
GIT REVERT - THE “SAFE” RESET
❯ git revert 2b0b3f2
[tech_posts a08a108] Revert "New blog post about python"
1 file changed, 0 insertions(+), 0 deletions(-)
delete mode 100644 posts/python.txt
135
SUMMARY: COMMON WAYS OF UNDOING CHANGES
➤ checkout
➤ reset
➤ revert
136
EXERCISE
➤ https://github.com/nnja/advanced-git/blob/master/exercises/
Exercise6-FixingMistakes.md
137
REBASE, AMEND
Rewrite history!
138
AMEND A COMMIT
➤ Amend is a quick and easy shortcut that lets you make changes
to the previous commit.
❯ cat index.txt
welcome.txt Welcome to my blog
python.txt Why python is my favorite language
140
BEFORE AFTER
➤ We can pull in all the latest changes from master, and apply our
commits on top of them by changing the parent commit of our
commits.
142
REBASE: REWINDING HEAD
❯ git checkout tech_posts
Switched to branch ‘tech_posts'
❯ git rebase master
First, rewinding head to replay your work on top of it...
Applying: Add a blog post about Python
143
REBASE: APPLY NEW COMMITS
❯ git rebase master
First, rewinding head to replay your work on top of it...
Applying: Add a blog post about Python (commit 4080a)
144
MERGE VS REBASE
scenario: on tech_posts branch
146
INTERACTIVE REBASE (REBASE -I OR REBASE --INTERACTIVE)
➤ Interactive rebase opens an editor with a list of “todos”
➤ in the format of: <command> <commit> <commit msg>
147
REBASE OPTIONS
• pick
• keep this commit
• reword
• keep the commit, just change the message
• edit
• keep the commit, but stop to edit more than the message
• squash
• combine this commit with the previous one. stop to edit the
message
• fixup
• combine this commit with the previous one. keep the previous
commit message
• exec
• run the command on this line after picking the previous commit
• drop
• remove the commit (tip: if you remove this line, the commit
will be dropped too!)
148
EXAMPLE REBASE
❯ git log --oneline
a37be8d (HEAD -> tech_posts) Oops, I forgot an index entry for my new post
6857c3d posts/django-framework.txt
2733233 Add a blog post about Python
149
TIP: USE REBASE TO SPLIT COMMITS
Editing a commit can also split it up into multiple commits!
1. Start an interactive rebase with rebase -i
150
TIP: “AMEND” ANY COMMIT WITH FIXUP & AUTOSQUASH!
What if we want to amend an arbitrary commit?
4. git will generate the right todos for you! just save and quit.
151
FIXUP & AUTOSQUASH EXAMPLE
❯ git log --oneline
9413427 (HEAD -> tech_posts) Add a new blog post explaining the pros and cons
of django
2733233 (master) Add a blog post about Python
25b3810 Add a README file to the project
cd0b57c (tag: v1.0, tag: my-first-commit) Initial commit
use the -i and --autosquash flags use ref of the parent commit
git will automatically reorder commits, and mark the commit with
fixup action
➤ When used as a flag, the command specified by exec will run after
every commit is applied.
➤ This can be used to run tests.
➤ The rebase will stop if the command fails, giving you a chance to
fix what’s wrong.
154
PULL THE RIP CORD!
➤ At any time before rebase is done, if things are going wrong:
➤ git rebase --abort
155
REBASE PRO TIP
➤ Before you rebase / fixup / squash / reorder:
➤ Make a copy of your current branch:
➤ git branch my_branch_backup
➤ git branch will make a new branch, without switching to it
156
REBASE ADVANTAGES
➤ Rebase is incredibly powerful!
➤ You can slice and dice your git history.
➤ It’s easy to fix previous mistakes in code.
➤ You can keep your git history neat and clean.
157
COMMIT EARLY & OFTEN VS GOOD COMMITS
➤ Git Best Practice:
➤ “commit often, perfect later, publish once”
158
WARNING: NEVER REWRITE PUBLIC HISTORY!
➤ Rebase commits are copies
➤ If other people are working on the same repository they would
be working on different commits.
➤ You could cause massive merge conflicts
➤ Even worse, you can cause people to lose their work!
159
EXERCISE
➤ https://github.com/nnja/advanced-git/blob/master/exercises/
Exercise7-RebaseAndAmend.md
160
FORKS, REMOTE REPOS
161
DISTRIBUTED VERSION CONTROL
Centralized Distributed
162
GITHUB VS GIT - THE KEY IS COLLABORATION
➤ Git:
➤ Open source version control software
➤ Github:
➤ Repository hosting
➤ Browse code
➤ Issues
➤ Pull Requests
➤ Forks
163
REMOTES
➤ A remote is a git repository stored elsewhere - on the web, in
github, etc.
➤ origin is the default name git gives to the server you cloned
from.
164
CLONE REPOSITORY git clone [email protected]:lisa/projA.git
Remote Repository
Local Repository
165
VIEWING REMOTES
❯ git remote -v
origin [email protected]:lisa/projA.git (fetch)
origin [email protected]:lisa/projA.git (push)
166
CLONED SOMEONE ELSE’S REPOSITORY
git clone [email protected]:dan/projB.git
167
FORK
➤ A fork is a copy of a repository that’s stored in your GitHub
account.
➤ You can clone your fork to your local computer.
168
MERGING CHANGES TO ORIGINAL PROJECT FROM A FORK
169
STAYING UP TO DATE
➤ While you work on your fork, other changes are getting merged
into the source repository.
170
UPSTREAM
➤ The upstream repository is the base repository you created a
fork from.
➤ This isn’t set up by default, you need to set it up manually.
➤ By adding an upstream remote, you can pull down changes that
have been added to the original repository after you forked it.
171
TRIANGULAR WORKFLOW
172
TRACKING BRANCHES
➤ Track a branch to tie it to an upstream branch.
➤ Bonus: Use git push / pull with no arguments
173
TRACKING BRANCHES
❯ git branch
* master
❯ git fetch
174
FETCH
➤ Git fetch is important for keeping your local repository up to
date with a remote.
➤ It pulls down all the changes that happened on the server
➤ But, it doesn’t change your local repository!
175
PULL
➤ Pulling will pull down the changes from the remote repository
to your local repository, and merging them with a local branch.
176
PUSH
➤ Pushing sends your changes to the remote repository
➤ git only allows you to push if your changes won’t cause a
conflict
➤ Tip:
➤ To see commits which haven’t been pushed upstream yet,
use:
➤ git cherry -v
177
GIT PULL —REBASE
➤ Git pull —rebase will fetch, update your local branch to copy
the upstream branch, then replay any commits you made via
rebase.
➤ Bonus: When you open a PR, there will be no unsightly merge
commits!
178
GIT PULL VS GIT PULL —REBASE
179
NOTE: TAGS
➤ Git doesn’t automatically push local tags to a remote
repository.
➤ To push tags:
➤ git push <tagname>
➤ git push --tags
180
CONTRIBUTING TO OPEN SOURCE PROJECTS - PULL REQUESTS
➤ Before opening a PR:
➤ Keep commit history clean and neat. Rebase if needed.
➤ Run projects tests on your code
➤ Pull in Upstream changes (preferably via rebase to avoid merge
commits)
➤ check for a CONTRIBUTING (.md/.txt) in the project root
182
PUSHING/MERGING YOUR CHANGES BACK TO A REMOTE
➤ Rule of thumb:
➤ Rebase commits on your local feature branch
➤ Merge feature branches back to origin (or upstream)
183
EXERCISE
➤ https://github.com/nnja/advanced-git/blob/master/exercises/
Exercise8-ForksAndRemoteRepos.md
184
DANGER ZONE
185
LOCAL DESTRUCTIVE OPERATIONS
➤ git checkout -- <file>
➤ If the file is present in the staging area, it’ll be overwritten.
➤ git reset --hard
➤ Will overwrite changes that are staged and in the working
area.
186
REMOTE DESTRUCTIVE OPERATIONS - REWRITING HISTORY
➤ There are many operations that can rewrite history:
➤ rebase
➤ amend
➤ reset
187
RECOVER LOST WORK
➤ Use ORIG_HEAD:
➤ The commit HEAD was pointing to before a:
➤ reset
➤ merge
➤ Check for repository copies:
➤ github
➤ coworker
188
ORIG_HEAD TO UNDO A MERGE
➤ use ORIG_HEAD to undo merges
➤ git reset --merge ORIG_HEAD
➤ use --merge flag to preserve any uncommitted changes
git reset
189
USING GIT REFLOG AND ‘@‘ SYNTAX
➤ By default, git keeps commits around for about 2 weeks.
➤ If you need to go back in time, and find a commit that’s no
longer referenced, you can look in the reflog.
➤ The syntax of reflog is different.
➤ HEAD@{2} means “the value of HEAD 2 moves ago”
❯ git reflog
e7cd68b (HEAD -> dont_overwrite_vary_header, origin/dont_overwrite_vary_header) HEAD@{0}: reset: m
94c49a4 HEAD@{1}: commit: A
e7cd68b (HEAD -> dont_overwrite_vary_header, origin/dont_overwrite_vary_header) HEAD@{2}: commit (
overwrite Vary header when setting for cookie access #2317
a54419a HEAD@{3}: rebase finished: returning to refs/heads/dont_overwrite_vary_header
a54419a HEAD@{4}: rebase: Don't overwrite Vary header when setting for cookie
190
ADVANCED TOOLS
191
GIT GREP - SEARCH YOUR CODE - IT’S BLAZING FAST!
➤ Only searches files in your repository by default:
➤ git grep -e <regular expression>
➤ Search in a file or a path:
➤ git grep -e <expression> -- <file or path>
➤ Searches in your staging area with a flag:
➤ git grep --cached -e <regular expression>
192
GIT GREP OUTPUT - IT’S HARD TO READ
➤ Use flags to print out the line number, group matches in a
single file together, and print a new line between file groups:
➤ git grep --line-number --heading --break -e <expr>
193
SUBMODULES
➤ Git merges allow you to embed the contents of another git
repository into your repository.
➤ Git then keeps track of which commit in the other repository
your repository points to.
➤ This may be useful for something like an internal library.
➤ Avoid them if possible! They can be hard to work with.
➤ Use a package manager for your programming language instead
(i.e. npm for javascript, PyPi for python)
194
GIT SUBTREE: SUBMODULE ALTERNATIVE
➤ Git Subtree:
➤ add other git projects as dependencies
➤ collaborators don’t have to install or updating submodules
➤ easy to keep dependencies up to date
195
CHERRY PICKING
❯ git checkout master
❯ git cherry-pick <SHA>
196
GIT BLAME
➤ The git blame command is used to find out about changes to a
file. It can tell you when and by who.
➤ Useful for looking up commits to figure out why a particular
change was made.
➤ The standard format is:
➤ git blame <filename>
197
GIT BLAME WHEN EXAMINING REFACTORING
➤ Git blame can point out authors who moved code around or
changed formatting while refactoring.
198
GIT BLAME A DELETED FILE
➤ use the diff-filter flag on log to see all commits where the file
was deleted:
➤ git log —diff-filter=D -- <deleted_file>
➤ git blame using the parent commit
➤ git blame <commit>^ -- <deleted_file>
199
GIT BLAME BY LINES OR FUNCTION
➤ Use git blame -L!
➤ It can be used with line numbers or a regular expression
➤ Line numbers:
➤ git blame -L1,5 -- <file>
➤ this example will blame lines 1 through 5
➤ Regular expression:
➤ git blame -L'/^def get/,/^def/' <file>
➤ this example will blame the python function that starts with
‘def get’ and will search until the next function definition
‘def ’
200
GIT BISECT
➤ Given a starting point and an end point, search through a
commit history to find which commit introduced a bug.
➤ Git does this via binary search - so it doesn’t have to test each
commit.
➤ It’s much faster than trying to identify the bad commit on your
own.
201
GIT BISECT
❯ git bisect start <BAD_SHA> <GOOD_SHA>
? ? ?
202
GIT BISECT - TESTING COMMITS
➤ Git will check out an arbitrary commit between the GOOD and
BAD SHAs.
➤ You then have two options:
1. Perform a manual test.
➤ Test Passes = run git bisect good
203
EXERCISE
➤ https://github.com/nnja/advanced-git/blob/master/exercises/
Exercise9-AdvancedTools.md
204
CUSTOMIZING GIT
205
CONFIGURATION: LOCAL VS. GLOBAL
➤ Local settings are per-repository
➤ Stored in:
➤ .git/config
➤ To set: git config <setting> <value>
➤ Global settings apply to all repositories
➤ Stored in:
➤ ~/.gitconfig
➤ To set: git config --global <setting> <value>
206
LOCAL VS GLOBAL .GITIGNORE
➤ Local: .git/.gitignore
➤ Global:
➤ Excludes files in all git repositories.
➤ OSX tip: Ignore .DS_Store files!
➤ Create a file. Example: ~/.gitignore
207
ADDITIONAL USEFUL CONFIG
➤ Always rebase a branch instead of merging.
➤ git config branch.<branch name>.rebase true
➤ i.e. git config branch.master.rebase true
208
ALIASES & GIT LOG, BEAUTIFIED
➤ Create aliases:
➤ git config --global alias.last "log -1 HEAD"
➤ git last <- will show the last commit
➤ Set up an alias for pretty log:
➤ git.io/pretty-logs
209
GIT HOOKS
➤ Scripts that run when a git event occurs.
➤ Located in the .git/hooks directory
➤ Many types, common ones are:
file purpose
210
SAMPLE HOOKS
➤ Hooks can be any executable file.
➤ Shell, python, ruby, etc.
➤ When you create a new git repository, you’ll see some sample
hooks in .git/hooks
➤ They’re confusing and not very helpful!
➤ To try one out, remove .sample from the file name.
211
HOOK EXAMPLE - PRE-COMMIT CHECK FOR SYNTAX ERRORS
➤ This hook will prevent python files with syntax errors from being commited.
http://git.io/hook-example
➤ To use it, name it .git/hooks/pre-commit and make it executable with chmod +x
1 #!/usr/bin/env python
import sys
import subprocess
output = subprocess.check_output(diff_command.split())
files = output.split('\n') if output else []
if output:
4 print 'Error in file %s. \nAborting commit!' % file
sys.exit(1) # return 1 (failure)
else:
212
sys.exit(0) # 0 is success status code
HOOK EXAMPLE: POST-MERGE, CHECK FOR NEW DEPENDENCIES
➤ This hook will warn if requirements.txt changed. http://git.io/merge-hook-
example
➤ To use it, name it .git/hooks/post-merge and make it executable with chmod +x
1 #!/usr/bin/env python
import sys
import subprocess
exit_code = subprocess.call(diff_requirements.split())
if exit_code == 1:
3 print 'The requirements file has changed! Remember to install new
dependencies.'
else:
print 'No new dependencies.'
213
GIT HOOK RESOURCES
➤ Github generated .gitignore files for many languages
➤ https://github.com/github/gitignore
➤ For a good resource of pre-written git hooks, and a framework
for writing git hooks in languages other than shell script:
➤ https://github.com/pre-commit/pre-commit
➤ For javascript specific git hooks, check out husky:
➤ https://github.com/typicode/husky
214
GIT TEMPLATES
➤ Git templates allow you to specify files that will be copied into
your .git folder after git init is run.
➤ You can specify which template dir to always use in your config
file.
➤ If you work on projects with multiple programming languages,
you can specify which template directory to use with a flag.
215
GIT TEMPLATE - PYTHON EXAMPLE
For a new python project in git, I’d like the following behaviors:
➤ Always set up a python style .gitignore
216
USING A GIT TEMPLATE
❯ tree ~/.git-templates/python
/Users/nina/.git-templates/python
└── hooks
├── post-merge
└── pre-commit
1 directory, 2 files
❯ cd ~/code/new_proj
❯ ls -l .git/hooks
total 16
-rwxr-xr-x 1 nina staff 329 Oct 1 18:35 post-merge
-rwxr-xr-x 1 nina staff 518 Oct 1 18:35 pre-commit
217
GIT TEMPLATE RESOURCES
➤ Github generated .gitignore files for many languages
➤ https://github.com/github/gitignore
218
GIT LINT
➤ Git lint is an open source tool that lets you set up linting for
different source files easily.
➤ Works for CSS, Javascript, Python, PHP, and many many others!
➤ https://github.com/sk-/git-lint
219
TIME SAVING ALIASES - FOR UNIX AND OS X
➤ When you use git day in and day out, having aliases helps!
➤ Add these to your .bashrc file, then run source ~/.bashrc
➤ https://git.io/git-alias
220
EXERCISE
➤ https://github.com/nnja/advanced-git/blob/master/exercises/
Exercise10-Hooks.md
221
GITHUB
Social Coding
222
NAVIGATE LIKE A PRO
➤ Press ‘?’ on any github.com page for a list of shortcuts.
➤ Then, hit ‘Show All’
223
NAVIGATE - GITHUB.COM FILE FINDER
224
GITHUB - PERMALINK TO CODE
➤ When viewing code on github, you’re looking at latest version
on a particular branch
➤ i.e. github.com/nnja/tweeter/blob/master/
➤ If you want to send someone a link to a particular set of
changes, and guarantee that they’ll see the same code you were
looking at, hit ‘y’ when visiting the file on github.
225
AUTOMATICALLY CLOSE ISSUES FROM PR OR COMMIT
➤ In the pull request, add to the description:
➤ fixes #<issue number> or closes#<issue number>
➤ In a commit, add closes#<issue number>to to message.
226
.GITHUB - TEMPLATES FOR ISSUES, PULL REQUESTS
➤ You can add a .github/ folder for your project to specify
templates for pull requests, issues, and contributing guidelines.
➤ These live in the following files:
➤ CONTRIBUTING.md
➤ ISSUE_TEMPLATE.md
➤ PULL_REQUEST_TEMPLATE.md
➤ These files will automatically populate the description text
when creating a new issue or PR.
227
CREATING PR FROM .GITHUB TEMPLATE
228
CONTINUOUS INTEGRATION
➤ Merging smaller commits frequently, instead of waiting until a
project is “done” and doing one big merge.
➤ This means that features can be released quicker!
➤ CI only works well when there are tests that ensure that new
commits didn’t “break the build”
➤ It’s even possible to perform a deployment at the end of a CI
build!
229
- INTEGRATES WITH GITHUB
➤ Travis CI is free for open source projects!
➤ It’s easy to specify what commands you need to run to run tests
➤ It’s also easy to test against multiple versions of a language
(python2 vs python3) and even multiple versions of libraries
➤ Tests run automatically on branches and pull requests
231
LOOK AT BUILD RESULTS
➤ visit travis-ci.org/<username>/<project>
232
DISPLAY BUILD STATUS OF YOUR PROJECT
➤ Add an image to your README to display the build status.
➤ Instructions: bit.ly/travis-status
233
HUB COMMAND LINE TOOL - HUB.GITHUB.COM
➤ To install hub on osx:
❯ brew install hub
❯ alias git=hub
# Add the line above to your .bashrc, then source .bashrc
234
EXERCISE
➤ Fork github.com/nnja/travis-ci-demo
➤ Navigate to your fork. Hit ’t’. Use the browser to look at
travis.yml
➤ Visit travis-ci.org/profile/ and log in with your GitHub
account
➤ Find your fork of the demo, enable travis on it by flipping the
switch.
236
GITHUB API
➤ GitHub has an incredibly powerful RESTful API.
➤ Currently on Version 3
237
OCTOCAT COMES IN MANY FLAVORS
➤ Api reference: developer.github.com/v3/libraries/
238
MAKING REQUESTS
➤ Un-authenticated
➤ Rate limited. 60 requests per hour
➤ Personal token
➤ Useful for testing, personal projects
➤ Requests authenticated as user who owns the token
➤ OAuth
➤ When your application acts on behalf of a user.
➤ The user will log-in via the OAuth flow in your project
239
CREATE AND UPDATE VIA API
➤ GitHub allows you to create via the API as well.
➤ It’s possible to create and update:
➤ Issues
➤ Pull Requests
➤ New Repositories
➤ Gists
240
STATUSES
➤ GitHub allows you to list statuses for a specific REF
➤ Potential statuses:
➤ Did the build pass?
➤ Is the PR approved by a reviewer?
➤ Using the status endpoint, integrate with:
➤ Slack
➤ Custom emails
➤ PagerDuty
➤ GET /repos/:owner/:repo/commits/:ref/statuses
241
LISTENING TO EVENTS - WEBHOOKS
➤ Create an app that subscribes to events
➤ Subscribed URLs will receive a POST request with a payload
when the event occurs
➤ Examples:
➤ when a user is added as a collaborator to a repo
➤ after a push to a repository
242
FINAL EXERCISE
➤ https://github.com/nnja/advanced-git/blob/master/exercises/
Exercise11-GitHubAPI.md
243
THE END!
git.io/advanced-git
[email protected]
@nnja
244
ADDITIONAL RESOURCES
➤ Git docs online
➤ https://www.kernel.org/pub/software/scm/git/docs/
➤ GitHub API React Examples
➤ https://react.rocks/tag/GitHub_API
➤ Bup: A backup system based on git Pacifies
➤ https://bup.github.io/
245