git-smart-ng 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 01623d5326a9e1b3c41dae2e5a2fc5eb8b348086bf020b2ca0789d5059605cf1
4
+ data.tar.gz: 3801286ed1be9fb39af0116e05473887462170a37006a7391684a0315dc404ff
5
+ SHA512:
6
+ metadata.gz: c16ddaa8bf266fb4f3db2605e7184c7c516b12fe973713a364d419162a6ae08c6bfdddf0df57db915efcbf27304771f6ed91fa7eec1868f6139f0bc7679c692b
7
+ data.tar.gz: 889c3de8fb210fd25dce50ca77f1776f5e77f5d756b8582f659a78da734d7a5c1b026fa57206e1764f250e26e14ce0ada333e90811f4c37d08bd93b9c393ac9c
data/Gemfile ADDED
@@ -0,0 +1,10 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gem 'colorize'
4
+
5
+ group :development do
6
+ gem 'rspec'
7
+ gem 'simplecov'
8
+ gem 'rocco'
9
+ gem 'rake'
10
+ end
data/Gemfile.lock ADDED
@@ -0,0 +1,36 @@
1
+ GEM
2
+ remote: https://rubygems.org/
3
+ specs:
4
+ colorize (0.5.8)
5
+ diff-lcs (1.1.3)
6
+ docile (1.1.1)
7
+ multi_json (1.8.2)
8
+ mustache (0.99.4)
9
+ rake (10.0.3)
10
+ redcarpet (1.17.2)
11
+ rocco (0.8.2)
12
+ mustache
13
+ redcarpet
14
+ rspec (2.7.0)
15
+ rspec-core (~> 2.7.0)
16
+ rspec-expectations (~> 2.7.0)
17
+ rspec-mocks (~> 2.7.0)
18
+ rspec-core (2.7.1)
19
+ rspec-expectations (2.7.0)
20
+ diff-lcs (~> 1.1.2)
21
+ rspec-mocks (2.7.0)
22
+ simplecov (0.8.2)
23
+ docile (~> 1.1.0)
24
+ multi_json
25
+ simplecov-html (~> 0.8.0)
26
+ simplecov-html (0.8.0)
27
+
28
+ PLATFORMS
29
+ ruby
30
+
31
+ DEPENDENCIES
32
+ colorize
33
+ rake
34
+ rocco
35
+ rspec
36
+ simplecov
data/LICENSE.txt ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2011 Glen Maddern and Envato Pty Ltd
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,68 @@
1
+ # git-smart
2
+
3
+ ![git-smart logo](https://github.com/geelen/git-smart/raw/master/docs/images/git-smart.png)
4
+
5
+ Adds some additional git commands to add some smarts to your workflow. These commands follow a few guidelines:
6
+
7
+ 0. It should do the 'right thing' in all situations - an inexperienced git user should be guided away from making simple mistakes.
8
+ 0. It should make every attempt to explain to the user what decisions it has made, and why.
9
+ 0. All git commands that modify the repository should be shown to the user - hopefully this helps the user eventually learn the underlying git commands, and when they're relevant.
10
+
11
+ ## Installing
12
+
13
+ All you need to do is grab the gem:
14
+
15
+ gem install git-smart
16
+
17
+ This will add an executable for each command, e.g. `git-smart-pull`. You call them using git's simple syntax for [custom commands](http://www.nullstyle.com/2007/06/22/create-custom-commands-in-git/), e.g. `git smart-pull`. They'll be removed when you uninstall the gem.
18
+
19
+ You almost certainly want to run this as well, to allow git commands to be output with colour:
20
+
21
+ git config --global color.ui always
22
+
23
+ Git normally only colours output when being run from the terminal, not from within scripts like these. This sorts that right out.
24
+
25
+ ## Get smart!
26
+
27
+ There's only three commands at this point, but there'll be more!
28
+
29
+ ### smart-pull
30
+
31
+ Run `git smart-pull` whenever you would have run `git pull`. It doesn't take any arguments, it'll use the tracking branch configuration or assume 'origin/same-branch-name'.
32
+
33
+ In brief, it'll detect the best way to grab the changes from the server and update your local branch, using a `git rebase -p` if there's no easier way. It'll also stash/pop local changes if need be.
34
+
35
+ Read what it does in detail: [smart-pull](http://github-displayer.heroku.com/geelen/git-smart/raw/master/docs/smart-pull.html)
36
+
37
+ Recommended alias to use: `gup`
38
+
39
+ ### smart-merge
40
+
41
+ Run `git smart-merge` when you would have run `git merge`. This is basically a wrapper around `git merge --no-ff`, which should have been the default anyway. It also does a stash/pop if required, and reports a bit of helpful output.
42
+
43
+ Details here: [smart-merge](http://github-displayer.heroku.com/geelen/git-smart/raw/master/docs/smart-merge.html)
44
+
45
+ Recommended alias to use: `gm`
46
+
47
+ ### smart-log
48
+
49
+ Big hat tip to [@ben\_h](http://twitter.com/ben_h) for this one - it's an alias to a completely badass git log format that not many people know about.
50
+
51
+ Details here: [smart-log](http://github-displayer.heroku.com/geelen/git-smart/raw/master/docs/smart-log.html)
52
+
53
+ Recommended alias to use: `gl`
54
+
55
+ ## Contributing to git-smart
56
+
57
+ * Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet
58
+ * Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it
59
+ * Fork the project
60
+ * Start a feature/bugfix branch
61
+ * Commit and push until you are happy with your contribution
62
+ * Make sure to add tests for it. This is important so I don't break it in a future version unintentionally.
63
+ * Please try not to mess with the Rakefile, version, or history. If you want to have your own version, or is otherwise necessary, that is fine, but please isolate to its own commit so I can cherry-pick around it.
64
+
65
+ ## Copyright
66
+
67
+ Copyright (c) 2011 Glen Maddern and Envato Pty Ltd. See LICENSE.txt for
68
+ further details.
data/Rakefile ADDED
@@ -0,0 +1,71 @@
1
+ require 'rubygems'
2
+ require 'bundler'
3
+
4
+ begin
5
+ Bundler.setup(:default, :development)
6
+ rescue Bundler::BundlerError => e
7
+ $stderr.puts e.message
8
+ $stderr.puts "Run `bundle install` to install missing gems"
9
+ exit e.status_code
10
+ end
11
+
12
+ require 'rake'
13
+
14
+ require 'rspec/core'
15
+ require 'rspec/core/rake_task'
16
+ RSpec::Core::RakeTask.new(:spec) do |spec|
17
+ spec.pattern = FileList['spec/**/*_spec.rb']
18
+ end
19
+
20
+ RSpec::Core::RakeTask.new(:rcov) do |spec|
21
+ spec.pattern = 'spec/**/*_spec.rb'
22
+ spec.rcov = true
23
+ end
24
+
25
+ task :default => :spec
26
+
27
+ require 'rdoc/task'
28
+ Rake::RDocTask.new do |rdoc|
29
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
30
+
31
+ rdoc.rdoc_dir = 'rdoc'
32
+ rdoc.title = "git-smart #{version}"
33
+ rdoc.rdoc_files.include('README*')
34
+ rdoc.rdoc_files.include('lib/**/*.rb')
35
+ end
36
+
37
+ desc "Generate the rocco docs"
38
+ task :rocco do
39
+ base_dir = File.dirname(__FILE__)
40
+ %x[cd #{base_dir}/lib/commands && rocco *.rb -o ../../docs]
41
+ %x[cd #{base_dir} && git add docs]
42
+ end
43
+
44
+ task :release => :rocco
45
+
46
+ desc "Generate a binary for each of our commands"
47
+ task :generate_binaries do
48
+ base_dir = File.dirname(__FILE__)
49
+ require "#{base_dir}/lib/git-smart"
50
+
51
+ require 'fileutils'
52
+ FileUtils.mkdir_p "#{base_dir}/bin"
53
+ GitSmart.commands.keys.each { |cmd|
54
+ filename = "#{base_dir}/bin/git-#{cmd}"
55
+ File.open(filename, 'w') { |out|
56
+ out.puts %Q{#!/usr/bin/env ruby
57
+
58
+ $:.unshift(File.join(File.expand_path(File.dirname(__FILE__)), '..', 'lib'))
59
+
60
+ require 'git-smart'
61
+
62
+ GitSmart.run('#{cmd}', ARGV)
63
+ }
64
+ }
65
+ `chmod a+x #{filename}`
66
+ `cd #{base_dir} && git add #{filename}`
67
+ puts "Wrote #{filename}"
68
+ }
69
+ end
70
+
71
+ task :build => :generate_binaries
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.1.10
data/bin/git-smart-log ADDED
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ $:.unshift(File.join(File.expand_path(File.dirname(__FILE__)), '..', 'lib'))
4
+
5
+ require 'git-smart'
6
+
7
+ GitSmart.run('smart-log', ARGV)
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ $:.unshift(File.join(File.expand_path(File.dirname(__FILE__)), '..', 'lib'))
4
+
5
+ require 'git-smart'
6
+
7
+ GitSmart.run('smart-merge', ARGV)
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ $:.unshift(File.join(File.expand_path(File.dirname(__FILE__)), '..', 'lib'))
4
+
5
+ require 'git-smart'
6
+
7
+ GitSmart.run('smart-pull', ARGV)
Binary file
@@ -0,0 +1,43 @@
1
+ # Introducing git-smart
2
+
3
+ Recently, I grappled with some unexpected git behaviour when trying to rebase local changes (in particular, merge commits) onto changes from upstream. I blogged about [the solution](http://notes.envato.com/developers/rebasing-merge-commits-in-git/), which is to use `git rebase -p`, but I still didn't feel 'done'.
4
+
5
+ Most of the dev team here at Envato had begun using my [aliases](https://gist.github.com/590895), but it's not exactly an easy or maintainable solution. I also wanted to do more, such as stashing local changes if required, using fast-forward when possible, and giving more feedback to the user. But most importantly, I wanted to remove the 'magic' from using someone else's aliases and help people understand the decisions behind choosing the 'correct' git command to run.
6
+
7
+ ## A gem is born
8
+
9
+ Git allows you to add arbitrary commands by placing executables on the path. When you type `git some-custom-command`, git looks for a `git-custom-command` executable on your path and executes it. It can be in any language you want and has no special access to git's internals. It's perfect.
10
+
11
+ Packaging gems also allows you to generate any number of custom executables onto the path. It's perfect, too!
12
+
13
+ Putting them together, we get [git-smart](http://github.com/geelen/git-smart):
14
+
15
+ ![git-smart logo](https://github.com/geelen/git-smart/raw/master/docs/images/git-smart.png)
16
+
17
+ Installing it is as easy as `gem install git-smart` and will give you three new commands, `git smart-pull`, `git smart-merge` and `git smart-log`:
18
+
19
+ ## git smart-pull, the new king of the 'fetch & rebase' workflow
20
+
21
+ The first command I wrote was designed to expand on the knowledge behind `gup`, giving people a reliably-safe method of pulling updates from the server. I also wanted to give plenty of feedback to the user while it runs, and have the source code as [readable and well-documented as possible](http://github-displayer.heroku.com/geelen/git-smart/raw/master/docs/smart-pull.html).
22
+
23
+ In a nutshell, this script will detect which branch you want to pull from, assuming origin/same-branch-name if you haven't set up branch-tracking. If the remote branch hasn't moved on, there's nothing to do. If your local branch hasn't moved on, it can simply be fast-forwarded (wrapped in a `git stash`/`git stash pop` if necessary). Only if both the remote and your local branch have moved on, fall back to a `git rebase -p`, again wrapped in a stash/pop if needed. Easy!
24
+
25
+ This is what it looks like:
26
+
27
+ ![screenshot](https://github.com/geelen/git-smart/raw/master/docs/images/smart-pull-screenshot.png)
28
+
29
+ ## git smart-merge, a non-fast-forward merge wrapped in a stash
30
+
31
+ If you haven't read ["A successful Git branching model"](http://nvie.com/posts/a-successful-git-branching-model/) by Vincent Driessen, you really should. It's good stuff, and it makes the argument for using the `--no-ff` flag whenever you merge. I won't repeat the arguments here, but I wrote `git smart-merge` to effectively make `--no-ff` the default. It also does a stash/pop if required.
32
+
33
+ For more detail, take a look at the [annotated source code](http://github-displayer.heroku.com/geelen/git-smart/raw/master/docs/smart-merge.html).
34
+
35
+ ## git smart-log, the most blinged out ASCII log possible
36
+
37
+ Use this in place of `git log`. I'll let the output speak for itself:
38
+
39
+ ![screenshot](https://github.com/geelen/git-smart/raw/master/docs/images/smart-log-comparison.png)
40
+
41
+ Check out the [code itself](http://github-displayer.heroku.com/geelen/git-smart/raw/master/docs/smart-log.html). Hat tip to [@ben_h](http://twitter.com/ben_h) for the guts of this.
42
+
43
+ Also, if you're on OSX and not using [brotherbard's fork of gitx](https://github.com/brotherbard/gitx/wiki), you really should be. It's absolutely the best way to navigate through a git project's history.
@@ -0,0 +1,59 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <meta http-equiv="content-type" content="text/html;charset=utf-8">
5
+ <title>smart-log.rb</title>
6
+ <link rel="stylesheet" href="http://jashkenas.github.com/docco/resources/docco.css">
7
+ </head>
8
+ <body>
9
+ <div id='container'>
10
+ <div id="background"></div>
11
+ <div id="jump_to">
12
+ Jump To &hellip;
13
+ <div id="jump_wrapper">
14
+ <div id="jump_page">
15
+ <a class="source" href="smart-log.html">smart-log.rb</a>
16
+ <a class="source" href="smart-merge.html">smart-merge.rb</a>
17
+ <a class="source" href="smart-pull.html">smart-pull.rb</a>
18
+ </div>
19
+ </div>
20
+ </div>
21
+ <table cellspacing=0 cellpadding=0>
22
+ <thead>
23
+ <tr>
24
+ <th class=docs><h1>smart-log.rb</h1></th>
25
+ <th class=code></th>
26
+ </tr>
27
+ </thead>
28
+ <tbody>
29
+ <tr id='section-1'>
30
+ <td class=docs>
31
+ <div class="octowrap">
32
+ <a class="octothorpe" href="#section-1">#</a>
33
+ </div>
34
+ <p>This is a super simple alias for the most badass of log outputs that git
35
+ offers. Uses git log &mdash;graph under the hood.</p>
36
+
37
+ <p>Thanks to <a href="http://twitter.com/ben_h">@ben_h</a> for this one!</p>
38
+ </td>
39
+ <td class=code>
40
+ <div class='highlight'><pre><span class="no">GitSmart</span><span class="o">.</span><span class="n">register</span> <span class="s1">&#39;smart-log&#39;</span> <span class="k">do</span> <span class="o">|</span><span class="n">repo</span><span class="p">,</span> <span class="n">args</span><span class="o">|</span></pre></div>
41
+ </td>
42
+ </tr>
43
+ <tr id='section-2'>
44
+ <td class=docs>
45
+ <div class="octowrap">
46
+ <a class="octothorpe" href="#section-2">#</a>
47
+ </div>
48
+ <p>Super simple, passes the args through to git log, but
49
+ ratchets up the badassness quotient.</p>
50
+
51
+ </td>
52
+ <td class=code>
53
+ <div class='highlight'><pre> <span class="n">repo</span><span class="o">.</span><span class="n">log_to_shell</span><span class="p">(</span><span class="s1">&#39;--pretty=format:%Cblue%h%d%Creset %ar %Cgreen%an%Creset %s&#39;</span><span class="p">,</span> <span class="s1">&#39;--graph&#39;</span><span class="p">,</span> <span class="o">*</span><span class="n">args</span><span class="p">)</span>
54
+ <span class="k">end</span></pre></div>
55
+ </td>
56
+ </tr>
57
+ </table>
58
+ </div>
59
+ </body>
@@ -0,0 +1,212 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <meta http-equiv="content-type" content="text/html;charset=utf-8">
5
+ <title>smart-merge.rb</title>
6
+ <link rel="stylesheet" href="http://jashkenas.github.com/docco/resources/docco.css">
7
+ </head>
8
+ <body>
9
+ <div id='container'>
10
+ <div id="background"></div>
11
+ <div id="jump_to">
12
+ Jump To &hellip;
13
+ <div id="jump_wrapper">
14
+ <div id="jump_page">
15
+ <a class="source" href="smart-log.html">smart-log.rb</a>
16
+ <a class="source" href="smart-merge.html">smart-merge.rb</a>
17
+ <a class="source" href="smart-pull.html">smart-pull.rb</a>
18
+ </div>
19
+ </div>
20
+ </div>
21
+ <table cellspacing=0 cellpadding=0>
22
+ <thead>
23
+ <tr>
24
+ <th class=docs><h1>smart-merge.rb</h1></th>
25
+ <th class=code></th>
26
+ </tr>
27
+ </thead>
28
+ <tbody>
29
+ <tr id='section-1'>
30
+ <td class=docs>
31
+ <div class="octowrap">
32
+ <a class="octothorpe" href="#section-1">#</a>
33
+ </div>
34
+ <p>Calling <code>git smart-merge branchname</code> will, quite simply, perform a
35
+ non-fast-forward merge wrapped in a stash push/pop, if that&rsquo;s required.
36
+ With some helpful extra output.</p>
37
+ </td>
38
+ <td class=code>
39
+ <div class='highlight'><pre><span class="no">GitSmart</span><span class="o">.</span><span class="n">register</span> <span class="s1">&#39;smart-merge&#39;</span> <span class="k">do</span> <span class="o">|</span><span class="n">repo</span><span class="p">,</span> <span class="n">args</span><span class="o">|</span></pre></div>
40
+ </td>
41
+ </tr>
42
+ <tr id='section-2'>
43
+ <td class=docs>
44
+ <div class="octowrap">
45
+ <a class="octothorpe" href="#section-2">#</a>
46
+ </div>
47
+ <p>Let&rsquo;s begin!</p>
48
+ </td>
49
+ <td class=code>
50
+ <div class='highlight'><pre> <span class="n">current_branch</span> <span class="o">=</span> <span class="n">repo</span><span class="o">.</span><span class="n">current_branch</span>
51
+ <span class="n">start</span> <span class="s2">&quot;Starting: smart-merge on branch &#39;</span><span class="si">#{</span><span class="n">current_branch</span><span class="si">}</span><span class="s2">&#39;&quot;</span></pre></div>
52
+ </td>
53
+ </tr>
54
+ <tr id='section-3'>
55
+ <td class=docs>
56
+ <div class="octowrap">
57
+ <a class="octothorpe" href="#section-3">#</a>
58
+ </div>
59
+ <p>Grab the merge_target the user specified</p>
60
+ </td>
61
+ <td class=code>
62
+ <div class='highlight'><pre> <span class="n">merge_target</span> <span class="o">=</span> <span class="n">args</span><span class="o">.</span><span class="n">shift</span>
63
+ <span class="n">failure</span> <span class="s2">&quot;Usage: git smart-merge ref&quot;</span> <span class="k">if</span> <span class="o">!</span><span class="n">merge_target</span></pre></div>
64
+ </td>
65
+ </tr>
66
+ <tr id='section-4'>
67
+ <td class=docs>
68
+ <div class="octowrap">
69
+ <a class="octothorpe" href="#section-4">#</a>
70
+ </div>
71
+ <p>Make sure git can resolve the reference to the merge_target</p>
72
+ </td>
73
+ <td class=code>
74
+ <div class='highlight'><pre> <span class="n">merge_sha</span> <span class="o">=</span> <span class="n">repo</span><span class="o">.</span><span class="n">sha</span><span class="p">(</span><span class="n">merge_target</span><span class="p">)</span>
75
+ <span class="n">failure</span> <span class="s2">&quot;Branch to merge &#39;</span><span class="si">#{</span><span class="n">merge_target</span><span class="si">}</span><span class="s2">&#39; not recognised by git!&quot;</span> <span class="k">if</span> <span class="o">!</span><span class="n">merge_sha</span></pre></div>
76
+ </td>
77
+ </tr>
78
+ <tr id='section-5'>
79
+ <td class=docs>
80
+ <div class="octowrap">
81
+ <a class="octothorpe" href="#section-5">#</a>
82
+ </div>
83
+ <p>If the SHA of HEAD and the merge_target are the same, we&rsquo;re trying to merge
84
+ the same commit with itself. Which is madness!</p>
85
+ </td>
86
+ <td class=code>
87
+ <div class='highlight'><pre> <span class="n">head</span> <span class="o">=</span> <span class="n">repo</span><span class="o">.</span><span class="n">sha</span><span class="p">(</span><span class="s1">&#39;HEAD&#39;</span><span class="p">)</span>
88
+ <span class="k">if</span> <span class="n">merge_sha</span> <span class="o">==</span> <span class="n">head</span>
89
+ <span class="n">note</span> <span class="s2">&quot;Branch &#39;</span><span class="si">#{</span><span class="n">merge_target</span><span class="si">}</span><span class="s2">&#39; has no new commits. Nothing to merge in.&quot;</span>
90
+ <span class="n">success</span> <span class="s1">&#39;Already up-to-date.&#39;</span>
91
+ <span class="k">else</span></pre></div>
92
+ </td>
93
+ </tr>
94
+ <tr id='section-6'>
95
+ <td class=docs>
96
+ <div class="octowrap">
97
+ <a class="octothorpe" href="#section-6">#</a>
98
+ </div>
99
+ <p>Determine the merge-base of the two commits, so we can report some useful output
100
+ about how many new commits have been added.</p>
101
+ </td>
102
+ <td class=code>
103
+ <div class='highlight'><pre> <span class="n">merge_base</span> <span class="o">=</span> <span class="n">repo</span><span class="o">.</span><span class="n">merge_base</span><span class="p">(</span><span class="n">head</span><span class="p">,</span> <span class="n">merge_sha</span><span class="p">)</span></pre></div>
104
+ </td>
105
+ </tr>
106
+ <tr id='section-7'>
107
+ <td class=docs>
108
+ <div class="octowrap">
109
+ <a class="octothorpe" href="#section-7">#</a>
110
+ </div>
111
+ <p>Report the number of commits on merge_target we&rsquo;re about to merge in.</p>
112
+ </td>
113
+ <td class=code>
114
+ <div class='highlight'><pre> <span class="n">new_commits_on_merge_target</span> <span class="o">=</span> <span class="n">repo</span><span class="o">.</span><span class="n">rev_list</span><span class="p">(</span><span class="n">merge_base</span><span class="p">,</span> <span class="n">merge_target</span><span class="p">)</span>
115
+ <span class="nb">puts</span> <span class="s2">&quot;Branch &#39;</span><span class="si">#{</span><span class="n">merge_target</span><span class="si">}</span><span class="s2">&#39; has diverged by </span><span class="si">#{</span><span class="n">new_commits_on_merge_target</span><span class="o">.</span><span class="n">length</span><span class="si">}</span><span class="s2"> commit</span><span class="si">#{</span><span class="s1">&#39;s&#39;</span> <span class="k">if</span> <span class="n">new_commits_on_merge_target</span><span class="o">.</span><span class="n">length</span> <span class="o">!=</span> <span class="mi">1</span><span class="si">}</span><span class="s2">. Merging in.&quot;</span></pre></div>
116
+ </td>
117
+ </tr>
118
+ <tr id='section-8'>
119
+ <td class=docs>
120
+ <div class="octowrap">
121
+ <a class="octothorpe" href="#section-8">#</a>
122
+ </div>
123
+ <p>Determine if our branch has moved on.</p>
124
+ </td>
125
+ <td class=code>
126
+ <div class='highlight'><pre> <span class="k">if</span> <span class="n">head</span> <span class="o">==</span> <span class="n">merge_base</span></pre></div>
127
+ </td>
128
+ </tr>
129
+ <tr id='section-9'>
130
+ <td class=docs>
131
+ <div class="octowrap">
132
+ <a class="octothorpe" href="#section-9">#</a>
133
+ </div>
134
+ <p>Note: Even though we <em>can</em> fast-forward here, it&rsquo;s a really bad idea since
135
+ it results in the disappearance of the branch in history. For a good discussion
136
+ on this topic, see this <a href="http://stackoverflow.com/questions/2850369/why-uses-git-fast-forward-merging-per-default">StackOverflow question</a>.</p>
137
+ </td>
138
+ <td class=code>
139
+ <div class='highlight'><pre> <span class="n">note</span> <span class="s2">&quot;Branch &#39;</span><span class="si">#{</span><span class="n">current_branch</span><span class="si">}</span><span class="s2">&#39; has not moved on since &#39;</span><span class="si">#{</span><span class="n">merge_target</span><span class="si">}</span><span class="s2">&#39; diverged. Running with --no-ff anyway, since a fast-forward is unexpected behaviour.&quot;</span>
140
+ <span class="k">else</span></pre></div>
141
+ </td>
142
+ </tr>
143
+ <tr id='section-10'>
144
+ <td class=docs>
145
+ <div class="octowrap">
146
+ <a class="octothorpe" href="#section-10">#</a>
147
+ </div>
148
+ <p>Report how many commits on our branch since merge_target diverged.</p>
149
+ </td>
150
+ <td class=code>
151
+ <div class='highlight'><pre> <span class="n">new_commits_on_branch</span> <span class="o">=</span> <span class="n">repo</span><span class="o">.</span><span class="n">rev_list</span><span class="p">(</span><span class="n">merge_base</span><span class="p">,</span> <span class="n">head</span><span class="p">)</span>
152
+ <span class="nb">puts</span> <span class="s2">&quot;Branch &#39;</span><span class="si">#{</span><span class="n">current_branch</span><span class="si">}</span><span class="s2">&#39; has </span><span class="si">#{</span><span class="n">new_commits_on_branch</span><span class="o">.</span><span class="n">length</span><span class="si">}</span><span class="s2"> new commit</span><span class="si">#{</span><span class="s1">&#39;s&#39;</span> <span class="k">if</span> <span class="n">new_commits_on_merge_target</span><span class="o">.</span><span class="n">length</span> <span class="o">!=</span> <span class="mi">1</span><span class="si">}</span><span class="s2"> since &#39;</span><span class="si">#{</span><span class="n">merge_target</span><span class="si">}</span><span class="s2">&#39; diverged.&quot;</span>
153
+ <span class="k">end</span></pre></div>
154
+ </td>
155
+ </tr>
156
+ <tr id='section-11'>
157
+ <td class=docs>
158
+ <div class="octowrap">
159
+ <a class="octothorpe" href="#section-11">#</a>
160
+ </div>
161
+ <p>Before we merge, detect if there are local changes and stash them.</p>
162
+ </td>
163
+ <td class=code>
164
+ <div class='highlight'><pre> <span class="n">stash_required</span> <span class="o">=</span> <span class="n">repo</span><span class="o">.</span><span class="n">dirty?</span>
165
+ <span class="k">if</span> <span class="n">stash_required</span>
166
+ <span class="n">note</span> <span class="s2">&quot;Working directory dirty. Stashing...&quot;</span>
167
+ <span class="n">repo</span><span class="o">.</span><span class="n">stash!</span>
168
+ <span class="k">end</span></pre></div>
169
+ </td>
170
+ </tr>
171
+ <tr id='section-12'>
172
+ <td class=docs>
173
+ <div class="octowrap">
174
+ <a class="octothorpe" href="#section-12">#</a>
175
+ </div>
176
+ <p>Perform the merge, using &mdash;no-ff.</p>
177
+ </td>
178
+ <td class=code>
179
+ <div class='highlight'><pre> <span class="n">repo</span><span class="o">.</span><span class="n">merge_no_ff!</span><span class="p">(</span><span class="n">merge_target</span><span class="p">)</span></pre></div>
180
+ </td>
181
+ </tr>
182
+ <tr id='section-13'>
183
+ <td class=docs>
184
+ <div class="octowrap">
185
+ <a class="octothorpe" href="#section-13">#</a>
186
+ </div>
187
+ <p>If we stashed before, pop now.</p>
188
+ </td>
189
+ <td class=code>
190
+ <div class='highlight'><pre> <span class="k">if</span> <span class="n">stash_required</span>
191
+ <span class="n">note</span> <span class="s2">&quot;Reapplying local changes...&quot;</span>
192
+ <span class="n">repo</span><span class="o">.</span><span class="n">stash_pop!</span>
193
+ <span class="k">end</span></pre></div>
194
+ </td>
195
+ </tr>
196
+ <tr id='section-14'>
197
+ <td class=docs>
198
+ <div class="octowrap">
199
+ <a class="octothorpe" href="#section-14">#</a>
200
+ </div>
201
+ <p>Display a nice completion message in large, friendly letters.</p>
202
+
203
+ </td>
204
+ <td class=code>
205
+ <div class='highlight'><pre> <span class="n">success</span> <span class="s2">&quot;All good. Created merge commit </span><span class="si">#{</span><span class="n">repo</span><span class="o">.</span><span class="n">sha</span><span class="p">(</span><span class="s1">&#39;HEAD&#39;</span><span class="p">)</span><span class="o">[</span><span class="mi">0</span><span class="p">,</span><span class="mi">7</span><span class="o">]</span><span class="si">}</span><span class="s2">.&quot;</span>
206
+ <span class="k">end</span>
207
+ <span class="k">end</span></pre></div>
208
+ </td>
209
+ </tr>
210
+ </table>
211
+ </div>
212
+ </body>