talks/git-flow/2014-03-01-drupalcamp-london/slides/index.html

587 lines
20 KiB
HTML
Executable file

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Never Commit to Master: An Introduction to Git Flow | DrupalCamp London 2014</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<link rel="stylesheet" href="css/reveal.min.css">
<link rel="stylesheet" href="css/theme/night.css" id="theme">
<link rel="stylesheet" href="lib/css/zenburn.css">
<link rel="stylesheet" href="lib/css/pdf.css">
<script>
document.write( '<link rel="stylesheet" href="css/print/' + ( window.location.search.match( /print-pdf/gi ) ? 'pdf' : 'paper' ) + '.css" type="text/css" media="print">' );
</script>
<!--[if lt IE 9]>
<script src="lib/js/html5shiv.js"></script>
<![endif]-->
</head>
<body>
<div class="reveal">
<div class="slides">
<section>
<h1>Never Commit to Master</h1>
<h3>An Introduction to Git Flow</h3>
<p>
<small>By <a href="http://www.oliverdavies.co.uk">Oliver Davies</a> / <a href="http://twitter.com/opdavies">@opdavies</a></small>
</p>
<aside class="notes">
Drupal for 8 years, Git since for 4 years, Git Flow for a year
</aside>
</section>
<section>
<h2>Me</h2>
<ul>
<li class="fragment">Oliver Davies</li>
<li class="fragment">Developer and Systems Administrator</li>
<li class="fragment"><a href="http://twitter.com/opdavies">@opdavies</a> (Twitter, D.O., IRC)</li>
<li class="fragment"><a href="http://dgo.to/@opdavies">http://dgo.to/@opdavies</a></li>
<li class="fragment">PHPer and Drupalista since 2007 (full time since 2010)</li>
<li class="fragment">Git user since 2010</li>
<li class="fragment">Git Flow user since 2013</li>
</ul>
</section>
<section>
<img src="images/precedent-white.png" style="background: none; border: none;">
</section>
<section>
<h2>Git Flow is:</h2>
<blockquote>"A collection of Git extensions to provide high-level repository operations for <a href="http://nvie.com/git-model">Vincent Driessen's branching model</a>."</blockquote>
<p><small>From <a href="https://github.com/nvie/gitflow">https://github.com/nvie/gitflow</a></small></p>
<aside class="notes">
* Read quote from slide *
Provides a wrapper around standard Git functionality
Everything in Git Flow can be done manually
</aside>
</section>
<section>
<h2>The Branching Model</h2>
<div class="image">
<img src="images/nvie.png" style="border: none;">
</div>
<p><small>From <a href=""></a></small></p>
<aside class="notes">
Separates production code from development code<br>
Encourages feature driven development<br>
Allows for releasing and tagging of code<br>
Multiple opportunities for QA and review
</aside>
</section>
<section>
<h2>Branches</h2>
<ul>
<li class="fragment"><code>master</code>: production code</li>
<li class="fragment"><code>develop</code>: development code</li>
<li class="fragment"><code>feature/</code>: a specific task or ticket (multiple)</li>
<li class="fragment"><code>release/</code>: temporary release branch for testing (single)</li>
<li class="fragment"><code>hotfix/</code>: temporary branch for emergency fixes</li>
<li class="fragment"><code>support/</code>: experimental</li>
</ul>
<aside class="notes">
master: stable production code, tagged at the end of each release (stable)<br>
develop: stores tested and verified development code, awaiting deployment (fairly stable)<br>
feature: unstable code relating to a specific task, bug or user story<br>
release: <br>
hotfix: Used to apply urgent fixes to production code
</aside>
</section>
<section>
<h2>Why use Git Flow?</h2>
<ul>
<li class="fragment">Separation of production and development code</li>
<li class="fragment">Flexibility</li>
<li class="fragment">Better code quality</li>
<li class="fragment">Encourages collaboration</li>
<li class="fragment">Encourages peer code reviews</li>
</ul>
<aside class="notes">
Separates code by using different branches<br>
Being able to easily switch between features<br>
Continuous testing of feature and release branches<br>
Collaboration through sharing of standard branch names<br>
Code reviews
</aside>
</section>
<section>
<h2>My rules of Git Flow</h2>
<ol>
<li class="fragment">Never, ever commit code directly to <code>master</code></li>
<li class="fragment">Only commit stable code to <code>develop</code></li>
<li class="fragment">Try not to commit directly to <code>develop</code></li>
<li class="fragment">One feature branch per user story/bug</li>
<li class="fragment">Commit early, commit often, push often</li>
</ol>
</section>
<section>
<h2>How do I use it?</h2>
<ul>
<li class="fragment">CLI
<ul>
<li class="fragment"><code>~ $ brew install git-flow</code></li>
<li class="fragment"><code>~ $ apt-get install git-flow</code></li>
<li class="fragment"><code>~ $ yum install gitflow</code></li>
</ul>
</li>
<li class="fragment"><a href="http://www.sourcetreeapp.com/">SourceTree</a> (free, cross-platform GUI)</li>
</ul>
<aside class="notes">
You can install and use Git Flow on the command line.<br>
There are packages for Ubuntu (apt), Red Hat and CentOS (yum) and OS X (Homebrew).<br>
You can also download SourceTree from Atlassian which is cross-platform
</aside>
</section>
<section>
<h2>Need Help?</h2>
<pre><code data-trim>
~ $ git flow help
# Shows the standard help menu
~ $ git flow {subcommand} help
# Shows the help menu for a specific subcommand
</code></pre>
</section>
<section>
<h2>Initialise Git Flow</h2>
<pre><code data-trim>
~ $ git flow init
</code></pre>
<aside class="notes">
This can be done at any time, with existing commits
</aside>
</section>
<section>
<h2>Create your default branches</h2>
<pre><code data-trim>
~ $ git flow init
No branches exist yet. Base branches must be created now.
Branch name for production releases: [master]
Branch name for "next release" development: [develop]
</code></pre>
</section>
<section>
<h2>Configure branch prefixes</h2>
<pre><code data-trim>
~ $ git flow init
No branches exist yet. Base branches must be created now.
Branch name for production releases: [master]
Branch name for "next release" development: [develop]
How to name your supporting branch prefixes?
Feature branches? [feature/]
Release branches? [release/]
Hotfix branches? [hotfix/]
Support branches? [support/]
Version tag prefix? []
</code></pre>
</section>
<section>
<h2>Tip: Automatically accept the <br>default branch names</h2>
<pre><code data-trim>
~ $ git flow init -d
# Accepts the default branch names.
</code></pre>
<aside class="notes">
<p>Adding -d accepts the default branch names.</p>
</aside>
</section>
<section>
<h2>Features</h2>
<p><code>$ git flow feature</code></p>
<ul>
<li class="fragment"><code>list</code>: lists all features</li>
<li class="fragment"><code>checkout</code>: checks out an existing feature</li>
<li class="fragment"><code>start</code>: starts a new feature</li>
<li class="fragment"><code>finish</code>: finishes a feature</li>
<li class="fragment"><code>publish</code>: pushes a feature into a remote repo</li>
<li class="fragment"><code>pull</code>: pulls a feature from a remote repo</li>
</ul>
<aside class="notes">
Checkout can be a full feature name or a prefix
</aside>
</section>
<section>
<h2>Start a new feature branch</h2>
<pre><code data-trim>
~ $ git flow feature start {name}
</code></pre>
<div class="fragment">
<pre><code data-trim>
~ $ git flow feature start foo
Switched to a new branch 'feature/foo'
Summary of actions:
- A new branch 'feature/foo' was created, based on 'develop'
- You are now on branch 'feature/foo'
Now, start committing on your feature. When done, use:
git flow feature finish foo
</code></pre>
</div>
<aside class="notes">
* Branches from develop
</aside>
</section>
<section>
<h2>Add and commit changes</h2>
<pre><code data-trim>
~ $ drush dl admin_menu
~ $ git add sites/all/modules/contrib/admin_menu
~ $ git commit -m "Added admin_menu"
</code></pre>
</section>
<!--
<section>
<h2>Features</h2>
<pre><code data-trim>
* 267dd3f - (HEAD, feature/foo, develop) Added admin_menu (8 minutes ago) [Oliver Davies]
* f3108db - Initial commit (9 minutes ago) [Oliver Davies]
* 2581201 - (master) Initial commit (9 minutes ago) [Oliver Davies]
</code></pre>
</section>
-->
<section>
<h2>Recommended: Rebase Your Feature</h2>
<p>Ensure that your feature is up-to-date</p>
<pre><code data-trim>
~ $ git flow feature rebase
Will try to rebase 'foo'...
First, rewinding head to replay your work on top of it...
Applying: Added admin_menu
</code></pre>
<aside class="notes">
Rewinds the feature, updates from develop and re-applies the feature changes<br>
Ensures that the feature code is up to date and will merge correctly.
</aside>
</section>
<section>
<h2>Finish a feature</h2>
<pre><code data-trim>
~ $ git flow feature finish {name}
</code></pre>
<div class="fragment">
<pre><code data-trim>
~ $ git flow feature finish foo
Switched to branch 'develop'
Updating 5c04d5a..6487134
Fast-forward
...
31 files changed, 5051 insertions(+)
Deleted branch feature/foo (was 6487134).
Summary of actions:
- The feature branch 'feature/foo' was merged into 'develop'
- Feature branch 'feature/foo' has been removed
- You are now on branch 'develop'
</code></pre>
</div>
<p class="fragment">And repeat...</p>
</section>
<section>
<h2>Releases</h2>
<p><code>$ git flow release</code></p>
<ul>
<li class="fragment"><code>list</code>: lists existing releases</li>
<li class="fragment"><code>start</code>: starts a new release</li>
<li class="fragment"><code>finish</code>: finishes a release</li>
</ul>
<aside class="notes">
Creates a new version of the prod code<br>
I tend to do this at the end of each sprint
</aside>
</section>
<section>
<h2>Start a new release</h2>
<pre><code data-trim>
~ $ git flow release start {version}
</code></pre>
<div class="fragment">
<pre><code data-trim>
~ $ git flow release start 2014-03-02.0
Switched to a new branch 'release/2014-03-02.0'
Summary of actions:
- A new branch 'release/2014-03-02.0' was created, based on 'develop'
- You are now on branch 'release/2014-03-02.0'
Follow-up actions:
- Bump the version number now!
- Start committing last-minute fixes in preparing your release
- When done, run:
git flow release finish '2014-03-02.0'
</code></pre>
</div>
<aside class="notes">
Final commits or bug fixes<br>
Database export
</aside>
</section>
<section>
<h2>Finish a release</h2>
<pre><code data-trim>
~ $ git flow release finish {version}
</code></pre>
<div class="fragment">
<pre><code data-trim>
~ $ git flow release finish 2014-03-02.0
...
Deleted branch release/2014-03-02.0 (was f2aee7d).
Summary of actions:
- Latest objects have been fetched from 'origin'
- Release branch has been merged into 'master'
- The release was tagged '2014-03-02.0'
- Release branch has been back-merged into 'develop'
- Release branch 'release/2014-03-02.0' has been deleted
</code></pre>
</div>
<aside class="notes">
Merges develop into master<br>
Enter a tag message<br>
Tags the release with the specified tag<br>
Advanced options for release tag singing with GPG
</aside>
</section>
<section>
<h2>Pushing changes remotely</h2>
<pre><code data-trim>
~ $ git push --all
# Push the changes to the remote branches.
~ $ git push --tags
# Push the tags.
</code></pre>
</section>
<section>
<h2>Tip: Finish a release in one command</h2>
<pre><code data-trim>
~ $ git flow release finish -pm {message} {version}
# Specify a commit message and automatically push the changes.
</code></pre>
<div class="fragment">
<pre><code data-trim>
~ $ git flow release finish -pm 2014-03-02.0 2014-03-02.0
</code></pre>
</div>
<aside class="notes">
$ git flow release finish -pm "tag message" {branch}
</aside>
</section>
<section>
<h2>finish-sprint.sh</h2>
<p><code>~ $ ./finish-sprint.sh 2014-03-02.1</code></p>
<pre><code data-trim>
#!/bin/bash
DRUPAL_DIR="/path/to/drupal/docroot"
TAG=$1
if [ -z $TAG ]; then
# A tag must be specified.
echo 'You must specify a tag.'
fi
# Go into the Drupal directory
cd $DRUPAL_DIR
# Start a new Git Flow release.
git flow release start $TAG -F
# Flush the cache.
drush cc all
# Export the database
drush sql-dump --gzip --result-file=../db/$TAG.sql
git add ../db/$TAG.sql
git commit -m "Exported database for $TAG"
# Finish and push the release
git flow release finish -pm $TAG $TAG
</code></pre>
</section>
<section>
<h2>Hotfixes</h2>
<p><code>$ git flow hotfix</code></p>
<ul>
<li class="fragment"><code>list</code>: list all hotfixes</li>
<li class="fragment"><code>start</code>: start a hotfix</li>
<li class="fragment"><code>finish</code>: finish a hotfix</li>
</ul>
<aside class="notes">
Applies an emergency fix to your production code<br>
Branches from master (by default)<br>
Merges back into master and develop
</aside>
</section>
<section>
<h2>Create a new hot fix</h2>
<pre class="fragment"><code data-trim>
~ $ git flow hotfix start {version}
</code></pre>
<pre class="fragment"><code data-trim>
~ $ git flow hotfix start 2014-03-02.2
Switched to a new branch 'hotfix/2014-03-02.2'
Summary of actions:
- A new branch 'hotfix/2014-03-02.2' was created, based on 'master'
- You are now on branch 'hotfix/2014-03-02.2'
Follow-up actions:
- Bump the version number now!
- Start committing your hot fixes
- When done, run:
git flow hotfix finish '2014-03-02.2'
</code></pre>
</section>
<section>
<h2>Commit your fixes</h2>
<pre><code data-trim>
~ $ git ci -am 'Updated .htaccess'
[hotfix/2014-03-02.2 6d04738] Updated .htaccess
1 file changed, 4 insertions(+), 4 deletions(-)
</code></pre>
</section>
<section>
<h2>Finish the hot fix</h2>
<pre><code data-trim>
~ $ git flow hotfix finish 2014-03-02.2
Switched to branch 'master'
Merge made by the 'recursive' strategy.
.htaccess | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
Switched to branch 'develop'
Merge made by the 'recursive' strategy.
.htaccess | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
Deleted branch hotfix/2014-03-02.2 (was 6d04738).
Summary of actions:
- Latest objects have been fetched from 'origin'
- Hotfix branch has been merged into 'master'
- The hotfix was tagged '2014-03-02.2'
- Hotfix branch has been back-merged into 'develop'
- Hotfix branch 'hotfix/2014-03-02.2' has been deleted
</code></pre>
</section>
<section>
<h2>Resources</h2>
<ul>
<li><a href="http://nvie.com/posts/a-successful-git-branching-model/">http://nvie.com/posts/a-successful-git-branching-model/</a></li>
<li><a href="http://jeffkreeftmeijer.com/2010/why-arent-you-using-git-flow/">http://jeffkreeftmeijer.com/2010/why-arent-you-using-git-flow/</a></li>
<li><a href="http://danielkummer.github.io/git-flow-cheatsheet/">http://danielkummer.github.io/git-flow-cheatsheet/</a></li>
<li><a href="https://github.com/nvie/gitflow">https://github.com/nvie/gitflow</a></li>
<li><a href="https://github.com/nvie/gitflow/wiki">https://github.com/nvie/gitflow/wiki</a></li>
</ul>
</section>
<section>
<h2>Demo</h2>
</section>
<section>
<h2>Questions?</h2>
</section>
<section>
<h2>Thanks</h2>
<p>Feedback appreciated!</p>
<ul>
<li>Slides: <a href="http://www.oliverdavies.co.uk/git-flow">http://www.oliverdavies.co.uk/git-flow</a></li>
<li>Session evaluation: <a href="http://2014.drupalcamplondon.co.uk/node/add/session-evaluation?nid=86">http://2014.drupalcamplondon.co.uk/node/add/session-evaluation?nid=86</a></li>
</ul>
</section>
</div> <!-- /.slides -->
</div> <!-- /.reveal -->
<script src="lib/js/head.min.js"></script>
<script src="js/reveal.min.js"></script>
<script>
// Full list of configuration options available here:
// https://github.com/hakimel/reveal.js#configuration
Reveal.initialize({
controls: true,
progress: true,
history: true,
center: true,
theme: Reveal.getQueryHash().theme, // available themes are in /css/theme
transition: Reveal.getQueryHash().transition || 'fade', // default/cube/page/concave/zoom/linear/fade/none
// Parallax scrolling
// parallaxBackgroundImage: 'https://s3.amazonaws.com/hakim-static/reveal-js/reveal-parallax-1.jpg',
// parallaxBackgroundSize: '2100px 900px',
// Optional libraries used to extend on reveal.js
dependencies: [
{ src: 'lib/js/classList.js', condition: function() { return !document.body.classList; } },
{ src: 'plugin/markdown/marked.js', condition: function() { return !!document.querySelector( '[data-markdown]' ); } },
{ src: 'plugin/markdown/markdown.js', condition: function() { return !!document.querySelector( '[data-markdown]' ); } },
{ src: 'plugin/highlight/highlight.js', async: true, callback: function() { hljs.initHighlightingOnLoad(); } },
{ src: 'plugin/zoom-js/zoom.js', async: true, condition: function() { return !!document.body.classList; } },
{ src: 'plugin/notes/notes.js', async: true, condition: function() { return !!document.body.classList; } }
]
});
</script>
</body>
</html>