git-fast-forward 0.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.markdown +42 -0
- data/bin/git-fast-forward +12 -0
- data/lib/git-fast-forward.rb +1 -0
- data/spec/git-fast-forward_spec.rb +93 -0
- metadata +64 -0
data/README.markdown
ADDED
@@ -0,0 +1,42 @@
|
|
1
|
+
git fast-forward
|
2
|
+
================
|
3
|
+
|
4
|
+
`git fast-forward` is a git command which fast-forwards a branch to another commit. It works just like merge, except that it never produces a merge commit. Thus, it only works when you're fast-forwarding to a commit that's a descendent of the current branch.
|
5
|
+
|
6
|
+
Workflow
|
7
|
+
--------
|
8
|
+
|
9
|
+
Here's how my team usually works:
|
10
|
+
|
11
|
+
master$ git pull --rebase
|
12
|
+
master$ git checkout -b new-feature
|
13
|
+
new-feature$ touch lib/new_code.rb
|
14
|
+
new-feature$ git add lib/new_code.rb
|
15
|
+
new-feature$ git commit -m "Implement awesome new feature."
|
16
|
+
|
17
|
+
[meanwhile, other people have pushed new code to master...]
|
18
|
+
|
19
|
+
new-feature$ git fetch
|
20
|
+
new-feature$ git rebase origin/master
|
21
|
+
new-feature$ git checkout master
|
22
|
+
master$ git merge new-feature ### <--- The problem.
|
23
|
+
master$ git push
|
24
|
+
|
25
|
+
This usually works fine, but the last part always bugs me. We rebase to keep a linear history---that's how we like it, as much as possible. But we use the merge command, which, if things aren't rebased quite right, will make a merge commit, which is exactly what we don't want. Usually, we won't notice it until it's pushed. Doesn't happen a lot, but enough to write a better tool.
|
26
|
+
|
27
|
+
|
28
|
+
Usage
|
29
|
+
-----
|
30
|
+
|
31
|
+
It's pretty straightforward:
|
32
|
+
|
33
|
+
$ gem install git-fast-forward # or whatever
|
34
|
+
$ git fast-forward <commit>
|
35
|
+
|
36
|
+
where `<commit>` is probably a topic branch you've just rebased. If the commit isn't a descendent of your current commit (and therefore not eligible for fast-forwarding), you'll get a nice error message and that's that. Otherwise, it'll fast forward just like `merge`. In fact, it even *calls* `merge`. So you'll get all that nice output.
|
37
|
+
|
38
|
+
|
39
|
+
Bugs, Requests, and Contributions
|
40
|
+
---------------------------------
|
41
|
+
|
42
|
+
This thing's pretty darn simple. If you'd like it to do something it doesn't, feel free to [add an issue](http://github.com/Peeja/git-fast-forward/issues). Same goes for bugs. Patches and pull requests are certainly welcome.
|
@@ -0,0 +1,12 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
destination = ARGV[0]
|
4
|
+
|
5
|
+
destination_is_a_descendent_of_head = (`git merge-base HEAD #{destination}` == `git rev-parse HEAD`)
|
6
|
+
|
7
|
+
if destination_is_a_descendent_of_head
|
8
|
+
system("git merge #{destination}")
|
9
|
+
else
|
10
|
+
$stderr.puts("#{destination} is not a descendent of the current branch. Refusing to fast-forward.")
|
11
|
+
exit 1
|
12
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
# Nothing to see here. Just keeps rubygems happy.
|
@@ -0,0 +1,93 @@
|
|
1
|
+
require 'spec'
|
2
|
+
|
3
|
+
ENV['PATH'] = "#{File.dirname(__FILE__) + '/../bin'}:#{ENV['PATH']}"
|
4
|
+
|
5
|
+
describe "git fast-forward" do
|
6
|
+
before do
|
7
|
+
system <<-SH
|
8
|
+
rm -rf test-repo
|
9
|
+
mkdir test-repo
|
10
|
+
cd test-repo
|
11
|
+
git init
|
12
|
+
SH
|
13
|
+
end
|
14
|
+
|
15
|
+
after do
|
16
|
+
system <<-SH
|
17
|
+
rm -rf test-repo
|
18
|
+
SH
|
19
|
+
end
|
20
|
+
|
21
|
+
def run(commands)
|
22
|
+
commands.split("\n").each do |command|
|
23
|
+
command = command.strip
|
24
|
+
next if command.empty?
|
25
|
+
puts
|
26
|
+
puts ">> #{command}"
|
27
|
+
system "cd test-repo && #{command}"
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def commit_named(commit_name)
|
32
|
+
`cd test-repo && git rev-parse --revs-only #{commit_name}`
|
33
|
+
end
|
34
|
+
|
35
|
+
context "the given commit is a descendent of the current branch" do
|
36
|
+
before do
|
37
|
+
run <<-SH
|
38
|
+
touch initial-file
|
39
|
+
git add initial-file
|
40
|
+
git commit -m "Initial commit."
|
41
|
+
git branch parent-branch
|
42
|
+
git checkout -b descendent-branch
|
43
|
+
touch new-file
|
44
|
+
git add new-file
|
45
|
+
git commit -m "Adding new-file."
|
46
|
+
SH
|
47
|
+
end
|
48
|
+
|
49
|
+
it "sets the current branch to the descendent commit" do
|
50
|
+
descendent_commit = commit_named("descendent-branch")
|
51
|
+
|
52
|
+
run <<-SH
|
53
|
+
git checkout parent-branch
|
54
|
+
git fast-forward descendent-branch
|
55
|
+
SH
|
56
|
+
|
57
|
+
commit_named("parent-branch").should == descendent_commit
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
context "the given commit is not a descendent of the current branch" do
|
62
|
+
before do
|
63
|
+
run <<-SH
|
64
|
+
touch initial-file
|
65
|
+
git add initial-file
|
66
|
+
git commit -m "Initial commit."
|
67
|
+
git checkout -b first-branch
|
68
|
+
|
69
|
+
git branch other-branch
|
70
|
+
touch second-file
|
71
|
+
git add second-file
|
72
|
+
git commit -m "Second commit."
|
73
|
+
|
74
|
+
git checkout other-branch
|
75
|
+
touch new-file
|
76
|
+
git add new-file
|
77
|
+
git commit -m "Adding new-file."
|
78
|
+
SH
|
79
|
+
end
|
80
|
+
|
81
|
+
it "exists with a status of 1 and leaves the branch where it is" do
|
82
|
+
first_branch_before_ff = commit_named("first-branch")
|
83
|
+
|
84
|
+
run <<-SH
|
85
|
+
git checkout first-branch
|
86
|
+
git fast-forward other-branch
|
87
|
+
SH
|
88
|
+
|
89
|
+
$?.exitstatus.should == 1
|
90
|
+
commit_named("first-branch").should == first_branch_before_ff
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
metadata
ADDED
@@ -0,0 +1,64 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: git-fast-forward
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease: false
|
5
|
+
segments:
|
6
|
+
- 0
|
7
|
+
- 0
|
8
|
+
- 0
|
9
|
+
version: 0.0.0
|
10
|
+
platform: ruby
|
11
|
+
authors:
|
12
|
+
- Peter Jaros
|
13
|
+
autorequire:
|
14
|
+
bindir: bin
|
15
|
+
cert_chain: []
|
16
|
+
|
17
|
+
date: 2010-10-02 00:00:00 -04:00
|
18
|
+
default_executable: git-fast-forward
|
19
|
+
dependencies: []
|
20
|
+
|
21
|
+
description: Git command that works like merge, but never creates a merge commit.
|
22
|
+
email: peter.a.jaros@gmail.com
|
23
|
+
executables:
|
24
|
+
- git-fast-forward
|
25
|
+
extensions: []
|
26
|
+
|
27
|
+
extra_rdoc_files:
|
28
|
+
- README.markdown
|
29
|
+
files:
|
30
|
+
- bin/git-fast-forward
|
31
|
+
- lib/git-fast-forward.rb
|
32
|
+
- README.markdown
|
33
|
+
has_rdoc: true
|
34
|
+
homepage: http://github.com/Peeja/git-fast-forward
|
35
|
+
licenses: []
|
36
|
+
|
37
|
+
post_install_message:
|
38
|
+
rdoc_options:
|
39
|
+
- --charset=UTF-8
|
40
|
+
require_paths:
|
41
|
+
- lib
|
42
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
43
|
+
requirements:
|
44
|
+
- - ">="
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
segments:
|
47
|
+
- 0
|
48
|
+
version: "0"
|
49
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
50
|
+
requirements:
|
51
|
+
- - ">="
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
segments:
|
54
|
+
- 0
|
55
|
+
version: "0"
|
56
|
+
requirements: []
|
57
|
+
|
58
|
+
rubyforge_project:
|
59
|
+
rubygems_version: 1.3.6
|
60
|
+
signing_key:
|
61
|
+
specification_version: 3
|
62
|
+
summary: Git command that works like merge, but never creates a merge commit.
|
63
|
+
test_files:
|
64
|
+
- spec/git-fast-forward_spec.rb
|