Advanced Git

Workflows for Developers

Slides by Matthew B. Gray / @jsflimflam

Special thanks to

  • Mike O' – For approving this course
  • Alison Aldred – For being generally awesome
  • Evan Giles – Inspiration and advice

Theme: Dark / Light
## Course Overview -------------------------------------------------------------------------------- * Getting Started * Personal workflows * Team workflows * Client workflows
* **Getting Started** <-- you are here * Personal workflows * Team workflows * Client workflows -------------------------------------------------------------------------------- ## Overview: Getting started - Basic config for these machines - Good config defaults - Quick review of basic git - Unlocking achievements, making git a bit more fun
### Basic config for these machines Git would like you to specify 1. Your full name 1. Your email address 1. Your favourite text editor ```bash git config --global user.name "Dr. Henry Killinger" git config --global user.email "fu@bar.baz" git config --global core.editor vim ``` All these settings are storred in **~/.gitconfig**
### Sane defaults for day to day use * Use colour to highlight branches and diffs * Make sure you only push the branch you're on * Show branches and tags in git log * Setup rebase as the default strategy for git pull ```bash git config --global color.ui always git config --global push.default current git config --global log.decorate full git config --global branch.autosetuprebase always ``` On your checkouts ```bash git config branch.rebase true ``` All these settings are storred in **~/.gitconfig**

Quick review of basic git

http://ndpsoftware.com/git-cheatsheet.html

### Unlocking achievements, making git a bit more fun Unlock Achievements! Track friends over RSS! Flaunt your achievements with a Splashy page!
![fork](images/github-git-acheivements.png)
### Unlocking achievements, making git a bit more fun ---------------------------------------- If you have a github account 1. Go to https://github.com/icefox/git-achievements 2. Fork that repo 3. Go to your forked project, and clone it ---------------------------------------- No account? You can still run it locally ```bash git clone https://github.com/icefox/git-achievements.git ```
### Setup Alias git-achievements in your shellrc file ```bash vim ~/.bashrc ``` ```bash export PATH="$PATH:~/git/git-achievements" alias git="git-achievements" ``` ```bash git config --global achievement.upload "true" ``` Keep your achievements after the course, save this ```bash ~/.git-achievements.log ```

Some fun achievements I've unlocked

--------------------------------------------------------------------------------

Cathedral Worker (Level 1)

Cloned submodule repository and checked out commits specified by superproject.

--------------------------------------------------------------------------------

--------------------------------------------------------------------------------

Garage Inventor (Level 1)

Used a custom alias for a Git command

--------------------------------------------------------------------------------

--------------------------------------------------------------------------------

Banker (Level 5)

Join two or more development histories together with git-merge.

--------------------------------------------------------------------------------

--------------------------------------------------------------------------------

Apprentice Thug (Level 3)

Forced pushed a branch with git-push -f

--------------------------------------------------------------------------------

--------------------------------------------------------------------------------

Let there be light

Commit without a parent.

--------------------------------------------------------------------------------

If there's more interest...

--> @jsflimflam's achievements -->

* Getting Started * **Personal workflows** <-- you are here * Team workflows * Client workflows -------------------------------------------------------------------------------- ## Overview: Personal workflows - Context hunting / Isolate and Triage issues - Mastering branches - Audit work interactively - Manage merge conflicts like a pro

Typical git workflow

Tools suited to personal workflow

