diff --git a/app/contexts/commit_load_context.rb b/app/contexts/commit_load_context.rb
index 1f23f633af322e528211a3b14b71b49c9fd1aa20..2cf5420d62dae3900dc935f6bf546559d696ae58 100644
--- a/app/contexts/commit_load_context.rb
+++ b/app/contexts/commit_load_context.rb
@@ -12,7 +12,6 @@ class CommitLoadContext < BaseContext
     commit = project.repository.commit(params[:id])
 
     if commit
-      commit = CommitDecorator.decorate(commit)
       line_notes = project.notes.for_commit_id(commit.id).inline
 
       result[:commit] = commit
diff --git a/app/controllers/blame_controller.rb b/app/controllers/blame_controller.rb
index 76caa4a69c4dea822b80b238a39879892c4d8914..310b567cfe6481df4e9c35715f12444729a6b6b1 100644
--- a/app/controllers/blame_controller.rb
+++ b/app/controllers/blame_controller.rb
@@ -8,7 +8,6 @@ class BlameController < ProjectResourceController
   before_filter :require_non_empty_project
 
   def show
-    @repo = @project.repo
-    @blame = Grit::Blob.blame(@repo, @commit.id, @path)
+    @blame = Gitlab::Git::Blame.new(project.repository, @commit.id, @path)
   end
 end
diff --git a/app/controllers/commits_controller.rb b/app/controllers/commits_controller.rb
index 9dc0d96883e3351082497b7bd8ed6b863aa10e0f..cde1f459d76c779cacf07a0518dd0d7db59c7b41 100644
--- a/app/controllers/commits_controller.rb
+++ b/app/controllers/commits_controller.rb
@@ -13,7 +13,6 @@ class CommitsController < ProjectResourceController
     @limit, @offset = (params[:limit] || 40), (params[:offset] || 0)
 
     @commits = @repo.commits(@ref, @path, @limit, @offset)
-    @commits = CommitDecorator.decorate_collection(@commits)
 
     respond_to do |format|
       format.html # index.html.erb
diff --git a/app/controllers/compare_controller.rb b/app/controllers/compare_controller.rb
index bd3f111517366c4183b1e9cb77e49c540939f60d..750e9c2380ef821c6835547c51d80f3d2fd8887d 100644
--- a/app/controllers/compare_controller.rb
+++ b/app/controllers/compare_controller.rb
@@ -8,15 +8,13 @@ class CompareController < ProjectResourceController
   end
 
   def show
-    result = Commit.compare(project, params[:from], params[:to])
+    compare = Gitlab::Git::Compare.new(project.repository, params[:from], params[:to])
 
-    @commits       = result[:commits]
-    @commit        = result[:commit]
-    @diffs         = result[:diffs]
-    @refs_are_same = result[:same]
+    @commits       = compare.commits
+    @commit        = compare.commit
+    @diffs         = compare.diffs
+    @refs_are_same = compare.same
     @line_notes    = []
-
-    @commits = CommitDecorator.decorate_collection(@commits)
   end
 
   def create
diff --git a/app/controllers/merge_requests_controller.rb b/app/controllers/merge_requests_controller.rb
index e2185361f4f75dc85124fc496b0b725d5fa5b99c..1950ebb29c7cb9755354e55456b7e687d2a75dca 100644
--- a/app/controllers/merge_requests_controller.rb
+++ b/app/controllers/merge_requests_controller.rb
@@ -94,12 +94,10 @@ class MergeRequestsController < ProjectResourceController
 
   def branch_from
     @commit = @repository.commit(params[:ref])
-    @commit = CommitDecorator.decorate(@commit)
   end
 
   def branch_to
     @commit = @repository.commit(params[:ref])
-    @commit = CommitDecorator.decorate(@commit)
   end
 
   def ci_status
@@ -143,7 +141,6 @@ class MergeRequestsController < ProjectResourceController
     # Get commits from repository
     # or from cache if already merged
     @commits = @merge_request.commits
-    @commits = CommitDecorator.decorate_collection(@commits)
 
     @allowed_to_merge = allowed_to_merge?
     @show_merge_controls = @merge_request.opened? && @commits.any? && @allowed_to_merge
diff --git a/app/controllers/refs_controller.rb b/app/controllers/refs_controller.rb
index 0e4dba3dc4b0074ae4d965b15a6979551aa69556..eb8d1e19616d98a446a05832205900e23efb82ad 100644
--- a/app/controllers/refs_controller.rb
+++ b/app/controllers/refs_controller.rb
@@ -34,7 +34,6 @@ class RefsController < ProjectResourceController
     @logs = contents.map do |content|
       file = params[:path] ? File.join(params[:path], content.name) : content.name
       last_commit = @repo.commits(@commit.id, file, 1).last
