diff --git a/app/controllers/projects/base_tree_controller.rb b/app/controllers/projects/base_tree_controller.rb
deleted file mode 100644
index a7b1b7b40e84dfd9ab45afb707ef4e5c30884e47..0000000000000000000000000000000000000000
--- a/app/controllers/projects/base_tree_controller.rb
+++ /dev/null
@@ -1,7 +0,0 @@
-class Projects::BaseTreeController < Projects::ApplicationController
-  include ExtractsPath
-
-  before_filter :authorize_download_code!
-  before_filter :require_non_empty_project
-end
-
diff --git a/app/controllers/projects/blob_controller.rb b/app/controllers/projects/blob_controller.rb
index 2412800c4931394a342c24b44b35bd02b60bb8e4..00b82ff1df359d1a178e573b544a9a8f6f52a98b 100644
--- a/app/controllers/projects/blob_controller.rb
+++ b/app/controllers/projects/blob_controller.rb
@@ -2,16 +2,70 @@
 class Projects::BlobController < Projects::ApplicationController
   include ExtractsPath
 
-  # Authorize
+  # Raised when given an invalid file path
+  class InvalidPathError < StandardError; end
+
   before_filter :authorize_download_code!
-  before_filter :require_non_empty_project
+  before_filter :require_non_empty_project, except: [:new, :create]
   before_filter :authorize_push_code!, only: [:destroy]
+  before_filter :assign_blob_vars
+  before_filter :commit, except: [:new, :create]
+  before_filter :blob, except: [:new, :create]
+  before_filter :from_merge_request, only: [:edit, :update]
+  before_filter :after_edit_path, only: [:edit, :update]
+  before_filter :require_branch_head, only: [:edit, :update]
+
+  def new
+    commit unless @repository.empty?
+  end
 
-  before_filter :blob
+  def create
+    file_path = File.join(@path, File.basename(params[:file_name]))
+    result = Files::CreateService.new(@project, current_user, params, @ref, file_path).execute
+
+    if result[:status] == :success
+      flash[:notice] = "Your changes have been successfully committed"
+      redirect_to project_blob_path(@project, File.join(@ref, file_path))
+    else
+      flash[:alert] = result[:message]
+      render :show
+    end
+  end
 
   def show
   end
 
+  def edit
+    @last_commit = Gitlab::Git::Commit.last_for_path(@repository, @ref, @path).sha
+  end
+
+  def update
+    result = Files::UpdateService.
+      new(@project, current_user, params, @ref, @path).execute
+
+    if result[:status] == :success
+      flash[:notice] = "Your changes have been successfully committed"
+
+      if from_merge_request
+        from_merge_request.reload_code
+      end
+
+      redirect_to after_edit_path
+    else
+      flash[:alert] = result[:message]
+      render :show
+    end
+  end
+
+  def preview
+    @content = params[:content]
+    diffy = Diffy::Diff.new(@blob.data, @content, diff: '-U 3',
+                            include_diff_info: true)
+    @diff_lines = Gitlab::Diff::Parser.new.parse(diffy.diff.scan(/.*\n/))
+
+    render layout: false
+  end
+
   def destroy
     result = Files::DeleteService.new(@project, current_user, params, @ref, @path).execute
 
@@ -46,10 +100,44 @@ class Projects::BlobController < Projects::ApplicationController
 
     if @blob
       @blob
-    elsif tree.entries.any?
-      redirect_to project_tree_path(@project, File.join(@ref, @path)) and return
     else
+      if tree = @repository.tree(@commit.id, @path)
+        if tree.entries.any?
+          redirect_to project_tree_path(@project, File.join(@ref, @path)) and return
+        end
+      end
+
       return not_found!
     end
   end
+
+  def commit
+    @commit = @repository.commit(@ref)
+
+    return not_found! unless @commit
+  end
+
+  def assign_blob_vars
+    @id = params[:id]
+    @ref, @path = extract_ref(@id)
+
+
+  rescue InvalidPathError
+    not_found!
+  end
+
+  def after_edit_path
+    @after_edit_path ||=
+      if from_merge_request
+        diffs_project_merge_request_path(from_merge_request.target_project, from_merge_request) +
+          "#file-path-#{hexdigest(@path)}"
+      else
+        project_blob_path(@project, @id)
+      end
+  end
+
+  def from_merge_request
+    # If blob edit was initiated from merge request page
+    @from_merge_request ||= MergeRequest.find_by(id: params[:from_merge_request_id])
+  end
 end
diff --git a/app/controllers/projects/edit_tree_controller.rb b/app/controllers/projects/edit_tree_controller.rb
deleted file mode 100644
index 65661c80410b66e22b578f1e78d6bfb64dea1ddb..0000000000000000000000000000000000000000
--- a/app/controllers/projects/edit_tree_controller.rb
+++ /dev/null
@@ -1,60 +0,0 @@
-class Projects::EditTreeController < Projects::BaseTreeController
-  before_filter :require_branch_head
-  before_filter :blob
-  before_filter :authorize_push_code!
-  before_filter :from_merge_request
-  before_filter :after_edit_path
-
-  def show
-    @last_commit = Gitlab::Git::Commit.last_for_path(@repository, @ref, @path).sha
-  end
-
-  def update
-    result = Files::UpdateService.
-      new(@project, current_user, params, @ref, @path).execute
-
-    if result[:status] == :success
-      flash[:notice] = "Your changes have been successfully committed"
-
-      if from_merge_request
-        from_merge_request.reload_code
-      end
-
-      redirect_to after_edit_path
-    else
-      flash[:alert] = result[:message]
-      render :show
-    end
-  end
-
-  def preview
-    @content = params[:content]
-
-    diffy = Diffy::Diff.new(@blob.data, @content, diff: '-U 3',
-                            include_diff_info: true)
-    @diff_lines = Gitlab::Diff::Parser.new.parse(diffy.diff.scan(/.*\n/))
-
-    render layout: false
-  end
-
-  private
-
-  def blob
-    @blob ||= @repository.blob_at(@commit.id, @path)
-  end
-
-  def after_edit_path
-    @after_edit_path ||=
-      if from_merge_request
-        diffs_project_merge_request_path(from_merge_request.target_project, from_merge_request) +
-          "#file-path-#{hexdigest(@path)}"
-      else
-        project_blob_path(@project, @id)
-      end
-  end
-
-  def from_merge_request
-    # If blob edit was initiated from merge request page
-    @from_merge_request ||= MergeRequest.find_by(id: params[:from_merge_request_id])
-  end
-end
diff --git a/app/controllers/projects/new_tree_controller.rb b/app/controllers/projects/new_tree_controller.rb
deleted file mode 100644
index ffba706b2f665223dae58078bf5e45bf381210e3..0000000000000000000000000000000000000000
--- a/app/controllers/projects/new_tree_controller.rb
+++ /dev/null
@@ -1,20 +0,0 @@
-class Projects::NewTreeController < Projects::BaseTreeController
-  before_filter :require_branch_head
-  before_filter :authorize_push_code!
-
-  def show
-  end
-
-  def update
-    file_path = File.join(@path, File.basename(params[:file_name]))
-    result = Files::CreateService.new(@project, current_user, params, @ref, file_path).execute
-
-    if result[:status] == :success
-      flash[:notice] = "Your changes have been successfully committed"
-      redirect_to project_blob_path(@project, File.join(@ref, file_path))
-    else
-      flash[:alert] = result[:message]
-      render :show
-    end
-  end
-end