Thinking in Git
Hi
Permanent link to these slides:
http://talks.edunham.net/linuxfestnorthwest2015/git
Note
Why listen to me?
- 5 years at OSL
- ran bootcamp, LUG
- Taught a lot of newbies this stuff
"Git is the most popular source code management and version control system
in the open source community. Its complexity and power make it the best
choice for most projects, while simultaneously giving it a daunting
learning curve for newcomers. This talk will assume no background
knowledge of version control, and will teach the basics of Git in order to
give you an accurate mental model of what the tool does, and help you fix
mistakes then ask the right questions if you run into problems using it
later."
Agenda
Note
You won't memorize all the commands in an hour but this will help you ask
the right questions
Thinking about Software Development
Why version control?
Note
TODO: pic of directory listing here instead
Types of version control
- Formal vs. impromptu
- Scalable vs. too much work
- Centralized vs. decentralized
- Concurrent vs. locking
- Diffs/patches vs. snapshots
Goals of Distributed Version Control
- Reliability
- No SPOF
- Eliminate network dependencies
Note
reliability means put one file in, get same file out again,
guaranteed. spell out Single Point of Failure.
Git's buzzwords
- Decentralized
- Distributed
- Data assurance
- Porcelain vs Plumbing
- FOSS (GPLv2)
Note
We'll get to branches later... but you've noticed people saying
oddly horticultural things like branches and trunks
How Git sees your project
Note
Unstaged | Staged | Committed
Using Git
Note
We're going to talk about a lot of commands now.
Don't be afraid. Don't expect to know everything at first.
These slides will be online; the link will show up again at the end.
Setting Up
Note
ECDSA is the new hotness -- elliptic-curve digital signature
algorithm -- much smaller keys have comparable security
- GitHub can handle ECDSA, GitLab only does RSA as of 5.1.0
What's a repository?
Database of snapshots of your code
Getting a repo
$ git init
$ git clone <git clone url>
# git@github.com:organization/reponame.git
# https://github.com/organization/reponame.git
Looking at a repo
$ git show
fatal: bad default revision 'HEAD'
# To be expected with nothing in the repo
$ git show
fatal: Not a git repository (or any of the
parent directories): .git
# not in a repo
$ git log
Undo?
Warning
This deletes your history. Only do it if you really want to stop
having a Git repo here.
What're staged changes?
- Staging area is like backstage -- decide what changes go into your snapshot
- Files or parts of files can be added or removed
Staging changes
$ touch foo
$ git add foo
Looking at staged changes
$ touch bar
$ git status
On branch master
Initial commit
Changes to be committed:
(use "git rm --cached <file>..."
to unstage)
new file: foo
Untracked files:
(use "git add <file>..." to include
in what will be committed)
bar
$ git commit --dry-run
Undo?
- Keeping uncommitted changes
- Go back to the latest committed version
Thinking about snapshots
- Represented as changes to a file plus pointers to unchanged files
- Not a diff (tracks all files)
- Not a duplicate of everything (points to unchanged files)
What's a commit?
Snapshot of changes
Includes snapshot (with pointers to unchanged files), author, date, committer
(can differ from author), parent commit
Making a commit
$ man git-commit
-a, --all
-i, --interactive
--reset-author
--date=<date> (see DATE FORMATS in man page)
--allow-empty
--amend
-o, --only
-S, --gpg-sign
Note
-o is for only files from command line disregarding the stash
Specifying file names disregards staged changes, plus stages all current
contents
Looking at commits
# details on latest or specified
$ git show
# Summary of recent, or a range
$ git log
$ man gitrevisions # ranges
What about commits per file?
Commit display options
$ git show
$ git show --oneline
# see PRETTY FORMATS section of
$ man git-show
# Check the GPG signature
$ git show --show-signature
# Want a GUI?
$ gitk
Undo?
# just one file
$ git checkout <commit> <filename>
$ git add <filename>
$ git commit -m "i put that file back how it was"
Or undo the whole commit
$ git revert <commit to revert to>
Note
next: remotes
Reverting makes a revert commit.
Reversability > hiding mistakes
What's a remote?
Another clone of more or less the same repo
(remember when we cloned to get a copy?)
Adding a Remote
$ man git-remote
$ git remote add <name> <url>
Looking at Remotes
$ git config -e
# OR
$ git remote show <name>
From one of my git configs...
[remote "origin"]
url = git@github.com:monte-language/monte.git
fetch = +refs/heads/*:refs/remotes/origin/*
[remote "ed"]
url = git@github.com:edunham/monte.git
fetch = +refs/heads/*:refs/remotes/ed/*
Undo?
Do you prefer text editor...
$ git config -e
# delete or change remote
... or commands?
$ man git-remote
$ git remote rename <old> <new>
$ git remote remove <name>
Note
"Undoing" push to remote is... trickier
next: tags
What's a tag?
- Marker attached to a specific commit
- Typically used for version or release number
Adding a Tag
$ man git-tag
$ git tag -m <msg> <tagname>
Default is lightweight tag -- just a reference for SHA-1 of latest commit
Pass -s or -u <key-id> to GPG-sign
Looking at Tags
# List all available tags
$ git tag
# List tags matching regex
$ git tag -l 'regex'
# I want this version!
$ git checkout <tag name>
Undo?
$ git tag -d <tagname>
# And remove it from a remote repo
$ git push origin :refs/tags/<tagname>
What's a branch?
A parallel path of development, starting from a commit that's in the tree
Note
Point out why the arrows are "backwards"
Making a branch
# track remote branch by default if one matches
$ git checkout -b <branchname>
# Shorthand for:
$ git branch <branchname> # create
$ git checkout <branchname> # check out
# Pushing a branch to a remote
$ git push <remotename> <branchname>
Looking at branches
$ git branch
$ git show <branchname>
Note
GitHub's "network" graph and gitk are good for this
Undo?
# delete only if fully merged
$ git branch -d
# Delete, I Don't care what I lose
$ git branch -D
# delete remote branch
$ git push <remotename> :<branchname>
What's a merge?
- Converges the divergent branches
- One branch gets updated, one branch stays unchanged
Note
that joke about how a group of developers is called a merge conflict
Making a Merge
# Branch you're changing
$ git checkout mywork
$ git merge master
# Merge conflicts?
$ git status
On branch mywork
You have unmerged paths.
(fix conflicts and run "git commit")
Note
COMMIT OR STASH CHANGES FIRST
Merge Conflicts
<<<<<<< HEAD
This content was in mywork but not master
=======
This content was in master but not mywork
>>>>>>> master
Replace all that stuff with what the content should be.
git add the file.
Check that you've got everything with git status, then commit.
Or consider git mergetool for an interactive option.
Looking at Merges
$ git diff <commit before> <merge commit>
# before merging, see changes
$ git log ..otherbranch
$ git diff ...otherbranch
$ gitk ...otherbranch
Undo?
$ git merge abort
$ git reset --keep HEAD@{1}
What's a rebase?
Changing history. Means others will have to force pull.
Note
Don't do this unless you know what you're doing... But here's how to
know what you're doing.
Rebasing
$ git rebase -i <commit range>
HEAD~4
# last 4 commits
# Oops I forgot to pull
$ git pull --rebase
Looking at the rebase
# Rebase 1a20f51..147c812 onto 1a20f51
#
# Commands:
# p, pick = use commit
# r, reword = use commit, but edit the commit message
# e, edit = use commit, but stop for amending
# s, squash = use commit, but meld into previous commit
# f, fixup = like "squash", but discard this commit's log message
# x, exec = run command (the rest of the line) using shell
#
# These lines can be re-ordered; they are executed from top to bottom.
#
# If you remove a line here THAT COMMIT WILL BE LOST.
Note
Make sure you have your git editor set!
Undo?
I should never have done that
$ git reset --hard ORIG_HEAD
I'm stuck in a broken rebase, get me out
GitHub Stuff
Not Exactly Git
- Less distributed paradigm
- Git never told us who to trust
- Git doesn't care who you are
Watch Linus's talk for more detail
HTTP vs SSH Clones
Permission denied (publickey).
fatal: Could not read from remote
repository.
Please make sure you have the
correct access rights and the
repository exists.
HTTP clone prompts for username and password
SSH clone uses key from your account
Forking
- Parallel repos (or possibly divergent)
- Act like the "center" of the centralized VCS
Pull Requests
- Formalizes "Hi, please merge my changes"
Annoying Tricks
- Branches keep adding their content to PRs
- Group management and access rights
- No project license required
Continuous Integration
Playing Well With Others
- Change history locally, never globally
- Never force push (unless you have to)
Focused commits with clear commit messages
Follow project standards for branching, tagging, etc.
Questions?
Permanent link to these slides:
http://talks.edunham.net/linuxfestnorthwest2015/git
Other Stuff
checkout
point HEAD at the tip of the specified branch
$ git checkout <revision> file
gitrevisions
git bisect
Binary Search:
git bisect start
git bisect bad <commit>
git bisect good <commit>
git bisect next
git bisect reset <commit>
git cherry-pick
$ git checkout <branch that needs special commit>
$ git cherry-pick <special commit from another branch>