-      last_commit = CommitDecorator.decorate(last_commit)
       {
         file_name: content.name,
         commit: last_commit
@@ -49,9 +48,7 @@ class RefsController < ProjectResourceController
 
     @repo = project.repository
     @commit = @repo.commit(@ref)
-    @commit = CommitDecorator.decorate(@commit)
     @tree = Tree.new(@commit.tree, @ref, params[:path])
-    @tree = TreeDecorator.new(@tree)
     @hex_path = Digest::SHA1.hexdigest(params[:path] || "")
 
     if params[:path]
diff --git a/app/decorators/commit_decorator.rb b/app/decorators/commit_decorator.rb
deleted file mode 100644
index 0337d8d43ceeb6c67ea07878d8b94d60f4358e4b..0000000000000000000000000000000000000000
--- a/app/decorators/commit_decorator.rb
+++ /dev/null
@@ -1,93 +0,0 @@
-class CommitDecorator < ApplicationDecorator
-  decorates :commit
-
-  # Returns a string describing the commit for use in a link title
-  #
-  # Example
-  #
-  #   "Commit: Alex Denisov - Project git clone panel"
-  def link_title
-    "Commit: #{author_name} - #{title}"
-  end
-
-  # Returns the commits title.
-  #
-  # Usually, the commit title is the first line of the commit message.
-  # In case this first line is longer than 80 characters, it is cut off
-  # after 70 characters and ellipses (`&hellp;`) are appended.
-  def title
-    title = safe_message
-
-    return no_commit_message if title.blank?
-
-    title_end = title.index(/\n/)
-    if (!title_end && title.length > 80) || (title_end && title_end > 80)
-      title[0..69] << "&hellip;".html_safe
-    else
-      title.split(/\n/, 2).first
-    end
-  end
-
-  # Returns the commits description
-  #
-  # cut off, ellipses (`&hellp;`) are prepended to the commit message.
-  def description
-    description = safe_message
-
-    title_end = description.index(/\n/)
-    if (!title_end && description.length > 80) || (title_end && title_end > 80)
-      "&hellip;".html_safe << description[70..-1]
-    else
-      description.split(/\n/, 2)[1].try(:chomp)
-    end
-  end
-
-  # Returns a link to the commit author. If the author has a matching user and
-  # is a member of the current @project it will link to the team member page.
-  # Otherwise it will link to the author email as specified in the commit.
-  #
-  # options:
-  #  avatar: true will prepend the avatar image
-  #  size:   size of the avatar image in px
-  def author_link(options = {})
-    person_link(options.merge source: :author)
-  end
-
-  # Just like #author_link but for the committer.
-  def committer_link(options = {})
-    person_link(options.merge source: :committer)
-  end
-
-  protected
-
-  def no_commit_message
-    "--no commit message"
-  end
-
-  # Private: Returns a link to a person. If the person has a matching user and
-  # is a member of the current @project it will link to the team member page.
-  # Otherwise it will link to the person email as specified in the commit.
-  #
-  # options:
-  #  source: one of :author or :committer
-  #  avatar: true will prepend the avatar image
-  #  size:   size of the avatar image in px
-  def person_link(options = {})
-    source_name = send "#{options[:source]}_name".to_sym
-    source_email = send "#{options[:source]}_email".to_sym
-    text = if options[:avatar]
-            avatar = h.image_tag h.gravatar_icon(source_email, options[:size]), class: "avatar #{"s#{options[:size]}" if options[:size]}", width: options[:size], alt: ""
-            %Q{#{avatar} <span class="commit-#{options[:source]}-name">#{source_name}</span>}
-          else
-            source_name
-          end
-
-    user = User.where('name like ? or email like ?', source_name, source_email).first
-
-    if user.nil?
-      h.mail_to(source_email, text.html_safe, class: "commit-#{options[:source]}-link")
-    else
-      h.link_to(text.html_safe, h.user_path(user), class: "commit-#{options[:source]}-link")
-    end
-  end
-end
diff --git a/app/decorators/tree_decorator.rb b/app/decorators/tree_decorator.rb
deleted file mode 100644
index 0e760f97dee3c64afc8eb80c9167a56b2328f48a..0000000000000000000000000000000000000000
--- a/app/decorators/tree_decorator.rb
+++ /dev/null
@@ -1,33 +0,0 @@
-class TreeDecorator < ApplicationDecorator
-  decorates :tree
-
-  def breadcrumbs(max_links = 2)
-    if path
-      part_path = ""
-      parts = path.split("\/")
-
-      yield('..', nil) if parts.count > max_links
-
-      parts.each do |part|
-        part_path = File.join(part_path, part) unless part_path.empty?
-        part_path = part if part_path.empty?
-
-        next unless parts.last(2).include?(part) if parts.count > max_links
-        yield(part, h.tree_join(ref, part_path))
-      end
-    end
-  end
-
-  def up_dir?
-    path.present?
-  end
-
-  def up_dir_path
-    file = File.join(path, "..")
-    h.tree_join(ref, file)
-  end
-
-  def readme
-    @readme ||= contents.find { |c| c.is_a?(Grit::Blob) and c.name =~ /^readme/i }
-  end
-end
diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb
index f03039e4b7577c539d504260af9fc2c86c6e1e08..cb9cb1a3322fe4fc23598a5b18645c2cbd5286de 100644
--- a/app/helpers/application_helper.rb
+++ b/app/helpers/application_helper.rb
@@ -96,7 +96,7 @@ module ApplicationHelper
     ]
 
     project_nav = []
-    if @project && @project.repository && @project.repository.root_ref
+    if @project && @project.repository.exists? && @project.repository.root_ref
       project_nav = [
         { label: "#{simple_sanitize(@project.name_with_namespace)} - Issues",   url: project_issues_path(@project) },
         { label: "#{simple_sanitize(@project.name_with_namespace)} - Commits",  url: project_commits_path(@project, @ref || @project.repository.root_ref) },
diff --git a/app/helpers/commits_helper.rb b/app/helpers/commits_helper.rb
index acdd48e04eb2697d391bff401324ddaf00d514ca..95ca294cd2d6bd9ca8049da927c4f79e160494d0 100644
--- a/app/helpers/commits_helper.rb
+++ b/app/helpers/commits_helper.rb
@@ -1,4 +1,20 @@
 module CommitsHelper
+  # Returns a link to the commit author. If the author has a matching user and
+  # is a member of the current @project it will link to the team member page.
+  # Otherwise it will link to the author email as specified in the commit.
+  #
+  # options:
+  #  avatar: true will prepend the avatar image
+  #  size:   size of the avatar image in px
+  def commit_author_link(commit, options = {})
+    commit_person_link(commit, options.merge(source: :author))
+  end
+
+  # Just like #author_link but for the committer.
+  def commit_committer_link(commit, options = {})
+    commit_person_link(commit, options.merge(source: :committer))
+  end
+
   def identification_type(line)
     if line[0] == "+"
       "new"
@@ -93,9 +109,7 @@ module CommitsHelper
   end
 
   def commit_to_html commit
-    if commit.model
-      escape_javascript(render 'commits/commit', commit: commit)
-    end
+    escape_javascript(render 'commits/commit', commit: commit)
   end
 
   def diff_line_content(line)
@@ -105,4 +119,58 @@ module CommitsHelper
       line
     end
   end
+
+  # Breadcrumb links for a Project and, if applicable, a tree path
+  def commits_breadcrumbs
+    return unless @project && @ref
+
+    # Add the root project link and the arrow icon
+    crumbs = content_tag(:li) do
+      content_tag(:span, nil, class: 'arrow') +
+      link_to(@project.name, project_commits_path(@project, @ref))
+    end
+
+    if @path
+      parts = @path.split('/')
+
+      parts.each_with_index do |part, i|
+        crumbs += content_tag(:span, '/', class: 'divider')
+        crumbs += content_tag(:li) do
+          # The text is just the individual part, but the link needs all the parts before it
+          link_to part, project_commits_path(@project, tree_join(@ref, parts[0..i].join('/')))
+        end
+      end
+    end
+
+    crumbs.html_safe
+  end
+
+  protected
+
+  # Private: Returns a link to a person. If the person has a matching user and
+  # is a member of the current @project it will link to the team member page.
+  # Otherwise it will link to the person email as specified in the commit.
+  #
+  # options:
+  #  source: one of :author or :committer
+  #  avatar: true will prepend the avatar image
+  #  size:   size of the avatar image in px
+  def commit_person_link(commit, options = {})
+    source_name = commit.send "#{options[:source]}_name".to_sym
+    source_email = commit.send "#{options[:source]}_email".to_sym
+    text = if options[:avatar]
+            avatar = image_tag(gravatar_icon(source_email, options[:size]), class: "avatar #{"s#{options[:size]}" if options[:size]}", width: options[:size], alt: "")
+            %Q{#{avatar} <span class="commit-#{options[:source]}-name">#{source_name}</span>}
+          else
+            source_name
+          end
+
+    user = User.where('name like ? or email like ?', source_name, source_email).first
+
+    if user.nil?
+      mail_to(source_email, text.html_safe, class: "commit-#{options[:source]}-link")
+    else
+      link_to(text.html_safe, user_path(user), class: "commit-#{options[:source]}-link")
+    end
+  end
 end
diff --git a/app/helpers/tree_helper.rb b/app/helpers/tree_helper.rb
index fab0085ba73dd93687b6000bcdc6408835eb834c..1cba947617996a971f44922732e8a67ca3889cd3 100644
--- a/app/helpers/tree_helper.rb
+++ b/app/helpers/tree_helper.rb
@@ -70,28 +70,26 @@ module TreeHelper
     end
   end
 
-  # Breadcrumb links for a Project and, if applicable, a tree path
-  def breadcrumbs
-    return unless @project && @ref
-
-    # Add the root project link and the arrow icon
-    crumbs = content_tag(:li) do
-      content_tag(:span, nil, class: 'arrow') +
-      link_to(@project.name, project_commits_path(@project, @ref))
-    end
+  def tree_breadcrumbs(tree, max_links = 2)
+    if tree.path
+      part_path = ""
+      parts = tree.path.split("\/")
+
+      yield('..', nil) if parts.count > max_links
 
-    if @path
-      parts = @path.split('/')
+      parts.each do |part|
+        part_path = File.join(part_path, part) unless part_path.empty?
+        part_path = part if part_path.empty?
 
-      parts.each_with_index do |part, i|
-        crumbs += content_tag(:span, '/', class: 'divider')
-        crumbs += content_tag(:li) do
-          # The text is just the individual part, but the link needs all the parts before it
-          link_to part, project_commits_path(@project, tree_join(@ref, parts[0..i].join('/')))
-        end
+        next unless parts.last(2).include?(part) if parts.count > max_links
+        yield(part, tree_join(tree.ref, part_path))
       end
     end
+  end
 
-    crumbs.html_safe
+  def up_dir_path tree
+    file = File.join(tree.path, "..")
+    tree_join(tree.ref, file)
   end
+
 end
diff --git a/app/mailers/emails/notes.rb b/app/mailers/emails/notes.rb
index de51debfeb52bb4bd0af9fd03038d2e3983dcc0c..769b6e0b8611786458b18b4118f59d69dc8b6295 100644
--- a/app/mailers/emails/notes.rb
+++ b/app/mailers/emails/notes.rb
@@ -3,7 +3,6 @@ module Emails
     def note_commit_email(recipient_id, note_id)
       @note = Note.find(note_id)
       @commit = @note.noteable
-      @commit = CommitDecorator.decorate(@commit)
       @project = @note.project
       mail(to: recipient(recipient_id), subject: subject("note for commit #{@commit.short_id}", @commit.title))
     end
diff --git a/app/models/commit.rb b/app/models/commit.rb
index 4d0c57b35fd918ced2d2c1c5fdcd5015302cb205..e3363350997ebc5ee1520e06d6a236e3f19e6b28 100644
--- a/app/models/commit.rb
+++ b/app/models/commit.rb
@@ -8,174 +8,70 @@ class Commit
   #
   DIFF_SAFE_SIZE = 100
 
-  attr_accessor :commit, :head, :refs
-
-  delegate  :message, :authored_date, :committed_date, :parents, :sha,
-            :date, :committer, :author, :diffs, :tree, :id, :stats,
-            :to_patch, to: :commit
-
-  class << self
-    def find_or_first(repo, commit_id = nil, root_ref)
-      commit = if commit_id
-                 repo.commit(commit_id)
-               else
-                 repo.commits(root_ref).first
-               end
-
-      Commit.new(commit) if commit
-    end
-
-    def fresh_commits(repo, n = 10)
-      commits = repo.heads.map do |h|
-        repo.commits(h.name, n).map { |c| Commit.new(c, h) }
-      end.flatten.uniq { |c| c.id }
-
-      commits.sort! do |x, y|
-        y.committed_date <=> x.committed_date
-      end
-
-      commits[0...n]
-    end
-
-    def commits_with_refs(repo, n = 20)
-      commits = repo.branches.map { |ref| Commit.new(ref.commit, ref) }
-
-      commits.sort! do |x, y|
-        y.committed_date <=> x.committed_date
-      end
-
-      commits[0..n]
-    end
-
-    def commits_since(repo, date)
-      commits = repo.heads.map do |h|
-        repo.log(h.name, nil, since: date).each { |c| Commit.new(c, h) }
-      end.flatten.uniq { |c| c.id }
-
-      commits.sort! do |x, y|
-        y.committed_date <=> x.committed_date
-      end
-
-      commits
-    end
-
-    def commits(repo, ref, path = nil, limit = nil, offset = nil)
-      if path
-        repo.log(ref, path, max_count: limit, skip: offset)
-      elsif limit && offset
-        repo.commits(ref, limit, offset)
-      else
-        repo.commits(ref)
-      end.map{ |c| Commit.new(c) }
-    end
-
-    def commits_between(repo, from, to)
-      repo.commits_between(from, to).map { |c| Commit.new(c) }
-    end
-
-    def compare(project, from, to)
-      result = {
-        commits: [],
-        diffs: [],
-        commit: nil,
-        same: false
-      }
-
-      return result unless from && to
-
-      first = project.repository.commit(to.try(:strip))
-      last = project.repository.commit(from.try(:strip))
-
-      if first && last
-        result[:same] = (first.id == last.id)
-        result[:commits] = project.repo.commits_between(last.id, first.id).map {|c| Commit.new(c)}
-
-        # Dont load diff for 100+ commits
-        result[:diffs] = if result[:commits].size > 100
-                           []
-                         else
-                           project.repo.diff(last.id, first.id) rescue []
-                         end
-
-        result[:commit] = Commit.new(first)
-      end
-
-      result
-    end
-  end
-
-  def initialize(raw_commit, head = nil)
-    raise "Nil as raw commit passed" unless raw_commit
-
-    @commit = raw_commit
-    @head = head
-  end
-
-  def short_id(length = 10)
-    id.to_s[0..length]
+  def self.decorate(commits)
+    commits.map { |c| self.new(c) }
   end
 
-  def safe_message
-    @safe_message ||= message
-  end
-
-  def created_at
-    committed_date
-  end
+  attr_accessor :raw
 
-  def author_email
-    author.email
-  end
+  def initialize(raw_commit)
+    raise "Nil as raw commit passed" unless raw_commit
 
-  def author_name
-    author.name
+    @raw = raw_commit
   end
 
-  # Was this commit committed by a different person than the original author?
-  def different_committer?
-    author_name != committer_name || author_email != committer_email
+  def id
+    @raw.id
   end
 
-  def committer_name
-    committer.name
+  # Returns a string describing the commit for use in a link title
+  #
+  # Example
+  #
+  #   "Commit: Alex Denisov - Project git clone panel"
+  def link_title
+    "Commit: #{author_name} - #{title}"
   end
 
-  def committer_email
-    committer.email
+  # Returns the commits title.
+  #
+  # Usually, the commit title is the first line of the commit message.
+  # In case this first line is longer than 80 characters, it is cut off
+  # after 70 characters and ellipses (`&hellp;`) are appended.
+  def title
+    title = safe_message
+
+    return no_commit_message if title.blank?
+
+    title_end = title.index(/\n/)
+    if (!title_end && title.length > 80) || (title_end && title_end > 80)
+      title[0..69] << "&hellip;".html_safe
+    else
+      title.split(/\n/, 2).first
+    end
   end
 
-  def prev_commit
-    @prev_commit ||= if parents.present?
-                       Commit.new(parents.first)
-                     else
-                       nil
-                     end
+  # Returns the commits description
+  #
+  # cut off, ellipses (`&hellp;`) are prepended to the commit message.
+  def description
+    description = safe_message
+
+    title_end = description.index(/\n/)
+    if (!title_end && description.length > 80) || (title_end && title_end > 80)
+      "&hellip;".html_safe << description[70..-1]
+    else
+      description.split(/\n/, 2)[1].try(:chomp)
+    end
   end
 
-  def prev_commit_id
-    prev_commit.try :id
+  def method_missing(m, *args, &block)
+    @raw.send(m, *args, &block)
   end
 
-  # Shows the diff between the commit's parent and the commit.
-  #
-  # Cuts out the header and stats from #to_patch and returns only the diff.
-  def to_diff
-    # see Grit::Commit#show
-    patch = to_patch
-
-    # discard lines before the diff
-    lines = patch.split("\n")
-    while !lines.first.start_with?("diff --git") do
-      lines.shift
-    end
-    lines.pop if lines.last =~ /^[\d.]+$/ # Git version
-    lines.pop if lines.last == "-- "      # end of diff
-    lines.join("\n")
-  end
+  def respond_to?(method)
+    return true if @raw.respond_to?(method)
 
-  def has_zero_stats?
-    stats.total.zero?
-  rescue
-    true
+    super
   end
 end
diff --git a/app/models/gollum_wiki.rb b/app/models/gollum_wiki.rb
index a1ee3a0899a0980c572a633e0a711a2e1b581dc1..16e801c1fdb2856c2b286a9568ab5d47fec374c5 100644
--- a/app/models/gollum_wiki.rb
+++ b/app/models/gollum_wiki.rb
@@ -50,7 +50,7 @@ class GollumWiki
   # Returns the last 30 Commit objects across the entire
   # repository.
   def recent_history
-    Commit.fresh_commits(wiki.repo, 30)
+    Gitlab::Git::Commit.fresh_commits(wiki.repo, 30)
   end
 
   # Finds a page within the repository based on a tile
@@ -90,13 +90,17 @@ class GollumWiki
   private
 
   def create_repo!
-    if gitlab_shell.add_repository(path_with_namespace)
+    if init_repo(path_with_namespace)
       Gollum::Wiki.new(path_to_repo)
     else
       raise CouldNotCreateWikiError
     end
   end
 
+  def init_repo(path_with_namespace)
+    gitlab_shell.add_repository(path_with_namespace)
+  end
+
   def commit_details(action, message = nil, title = nil)
     commit_message = message || default_message(action, title)
 
@@ -114,5 +118,4 @@ class GollumWiki
   def path_to_repo
     @path_to_repo ||= File.join(Gitlab.config.gitlab_shell.repos_path, "#{path_with_namespace}.git")
   end
-
 end
diff --git a/app/models/merge_request.rb b/app/models/merge_request.rb
index 9d42b1e1f32c7d9f207ab03c27cbc13077bd5005..8d3780532f39f59da3cb751d641981c59fb89973 100644
--- a/app/models/merge_request.rb
+++ b/app/models/merge_request.rb
@@ -152,7 +152,17 @@ class MergeRequest < ActiveRecord::Base
   end
 
   def commits
-    st_commits || []
+    if st_commits.present?
+      # check if merge request commits are valid
+      if st_commits.first.respond_to?(:short_id)
+        st_commits
+      else
+        # if commits are invalid - simply reload it from repo
+        reloaded_commits
+      end
+    else
+      []
+    end
   end
 
   def probably_merged?
@@ -169,9 +179,8 @@ class MergeRequest < ActiveRecord::Base
   end
 
   def unmerged_commits
-    self.project.repo.
+    self.project.repository.
       commits_between(self.target_branch, self.source_branch).
-      map {|c| Commit.new(c)}.
       sort_by(&:created_at).
       reverse
   end
diff --git a/app/models/network/commit.rb b/app/models/network/commit.rb
index d0bc61c3bf79121379336d3cd71c15482ba5cd41..3cd0c015fa021edb2626836e820ddad609a691c8 100644
--- a/app/models/network/commit.rb
+++ b/app/models/network/commit.rb
@@ -8,7 +8,7 @@ module Network
     attr_accessor :time, :spaces, :parent_spaces
 
     def initialize(raw_commit, refs)
-      @commit = ::Commit.new(raw_commit)
+      @commit = Gitlab::Git::Commit.new(raw_commit)
       @time = -1
       @spaces = []
       @parent_spaces = []
diff --git a/app/models/project.rb b/app/models/project.rb
index 6871afca50a2f9348bbf323e9fe14fe32312a59f..0263ffefdf074a7597278e608c2187a87b945436 100644
--- a/app/models/project.rb
+++ b/app/models/project.rb
@@ -141,13 +141,7 @@ class Project < ActiveRecord::Base
   end
 
   def repository
-    if path
-      @repository ||= Repository.new(path_with_namespace, default_branch)
-    else
-      nil
-    end
-  rescue Grit::NoSuchPathError
-    nil
+    @repository ||= Repository.new(path_with_namespace, default_branch)
   end
 
   def saved?
@@ -332,14 +326,14 @@ class Project < ActiveRecord::Base
   end
 
   def valid_repo?
-    repo
+    repository.exists?
   rescue
     errors.add(:path, "Invalid repository path")
     false
   end
 
   def empty_repo?
-    !repository || repository.empty?
+    !repository.exists? || repository.empty?
   end
 
   def ensure_satellite_exists
@@ -363,7 +357,7 @@ class Project < ActiveRecord::Base
   end
 
   def repo_exists?
-    @repo_exists ||= (repository && repository.branches.present?)
+    @repo_exists ||= repository.exists?
   rescue
     @repo_exists = false
   end
diff --git a/app/models/repository.rb b/app/models/repository.rb
index 7f56047b3de6161b258f9b75b90b7b0f1b146c51..ed600e292326ea0605cf0f7de6125921ca58fe4b 100644
--- a/app/models/repository.rb
+++ b/app/models/repository.rb
@@ -1,170 +1,45 @@
 class Repository
-  include Gitlab::Popen
+  attr_accessor :raw_repository
 
-  # Repository directory name with namespace direcotry
-  # Examples:
-  #   gitlab/gitolite
-  #   diaspora
-  #
-  attr_accessor :path_with_namespace
-
-  # Grit repo object
-  attr_accessor :repo
-
-  # Default branch in the repository
-  attr_accessor :root_ref
-
-  def initialize(path_with_namespace, root_ref = 'master')
-    @root_ref = root_ref || "master"
-    @path_with_namespace = path_with_namespace
-
-    # Init grit repo object
-    repo
-  end
-
-  def raw
-    repo
-  end
-
-  def path_to_repo
-    @path_to_repo ||= File.join(Gitlab.config.gitlab_shell.repos_path, "#{path_with_namespace}.git")
-  end
-
-  def repo
-    @repo ||= Grit::Repo.new(path_to_repo)
-  end
-
-  def commit(commit_id = nil)
-    Commit.find_or_first(repo, commit_id, root_ref)
+  def initialize(path_with_namespace, default_branch)
+    @raw_repository = Gitlab::Git::Repository.new(path_with_namespace, default_branch)
+  rescue Gitlab::Git::Repository::NoRepository
+    nil
   end
 
-  def fresh_commits(n = 10)
-    Commit.fresh_commits(repo, n)
+  def exists?
+    raw_repository
   end
 
-  def commits_with_refs(n = 20)
-    Commit.commits_with_refs(repo, n)
+  def empty?
+    raw_repository.empty?
   end
 
-  def commits_since(date)
-    Commit.commits_since(repo, date)
+  def commit(id = nil)
+    commit = raw_repository.commit(id)
+    commit = Commit.new(commit) if commit
+    commit
   end
 
   def commits(ref, path = nil, limit = nil, offset = nil)
-    Commit.commits(repo, ref, path, limit, offset)
-  end
-
-  def last_commit_for(ref, path = nil)
-    commits(ref, path, 1).first
-  end
-
-  def commits_between(from, to)
-    Commit.commits_between(repo, from, to)
+    commits = raw_repository.commits(ref, path, limit, offset)
+    commits = Commit.decorate(commits) if commits.present?
+    commits
   end
 
-  # Returns an Array of branch names
-  # sorted by name ASC
-  def branch_names
-    branches.map(&:name)
+  def commits_between(target, source)
+    commits = raw_repository.commits_between(target, source)
+    commits = Commit.decorate(commits) if commits.present?
+    commits
   end
 
-  # Returns an Array of Branches
-  def branches
-    repo.branches.sort_by(&:name)
+  def method_missing(m, *args, &block)
+    raw_repository.send(m, *args, &block)
   end
 
-  # Returns an Array of tag names
-  def tag_names
-    repo.tags.collect(&:name).sort.reverse
-  end
-
-  # Returns an Array of Tags
-  def tags
-    repo.tags.sort_by(&:name).reverse
-  end
-
-  # Returns an Array of branch and tag names
-  def ref_names
-    [branch_names + tag_names].flatten
-  end
-
-  def heads
-    @heads ||= repo.heads
-  end
-
-  def tree(fcommit, path = nil)
-    fcommit = commit if fcommit == :head
-    tree = fcommit.tree
-    path ? (tree / path) : tree
-  end
-
-  def has_commits?
-    !!commit
-  rescue Grit::NoSuchPathError
-    false
-  end
-
-  def empty?
-    !has_commits?
-  end
-
-  # Discovers the default branch based on the repository's available branches
-  #
-  # - If no branches are present, returns nil
-  # - If one branch is present, returns its name
-  # - If two or more branches are present, returns the one that has a name
-  #   matching root_ref (default_branch or 'master' if default_branch is nil)
-  def discover_default_branch
-    if branch_names.length == 0
-      nil
-    elsif branch_names.length == 1
-      branch_names.first
-    else
-      branch_names.select { |v| v == root_ref }.first
-    end
-  end
-
-  # Archive Project to .tar.gz
-  #
-  # Already packed repo archives stored at
-  # app_root/tmp/repositories/project_name/project_name-commit-id.tag.gz
-  #
-  def archive_repo(ref)
-    ref = ref || self.root_ref
-    commit = self.commit(ref)
-    return nil unless commit
-
-    # Build file path
-    file_name = self.path_with_namespace.gsub("/","_") + "-" + commit.id.to_s + ".tar.gz"
-    storage_path = Rails.root.join("tmp", "repositories")
-    file_path = File.join(storage_path, self.path_with_namespace, file_name)
-
-    # Put files into a directory before archiving
-    prefix = File.basename(self.path_with_namespace) + "/"
-
-    # Create file if not exists
-    unless File.exists?(file_path)
-      FileUtils.mkdir_p File.dirname(file_path)
-      file = self.repo.archive_to_file(ref, prefix,  file_path)
-    end
-
-    file_path
-  end
-
-  # Return repo size in megabytes
-  # Cached in redis
-  def size
-    Rails.cache.fetch(cache_key(:size)) do
-      size = popen('du -s', path_to_repo).first.strip.to_i
-      (size.to_f / 1024).round(2)
-    end
-  end
-
-  def expire_cache
-    Rails.cache.delete(cache_key(:size))
-  end
+  def respond_to?(method)
+    return true if raw_repository.respond_to?(method)
 
-  def cache_key(type)
-    "#{type}:#{path_with_namespace}"
+    super
   end
 end
diff --git a/app/models/tree.rb b/app/models/tree.rb
index 96395a42394a75b77d08621ac6c046ddb26d99cb..4b6c5b133e9c3574018cc2934353792638d877ec 100644
--- a/app/models/tree.rb
+++ b/app/models/tree.rb
@@ -26,4 +26,12 @@ class Tree
   def empty?
     data.blank?
   end
+
+  def up_dir?
+    path.present?
+  end
+
+  def readme
+    @readme ||= contents.find { |c| c.is_a?(Grit::Blob) and c.name =~ /^readme/i }
+  end
 end
diff --git a/app/models/wiki_page.rb b/app/models/wiki_page.rb
index adc77b22231eb49b316f91022bae362d2c21f230..497d69e8e90bab7b1b3a2721454144541ff026f6 100644
--- a/app/models/wiki_page.rb
+++ b/app/models/wiki_page.rb
@@ -79,14 +79,14 @@ class WikiPage
   def version
     return nil unless persisted?
 
-    @version ||= Commit.new(@page.version)
+    @version ||= Commit.new(Gitlab::Git::Commit.new(@page.version))
   end
 
   # Returns an array of Gitlab Commit instances.
   def versions
     return [] unless persisted?
 
-    @page.versions.map { |v| Commit.new(v) }
+    @page.versions.map { |v| Commit.new(Gitlab::Git::Commit.new(v)) }
   end
 
   # Returns the Date that this latest version was
diff --git a/app/views/admin/projects/show.html.haml b/app/views/admin/projects/show.html.haml
index 27c687bb3927c896e08d7b8e9fae0b2688507077..92b8960151e89ff2e334d24904792b00c24cf869 100644
--- a/app/views/admin/projects/show.html.haml
+++ b/app/views/admin/projects/show.html.haml
@@ -46,18 +46,21 @@
           %span.light ssh:
           %strong
             = link_to @project.ssh_url_to_repo
-        %li
-          %span.light fs:
-          %strong
-            = @repository.path_to_repo
+        - if @project.repository.exists?
+          %li
+            %span.light fs:
+            %strong
+              = @repository.path_to_repo
 
-        %li
-          %span.light last commit:
-          %strong
-            - if @repository
+          %li
+            %span.light last commit:
+            %strong
               = last_commit(@project)
-            - else
-              never
+        - else
+          %li
+            %span.light repository:
+            %strong.cred
+              does not exist
 
         %li
           %span.light access:
diff --git a/app/views/blame/show.html.haml b/app/views/blame/show.html.haml
index b2a45ef5303300d962cfc98cbffca9019dda3f5e..96d153e627f778789042855f89fe86dc7fa591f6 100644
--- a/app/views/blame/show.html.haml
+++ b/app/views/blame/show.html.haml
@@ -6,7 +6,7 @@
       %i.icon-angle-right
       = link_to project_tree_path(@project, @ref) do
         = @project.name
-    - @tree.breadcrumbs(6) do |link|
+    - tree_breadcrumbs(@tree, 6) do |link|
       \/
       %li= link
   .clear
@@ -22,13 +22,13 @@
       %table
         - current_line = 1
         - @blame.each do |commit, lines|
-          - commit = CommitDecorator.decorate(Commit.new(commit))
+          - commit = Commit.new(commit)
           %tr
             %td.blame-commit
               %span.commit
                 = link_to commit.short_id(8), project_commit_path(@project, commit), class: "commit_short_id"
                 &nbsp;
-                = commit.author_link avatar: true, size: 16
+                = commit_author_link(commit, avatar: true, size: 16)
                 &nbsp;
                 = link_to_gfm truncate(commit.title, length: 20), project_commit_path(@project, commit.id), class: "row_title"
             %td.lines.blame-numbers
diff --git a/app/views/commit/_commit_box.html.haml b/app/views/commit/_commit_box.html.haml
index 4c80c13ced14a481268f7e6ce4f839e154b46b9d..646791773b292ac9d8600e51ce557dec7a840f81 100644
--- a/app/views/commit/_commit_box.html.haml
+++ b/app/views/commit/_commit_box.html.haml
@@ -24,14 +24,14 @@
     .row
       .span5
         .author
-          = @commit.author_link avatar: true, size: 32
+          = commit_author_link(@commit, avatar: true, size: 32)
           authored
           %time{title: @commit.authored_date.stamp("Aug 21, 2011 9:23pm")}
             #{time_ago_in_words(@commit.authored_date)} ago
         - if @commit.different_committer?
           .committer
             &rarr;
-            = @commit.committer_link
+            = commit_committer_link(@commit)
             committed
             %time{title: @commit.committed_date.stamp("Aug 21, 2011 9:23pm")}
               #{time_ago_in_words(@commit.committed_date)} ago
diff --git a/app/views/commits/_commit.html.haml b/app/views/commits/_commit.html.haml
index 2f5ff130f03d1d47a993dcee9aaff4d10aa9fb5f..65d920305b12448997ceca6e6e907368ba356bc4 100644
--- a/app/views/commits/_commit.html.haml
+++ b/app/views/commits/_commit.html.haml
@@ -4,7 +4,7 @@
       %strong= link_to "Browse Code ยป", project_tree_path(@project, commit), class: "right"
   %p
     = link_to commit.short_id(8), project_commit_path(@project, commit), class: "commit_short_id"
-    = commit.author_link avatar: true, size: 24
+    = commit_author_link(commit, avatar: true, size: 24)
     &nbsp;
     = link_to_gfm truncate(commit.title, length: 70), project_commit_path(@project, commit.id), class: "row_title"
 
diff --git a/app/views/commits/show.html.haml b/app/views/commits/show.html.haml
index d180b8ec4260e9f07bad7a56c0354ebb4eb8f69a..586b21dfa5d0de7fda0b929d3be5c5a9f1675714 100644
--- a/app/views/commits/show.html.haml
+++ b/app/views/commits/show.html.haml
@@ -2,7 +2,7 @@
 
 - if @path.present?
   %ul.breadcrumb
-    = breadcrumbs
+    = commits_breadcrumbs
 
 %div{id: dom_id(@project)}
   #commits-list= render "commits"
diff --git a/app/views/compare/show.html.haml b/app/views/compare/show.html.haml
index 476be2550af36754eedf66be4cfe6bc845f3193b..56c4a113ea0d0d3cf9d48569d9bae496e451c9f9 100644
--- a/app/views/compare/show.html.haml
+++ b/app/views/compare/show.html.haml
@@ -16,7 +16,7 @@
   %div.ui-box
     %h5.title
       Commits (#{@commits.count})
-    %ul.well-list= render @commits
+    %ul.well-list= render Commit.decorate(@commits)
 
   - unless @diffs.empty?
     %h4 Diff
diff --git a/app/views/events/_commit.html.haml b/app/views/events/_commit.html.haml
index ea417aa9f30934ecb0ea38edbb83f35011ebb685..f2f2d47ef96f5ff0388286f44eb609fe5af316e9 100644
--- a/app/views/events/_commit.html.haml
+++ b/app/views/events/_commit.html.haml
@@ -1,4 +1,3 @@
-- commit = CommitDecorator.decorate(commit)
 %li.commit
   %p
     = link_to commit.short_id(8), project_commit_path(project, commit), class: "commit_short_id"
diff --git a/app/views/projects/_clone_panel.html.haml b/app/views/projects/_clone_panel.html.haml
index 9a2be4292064ed1b15791f99652e6cd6b8c4feb3..91353147c6b8908b256142eb735692d9e1a024b2 100644
--- a/app/views/projects/_clone_panel.html.haml
+++ b/app/views/projects/_clone_panel.html.haml
@@ -4,7 +4,7 @@
       .form-horizontal= render "shared/clone_panel"
     .span4.pull-right
       .pull-right
-        - unless @project.empty_repo?
+        - if @project.empty_repo?
           - if can? current_user, :download_code, @project
             = link_to archive_project_repository_path(@project), class: "btn-small btn grouped" do
               %i.icon-download-alt
diff --git a/app/views/repositories/_branch.html.haml b/app/views/repositories/_branch.html.haml
index a6faa5fd633ffe44e4e905ac624c9ae22997c10a..dd91e14b66b78c8609126776dc3aa84bb0b22077 100644
--- a/app/views/repositories/_branch.html.haml
+++ b/app/views/repositories/_branch.html.haml
@@ -1,5 +1,4 @@
-- commit = Commit.new(branch.commit)
-- commit = CommitDecorator.decorate(commit)
+- commit = Commit.new(Gitlab::Git::Commit.new(branch.commit))
 %tr
   %td
     = link_to project_commits_path(@project, branch.name) do
diff --git a/app/views/repositories/_feed.html.haml b/app/views/repositories/_feed.html.haml
index eaf15ca77d63237da15022f7dfce7c139349131b..6bb75265ffb2a649a463c1f16cb2523fbfa1189e 100644
--- a/app/views/repositories/_feed.html.haml
+++ b/app/views/repositories/_feed.html.haml
@@ -1,5 +1,4 @@
 - commit = update
-- commit = CommitDecorator.new(commit)
 %tr
   %td
     = link_to project_commits_path(@project, commit.head.name) do
diff --git a/app/views/repositories/tags.html.haml b/app/views/repositories/tags.html.haml
index d4b8bbe10d428948251b4601bab3281e03d69b07..2d31112499224c346d7f21403f95c7c322cad8cf 100644
--- a/app/views/repositories/tags.html.haml
+++ b/app/views/repositories/tags.html.haml
@@ -7,8 +7,7 @@
         %th Last commit
         %th
     - @tags.each do |tag|
-      - commit = Commit.new(tag.commit)
-      - commit = CommitDecorator.decorate(commit)
+      - commit = Commit.new(Gitlab::Git::Commit.new(tag.commit))
       %tr
         %td
           %strong
diff --git a/app/views/tree/_tree.html.haml b/app/views/tree/_tree.html.haml
index 24a57ae7a29ab538e80dfa6d854c6285dba3216c..caab6e45bb41f8f87327b6a7bfcda7f59d0512cb 100644
--- a/app/views/tree/_tree.html.haml
+++ b/app/views/tree/_tree.html.haml
@@ -3,7 +3,7 @@
     %i.icon-angle-right
     = link_to project_tree_path(@project, @ref) do
       = @project.path
-  - tree.breadcrumbs(6) do |title, path|
+  - tree_breadcrumbs(tree, 6) do |title, path|
     \/
     %li
       - if path
@@ -27,7 +27,7 @@
         %tr.tree-item
           %td.tree-item-file-name
             = image_tag "file_empty.png", size: '16x16'
-            = link_to "..", project_tree_path(@project, tree.up_dir_path)
+            = link_to "..", project_tree_path(@project, up_dir_path(tree))
           %td
           %td
           %td
diff --git a/app/views/tree/_tree_commit_column.html.haml b/app/views/tree/_tree_commit_column.html.haml
index 9d02132b0f4451939c16bb95ef720cc86d190ce1..7ae2582c130af4537208212f692f8708452860d0 100644
--- a/app/views/tree/_tree_commit_column.html.haml
+++ b/app/views/tree/_tree_commit_column.html.haml
@@ -1,2 +1,2 @@
-%span.tree_author= commit.author_link avatar: true
+%span.tree_author= commit_author_link(commit, avatar: true)
 = link_to_gfm truncate(commit.title, length: 80), project_commit_path(@project, commit.id), class: "tree-commit-link"
diff --git a/app/views/wikis/history.html.haml b/app/views/wikis/history.html.haml
index 599e9cf67933184561443b5323a07cca8a80933f..f4946ed000d3e393d2ffb3c3462b94cd1c7987d1 100644
--- a/app/views/wikis/history.html.haml
+++ b/app/views/wikis/history.html.haml
@@ -14,12 +14,13 @@
       %th Format
   %tbody
     - @wiki.versions.each do |version|
-      - commit = CommitDecorator.new(version)
+      - commit = version
       %tr
         %td
           = link_to project_wiki_path(@project, @wiki, version_id: commit.id) do
             = commit.short_id
-        %td= commit.author_link avatar: true, size: 24
+        %td
+          = commit_author_link(commit, avatar: true, size: 24)
         %td
           = commit.title
         %td
diff --git a/app/views/wikis/pages.html.haml b/app/views/wikis/pages.html.haml
index eb65599d08739ad9842bfcf3c322c988fac86edc..95d5eef16f5e888242fb9f46b4fe89b91a1883d9 100644
--- a/app/views/wikis/pages.html.haml
+++ b/app/views/wikis/pages.html.haml
@@ -21,5 +21,5 @@
           = wiki_page.created_at.to_s(:short) do
             (#{time_ago_in_words(wiki_page.created_at)}
             ago)
-        - commit = CommitDecorator.decorate(wiki_page.version)
-        %td= commit.author_link avatar: true, size: 24
+        %td
+          = commit_author_link(wiki_page.version, avatar: true, size: 24)
diff --git a/app/views/wikis/show.html.haml b/app/views/wikis/show.html.haml
index b660a15ee325df6b7e037ec67aaa486201bcf03b..b237bc524ed722c66e964a7e9a3ddf68f9bf137a 100644
--- a/app/views/wikis/show.html.haml
+++ b/app/views/wikis/show.html.haml
@@ -13,5 +13,4 @@
     = preserve do
       = render_wiki_content(@wiki)
 
-- commit = CommitDecorator.new(@wiki.version)
-%p.time Last edited by #{commit.author_link(avatar: true, size: 16)} #{time_ago_in_words @wiki.created_at} ago
+%p.time Last edited by #{commit_author_link(@wiki.version, avatar: true, size: 16)} #{time_ago_in_words @wiki.created_at} ago
diff --git a/features/steps/project/project_browse_commits.rb b/features/steps/project/project_browse_commits.rb
index 3433c2ba5f6b60cc9ab5061ae0a1e792f9c4b71c..b4c595fa5aac6ec4aa07c0d3a72b572378891030 100644
--- a/features/steps/project/project_browse_commits.rb
+++ b/features/steps/project/project_browse_commits.rb
@@ -15,7 +15,7 @@ class ProjectBrowseCommits < Spinach::FeatureSteps
   end
 
   Then 'I see commits atom feed' do
-    commit = CommitDecorator.decorate(@project.repository.commit)
+    commit = @project.repository.commit
     page.response_headers['Content-Type'].should have_content("application/atom+xml")
     page.body.should have_selector("title", :text => "Recent commits to #{@project.name}")
     page.body.should have_selector("author email", :text => commit.author_email)
diff --git a/features/steps/shared/project.rb b/features/steps/shared/project.rb
index 81863a54f3d99389c72c5ad09325a9abbba1f752..b16032a83000d8f518f668ec077e17d8f136a485 100644
--- a/features/steps/shared/project.rb
+++ b/features/steps/shared/project.rb
@@ -3,14 +3,14 @@ module SharedProject
 
   # Create a project without caring about what it's called
   And "I own a project" do
-    @project = create(:project)
+    @project = create(:project_with_code)
     @project.team << [@user, :master]
   end
 
   # Create a specific project called "Shop"
   And 'I own project "Shop"' do
     @project = Project.find_by_name "Shop"
-    @project ||= create(:project, name: "Shop")
+    @project ||= create(:project_with_code, name: "Shop")
     @project.team << [@user, :master]
   end
 
diff --git a/features/steps/userteams/userteams.rb b/features/steps/userteams/userteams.rb
index 70ad3cca43a56f2c08ad346f12c134ad2fb79e3a..9a86572e1acaf5791fa78bf30efaea5033d93db6 100644
--- a/features/steps/userteams/userteams.rb
+++ b/features/steps/userteams/userteams.rb
@@ -132,7 +132,7 @@ class Userteams < Spinach::FeatureSteps
     team = UserTeam.last
     team.projects.each do |project|
       team.members.each do |member|
-        3.times { project.merge_requests << create(:merge_request, assignee: member) }
+        3.times { create(:merge_request, assignee: member, project: project) }
       end
     end
   end
@@ -157,7 +157,7 @@ class Userteams < Spinach::FeatureSteps
     team = UserTeam.last
     team.projects.each do |project|
       team.members.each do |member|
-        3.times { project.merge_requests << create(:merge_request, assignee: member) }
+        3.times { create(:merge_request, assignee: member, project: project) }
       end
     end
   end
diff --git a/features/support/env.rb b/features/support/env.rb
index 90a61dd16c6c60411181f5cb8024e9e0b2bc69ac..08b627f57b7de9183a6c31a0d047c57893f5740e 100644
--- a/features/support/env.rb
+++ b/features/support/env.rb
@@ -14,7 +14,7 @@ require 'spinach/capybara'
 require 'sidekiq/testing/inline'
 
 
-%w(stubbed_repository valid_commit select2_helper).each do |f|
+%w(valid_commit select2_helper test_env).each do |f|
   require Rails.root.join('spec', 'support', f)
 end
 
@@ -35,13 +35,8 @@ Capybara.default_wait_time = 10
 DatabaseCleaner.strategy = :truncation
 
 Spinach.hooks.before_scenario do
-  # Use tmp dir for FS manipulations
-  Gitlab.config.gitlab_shell.stub(repos_path: Rails.root.join('tmp', 'test-git-base-path'))
-  Gitlab::Shell.any_instance.stub(:add_repository) do |path|
-    create_temp_repo("#{Rails.root}/tmp/test-git-base-path/#{path}.git")
-  end
-  FileUtils.rm_rf Gitlab.config.gitlab_shell.repos_path
-  FileUtils.mkdir_p Gitlab.config.gitlab_shell.repos_path
+  TestEnv.init
+
   DatabaseCleaner.start
 end
 
@@ -54,9 +49,3 @@ Spinach.hooks.before_run do
 
   include FactoryGirl::Syntax::Methods
 end
-
-def create_temp_repo(path)
-  FileUtils.mkdir_p path
-  command = "git init --quiet --bare #{path};"
-  system(command)
-end
diff --git a/lib/api/projects.rb b/lib/api/projects.rb
index d4f50fda1b54b4b5f2366e67abfe7b2628048538..ce94c34bd09f921d2d2850241f06124ab9f7623a 100644
--- a/lib/api/projects.rb
+++ b/lib/api/projects.rb
@@ -372,7 +372,7 @@ module Gitlab
         ref = params[:ref_name] || user_project.try(:default_branch) || 'master'
 
         commits = user_project.repository.commits(ref, nil, per_page, page * per_page)
-        present CommitDecorator.decorate(commits), with: Entities::RepoCommit
+        present commits, with: Entities::RepoCommit
       end
 
       # Get a project snippets
diff --git a/lib/extracts_path.rb b/lib/extracts_path.rb
index 351fc2f23aeeb197915d995ddc48245a1f568228..2e3ab1b2701ebb3200c1cebe95e463cb5228f4e4 100644
--- a/lib/extracts_path.rb
+++ b/lib/extracts_path.rb
@@ -85,8 +85,8 @@ module ExtractsPath
   # - @id     - A string representing the joined ref and path
   # - @ref    - A string representing the ref (e.g., the branch, tag, or commit SHA)
   # - @path   - A string representing the filesystem path
-  # - @commit - A CommitDecorator representing the commit from the given ref
-  # - @tree   - A TreeDecorator representing the tree at the given ref/path
+  # - @commit - A Commit representing the commit from the given ref
+  # - @tree   - A Tree representing the tree at the given ref/path
   #
   # If the :id parameter appears to be requesting a specific response format,
   # that will be handled as well.
@@ -100,11 +100,9 @@ module ExtractsPath
 
     # It is used "@project.repository.commits(@ref, @path, 1, 0)",
     # because "@project.repository.commit(@ref)" returns wrong commit when @ref is tag name.
-    commits = @project.repository.commits(@ref, @path, 1, 0)
-    @commit = CommitDecorator.decorate(commits.first)
+    @commit = @project.repository.commits(@ref, @path, 1, 0).first
 
     @tree = Tree.new(@commit.tree, @ref, @path)
-    @tree = TreeDecorator.new(@tree)
 
     raise InvalidPathError if @tree.invalid?
   rescue RuntimeError, NoMethodError, InvalidPathError
diff --git a/lib/gitlab/git/blame.rb b/lib/gitlab/git/blame.rb
new file mode 100644
index 0000000000000000000000000000000000000000..d6e988b6762a8d8ce5409b549161233a0027bb82
--- /dev/null
+++ b/lib/gitlab/git/blame.rb
@@ -0,0 +1,22 @@
+module Gitlab
+  module Git
+    class Blame
+
+      attr_accessor :repository, :sha, :path
+
+      def initialize(repository, sha, path)
+        @repository, @sha, @path = repository, sha, path
+
+      end
+
+      def each
+        raw_blame = Grit::Blob.blame(repository.repo, sha, path)
+
+        raw_blame.each do |commit, lines|
+          commit = Gitlab::Git::Commit.new(commit)
+          yield(commit, lines)
+        end
+      end
+    end
+  end
+end
diff --git a/lib/gitlab/git/commit.rb b/lib/gitlab/git/commit.rb
new file mode 100644
index 0000000000000000000000000000000000000000..35991a383f68b6abd3d089c89e045f24eaad44fd
--- /dev/null
+++ b/lib/gitlab/git/commit.rb
@@ -0,0 +1,153 @@
+# Gitlab::Git::Commit is a wrapper around native Grit::Commit object
+# We dont want to use grit objects inside app/
+# It helps us easily migrate to rugged in future
+module Gitlab
+  module Git
+    class Commit
+      attr_accessor :raw_commit, :head, :refs
+
+      delegate  :message, :authored_date, :committed_date, :parents, :sha,
+        :date, :committer, :author, :diffs, :tree, :id, :stats, :to_patch,
+        to: :raw_commit
+
+      class << self
+        def find_or_first(repo, commit_id = nil, root_ref)
+          commit = if commit_id
+                     repo.commit(commit_id)
+                   else
+                     repo.commits(root_ref).first
+                   end
+
+          Commit.new(commit) if commit
+        end
+
+        def fresh_commits(repo, n = 10)
+          commits = repo.heads.map do |h|
+            repo.commits(h.name, n).map { |c| Commit.new(c, h) }
+          end.flatten.uniq { |c| c.id }
+
+          commits.sort! do |x, y|
+            y.committed_date <=> x.committed_date
+          end
+
+          commits[0...n]
+        end
+
+        def commits_with_refs(repo, n = 20)
+          commits = repo.branches.map { |ref| Commit.new(ref.commit, ref) }
+
+          commits.sort! do |x, y|
+            y.committed_date <=> x.committed_date
+          end
+
+          commits[0..n]
+        end
+
+        def commits_since(repo, date)
+          commits = repo.heads.map do |h|
+            repo.log(h.name, nil, since: date).each { |c| Commit.new(c, h) }
+          end.flatten.uniq { |c| c.id }
+
+          commits.sort! do |x, y|
+            y.committed_date <=> x.committed_date
+          end
+
+          commits
+        end
+
+        def commits(repo, ref, path = nil, limit = nil, offset = nil)
+          if path
+            repo.log(ref, path, max_count: limit, skip: offset)
+          elsif limit && offset
+            repo.commits(ref, limit, offset)
+          else
+            repo.commits(ref)
+          end.map{ |c| Commit.new(c) }
+        end
+
+        def commits_between(repo, from, to)
+          repo.commits_between(from, to).map { |c| Commit.new(c) }
+        end
+      end
+
+      def initialize(raw_commit, head = nil)
+        raise "Nil as raw commit passed" unless raw_commit
+
+        @raw_commit = raw_commit
+        @head = head
+      end
+
+      def short_id(length = 10)
+        id.to_s[0..length]
+      end
+
+      def safe_message
+        @safe_message ||= message
+      end
+
+      def created_at
+        committed_date
+      end
+
+      def author_email
+        author.email
+      end
+
+      def author_name
+        author.name
+      end
+
+      # Was this commit committed by a different person than the original author?
+      def different_committer?
+        author_name != committer_name || author_email != committer_email
+      end
+
+      def committer_name
+        committer.name
+      end
+
+      def committer_email
+        committer.email
+      end
+
+      def prev_commit
+        @prev_commit ||= if parents.present?
+                           Commit.new(parents.first)
+                         else
+                           nil
+                         end
+      end
+
+      def prev_commit_id
+        prev_commit.try :id
+      end
+
+      # Shows the diff between the commit's parent and the commit.
+      #
+      # Cuts out the header and stats from #to_patch and returns only the diff.
+      def to_diff
+        # see Grit::Commit#show
+        patch = to_patch
+
+        # discard lines before the diff
+        lines = patch.split("\n")
+        while !lines.first.start_with?("diff --git") do
+          lines.shift
+        end
+        lines.pop if lines.last =~ /^[\d.]+$/ # Git version
+          lines.pop if lines.last == "-- "      # end of diff
+        lines.join("\n")
+      end
+
+      def has_zero_stats?
+        stats.total.zero?
+      rescue
+        true
+      end
+
+      def no_commit_message
+        "--no commit message"
+      end
+    end
+  end
+end
diff --git a/lib/gitlab/git/compare.rb b/lib/gitlab/git/compare.rb
new file mode 100644
index 0000000000000000000000000000000000000000..1fa4306200f78ade17e2483c7f363fe73dd23486
--- /dev/null
+++ b/lib/gitlab/git/compare.rb
@@ -0,0 +1,37 @@
+module Gitlab
+  module Git
+    class Compare
+      attr_accessor :commits, :commit, :diffs, :same
+
+      def initialize(repository, from, to)
+        @commits, @diffs = [], []
+        @commit = nil
+        @same = false
+
+        return unless from && to
+
+        first = repository.commit(to.try(:strip))
+        last = repository.commit(from.try(:strip))
+
+        return unless first && last
+
+        if first.id == last.id
+          @same = true
+          return
+        end
+
+        @commit = Commit.new(first)
+
+        @commits = repository.commits_between(last.id, first.id)
+        @commits = @commits.map { |c| Commit.new(c) }
+
+        @diffs = if @commits.size > 100
+                   []
+                 else
+                   repository.repo.diff(last.id, first.id) rescue []
+                 end
+      end
+    end
+  end
+end
+
diff --git a/lib/gitlab/git/repository.rb b/lib/gitlab/git/repository.rb
new file mode 100644
index 0000000000000000000000000000000000000000..30344a3dec5d3b4a048254d5c9d1ce102a376a9e
--- /dev/null
+++ b/lib/gitlab/git/repository.rb
@@ -0,0 +1,185 @@
+# Gitlab::Git::Gitlab::Git::Commit is a wrapper around native Grit::Repository object
+# We dont want to use grit objects inside app/
+# It helps us easily migrate to rugged in future
+module Gitlab
+  module Git
+    class Repository
+      include Gitlab::Popen
+
+      class NoRepository < StandardError; end
+
+      # Repository directory name with namespace direcotry
+      # Examples:
+      #   gitlab/gitolite
+      #   diaspora
+      #
+      attr_accessor :path_with_namespace
+
+      # Grit repo object
+      attr_accessor :repo
+
+      # Default branch in the repository
+      attr_accessor :root_ref
+
+      def initialize(path_with_namespace, root_ref = 'master')
+        @root_ref = root_ref || "master"
+        @path_with_namespace = path_with_namespace
+
+        # Init grit repo object
+        repo
+      end
+
+      def raw
+        repo
+      end
+
+      def path_to_repo
+        @path_to_repo ||= File.join(repos_path, "#{path_with_namespace}.git")
+      end
+
+      def repos_path
+        Gitlab.config.gitlab_shell.repos_path
+      end
+
+      def repo
+        @repo ||= Grit::Repo.new(path_to_repo)
+      rescue Grit::NoSuchPathError
+        raise NoRepository.new('no repository for such path')
+      end
+
+      def commit(commit_id = nil)
+        Gitlab::Git::Commit.find_or_first(repo, commit_id, root_ref)
+      end
+
+      def fresh_commits(n = 10)
+        Gitlab::Git::Commit.fresh_commits(repo, n)
+      end
+
+      def commits_with_refs(n = 20)
+        Gitlab::Git::Commit.commits_with_refs(repo, n)
+      end
+
+      def commits_since(date)
+        Gitlab::Git::Commit.commits_since(repo, date)
+      end
+
+      def commits(ref, path = nil, limit = nil, offset = nil)
+        Gitlab::Git::Commit.commits(repo, ref, path, limit, offset)
+      end
+
+      def last_commit_for(ref, path = nil)
+        commits(ref, path, 1).first
+      end
+
+      def commits_between(from, to)
+        Gitlab::Git::Commit.commits_between(repo, from, to)
+      end
+
+      # Returns an Array of branch names
+      # sorted by name ASC
+      def branch_names
+        branches.map(&:name)
+      end
+
+      # Returns an Array of Branches
+      def branches
+        repo.branches.sort_by(&:name)
+      end
+
+      # Returns an Array of tag names
+      def tag_names
+        repo.tags.collect(&:name).sort.reverse
+      end
+
+      # Returns an Array of Tags
+      def tags
+        repo.tags.sort_by(&:name).reverse
+      end
+
+      # Returns an Array of branch and tag names
+      def ref_names
+        [branch_names + tag_names].flatten
+      end
+
+      def heads
+        @heads ||= repo.heads
+      end
+
+      def tree(fcommit, path = nil)
+        fcommit = commit if fcommit == :head
+        tree = fcommit.tree
+        path ? (tree / path) : tree
+      end
+
+      def has_commits?
+        !!commit
+      rescue Grit::NoSuchPathError
+        false
+      end
+
+      def empty?
+        !has_commits?
+      end
+
+      # Discovers the default branch based on the repository's available branches
+      #
+      # - If no branches are present, returns nil
+      # - If one branch is present, returns its name
+      # - If two or more branches are present, returns the one that has a name
+      #   matching root_ref (default_branch or 'master' if default_branch is nil)
+      def discover_default_branch
+        if branch_names.length == 0
+          nil
+        elsif branch_names.length == 1
+          branch_names.first
+        else
+          branch_names.select { |v| v == root_ref }.first
+        end
+      end
+
+      # Archive Project to .tar.gz
+      #
+      # Already packed repo archives stored at
+      # app_root/tmp/repositories/project_name/project_name-commit-id.tag.gz
+      #
+      def archive_repo(ref)
+        ref = ref || self.root_ref
+        commit = self.commit(ref)
+        return nil unless commit
+
+        # Build file path
+        file_name = self.path_with_namespace.gsub("/","_") + "-" + commit.id.to_s + ".tar.gz"
+        storage_path = Rails.root.join("tmp", "repositories")
+        file_path = File.join(storage_path, self.path_with_namespace, file_name)
+
+        # Put files into a directory before archiving
+        prefix = File.basename(self.path_with_namespace) + "/"
+
+        # Create file if not exists
+        unless File.exists?(file_path)
+          FileUtils.mkdir_p File.dirname(file_path)
+          file = self.repo.archive_to_file(ref, prefix,  file_path)
+        end
+
+        file_path
+      end
+
+      # Return repo size in megabytes
+      # Cached in redis
+      def size
+        Rails.cache.fetch(cache_key(:size)) do
+          size = popen('du -s', path_to_repo).first.strip.to_i
+          (size.to_f / 1024).round(2)
+        end
+      end
+
+      def expire_cache
+        Rails.cache.delete(cache_key(:size))
+      end
+
+      def cache_key(type)
+        "#{type}:#{path_with_namespace}"
+      end
+    end
+  end
+end
diff --git a/lib/gitlab/markdown.rb b/lib/gitlab/markdown.rb
index 762eb37298066733acb6c43a0d331b4d6e33da7a..ad6ba3e8fd69ce1cd91371eb5a2507075a1cf2e0 100644
--- a/lib/gitlab/markdown.rb
+++ b/lib/gitlab/markdown.rb
@@ -187,7 +187,7 @@ module Gitlab
 
     def reference_commit(identifier)
       if @project.valid_repo? && commit = @project.repository.commit(identifier)
-        link_to(identifier, project_commit_url(@project, commit), html_options.merge(title: CommitDecorator.new(commit).link_title, class: "gfm gfm-commit #{html_options[:class]}"))
+        link_to(identifier, project_commit_url(@project, commit), html_options.merge(title: commit.link_title, class: "gfm gfm-commit #{html_options[:class]}"))
       end
     end
   end
diff --git a/lib/tasks/cache.rake b/lib/tasks/cache.rake
new file mode 100644
index 0000000000000000000000000000000000000000..8320b9b2576b245a237c887ffadc306bc44388cd
--- /dev/null
+++ b/lib/tasks/cache.rake
@@ -0,0 +1,6 @@
+namespace :cache do
+  desc "GITLAB | Clear redis cache"
+  task :clear => :environment do
+    Rails.cache.clear
+  end
+end
diff --git a/spec/controllers/commit_controller_spec.rb b/spec/controllers/commit_controller_spec.rb
index 7bf13822829bc4607a698c7bb6358f5fb945c705..5fffbf0e5f3b30579120ab04eac33f6c12b40df5 100644
--- a/spec/controllers/commit_controller_spec.rb
+++ b/spec/controllers/commit_controller_spec.rb
@@ -1,7 +1,7 @@
 require 'spec_helper'
 
 describe CommitController do
-  let(:project) { create(:project) }
+  let(:project) { create(:project_with_code) }
   let(:user)    { create(:user) }
   let(:commit)  { project.repository.last_commit_for("master") }
 
diff --git a/spec/controllers/commits_controller_spec.rb b/spec/controllers/commits_controller_spec.rb
index 99cbcd13d56613e55ac6738448adf973be814731..ce4029173a5aacc98b5278b552b56bc4da3d86eb 100644
--- a/spec/controllers/commits_controller_spec.rb
+++ b/spec/controllers/commits_controller_spec.rb
@@ -1,7 +1,7 @@
 require 'spec_helper'
 
 describe CommitsController do
-  let(:project) { create(:project) }
+  let(:project) { create(:project_with_code) }
   let(:user)    { create(:user) }
 
   before do
diff --git a/spec/controllers/merge_requests_controller_spec.rb b/spec/controllers/merge_requests_controller_spec.rb
index 37e36efc1ca7d23d74ae3287911ee55d7cda4595..e8dd9bf995c219f0310eb6a73559b1f5e4194575 100644
--- a/spec/controllers/merge_requests_controller_spec.rb
+++ b/spec/controllers/merge_requests_controller_spec.rb
@@ -1,7 +1,7 @@
 require 'spec_helper'
 
 describe MergeRequestsController do
-  let(:project) { create(:project) }
+  let(:project) { create(:project_with_code) }
   let(:user)    { create(:user) }
   let(:merge_request) { create(:merge_request_with_diffs, project: project, target_branch: "bcf03b5d~3", source_branch: "bcf03b5d") }
 
diff --git a/spec/controllers/tree_controller_spec.rb b/spec/controllers/tree_controller_spec.rb
index 81c7656d07a2bed48821393f9df2159a5333026d..8232f1472e120ac0060cf7fb8d33e8b3ef99d464 100644
--- a/spec/controllers/tree_controller_spec.rb
+++ b/spec/controllers/tree_controller_spec.rb
@@ -1,7 +1,7 @@
 require 'spec_helper'
 
 describe TreeController do
-  let(:project) { create(:project) }
+  let(:project) { create(:project_with_code) }
   let(:user)    { create(:user) }
 
   before do
diff --git a/spec/factories.rb b/spec/factories.rb
index 41766859468475aa6954c5dfcc361a17699dcc9e..3205cabd150da25a4800b33e5e71fee77ebe955c 100644
--- a/spec/factories.rb
+++ b/spec/factories.rb
@@ -34,6 +34,10 @@ FactoryGirl.define do
     issues_tracker_id { "project_name_in_redmine" }
   end
 
+  factory :project_with_code, parent: :project do
+    path { 'gitlabhq' }
+  end
+
   factory :group do
     sequence(:name) { |n| "group#{n}" }
     path { name.downcase.gsub(/\s/, '_') }
@@ -73,7 +77,7 @@ FactoryGirl.define do
   factory :merge_request do
     title
     author
-    project
+    project factory: :project_with_code
     source_branch "master"
     target_branch "stable"
 
@@ -82,9 +86,9 @@ FactoryGirl.define do
       target_branch "master" # pretend bcf03b5d~3
       source_branch "stable" # pretend bcf03b5d
       st_commits do
-        [Commit.new(project.repo.commit('bcf03b5d')),
-         Commit.new(project.repo.commit('bcf03b5d~1')),
-         Commit.new(project.repo.commit('bcf03b5d~2'))]
+        [Commit.new(project.repository.commit('bcf03b5d')),
+         Commit.new(project.repository.commit('bcf03b5d~1')),
+         Commit.new(project.repository.commit('bcf03b5d~2'))]
       end
       st_diffs do
         project.repo.diff("bcf03b5d~3", "bcf03b5d")
@@ -116,6 +120,7 @@ FactoryGirl.define do
     factory :note_on_merge_request_diff, traits: [:on_merge_request, :on_diff]
 
     trait :on_commit do
+      project factory: :project_with_code
       commit_id     "bcf03b5de6c33f3869ef70d68cf06e679d1d7f9a"
       noteable_type "Commit"
     end
@@ -125,6 +130,7 @@ FactoryGirl.define do
     end
 
     trait :on_merge_request do
+      project factory: :project_with_code
       noteable_id   1
       noteable_type "MergeRequest"
     end
diff --git a/spec/features/gitlab_flavored_markdown_spec.rb b/spec/features/gitlab_flavored_markdown_spec.rb
index a57e34ac5d25be9285c075528ae35cb850f9f54e..653ff8651758b2f290b8583b95340c51a4f79093 100644
--- a/spec/features/gitlab_flavored_markdown_spec.rb
+++ b/spec/features/gitlab_flavored_markdown_spec.rb
@@ -1,7 +1,7 @@
 require 'spec_helper'
 
 describe "Gitlab Flavored Markdown" do
-  let(:project) { create(:project) }
+  let(:project) { create(:project_with_code) }
   let(:issue) { create(:issue, project: project) }
   let(:merge_request) { create(:merge_request, project: project) }
   let(:fred) do
diff --git a/spec/features/notes_on_merge_requests_spec.rb b/spec/features/notes_on_merge_requests_spec.rb
index d48dffc094520b541a84b6ea9fe574b790d35554..82f442798de70b09bcbb0091e51ec48bc65593c6 100644
--- a/spec/features/notes_on_merge_requests_spec.rb
+++ b/spec/features/notes_on_merge_requests_spec.rb
@@ -1,7 +1,7 @@
 require 'spec_helper'
 
 describe "On a merge request", js: true do
-  let!(:project) { create(:project) }
+  let!(:project) { create(:project_with_code) }
   let!(:merge_request) { create(:merge_request, project: project) }
 
   before do
@@ -83,7 +83,7 @@ end
 
 
 describe "On a merge request diff", js: true, focus: true do
-  let!(:project) { create(:project) }
+  let!(:project) { create(:project_with_code) }
   let!(:merge_request) { create(:merge_request_with_diffs, project: project) }
 
   before do
diff --git a/spec/features/profile_spec.rb b/spec/features/profile_spec.rb
index c18d8f921a3a60bc95ae8eb397c8f0cd8751dbdc..51b95c2595dab3bb6eedd8dc2c292afcdc671032 100644
--- a/spec/features/profile_spec.rb
+++ b/spec/features/profile_spec.rb
@@ -12,8 +12,9 @@ describe "Profile account page" do
       Gitlab.config.gitlab.stub(:signup_enabled).and_return(true)
       visit account_profile_path
     end
+
     it { page.should have_content("Remove account") }
-    
+
     it "should delete the account", js: true do
       expect { click_link "Delete account" }.to change {User.count}.by(-1)
       current_path.should == new_user_session_path
@@ -45,4 +46,4 @@ describe "Profile account page" do
       current_path.should == account_profile_path
     end
   end
-end
\ No newline at end of file
+end
diff --git a/spec/features/security/project_access_spec.rb b/spec/features/security/project_access_spec.rb
index 179ebffc2adebd5a1a54732e759a61bfe25cc53d..cfbb8f135ab0c05fb8d373732cf6f0eb2cc26138 100644
--- a/spec/features/security/project_access_spec.rb
+++ b/spec/features/security/project_access_spec.rb
@@ -14,7 +14,7 @@ describe "Application access" do
   end
 
   describe "Project" do
-    let(:project)  { create(:project) }
+    let(:project)  { create(:project_with_code) }
 
     let(:master)   { create(:user) }
     let(:guest)    { create(:user) }
diff --git a/spec/helpers/gitlab_markdown_helper_spec.rb b/spec/helpers/gitlab_markdown_helper_spec.rb
index b9025026c1bbed705f664b039c54d06e766b2ead..4140ba484f0afd941cea48a854bf326334956c3f 100644
--- a/spec/helpers/gitlab_markdown_helper_spec.rb
+++ b/spec/helpers/gitlab_markdown_helper_spec.rb
@@ -4,10 +4,10 @@ describe GitlabMarkdownHelper do
   include ApplicationHelper
   include IssuesHelper
 
-  let!(:project) { create(:project) }
+  let!(:project) { create(:project_with_code) }
 
   let(:user)          { create(:user, username: 'gfm') }
-  let(:commit)        { CommitDecorator.decorate(project.repository.commit) }
+  let(:commit)        { project.repository.commit }
   let(:issue)         { create(:issue, project: project) }
   let(:merge_request) { create(:merge_request, project: project) }
   let(:snippet)       { create(:snippet, project: project) }
diff --git a/spec/lib/git/commit_spec.rb b/spec/lib/git/commit_spec.rb
new file mode 100644
index 0000000000000000000000000000000000000000..475bc359a18503db4d12004126f3f6393ed07f36
--- /dev/null
+++ b/spec/lib/git/commit_spec.rb
@@ -0,0 +1,49 @@
+require "spec_helper"
+
+describe Gitlab::Git::Commit do
+  let(:commit) { create(:project_with_code).repository.commit }
+
+  describe "Commit info" do
+    before do
+      @committer = double(
+        email: 'mike@smith.com',
+        name: 'Mike Smith'
+      )
+
+      @author = double(
+        email: 'john@smith.com',
+        name: 'John Smith'
+      )
+
+      @raw_commit = double(
+        id: "bcf03b5de6abcf03b5de6c",
+        author: @author,
+        committer: @committer,
+        committed_date: Date.yesterday,
+        message: 'Refactoring specs'
+      )
+
+      @commit = Gitlab::Git::Commit.new(@raw_commit)
+    end
+
+    it { @commit.short_id.should == "bcf03b5de6a" }
+    it { @commit.safe_message.should == @raw_commit.message }
+    it { @commit.created_at.should == @raw_commit.committed_date }
+    it { @commit.author_email.should == @author.email }
+    it { @commit.author_name.should == @author.name }
+    it { @commit.committer_name.should == @committer.name }
+    it { @commit.committer_email.should == @committer.email }
+    it { @commit.different_committer?.should be_true }
+  end
+
+  describe "Class methods" do
+    subject { Gitlab::Git::Commit }
+
+    it { should respond_to(:find_or_first) }
+    it { should respond_to(:fresh_commits) }
+    it { should respond_to(:commits_with_refs) }
+    it { should respond_to(:commits_since) }
+    it { should respond_to(:commits_between) }
+    it { should respond_to(:commits) }
+  end
+end
diff --git a/spec/models/repository_spec.rb b/spec/lib/git/repository_spec.rb
similarity index 96%
rename from spec/models/repository_spec.rb
rename to spec/lib/git/repository_spec.rb
index 71f9b964e70a012e5af52ddae02bcfebcaf9af11..b2b6f1964de6622bd630674849db53d5dee29f22 100644
--- a/spec/models/repository_spec.rb
+++ b/spec/lib/git/repository_spec.rb
@@ -1,8 +1,7 @@
 require "spec_helper"
 
-describe Repository do
-  let(:project) { create(:project) }
-  let(:repository) { project.repository }
+describe Gitlab::Git::Repository do
+  let(:repository) { Gitlab::Git::Repository.new('gitlabhq', 'master') }
 
   describe "Respond to" do
     subject { repository }
diff --git a/spec/mailers/notify_spec.rb b/spec/mailers/notify_spec.rb
index 472458e8691b12f8d9850e487005a273ab08869a..84ce7e86d2731122e4aeebb86972e06bca2f44c7 100644
--- a/spec/mailers/notify_spec.rb
+++ b/spec/mailers/notify_spec.rb
@@ -5,7 +5,7 @@ describe Notify do
   include EmailSpec::Matchers
 
   let(:recipient) { create(:user, email: 'recipient@example.com') }
-  let(:project) { create(:project) }
+  let(:project) { create(:project_with_code) }
 
   shared_examples 'a multiple recipients email' do
     it 'is sent to the given recipient' do
@@ -277,14 +277,7 @@ describe Notify do
       end
 
       describe 'on a commit' do
-        let(:commit) do
-          mock(:commit).tap do |commit|
-            commit.stub(:id).and_return('fauxsha1')
-            commit.stub(:project).and_return(project)
-            commit.stub(:short_id).and_return('fauxsha1')
-            commit.stub(:safe_message).and_return('some message')
-          end
-        end
+        let(:commit) { project.repository.commit }
 
         before(:each) { note.stub(:noteable).and_return(commit) }
 
@@ -297,7 +290,7 @@ describe Notify do
         end
 
         it 'contains a link to the commit' do
-          should have_body_text /fauxsha1/
+          should have_body_text commit.short_id
         end
       end
 
diff --git a/spec/models/commit_spec.rb b/spec/models/commit_spec.rb
index 91301029e89c91b8a38b39eba3f4bb9c836bb4c9..6cf777bec0437e6ed75029b6658d206b116598a6 100644
--- a/spec/models/commit_spec.rb
+++ b/spec/models/commit_spec.rb
@@ -1,83 +1,35 @@
 require 'spec_helper'
 
 describe Commit do
-  let(:commit) { create(:project).repository.commit }
+  let(:commit) { create(:project_with_code).repository.commit }
 
-  describe CommitDecorator do
-    let(:decorator) { CommitDecorator.new(commit) }
 
-    describe '#title' do
-      it "returns no_commit_message when safe_message is blank" do
-        decorator.stub(:safe_message).and_return('')
-        decorator.title.should == "--no commit message"
-      end
-
-      it "truncates a message without a newline at 70 characters" do
-        message = commit.safe_message * 10
-
-        decorator.stub(:safe_message).and_return(message)
-        decorator.title.should == "#{message[0..69]}&hellip;"
-      end
-
-      it "truncates a message with a newline before 80 characters at the newline" do
-        message = commit.safe_message.split(" ").first
-
-        decorator.stub(:safe_message).and_return(message + "\n" + message)
-        decorator.title.should == message
-      end
-
-      it "truncates a message with a newline after 80 characters at 70 characters" do
-        message = (commit.safe_message * 10) + "\n"
-
-        decorator.stub(:safe_message).and_return(message)
-        decorator.title.should == "#{message[0..69]}&hellip;"
-      end
+  describe '#title' do
+    it "returns no_commit_message when safe_message is blank" do
+      commit.stub(:safe_message).and_return('')
+      commit.title.should == "--no commit message"
     end
-  end
 
-  describe "Commit info" do
-    before do
-      @committer = double(
-        email: 'mike@smith.com',
-        name: 'Mike Smith'
-      )
+    it "truncates a message without a newline at 70 characters" do
+      message = commit.safe_message * 10
 
-      @author = double(
-        email: 'john@smith.com',
-        name: 'John Smith'
-      )
+      commit.stub(:safe_message).and_return(message)
+      commit.title.should == "#{message[0..69]}&hellip;"
+    end
 
-      @raw_commit = double(
-        id: "bcf03b5de6abcf03b5de6c",
-        author: @author,
-        committer: @committer,
-        committed_date: Date.yesterday,
-        message: 'Refactoring specs'
-      )
+    it "truncates a message with a newline before 80 characters at the newline" do
+      message = commit.safe_message.split(" ").first
 
-      @commit = Commit.new(@raw_commit)
+      commit.stub(:safe_message).and_return(message + "\n" + message)
+      commit.title.should == message
     end
 
-    it { @commit.short_id.should == "bcf03b5de6a" }
-    it { @commit.safe_message.should == @raw_commit.message }
-    it { @commit.created_at.should == @raw_commit.committed_date }
-    it { @commit.author_email.should == @author.email }
-    it { @commit.author_name.should == @author.name }
-    it { @commit.committer_name.should == @committer.name }
-    it { @commit.committer_email.should == @committer.email }
-    it { @commit.different_committer?.should be_true }
-  end
+    it "truncates a message with a newline after 80 characters at 70 characters" do
+      message = (commit.safe_message * 10) + "\n"
 
-  describe "Class methods" do
-    subject { Commit }
-
-    it { should respond_to(:find_or_first) }
-    it { should respond_to(:fresh_commits) }
-    it { should respond_to(:commits_with_refs) }
-    it { should respond_to(:commits_since) }
-    it { should respond_to(:commits_between) }
-    it { should respond_to(:commits) }
-    it { should respond_to(:compare) }
+      commit.stub(:safe_message).and_return(message)
+      commit.title.should == "#{message[0..69]}&hellip;"
+    end
   end
 
   describe "delegation" do
diff --git a/spec/models/gollum_wiki_spec.rb b/spec/models/gollum_wiki_spec.rb
index 87601683275163ec8f858b193f540b35abacd923..aa850dfd0a334b16b17452eed366e43e3a2479a7 100644
--- a/spec/models/gollum_wiki_spec.rb
+++ b/spec/models/gollum_wiki_spec.rb
@@ -81,7 +81,7 @@ describe GollumWiki do
     end
 
     it "raises CouldNotCreateWikiError if it can't create the wiki repository" do
-      Gitlab::Shell.any_instance.stub(:add_repository).and_return(false)
+      GollumWiki.any_instance.stub(:init_repo).and_return(false)
       expect { GollumWiki.new(project, user).wiki }.to raise_exception(GollumWiki::CouldNotCreateWikiError)
     end
   end
diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb
index 53388b933eef8c4b72506849b3d7482757fb9831..cbc7f278c2ac43db33c62070dc4f1af03cb273d8 100644
--- a/spec/models/project_spec.rb
+++ b/spec/models/project_spec.rb
@@ -119,7 +119,7 @@ describe Project do
   end
 
   describe :update_merge_requests do
-    let(:project) { create(:project) }
+    let(:project) { create(:project_with_code) }
 
     before do
       @merge_request = create(:merge_request, project: project)
@@ -189,10 +189,6 @@ describe Project do
     it "should return valid repo" do
       project.repository.should be_kind_of(Repository)
     end
-
-    it "should return nil" do
-      Project.new(path: "empty").repository.should be_nil
-    end
   end
 
   describe :issue_exists? do
@@ -249,7 +245,7 @@ describe Project do
   end
 
   describe :open_branches do
-    let(:project) { create(:project) }
+    let(:project) { create(:project_with_code) }
 
     before do
       project.protected_branches.create(name: 'master')
diff --git a/spec/requests/api/merge_requests_spec.rb b/spec/requests/api/merge_requests_spec.rb
index e7af056af8ecea691b1bebf66a8548e006d3d40c..25bbd9860bd6cee0c7a59eb46b152006345417f8 100644
--- a/spec/requests/api/merge_requests_spec.rb
+++ b/spec/requests/api/merge_requests_spec.rb
@@ -4,7 +4,7 @@ describe Gitlab::API do
   include ApiHelpers
 
   let(:user) { create(:user ) }
-  let!(:project) { create(:project, namespace: user.namespace ) }
+  let!(:project) { create(:project_with_code, creator_id: user.id) }
   let!(:merge_request) { create(:merge_request, author: user, assignee: user, project: project, title: "Test") }
   before { project.team << [user, :reporters] }
 
diff --git a/spec/requests/api/projects_spec.rb b/spec/requests/api/projects_spec.rb
index cddb72640189df893e847fb8e9a117d4f1f6b979..aca3919ad081e74bb80d9475beaa5d3eb5b1a594 100644
--- a/spec/requests/api/projects_spec.rb
+++ b/spec/requests/api/projects_spec.rb
@@ -7,7 +7,7 @@ describe Gitlab::API do
   let(:user2) { create(:user) }
   let(:user3) { create(:user) }
   let(:admin) { create(:admin) }
-  let!(:project) { create(:project, namespace: user.namespace ) }
+  let!(:project) { create(:project_with_code, creator_id: user.id) }
   let!(:hook) { create(:project_hook, project: project, url: "http://example.com") }
   let!(:snippet) { create(:snippet, author: user, project: project, title: 'example') }
   let!(:users_project) { create(:users_project, user: user, project: project, project_access: UsersProject::MASTER) }
diff --git a/spec/services/git_push_service_spec.rb b/spec/services/git_push_service_spec.rb
index 9fc5fd62531036641963047f1948660cbd78ee52..286a8cdaa22da32c5de8bdd3be337360ed0027a7 100644
--- a/spec/services/git_push_service_spec.rb
+++ b/spec/services/git_push_service_spec.rb
@@ -2,7 +2,7 @@ require 'spec_helper'
 
 describe GitPushService do
   let (:user)          { create :user }
-  let (:project)       { create :project }
+  let (:project)       { create :project_with_code }
   let (:service) { GitPushService.new }
 
   before do
diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb
index 03c586f81cfe14a180454f4355e1f2092ef47b27..8a01c9306855a63d6825addd53c4ebdf0ab4ade3 100644
--- a/spec/spec_helper.rb
+++ b/spec/spec_helper.rb
@@ -47,11 +47,7 @@ Spork.prefork do
     config.use_transactional_fixtures = false
 
     config.before do
-      # Use tmp dir for FS manipulations
-      temp_repos_path = Rails.root.join('tmp', 'test-git-base-path')
-      Gitlab.config.gitlab_shell.stub(repos_path: temp_repos_path)
-      FileUtils.rm_rf temp_repos_path
-      FileUtils.mkdir_p temp_repos_path
+      TestEnv.init
     end
   end
 end
diff --git a/spec/support/stubbed_repository.rb b/spec/support/stubbed_repository.rb
deleted file mode 100644
index 6376c8d5ea1a7814b7e5c2d4a96157779e759ef3..0000000000000000000000000000000000000000
--- a/spec/support/stubbed_repository.rb
+++ /dev/null
@@ -1,75 +0,0 @@
-require "repository"
-require "project"
-require "merge_request"
-require "shell"
-
-# Stubs out all Git repository access done by models so that specs can run
-# against fake repositories without Grit complaining that they don't exist.
-class Project
-  def repository
-    if path == "empty" || !path
-      nil
-    else
-      GitLabTestRepo.new(path_with_namespace)
-    end
-  end
-
-  def satellite
-    FakeSatellite.new
-  end
-
-  class FakeSatellite
-    def exists?
-      true
-    end
-
-    def destroy
-      true
-    end
-
-    def create
-      true
-    end
-  end
-end
-
-class MergeRequest
-  def check_if_can_be_merged
-    true
-  end
-end
-
-class GitLabTestRepo < Repository
-  def repo
-    @repo ||= Grit::Repo.new(Rails.root.join('tmp', 'repositories', 'gitlabhq'))
-  end
-
-  # patch repo size (in mb)
-  def size
-    12.45
-  end
-end
-
-module Gitlab
-  class Shell
-    def add_repository name
-      true
-    end
-
-    def mv_repository name, new_name
-      true
-    end
-
-    def remove_repository name
-      true
-    end
-
-    def add_key id, key
-      true
-    end
-
-    def remove_key id, key
-      true
-    end
-  end
-end
diff --git a/spec/support/test_env.rb b/spec/support/test_env.rb
new file mode 100644
index 0000000000000000000000000000000000000000..370094d376510f00ae815b1990b109b182ec5714
--- /dev/null
+++ b/spec/support/test_env.rb
@@ -0,0 +1,63 @@
+module TestEnv
+  extend self
+
+  # Test environment
+  #
+  # all repositories and namespaces stored at
+  # RAILS_APP/tmp/test-git-base-path
+  #
+  # Next shell methods are stubbed and return true
+  # -  mv_repository
+  # -  remove_repository
+  # -  add_key
+  # -  remove_key
+  #
+  def init
+    # Use tmp dir for FS manipulations
+    repos_path = Rails.root.join('tmp', 'test-git-base-path')
+    Gitlab.config.gitlab_shell.stub(repos_path: repos_path)
+
+    GollumWiki.any_instance.stub(:init_repo) do |path|
+      create_temp_repo(File.join(repos_path, "#{path}.git"))
+    end
+
+    Gitlab::Shell.any_instance.stub(
+      add_repository: true,
+      mv_repository: true,
+      remove_repository: true,
+      add_key: true,
+      remove_key: true
+    )
+
+    Gitlab::Satellite::Satellite.any_instance.stub(
+      exists?: true,
+      destroy: true,
+      create: true
+    )
+
+    MergeRequest.any_instance.stub(
+      check_if_can_be_merged: true
+    )
+
+    Repository.any_instance.stub(
+      size: 12.45
+    )
+
+    # Remove tmp/test-git-base-path
+    FileUtils.rm_rf Gitlab.config.gitlab_shell.repos_path
+
+    # Recreate tmp/test-git-base-path
+    FileUtils.mkdir_p Gitlab.config.gitlab_shell.repos_path
+
+    # Symlink tmp/repositories/gitlabhq to tmp/test-git-base-path/gitlabhq
+    seed_repo = Rails.root.join('tmp', 'repositories', 'gitlabhq')
+    target_repo = File.join(repos_path, 'gitlabhq.git')
+    system("ln -s #{seed_repo} #{target_repo}")
+  end
+
+  def create_temp_repo(path)
+    FileUtils.mkdir_p path
+    command = "git init --quiet --bare #{path};"
+    system(command)
+  end
+end
diff --git a/spec/workers/post_receive_spec.rb b/spec/workers/post_receive_spec.rb
index a4751bd0bafc1840a4d79893140f5d2dcdf83429..46e86dbe00aee86ddc83eb3c9313153feefc18c3 100644
--- a/spec/workers/post_receive_spec.rb
+++ b/spec/workers/post_receive_spec.rb
@@ -9,7 +9,7 @@ describe PostReceive do
   end
 
   context "web hook" do
-    let(:project) { create(:project) }
+    let(:project) { create(:project_with_code) }
     let(:key) { create(:key, user: project.owner) }
     let(:key_id) { key.shell_id }