diff --git a/CHANGELOG b/CHANGELOG
index a964a1922162fb2bbf7a0502f7b8297cf1b133dd..adb1d65c1359781c1caa6431f39b1c88248e3e78 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,18 +1,18 @@
 Please view this file on the master branch, on stable branches it's out of date.
 
 v 7.13.0 (unreleased)
+  - Fix user autocomplete for unauthenticated users accessing public projects (Stan Hu)
   - Fix redirection to home page URL for unauthorized users (Daniel Gerhardt)
   - Add branch switching support for graphs (Daniel Gerhardt)
   - Fix external issue tracker hook/test for HTTPS URLs (Daniel Gerhardt)
   - Remove link leading to a 404 error in Deploy Keys page (Stan Hu)
   - Add support for unlocking users in admin settings (Stan Hu)
   - Add Irker service configuration options (Stan Hu)
-  - Fix order of issues imported form GitHub (Hiroyuki Sato)
+  - Fix order of issues imported from GitHub (Hiroyuki Sato)
   - Bump rugments to 1.0.0beta8 to fix C prototype function highlighting (Jonathon Reinhart)
   - Fix Merge Request webhook to properly fire "merge" action when accepted from the web UI
   - Add `two_factor_enabled` field to admin user API (Stan Hu)
   - Fix invalid timestamps in RSS feeds (Rowan Wookey)
-  - Fix error when deleting a user who has projects (Stan Hu)
   - Fix downloading of patches on public merge requests when user logged out (Stan Hu)
   - The password for the default administrator (root) account has been changed from "5iveL!fe" to "password".
   - Fix Error 500 when relative submodule resolves to a namespace that has a different name from its path (Stan Hu)
@@ -43,6 +43,7 @@ v 7.13.0 (unreleased)
   - Redesign project page. Show README as default instead of activity. Move project activity to separate page
   - Make left menu more hierarchical and less contextual by adding back item at top
   - A fork can’t have a visibility level that is greater than the original project.
+  - Faster code search in repository and wiki. Fixes search page timeout for big repositories 
 
 v 7.12.2
   - Correctly show anonymous authorized applications under Profile > Applications.
diff --git a/app/assets/javascripts/dropzone_input.js.coffee b/app/assets/javascripts/dropzone_input.js.coffee
index a747614601055416fbc21df03d62b8946a883fa1..a4f511301c19bf321751561ab98147263791fb4f 100644
--- a/app/assets/javascripts/dropzone_input.js.coffee
+++ b/app/assets/javascripts/dropzone_input.js.coffee
@@ -25,10 +25,10 @@ class @DropzoneInput
     form_dropzone = $(form).find('.div-dropzone')
     form_dropzone.parent().addClass "div-dropzone-wrapper"
     form_dropzone.append divHover
-    $(".div-dropzone-hover").append iconPaperclip
+    form_dropzone.find(".div-dropzone-hover").append iconPaperclip
     form_dropzone.append divSpinner
-    $(".div-dropzone-spinner").append iconSpinner
-    $(".div-dropzone-spinner").css
+    form_dropzone.find(".div-dropzone-spinner").append iconSpinner
+    form_dropzone.find(".div-dropzone-spinner").css
       "opacity": 0
       "display": "none"
 
diff --git a/app/controllers/autocomplete_controller.rb b/app/controllers/autocomplete_controller.rb
index 11af9895261f1a683df092e4f03d9dad02a6e0c5..52e9c58b47cab90142bce38519fc53a586ddb7b5 100644
--- a/app/controllers/autocomplete_controller.rb
+++ b/app/controllers/autocomplete_controller.rb
@@ -1,22 +1,35 @@
 class AutocompleteController < ApplicationController
+  skip_before_action :authenticate_user!, only: [:users]
+
   def users
-    @users =
-      if params[:project_id].present?
-        project = Project.find(params[:project_id])
+    begin
+      @users =
+        if params[:project_id].present?
+          project = Project.find(params[:project_id])
 
-        if can?(current_user, :read_project, project)
-          project.team.users
-        end
-      elsif params[:group_id]
-        group = Group.find(params[:group_id])
+          if can?(current_user, :read_project, project)
+            project.team.users
+          end
+        elsif params[:group_id]
+          group = Group.find(params[:group_id])
 
-        if can?(current_user, :read_group, group)
-          group.users
+          if can?(current_user, :read_group, group)
+            group.users
+          end
+        elsif current_user
+          User.all
         end
