git-smart 0.1.3 → 0.1.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/Gemfile +1 -0
- data/Gemfile.lock +6 -0
- data/README.md +10 -20
- data/Rakefile +7 -0
- data/VERSION +1 -1
- data/docs/images/git-smart.png +0 -0
- data/docs/smart-merge.html +211 -0
- data/docs/smart-pull.html +274 -0
- data/git-smart.gemspec +13 -2
- data/lib/commands/smart-merge.rb +63 -0
- data/lib/commands/smart-pull.rb +38 -10
- data/lib/git-smart/git_repo.rb +27 -10
- data/spec/smart-merge_failures_spec.rb +46 -0
- data/spec/smart-merge_spec.rb +101 -0
- data/spec/smart-pull_spec.rb +2 -5
- data/spec/spec_helper.rb +2 -1
- metadata +52 -23
data/git-smart.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{git-smart}
|
8
|
-
s.version = "0.1.
|
8
|
+
s.version = "0.1.4"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Glen Maddern"]
|
12
|
-
s.date = %q{2011-01-
|
12
|
+
s.date = %q{2011-01-05}
|
13
13
|
s.default_executable = %q{git-smart}
|
14
14
|
s.description = %q{Installs some additional 'smart' git commands, like `git smart-pull`.}
|
15
15
|
s.email = %q{glenmaddern@gmail.com}
|
@@ -26,7 +26,11 @@ Gem::Specification.new do |s|
|
|
26
26
|
"Rakefile",
|
27
27
|
"VERSION",
|
28
28
|
"bin/git-smart",
|
29
|
+
"docs/images/git-smart.png",
|
30
|
+
"docs/smart-merge.html",
|
31
|
+
"docs/smart-pull.html",
|
29
32
|
"git-smart.gemspec",
|
33
|
+
"lib/commands/smart-merge.rb",
|
30
34
|
"lib/commands/smart-pull.rb",
|
31
35
|
"lib/core_ext/array.rb",
|
32
36
|
"lib/core_ext/hash.rb",
|
@@ -37,6 +41,8 @@ Gem::Specification.new do |s|
|
|
37
41
|
"lib/git-smart/git_repo.rb",
|
38
42
|
"lib/git-smart/git_smart.rb",
|
39
43
|
"lib/git-smart/safe_shell.rb",
|
44
|
+
"spec/smart-merge_failures_spec.rb",
|
45
|
+
"spec/smart-merge_spec.rb",
|
40
46
|
"spec/smart-pull_spec.rb",
|
41
47
|
"spec/spec_helper.rb"
|
42
48
|
]
|
@@ -46,6 +52,8 @@ Gem::Specification.new do |s|
|
|
46
52
|
s.rubygems_version = %q{1.3.7}
|
47
53
|
s.summary = %q{Add some smarts to your git workflow}
|
48
54
|
s.test_files = [
|
55
|
+
"spec/smart-merge_failures_spec.rb",
|
56
|
+
"spec/smart-merge_spec.rb",
|
49
57
|
"spec/smart-pull_spec.rb",
|
50
58
|
"spec/spec_helper.rb"
|
51
59
|
]
|
@@ -60,12 +68,14 @@ Gem::Specification.new do |s|
|
|
60
68
|
s.add_development_dependency(%q<rcov>, [">= 0"])
|
61
69
|
s.add_development_dependency(%q<bundler>, ["~> 1.0.0"])
|
62
70
|
s.add_development_dependency(%q<jeweler>, ["~> 1.5.2"])
|
71
|
+
s.add_development_dependency(%q<rocco>, [">= 0"])
|
63
72
|
else
|
64
73
|
s.add_dependency(%q<colorize>, [">= 0"])
|
65
74
|
s.add_dependency(%q<rspec>, ["~> 2.3.0"])
|
66
75
|
s.add_dependency(%q<rcov>, [">= 0"])
|
67
76
|
s.add_dependency(%q<bundler>, ["~> 1.0.0"])
|
68
77
|
s.add_dependency(%q<jeweler>, ["~> 1.5.2"])
|
78
|
+
s.add_dependency(%q<rocco>, [">= 0"])
|
69
79
|
end
|
70
80
|
else
|
71
81
|
s.add_dependency(%q<colorize>, [">= 0"])
|
@@ -73,6 +83,7 @@ Gem::Specification.new do |s|
|
|
73
83
|
s.add_dependency(%q<rcov>, [">= 0"])
|
74
84
|
s.add_dependency(%q<bundler>, ["~> 1.0.0"])
|
75
85
|
s.add_dependency(%q<jeweler>, ["~> 1.5.2"])
|
86
|
+
s.add_dependency(%q<rocco>, [">= 0"])
|
76
87
|
end
|
77
88
|
end
|
78
89
|
|
@@ -0,0 +1,63 @@
|
|
1
|
+
#Calling `git smart-merge branchname` will, quite simply, perform a
|
2
|
+
#non-fast-forward merge wrapped in a stash push/pop, if that's required.
|
3
|
+
#With some helpful extra output.
|
4
|
+
GitSmart.register 'smart-merge' do |repo, args|
|
5
|
+
#Let's begin!
|
6
|
+
current_branch = repo.current_branch
|
7
|
+
start "Starting: smart-merge on branch '#{current_branch}'"
|
8
|
+
|
9
|
+
#Grab the merge_target the user specified
|
10
|
+
merge_target = args.shift
|
11
|
+
failure "Usage: git smart-merge ref" if !merge_target
|
12
|
+
|
13
|
+
#Make sure git can resolve the reference to the merge_target
|
14
|
+
merge_sha = repo.sha(merge_target)
|
15
|
+
failure "Branch to merge '#{merge_target}' not recognised by git!" if !merge_sha
|
16
|
+
|
17
|
+
#If the SHA of HEAD and the merge_target are the same, we're trying to merge
|
18
|
+
#the same commit with itself. Which is madness!
|
19
|
+
head = repo.sha('HEAD')
|
20
|
+
if merge_sha == head
|
21
|
+
note "Branch '#{merge_target}' has no new commits. Nothing to merge in."
|
22
|
+
success 'Already up-to-date.'
|
23
|
+
else
|
24
|
+
#Determine the merge-base of the two commits, so we can report some useful output
|
25
|
+
#about how many new commits have been added.
|
26
|
+
merge_base = repo.merge_base(head, merge_sha)
|
27
|
+
|
28
|
+
#Report the number of commits on merge_target we're about to merge in.
|
29
|
+
new_commits_on_merge_target = repo.rev_list(merge_base, merge_target)
|
30
|
+
puts "Branch '#{merge_target}' has diverged by #{new_commits_on_merge_target.length} commit#{'s' if new_commits_on_merge_target.length != 1}. Merging in."
|
31
|
+
|
32
|
+
#Determine if our branch has moved on.
|
33
|
+
if head == merge_base
|
34
|
+
#Note: Even though we _can_ fast-forward here, it's a really bad idea since
|
35
|
+
#it results in the disappearance of the branch in history. For a good discussion
|
36
|
+
#on this topic, see this [StackOverflow question](http://stackoverflow.com/questions/2850369/why-uses-git-fast-forward-merging-per-default).
|
37
|
+
note "Branch '#{current_branch}' has not moved on since '#{merge_target}' diverged. Running with --no-ff anyway, since a fast-forward is unexpected behaviour."
|
38
|
+
else
|
39
|
+
#Report how many commits on our branch since merge_target diverged.
|
40
|
+
new_commits_on_branch = repo.rev_list(merge_base, head)
|
41
|
+
puts "Branch '#{current_branch}' has #{new_commits_on_branch.length} new commit#{'s' if new_commits_on_merge_target.length != 1} since '#{merge_target}' diverged."
|
42
|
+
end
|
43
|
+
|
44
|
+
#Before we merge, detect if there are local changes and stash them.
|
45
|
+
stash_required = repo.dirty?
|
46
|
+
if stash_required
|
47
|
+
note "Working directory dirty. Stashing..."
|
48
|
+
repo.stash!
|
49
|
+
end
|
50
|
+
|
51
|
+
#Perform the merge, using --no-ff.
|
52
|
+
repo.merge_no_ff!(merge_target)
|
53
|
+
|
54
|
+
#If we stashed before, pop now.
|
55
|
+
if stash_required
|
56
|
+
note "Reapplying local changes..."
|
57
|
+
repo.stash_pop!
|
58
|
+
end
|
59
|
+
|
60
|
+
#Display a nice completion message in large, friendly letters.
|
61
|
+
success "All good. Created merge commit #{repo.sha('HEAD')[0,7]}."
|
62
|
+
end
|
63
|
+
end
|
data/lib/commands/smart-pull.rb
CHANGED
@@ -1,13 +1,22 @@
|
|
1
|
+
#Calling `git smart-pull` will fetch remote tracked changes
|
2
|
+
#and reapply your work on top of it. It's like a much, much
|
3
|
+
#smarter version of `git pull --rebase`.
|
4
|
+
#
|
5
|
+
#For some background as to why this is needed, see [my blog
|
6
|
+
#post about the perils of rebasing merge commits](https://gist.github.com/591209)
|
7
|
+
#
|
8
|
+
#This is how it works:
|
9
|
+
|
1
10
|
GitSmart.register 'smart-pull' do |repo, args|
|
2
|
-
#
|
11
|
+
#Let's begin!
|
3
12
|
branch = repo.current_branch
|
4
13
|
start "Starting: smart-pull on branch '#{branch}'"
|
5
14
|
|
6
|
-
#
|
15
|
+
#Let's not have any arguments, fellas.
|
7
16
|
warn "Ignoring arguments: #{args.inspect}" if !args.empty?
|
8
17
|
|
9
|
-
#
|
10
|
-
#
|
18
|
+
#Try grabbing the tracking remote from the config. If it doesn't exist,
|
19
|
+
#notify the user and default to 'origin'
|
11
20
|
tracking_remote = repo.tracking_remote ||
|
12
21
|
note("No tracking remote configured, assuming 'origin'") ||
|
13
22
|
'origin'
|
@@ -16,58 +25,77 @@ GitSmart.register 'smart-pull' do |repo, args|
|
|
16
25
|
# but generally that's a good thing. This is the only communication we need to do with the server.
|
17
26
|
repo.fetch!(tracking_remote)
|
18
27
|
|
19
|
-
#
|
20
|
-
#
|
28
|
+
#Try grabbing the tracking branch from the config. If it doesn't exist,
|
29
|
+
#notify the user and choose the branch of the same name
|
21
30
|
tracking_branch = repo.tracking_branch ||
|
22
31
|
note("No tracking branch configured, assuming '#{branch}'") ||
|
23
32
|
branch
|
24
33
|
|
25
|
-
#
|
34
|
+
#Check the specified upstream branch exists. Fail if it doesn't.
|
26
35
|
upstream_branch = "#{tracking_remote}/#{tracking_branch}"
|
27
36
|
failure("Upstream branch '#{upstream_branch}' doesn't exist!") if !repo.exists?(upstream_branch)
|
28
37
|
|
38
|
+
#Grab the SHAs of the commits we'll be working with.
|
29
39
|
head = repo.sha('HEAD')
|
30
40
|
remote = repo.sha(upstream_branch)
|
31
41
|
|
42
|
+
#If both HEAD and our upstream_branch resolve to the same SHA, there's nothing to do!
|
32
43
|
if head == remote
|
33
44
|
puts "Neither your local branch '#{branch}', nor the remote branch '#{upstream_branch}' have moved on."
|
34
45
|
success "Already up-to-date"
|
35
46
|
else
|
47
|
+
#Find out where the two branches diverged using merge-base. It's what git
|
48
|
+
#uses internally.
|
36
49
|
merge_base = repo.merge_base(head, remote)
|
37
50
|
|
51
|
+
#By comparing the merge_base to both HEAD and the remote, we can
|
52
|
+
#determine whether both or only one have moved on.
|
53
|
+
#If the remote hasn't changed, we're already up to date, so there's nothing
|
54
|
+
#to pull.
|
38
55
|
if merge_base == remote
|
39
56
|
puts "Remote branch '#{upstream_branch}' has not moved on."
|
40
57
|
success "Already up-to-date"
|
41
58
|
else
|
59
|
+
#If the remote _has_ moved on, we actually have some work to do:
|
60
|
+
#
|
61
|
+
#First, report how many commits are new on remote. Because that's useful information.
|
42
62
|
new_commits_on_remote = repo.rev_list(merge_base, remote)
|
43
63
|
is_are, s_or_not = (new_commits_on_remote.length == 1) ? ['is', ''] : ['are', 's']
|
44
|
-
note "There #{is_are} #{new_commits_on_remote.length} new commit#{s_or_not} on
|
64
|
+
note "There #{is_are} #{new_commits_on_remote.length} new commit#{s_or_not} on '#{upstream_branch}'."
|
45
65
|
|
66
|
+
#Next, detect if there are local changes and stash them.
|
46
67
|
stash_required = repo.dirty?
|
47
68
|
if stash_required
|
48
69
|
note "Working directory dirty. Stashing..."
|
49
70
|
repo.stash!
|
50
|
-
else
|
51
|
-
puts "No uncommitted changes, no need to stash."
|
52
71
|
end
|
53
72
|
|
54
73
|
success_messages = []
|
55
74
|
|
75
|
+
#Then, bring the local branch up to date.
|
76
|
+
#
|
77
|
+
#If our local branch hasn't moved on, that's easy - we just need to fast-forward.
|
56
78
|
if merge_base == head
|
57
79
|
puts "Local branch '#{branch}' has not moved on. Fast-forwarding..."
|
58
80
|
repo.fast_forward!(upstream_branch)
|
59
81
|
success_messages << "Fast forwarded from #{head[0,7]} to #{remote[0,7]}"
|
60
82
|
else
|
83
|
+
#If our local branch has new commits, we need to rebase them on top of master.
|
84
|
+
#
|
85
|
+
#When we rebase, we use `git rebase -p`, which attempts to recreate merges
|
86
|
+
#instead of ignoring them. For a description as to why, see my [blog post]((https://gist.github.com/591209).
|
61
87
|
note "Both local and remote branches have moved on. Branch 'master' needs to be rebased onto 'origin/master'"
|
62
88
|
repo.rebase_preserving_merges!(upstream_branch)
|
63
89
|
success_messages << "HEAD moved from #{head[0,7]} to #{repo.sha('HEAD')[0,7]}."
|
64
90
|
end
|
65
91
|
|
92
|
+
#If we stashed before, pop now.
|
66
93
|
if stash_required
|
67
94
|
note "Reapplying local changes..."
|
68
95
|
repo.stash_pop!
|
69
96
|
end
|
70
97
|
|
98
|
+
#Display a nice completion message in large, friendly letters.
|
71
99
|
success ["All good.", *success_messages].join(" ")
|
72
100
|
end
|
73
101
|
|
data/lib/git-smart/git_repo.rb
CHANGED
@@ -22,7 +22,9 @@ class GitRepo
|
|
22
22
|
def tracking_branch
|
23
23
|
key = "branch.#{current_branch}.merge"
|
24
24
|
value = config(key)
|
25
|
-
if value
|
25
|
+
if value.nil?
|
26
|
+
value
|
27
|
+
elsif value =~ /^refs\/heads\/(.*)$/
|
26
28
|
$1
|
27
29
|
else
|
28
30
|
raise GitSmart::UnexpectedOutput.new("Expected the config of '#{key}' to be /refs/heads/branchname, got '#{value}'")
|
@@ -30,7 +32,7 @@ class GitRepo
|
|
30
32
|
end
|
31
33
|
|
32
34
|
def fetch!(remote)
|
33
|
-
|
35
|
+
git!('fetch', remote)
|
34
36
|
end
|
35
37
|
|
36
38
|
def merge_base(ref_a, ref_b)
|
@@ -61,6 +63,7 @@ class GitRepo
|
|
61
63
|
when /^M/; :modified
|
62
64
|
when /^A/; :added
|
63
65
|
when /^\?\?/; :untracked
|
66
|
+
when /^UU/; :conflicted
|
64
67
|
else raise GitSmart::UnexpectedOutput.new("Expected the output of git status to only have lines starting with A,M, or ??. Got: \n#{raw_status}")
|
65
68
|
end
|
66
69
|
}
|
@@ -71,19 +74,19 @@ class GitRepo
|
|
71
74
|
end
|
72
75
|
|
73
76
|
def fast_forward!(upstream)
|
74
|
-
|
77
|
+
git!('merge', '--ff-only', upstream)
|
75
78
|
end
|
76
79
|
|
77
80
|
def stash!
|
78
|
-
|
81
|
+
git!('stash')
|
79
82
|
end
|
80
83
|
|
81
84
|
def stash_pop!
|
82
|
-
|
85
|
+
git!('stash', 'pop')
|
83
86
|
end
|
84
87
|
|
85
88
|
def rebase_preserving_merges!(upstream)
|
86
|
-
|
89
|
+
git!('rebase', '-p', upstream)
|
87
90
|
end
|
88
91
|
|
89
92
|
def log(nr)
|
@@ -94,16 +97,22 @@ class GitRepo
|
|
94
97
|
log(nr).map(&:last)
|
95
98
|
end
|
96
99
|
|
100
|
+
def merge_no_ff!(target)
|
101
|
+
git!('merge', '--no-ff', target)
|
102
|
+
end
|
103
|
+
|
97
104
|
# helper methods, left public in case other commands want to use them directly
|
98
105
|
|
99
106
|
def git(*args)
|
100
|
-
|
107
|
+
output = exec_git(*args)
|
108
|
+
$?.success? ? output : ''
|
101
109
|
end
|
102
110
|
|
103
|
-
def
|
111
|
+
def git!(*args)
|
104
112
|
puts "Executing: #{['git', *args].join(" ")}"
|
105
|
-
output =
|
106
|
-
|
113
|
+
output = exec_git(*args)
|
114
|
+
to_display = output.split("\n").map { |l| " #{l}" }.join("\n")
|
115
|
+
$?.success? ? puts(to_display) : raise(GitSmart::UnexpectedOutput.new(to_display))
|
107
116
|
output
|
108
117
|
end
|
109
118
|
|
@@ -111,4 +120,12 @@ class GitRepo
|
|
111
120
|
remote = git('config', name).chomp
|
112
121
|
remote.empty? ? nil : remote
|
113
122
|
end
|
123
|
+
|
124
|
+
private
|
125
|
+
|
126
|
+
def exec_git(*args)
|
127
|
+
Dir.chdir(@dir) {
|
128
|
+
SafeShell.execute('git', *args)
|
129
|
+
}
|
130
|
+
end
|
114
131
|
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/spec_helper'
|
2
|
+
|
3
|
+
require 'fileutils'
|
4
|
+
|
5
|
+
describe 'smart-merge with failures' do
|
6
|
+
def local_dir; WORKING_DIR + '/local'; end
|
7
|
+
|
8
|
+
before :each do
|
9
|
+
%x[
|
10
|
+
cd #{WORKING_DIR}
|
11
|
+
mkdir local
|
12
|
+
cd local
|
13
|
+
git init
|
14
|
+
echo -e 'one\ntwo\nthree\nfour\n' > README
|
15
|
+
mkdir lib
|
16
|
+
echo 'puts "pro hax"' > lib/codes.rb
|
17
|
+
git add .
|
18
|
+
git commit -m 'first'
|
19
|
+
]
|
20
|
+
end
|
21
|
+
|
22
|
+
context "with conflicting changes on master and newbranch" do
|
23
|
+
before :each do
|
24
|
+
%x[
|
25
|
+
cd #{local_dir}
|
26
|
+
git checkout -b newbranch 2> /dev/null
|
27
|
+
echo 'one\nnewbranch changes\nfour\n' > README
|
28
|
+
git commit -am 'newbranch_commit'
|
29
|
+
|
30
|
+
git checkout master 2> /dev/null
|
31
|
+
|
32
|
+
echo 'one\nmaster changes\nfour\n' > README
|
33
|
+
git commit -am 'master_commit'
|
34
|
+
]
|
35
|
+
end
|
36
|
+
|
37
|
+
it "should report the failure and give instructions to the user" do
|
38
|
+
out = run_command(local_dir, 'smart-merge', 'newbranch')
|
39
|
+
local_dir.should have_git_status(:conflicted => ['README'])
|
40
|
+
out.should_not report("All good")
|
41
|
+
out.should report("Executing: git merge --no-ff newbranch")
|
42
|
+
out.should report("CONFLICT (content): Merge conflict in README")
|
43
|
+
out.should report("Automatic merge failed; fix conflicts and then commit the result.")
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,101 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/spec_helper'
|
2
|
+
|
3
|
+
require 'fileutils'
|
4
|
+
|
5
|
+
describe 'smart-merge' do
|
6
|
+
def local_dir; WORKING_DIR + '/local'; end
|
7
|
+
|
8
|
+
before :each do
|
9
|
+
%x[
|
10
|
+
cd #{WORKING_DIR}
|
11
|
+
mkdir local
|
12
|
+
cd local
|
13
|
+
git init
|
14
|
+
echo 'hurr durr' > README
|
15
|
+
mkdir lib
|
16
|
+
echo 'puts "pro hax"' > lib/codes.rb
|
17
|
+
git add .
|
18
|
+
git commit -m 'first'
|
19
|
+
]
|
20
|
+
end
|
21
|
+
|
22
|
+
it "should require an argument" do
|
23
|
+
out = run_command(local_dir, 'smart-merge')
|
24
|
+
out.should report("Usage: git smart-merge ref")
|
25
|
+
end
|
26
|
+
|
27
|
+
it "should require a valid branch" do
|
28
|
+
out = run_command(local_dir, 'smart-merge', 'foo')
|
29
|
+
out.should report("Branch to merge 'foo' not recognised by git!")
|
30
|
+
end
|
31
|
+
|
32
|
+
it "should report nothing to do if the branch hasn't moved on" do
|
33
|
+
%x[
|
34
|
+
cd #{local_dir}
|
35
|
+
git branch unmoved
|
36
|
+
]
|
37
|
+
out = run_command(local_dir, 'smart-merge', 'unmoved')
|
38
|
+
out.should report("Branch 'unmoved' has no new commits. Nothing to merge in.")
|
39
|
+
out.should report("Already up-to-date.")
|
40
|
+
end
|
41
|
+
|
42
|
+
context "with local changes to newbranch" do
|
43
|
+
before :each do
|
44
|
+
%x[
|
45
|
+
cd #{local_dir}
|
46
|
+
git checkout -b newbranch 2> /dev/null
|
47
|
+
echo 'moar things!' >> README
|
48
|
+
echo 'puts "moar code!"' >> lib/moar.rb
|
49
|
+
git add .
|
50
|
+
git commit -m 'moar'
|
51
|
+
|
52
|
+
git checkout master 2> /dev/null
|
53
|
+
]
|
54
|
+
end
|
55
|
+
|
56
|
+
it "should merge --no-ff, despite the branch being fast-forwardable" do
|
57
|
+
out = run_command(local_dir, 'smart-merge', 'newbranch')
|
58
|
+
out.should report("Branch 'newbranch' has diverged by 1 commit. Merging in.")
|
59
|
+
out.should report("* Branch 'master' has not moved on since 'newbranch' diverged. Running with --no-ff anyway, since a fast-forward is unexpected behaviour.")
|
60
|
+
out.should report("Executing: git merge --no-ff newbranch")
|
61
|
+
out.should report("2 files changed, 2 insertions(+), 0 deletions(-)")
|
62
|
+
out.should report(/All good\. Created merge commit [\w]{7}\./)
|
63
|
+
end
|
64
|
+
|
65
|
+
context "and changes on master" do
|
66
|
+
before :each do
|
67
|
+
%x[
|
68
|
+
cd #{local_dir}
|
69
|
+
echo "puts 'moar codes too!'" >> lib/codes.rb
|
70
|
+
git add .
|
71
|
+
git commit -m 'changes on master'
|
72
|
+
]
|
73
|
+
end
|
74
|
+
|
75
|
+
it "should merge in ok" do
|
76
|
+
out = run_command(local_dir, 'smart-merge', 'newbranch')
|
77
|
+
out.should report("Branch 'newbranch' has diverged by 1 commit. Merging in.")
|
78
|
+
out.should report("Branch 'master' has 1 new commit since 'newbranch' diverged.")
|
79
|
+
out.should report("Executing: git merge --no-ff newbranch")
|
80
|
+
out.should report("2 files changed, 2 insertions(+), 0 deletions(-)")
|
81
|
+
out.should report(/All good\. Created merge commit [\w]{7}\./)
|
82
|
+
end
|
83
|
+
|
84
|
+
it "should stash then merge if working tree is dirty" do
|
85
|
+
%x[
|
86
|
+
cd #{local_dir}
|
87
|
+
echo "i am nub" > noob
|
88
|
+
echo "puts 'moar codes too!'" >> lib/codes.rb
|
89
|
+
git add noob
|
90
|
+
]
|
91
|
+
out = run_command(local_dir, 'smart-merge', 'newbranch')
|
92
|
+
out.should report("Executing: git stash")
|
93
|
+
out.should report("Executing: git merge --no-ff newbranch")
|
94
|
+
out.should report("2 files changed, 2 insertions(+), 0 deletions(-)")
|
95
|
+
out.should report("Reapplying local changes...")
|
96
|
+
out.should report("Executing: git stash pop")
|
97
|
+
out.should report(/All good\. Created merge commit [\w]{7}\./)
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|