Thinking in Git

Hi

Permanent link to these slides:

http://talks.edunham.net/openwest2015/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

_images/gitlogo.png

Note

You won't memorize all the commands in an hour but this will help you ask the right questions

Thinking about Software Development

_images/compiling.png

Why version control?

Note

TODO: pic of directory listing here instead

_images/phdcomic.gif

Types of version control

_images/deskdisaster.jpg

Goals of Distributed Version Control

_images/dvcs.gif

Note

reliability means put one file in, get same file out again, guaranteed. spell out Single Point of Failure.

Git's buzzwords

_images/oaktree.jpg

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

_images/staging.png

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?

_images/filmstrip.png

Database of snapshots of your code

$ ls .git/

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.
$ rm -rf .git
_images/kaboom.jpg

What're staged changes?

_images/staging.png

Staging changes

_images/thewings.jpg
$ 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?

$ git rm --cached foo
$ git reset HEAD foo

Note

next, snapshots

Thinking about snapshots

_images/polaroid.jpeg
_images/snapshots_model.png

Note

next, commits

What's a commit?

Snapshot of changes

Includes snapshot (with pointers to unchanged files), author, date, committer (can differ from author), parent commit

_images/snapshots_model.png

Making a commit

_images/tardis.jpg
$ git 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

_images/gitk.png
# details on latest or specified
$ git show

# Summary of recent, or a range
$ git log

$ man gitrevisions # ranges

What about commits per file?

$ git blame <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>
_images/tardis2.jpg

Note

next: remotes Reverting makes a revert commit. Reversability > hiding mistakes

What's a remote?


_images/remotes.png

Another clone of more or less the same repo

(remember when we cloned to get a copy?)


_images/sheepclones.jpg

Adding a Remote


$ man git-remote

$ git remote add <name> <url>

_images/remotes.jpg

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?

_images/graffiti.jpg
_images/tags.png

Adding a Tag

_images/bookmarks.jpg
$ 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?

_images/gitflow_branches.png

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>

_images/branchgraph.png

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>
_images/pruning_bonsai.jpg

What's a merge?

_images/pdx.jpe

Note

that joke about how a group of developers is called a merge conflict

Making a Merge

_images/merge.png
# 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?


_images/billted.jpg

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

$ git rebase --abort

GitHub Stuff

_images/github.png

Not Exactly Git

_images/github.png

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

_images/forking.gif

Pull Requests


_images/pr-button.png

Annoying Tricks



_images/gh-teams.png

Extra Features

Continuous Integration


_images/jenkins.png
_images/travis.png

Playing Well With Others


_images/communication_dalek.jpe

Questions?


Go to Ben Loveridge's talk at 9am Saturday: Git with the flow: maintainable branch strategies using Git[Hub] Flow

Permanent link to these slides:

http://talks.edunham.net/openwest2015/git

Other Stuff

checkout


$ git checkout branch

point HEAD at the tip of the specified branch

$ git checkout <revision> file

gitrevisions


$ man 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>