git-smart 0.1.3 → 0.1.4
Sign up to get free protection for your applications and to get access to all the features.
- 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
|