-      else
-        User.all
+    rescue ActiveRecord::RecordNotFound
+      if current_user
+        return render json: {}, status: 404
       end
+    end
+
+    if @users.nil? && current_user.nil?
+      authenticate_user!
+    end
 
+    @users ||= User.none
     @users = @users.search(params[:search]) if params[:search].present?
     @users = @users.active
     @users = @users.page(params[:page]).per(PER_PAGE)
diff --git a/app/models/repository.rb b/app/models/repository.rb
index c767d1051d12cb0544cf97536937ccd41a4f013e..6262b5c4c92165bacedcf4f81b238eab8216dc42 100644
--- a/app/models/repository.rb
+++ b/app/models/repository.rb
@@ -431,6 +431,40 @@ class Repository
     end
   end
 
+  def search_files(query, ref)
+    offset = 2
+    args = %W(git grep -i -n --before-context #{offset} --after-context #{offset} #{query} #{ref || root_ref})
+    Gitlab::Popen.popen(args, path_to_repo).first.scrub.split(/^--$/)
+  end
+
+  def parse_search_result(result)
+    ref = nil
+    filename = nil
+    startline = 0
+
+    lines = result.lines
+    lines.each_with_index do |line, index|
+      if line =~ /^.*:.*:\d+:/
+        ref, filename, startline = line.split(':')
+        startline = startline.to_i - index
+        break
+      end
+    end
+
+    data = lines.map do |line|
+      line.sub(ref, '').sub(filename, '').sub(/^:-\d+-/, '').sub(/^::\d+:/, '')
+    end
+
+    data = data.join("")
+
+    OpenStruct.new(
+      filename: filename,
+      ref: ref,
+      startline: startline,
+      data: data
+    )
+  end
+
   private
 
   def cache
diff --git a/app/views/search/results/_blob.html.haml b/app/views/search/results/_blob.html.haml
index 84e9be82c444e2596cc2c95472ed282a9e5dd18f..58f58eff54d048db97352ba8b494604c450d89ff 100644
--- a/app/views/search/results/_blob.html.haml
+++ b/app/views/search/results/_blob.html.haml
@@ -1,3 +1,4 @@
+- blob = @project.repository.parse_search_result(blob)
 .blob-result
   .file-holder
     .file-title
diff --git a/app/views/search/results/_wiki_blob.html.haml b/app/views/search/results/_wiki_blob.html.haml
index f9c5810e3d057962ec92eb8f913e3b7b2c93b4ed..c03438eb9525705759a0199609b231e928841eb6 100644
--- a/app/views/search/results/_wiki_blob.html.haml
+++ b/app/views/search/results/_wiki_blob.html.haml
@@ -1,3 +1,4 @@
+- wiki_blob = @project.repository.parse_search_result(wiki_blob)
 .blob-result
   .file-holder
     .file-title
diff --git a/docker/README.md b/docker/README.md
index 8df603eca4f0f39d5dedfd64fd255d6986701914..293ca79f915ded71f144820e1bcac6e9af289995 100644
--- a/docker/README.md
+++ b/docker/README.md
@@ -94,12 +94,12 @@ To upgrade GitLab to new version you have to do:
 sudo docker stop gitlab
 ```
 
-1. stop running container, 
+1. stop running container,
 ```bash
 sudo docker rm gitlab
 ```
 
-1. remove existing container, 
+1. remove existing container,
 ```bash
 sudo docker pull gitlab/gitlab-ce:latest
 ```
@@ -162,4 +162,6 @@ sudo docker push gitlab/gitlab-ce:latest
 
 ## Troubleshooting
 
-Please see the [troubleshooting](troubleshooting.md) file in this directory.
\ No newline at end of file
+Please see the [troubleshooting](troubleshooting.md) file in this directory.
+
+Note: We use `fig.yml` to have compatibility with fig and because docker-compose also supports it.
diff --git a/spec/controllers/autocomplete_controller_spec.rb b/spec/controllers/autocomplete_controller_spec.rb
index 9ad9cb41cc14e3aa3063f9caac50ff26d6d3dbc0..1230017c27099c059004824f6927f6c4a3182a4c 100644
--- a/spec/controllers/autocomplete_controller_spec.rb
+++ b/spec/controllers/autocomplete_controller_spec.rb
@@ -9,15 +9,27 @@ describe AutocompleteController do
     before do
       sign_in(user)
       project.team << [user, :master]
-
-      get(:users, project_id: project.id)
     end
 
     let(:body) { JSON.parse(response.body) }
 
-    it { expect(body).to be_kind_of(Array) }
-    it { expect(body.size).to eq 1 }
-    it { expect(body.first["username"]).to eq user.username }
+    describe 'GET #users with project ID' do
+      before do
+        get(:users, project_id: project.id)
+      end
+
+      it { expect(body).to be_kind_of(Array) }
+      it { expect(body.size).to eq 1 }
+      it { expect(body.first["username"]).to eq user.username }
+    end
+
+    describe 'GET #users with unknown project' do
+      before do
+        get(:users, project_id: 'unknown')
+      end
+
+      it { expect(response.status).to eq(404) }
+    end
   end
 
   context 'group members' do
@@ -26,15 +38,27 @@ describe AutocompleteController do
     before do
       sign_in(user)
       group.add_owner(user)
-
-      get(:users, group_id: group.id)
     end
 
     let(:body) { JSON.parse(response.body) }
 
-    it { expect(body).to be_kind_of(Array) }
-    it { expect(body.size).to eq 1 }
-    it { expect(body.first["username"]).to eq user.username }
+    describe 'GET #users with group ID' do
+      before do
+        get(:users, group_id: group.id)
+      end
+
+      it { expect(body).to be_kind_of(Array) }
+      it { expect(body.size).to eq 1 }
+      it { expect(body.first["username"]).to eq user.username }
+    end
+
+    describe 'GET #users with unknown group ID' do
+      before do
+        get(:users, group_id: 'unknown')
+      end
+
+      it { expect(response.status).to eq(404) }
+    end
   end
 
   context 'all users' do
@@ -48,4 +72,52 @@ describe AutocompleteController do
     it { expect(body).to be_kind_of(Array) }
     it { expect(body.size).to eq User.count }
   end
+
+  context 'unauthenticated user' do
+    let(:public_project) { create(:project, :public) }
+    let(:body) { JSON.parse(response.body) }
+
+    describe 'GET #users with public project' do
+      before do
+        public_project.team << [user, :guest]
+        get(:users, project_id: public_project.id)
+      end
+
+      it { expect(body).to be_kind_of(Array) }
+      it { expect(body.size).to eq 1 }
+    end
+
+    describe 'GET #users with project' do
+      before do
+        get(:users, project_id: project.id)
+      end
+
+      it { expect(response.status).to eq(302) }
+    end
+
+    describe 'GET #users with unknown project' do
+      before do
+        get(:users, project_id: 'unknown')
+      end
+
+      it { expect(response.status).to eq(302) }
+    end
+
+    describe 'GET #users with inaccessible group' do
+      before do
+        project.team << [user, :guest]
+        get(:users, group_id: user.namespace.id)
+      end
+
+      it { expect(response.status).to eq(302) }
+    end
+
+    describe 'GET #users with no project' do
+      before do
+        get(:users)
+      end
+
+      it { expect(response.status).to eq(302) }
+    end
+  end
 end
diff --git a/spec/models/repository_spec.rb b/spec/models/repository_spec.rb
index a083dcb127425cc2a9140c73c1c75bbf1f1231bf..d25351b0f0ebd475252c8df428bfaf6f862bf833 100644
--- a/spec/models/repository_spec.rb
+++ b/spec/models/repository_spec.rb
@@ -47,4 +47,28 @@ describe Repository do
       it { is_expected.to be_falsey }
     end
   end
+
+  describe "search_files" do
+    let(:results) { repository.search_files('feature', 'master') }
+    subject { results }
+
+    it { is_expected.to be_an Array }
+
+    describe 'result' do
+      subject { results.first }
+
+      it { is_expected.to be_an String }
+      it { expect(subject.lines[2]).to eq("master:CHANGELOG:188:  - Feature: Replace teams with group membership\n") }
+    end
+
+    describe 'parsing result' do
+      subject { repository.parse_search_result(results.first) }
+
+      it { is_expected.to be_an OpenStruct }
+      it { expect(subject.filename).to eq('CHANGELOG') }
+      it { expect(subject.ref).to eq('master') }
+      it { expect(subject.startline).to eq(186) }
+      it { expect(subject.data.lines[2]).to eq("  - Feature: Replace teams with group membership\n") }
+    end
+  end
 end