- Personal workflows... - **Isolate and Triage: Context hunting** <-- you are here - Work: Mastering branches - Update, Test: Audit work interactively - Share: Manage merge conflicts like a pro
### Context hunting / Isolate, Triage ---------------------------------------- This is a BEFORE YOU START thing, helps isolate and triage Context is important when you start to 1. Avoid regressing your codebase 2. Find out if code is still under warantey 3. Get help if you get stuck, seek out a human ---------------------------------------- - Personal workflows... - Isolate and Triage: Context hunting * Log - Show commit logs * Bisect - binary search for bugs * Blame - revision and author for lines of a file * Pickaxe - Search commit diffs for changes
### Context hunting / Isolate, Triage - Personal workflows... - Isolate and Triage: Context hunting * Log <-- you are here * Bisect * Blame * Pickaxe ----------------------------------------
Regular log ```bash git log ``` ![regular git log](images/git-log.png)
Show me contents of patches ```bash git log -p ``` ![patch mode git log](images/git-log-p.png)
Show me a summary of patches ```bash git log --stat ``` ![stats](images/git-log-stat.png)
Find changes associated with text in a commit message: ```bash git log --grep '$search_term' git log --grep 'bug#1234' ``` ![grep for messages](images/git-log-grep-term.png)
### Context hunting / Isolate, Triage - Personal workflows... - Isolate and Triage: Context hunting * Log * Bisect <-- you are here * Blame * Pickaxe ----------------------------------------
To start bisecting, you use these commands ```bash git bisect start $bad_commit $good_commit ``` 'Unwanted' behaviour? ```bash git bisect bad ``` 'Wanted' behaviour? ```bash git bisect good ```
When you're done, tidy up the markers with ```bash git bisect reset ```
Sometimes it's guess work, but there are still commands to help you out. If what you're on is untestable, you can skip ```bash git bisect skip ``` Or you can guess good/bad, play it out and see ```bash git bisect log > bisect.log git bisect replay bisect.log ```
### Context hunting / Isolate, Triage - Personal workflows... - Isolate and Triage: Context hunting * Log * Bisect * Blame <-- you are here * Pickaxe ---------------------------------------- Basic usage ```bash git blame $filename git show $hash ``` Ignore whitespace ```bash git blame -w $filename ``` Copy paste detection in a file, and across the repo ```bash git blame -M $filename git blame -C $filename ```
### Context hunting / Isolate, Triage - Personal workflows... - Isolate and Triage: Context hunting * Log * Bisect * Blame * Pickaxe <-- you are here ---------------------------------------- ```bash git log -S 'some distinct line that changed' git log --stat -S '$racebook_uri_result' ``` * Find all the changes to a line in your entire history * The pickaxe can help find code that’s been deleted or moved * Typically helps you with questions like - What happened to myFabuliousFunc(), it's gone! - When did $mySillyVariable get referenced everywhere? * Works with log, diff, and format-patch
### Activity: Testing bisect 1. Clone the jabberwocky repo, pull tags 2. Checkout the changes made with git log 3. Use bisect with v1 and v2 tags as good/bad commits 4. find the commit that broke the page ```bash git clone https://github.com/jsflimflam/jabberwocky cd jabberwocky git fetch --tags git log -p git log --stat git bisect start $bad $good ``` Exhibits wanted behaviour? ```bash git bisect good ``` Exhibits unwanted behaviour? ```bash git bisect bad ```
Tidy up with ```bash git bisect reset ```
### Activity: Testing log, pickaxe, blame and show 1. Clone jquery repo 2. Use git log to find fixes to issue #14756 3. Use pickaxe to find commits that added or removed 'parseFloat' 4. Try git blame on the .gitignore file 5. With this info, show the commit that blacklisted bower_components ```bash git clone https://github.com/jquery/jquery git log --grep 'asdf' git log -S 'asdf' git blame $file git show $hash ```

Tools suited to personal workflow

- Personal workflows... - Isolate and Triage: Context hunting - **Work: Mastering branches** <-- you are here - Update, Test: Audit work interactively - Share: Manage merge conflicts like a pro

Mastering branches: Overview


Git thinks in Snapshots, Not Differences > The major difference between Git and any other VCS (Subversion and friends included) > is the way Git thinks about its data. src: git-scm.com, ch 1.3 Getting Started: Git Basics

SVN commits

Git commits

![](images/branches-typical.png) ![](images/branches-multi.png) Typical branching, images from http://git-scm.com
![](images/branches-perspective.png) How branches can be used for workflow
* Nodes represent diffs with respect to each other * Nodes represent entire filesystem layout on their own * Nodes are immutable ---------------------------------------- You can describe nodes with a... * **branch** - a name to track your work * **tag** - a label, it doesn't move * **commit hash** - complete history and set of files * **HEAD** - your current checkout * **$ref^** - above are $refs, chain ^ or ~ to go up a branch ---------------------------------------- Lets look at how we can use these with commands

Mastering branches: Commands

Interesting commands with branches ```bash git checkout $branch git reset $ref git rebase $branch git rebase --interactive $branch ``` ---------------------------------------- * **Checkout**: context dependent command... 1. Either reset unstaged file(s) 2. Or switch branches * **Rebase**: Batch move commits and rewrite history * **Reset**: Move branches around arbitarily * **Reflog**: Save my ass! What have I had 'checked out' recently? ---------------------------------------- Whiteboard time!
```bash # NOES!! Undo!! git reflog ```

Mastering branches: Headless state

If you're not on a branch, git puts you in a headless state ```bash git checkout $tag git checkout $commit ```
Trying something like this... ```bash git checkout HEAD^ ``` Results in something like this...
```text You are in 'detached HEAD' state. You can look around, make experimental changes and commit them, and you can discard any commits you make in this state without impacting any branches by performing another checkout. If you want to create a new branch to retain commits you create, you may do so (now or later) by using -b with the checkout command again. Example: git checkout -b new_branch_name HEAD is now at f4b37d8... CSS: Return values should be numbers ``` Which is git being melodramatic
### Activity: Mastering Branches 1. Navigate to your Jabberwocky repo clone 2. Checkout 'master' 3. Fix the bug, commit 4. Interactive rebase onto the tag v1 5. Squash your fix with 'Oops' and give it a message. ```bash cd $jabberwocky_dir vim jabberwocky.html git add jabberwocky.html git commit git log git rebase $ref --interactive git log -p ``` ...it's as if the error was never there. Now put it back ```bash git reset origin/master --hard ```

Tools suited to personal workflow

- Personal workflows... - Isolate and Triage: Context hunting - Work: Mastering branches - **Update, Test: Audit work interactively** <-- you are here - Share: Manage merge conflicts like a pro
### Audit work interactively Audit your work interactively with your staging area 1. When you're ready to commit locally 2. When you want to break up a monstor commit ---------------------------------------- ### Quick activity Add your own verse to the jabberwocky poem, then run ```bash git add -p ``` Check what's happened with ```bash git status ``` Put stuff back with ```bash git reset HEAD ```

Tools suited to personal workflow

- Personal workflows... - Isolate and Triage: Context hunting - Work: Mastering branches - Update, Test: Audit work interactively - **Share: Manage merge conflicts like a pro** <-- you are here
### Manage merge conflicts like a pro Source control is about social coding and interactions. A conflict should be a conversation. When you see ```bash CONFLICT (content): Merge conflict in jabberwocky.html Automatic merge failed; fix conflicts and then commit the result. ``` Get info with ```bash git status git blame $file ``` Markers are usually HEAD and a $ref, wher 1. HEAD is work of yours 2. $ref is the thing you're in conflict with ```bash git reflog git merge $ref ```

How I hope you feel when you walk out of this room

* Getting Started * Personal workflows * **Team workflows** <-- you are here * Client workflows -------------------------------------------------------------------------------- ## Overview: Team workflows - Quickly setup local, network accessible repos - Working with people who don't enjoy source control - Clean history, rebase verses merge
### Quickly setup local, network accessible repos ![](images/dictator-lieutenant-contributors.png)
### Quickly setup local, network accessible repos Git just tracks content. All history is stored in .git directory, and sharing is just mushing content around in there. To modify remotes... ```bash git remote add $alias $location git remote rm $alias ``` Location can be... 1. ssh://[user@]host.xz[:port]/path/to/repo.git/ 1. git://host.xz[:port]/path/to/repo.git/ 1. http[s]://host.xz[:port]/path/to/repo.git/ 1. ftp[s]://host.xz[:port]/path/to/repo.git/ 1. rsync://host.xz/path/to/repo.git/
### Quickly setup local, network accessible repos Share your terrible poetry with your neighbour. This is for unauthenticated read-only access. ```bash cd ~/jabberwocky/.git touch git-daemon-export-ok git daemon --reuseaddr --base-path=$HOME/jabberwocky/ $HOME/jabberwocky/.git ``` Where ~/jabberwocky is the jabberwocky checkout. When this is setup, exchange details and try clone... ```bash git clone git://$host/ jabberwocky-neighbour cd jabberwocky-neighbour ``` or add a remote... ```bash git remote add neighbour git://$host/ git fetch --all git log neighbour/master git diff neighbour/master master ```
Now lets try merge conflicts! ```bash git merge neighbour/master git status git blame $file ```
### Working with people who don't enjoy source control Idea #1: Empower them, let them mange their commits, but manage their merges ![](images/branches-typical.png)
### Working with people who don't enjoy source control Idea #2: Manage their commits and merges ```bash while true; do clear; git add . git commit -m "$designer updated UX." sleep 5; done; ```
### Clean history, rebase verses merge * When to merge: If you've pushed it, you can't change things without pain. * If you have multiple conflicts, try for a merge * Use KISS where possible ---------------------------------------- Discuss: ```bash git pull --rebase ``` ```bash git config --global branch.autosetuprebase always git pull ``` ```bash git rebase --abort git merge --abort ```

How an svn user sees git workflow

* Getting Started * Personal workflows * Team workflows * **Client workflows** <-- you are here -------------------------------------------------------------------------------- ## Overview: Client workflows - Strategies for dealing with client requirements - Strategies for database patching on branches
### Database patching on branches Git doesn't care about non-filesystem entities Database patching is important to get right ---------------------------------------- You can either use convetion, or process to manage this 1. Numeric patch - set 1+$current in your filename 2. Automatic numeric patch - use a merge script on release
### Strategies for dealing with client requirements The battle of flexibility vs simplicity ---------------------------------------- A typical client may ask you to be flexable on the following * Track changes, find bugs and release when you can * Working on releases in parallel * Construct release candidates based on feature sets * Release partial applications (modular)

Release all the things!

### Client requirements: Linear history * Simple * Track changes, find bugs and release when you can * Easy to bring new devs on board ![](images/basic-branching-1.png) ![](images/basic-branching-2.png)
### Client requirements: Merge forward releases * Fairly simple * Work on multiple releases at the same time * Can work on upstream while downstream is still going ![](images/release-branches.png)
### Client requirements: Feature releases * Every piece of work is a feature * Features are octo-merged into a release candidate * Need to track production somehow * Cannot release 'backwards' ![](images/feature-releases-1.png)
### Feature releases... omg ![](images/feature-releases-2.png)
### Feature releases... more woah ![](images/feature-releases-3.png)
### Client requirements: Microkernel architecture * Difficulty is abstracted to the application * Modules of application can be worked on at the same time * Release would package together multiple pieces of work ![](images/basic-branching-2.png) ![](images/release-branches.png)

Each has it's costs, choose the one that works best

Further Reading


Attribution

Thanks! - @jsflimflam