diff --git a/CHANGELOG b/CHANGELOG
index 3c4f4d93374b370f2edd73776a60bac81cba9da9..04494a0d692eb0a3f7eb7e025fad89f83b48e4c1 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -32,6 +32,7 @@ v 6.6.0
   - Restyle Issue#show page and MR#show page
   - Ability to filter by multiple labels for Issues page
   - Rails version to 4.0.3
+  - Blob and tree gfm links to anchors work
 
 v 6.5.1
   - Fix branch selectbox when create merge request from fork
diff --git a/app/helpers/gitlab_markdown_helper.rb b/app/helpers/gitlab_markdown_helper.rb
index b25662e3ba27b054efc329ae1b476120d14e172e..6cad5e4658e7610c77086320e8ccb4e7670f3438 100644
--- a/app/helpers/gitlab_markdown_helper.rb
+++ b/app/helpers/gitlab_markdown_helper.rb
@@ -124,12 +124,14 @@ module GitlabMarkdownHelper
   end
 
   def rebuild_path(path_with_namespace, path, requested_path, ref)
+    path.gsub!(/(#.*)/, "")
+    id = $1 || ""
     file_path = relative_file_path(path, requested_path)
     [
       path_with_namespace,
       path_with_ref(file_path, ref),
       file_path
-    ].compact.join("/")
+    ].compact.join("/").gsub(/\/*$/, '') + id
   end
 
   # Checks if the path exists in the repo
@@ -154,6 +156,7 @@ module GitlabMarkdownHelper
   # If we are at doc/api and the README.md shown in below the tree view
   # this takes the rquest path(doc/api) and adds users.md so the path looks like doc/api/users.md
   def build_nested_path(path, request_path)
+    return request_path if path == ""
     return path unless request_path
     if local_path(request_path) == "tree"
       base = request_path.split("/").push(path)
@@ -166,7 +169,7 @@ module GitlabMarkdownHelper
   end
 
   def file_exists?(path)
-    return false if path.nil? || path.empty?
+    return false if path.nil?
     return @repository.blob_at(current_sha, path).present? || @repository.tree(current_sha, path).entries.any?
   end
 
diff --git a/features/project/source/markdown_render.feature b/features/project/source/markdown_render.feature
index 42d6ebcb1cf728e91ed090fcf178a7e60b3da1b5..970a9e57864c8b9c2f7e4c396094050ae765e1cc 100644
--- a/features/project/source/markdown_render.feature
+++ b/features/project/source/markdown_render.feature
@@ -4,9 +4,7 @@ Feature: Project markdown render
     And I own project "Delta"
     Given I visit project source page
 
-  # -------------------------------------------
-  # README
-  # -------------------------------------------
+  # Tree README
 
   Scenario: Tree view should have correct links in README
     Given I go directory which contains README file
@@ -41,9 +39,7 @@ Feature: Project markdown render
     Then I should see rendered README which contains correct links
     And Header "Application details" should have correct id and link
 
-  # -------------------------------------------
-  # File content
-  # -------------------------------------------
+  # Blob
 
   Scenario: I navigate to doc directory to view documentation in master
     And I navigate to the doc/api/README
@@ -61,9 +57,7 @@ Feature: Project markdown render
     And I navigate to the doc/api/README
     And Header "GitLab API" should have correct id and link
 
-  # -------------------------------------------
-  # Markdown branch README
-  # -------------------------------------------
+  # Markdown branch
 
   Scenario: I browse files from markdown branch
     When I visit markdown branch
@@ -93,9 +87,31 @@ Feature: Project markdown render
     And I click on raketasks in doc/api/README
     Then I should see correct directory rendered for markdown branch
 
-  # -------------------------------------------
+  Scenario: Tree markdown links view empty urls should have correct urls
+    When I visit markdown branch
+    Then The link with text "empty" should have url "tree/markdown"
+    When I visit markdown branch "README.md" blob
+    Then The link with text "empty" should have url "blob/markdown/README.md"
+    When I visit markdown branch "d" tree
+    Then The link with text "empty" should have url "tree/markdown/d"
+    When I visit markdown branch "d/README.md" blob
+    Then The link with text "empty" should have url "blob/markdown/d/README.md"
+
+  # "ID" means "#id" on the tests below, because we are unable to escape the hash sign.
+  # which Spinach interprets as the start of a comment.
+  Scenario: All markdown links with ids should have correct urls
+    When I visit markdown branch
+    Then The link with text "ID" should have url "tree/markdownID"
+    Then The link with text "/ID" should have url "tree/markdownID"
+    Then The link with text "README.mdID" should have url "blob/markdown/README.mdID"
+    Then The link with text "d/README.mdID" should have url "blob/markdown/d/README.mdID"
+    When I visit markdown branch "README.md" blob
+    Then The link with text "ID" should have url "blob/markdown/README.mdID"
+    Then The link with text "/ID" should have url "blob/markdown/README.mdID"
+    Then The link with text "README.mdID" should have url "blob/markdown/README.mdID"
+    Then The link with text "d/README.mdID" should have url "blob/markdown/d/README.mdID"
+
   # Wiki
-  # -------------------------------------------
 
   Scenario: I create a wiki page with different links
     Given I go to wiki page
diff --git a/features/steps/project/project_markdown_render.rb b/features/steps/project/project_markdown_render.rb
index 89fbb7408c29f833a02d1eb1e932e7a72c824589..8fbf2753aa71df11ba9486c166fe151c6c1575ee 100644
--- a/features/steps/project/project_markdown_render.rb
+++ b/features/steps/project/project_markdown_render.rb
@@ -1,3 +1,6 @@
+# If you need to modify the existing seed repository for your tests,
+# it is recommended that you make the changes on the `markdown` branch of the seed project repository,
+# which should only be used by tests in this file. See `/spec/factories.rb#project` for more info.
 class Spinach::Features::ProjectMarkdownRender < Spinach::FeatureSteps
   include SharedAuthentication
   include SharedPaths
@@ -50,7 +53,7 @@ class Spinach::Features::ProjectMarkdownRender < Spinach::FeatureSteps
   end
 
   Then 'I should see correct doc/api directory rendered' do
-    current_path.should == project_tree_path(@project, "master/doc/api/")
+    current_path.should == project_tree_path(@project, "master/doc/api")
     page.should have_content "README.md"
     page.should have_content "users.md"
   end
@@ -64,6 +67,18 @@ class Spinach::Features::ProjectMarkdownRender < Spinach::FeatureSteps
     page.should have_content "bundle exec rake gitlab:env:info RAILS_ENV=production"
   end
 
+  And 'I click on link "empty" in the README' do
+    within('.readme-holder') do
+      click_link "empty"
+    end
+  end
+
+  And 'I click on link "id" in the README' do
+    within('.readme-holder') do
+      click_link "#id"
+    end
+  end
+
   And 'I navigate to the doc/api/README' do
     click_link "doc"
     click_link "api"
@@ -90,10 +105,24 @@ class Spinach::Features::ProjectMarkdownRender < Spinach::FeatureSteps
     click_link "Rake tasks"
   end
 
+  # Markdown branch
+
   When 'I visit markdown branch' do
     visit project_tree_path(@project, "markdown")
   end
 
+  When 'I visit markdown branch "README.md" blob' do
+    visit project_blob_path(@project, "markdown/README.md")
+  end
+
+  When 'I visit markdown branch "d" tree' do
+    visit project_tree_path(@project, "markdown/d")
+  end
+
+  When 'I visit markdown branch "d/README.md" blob' do
+    visit project_blob_path(@project, "markdown/d/README.md")
+  end
+
   Then 'I should see files from repository in markdown branch' do
     current_path.should == project_tree_path(@project, "markdown")
     page.should have_content "Gemfile"
@@ -124,6 +153,50 @@ class Spinach::Features::ProjectMarkdownRender < Spinach::FeatureSteps
     page.should have_content "Get a list of users."
   end
 
+  # Expected link contents
+
+  Then 'The link with text "empty" should have url "tree/markdown"' do
+    find('a', text: /^empty$/)['href'] == current_host + project_tree_path(@project, "markdown")
+  end
+
+  Then 'The link with text "empty" should have url "blob/markdown/README.md"' do
+    find('a', text: /^empty$/)['href'] == current_host + project_blob_path(@project, "markdown/README.md")
+  end
+
+  Then 'The link with text "empty" should have url "tree/markdown/d"' do
+    find('a', text: /^empty$/)['href'] == current_host + project_tree_path(@project, "markdown/d")
+  end
+
+  Then 'The link with text "empty" should have url "blob/markdown/d/README.md"' do
+    find('a', text: /^empty$/)['href'] == current_host + project_blob_path(@project, "markdown/d/README.md")
+  end
+
+  Then 'The link with text "ID" should have url "tree/markdownID"' do
+    find('a', text: /^#id$/)['href'] == current_host + project_tree_path(@project, "markdown") + '#id'
+  end
+
+  Then 'The link with text "/ID" should have url "tree/markdownID"' do
+    find('a', text: /^\/#id$/)['href'] == current_host + project_tree_path(@project, "markdown") + '#id'
+  end
+
+  Then 'The link with text "README.mdID" should have url "blob/markdown/README.mdID"' do
+    find('a', text: /^README.md#id$/)['href'] == current_host + project_blob_path(@project, "markdown/README.md") + '#id'
+  end
+
+  Then 'The link with text "d/README.mdID" should have url "blob/markdown/d/README.mdID"' do
+    find('a', text: /^d\/README.md#id$/)['href'] == current_host + project_blob_path(@project, "d/markdown/README.md") + '#id'
+  end
+
+  Then 'The link with text "ID" should have url "blob/markdown/README.mdID"' do
+    find('a', text: /^#id$/)['href'] == current_host + project_blob_path(@project, "markdown/README.md") + '#id'
+  end
+
+  Then 'The link with text "/ID" should have url "blob/markdown/README.mdID"' do
+    find('a', text: /^\/#id$/)['href'] == current_host + project_blob_path(@project, "markdown/README.md") + '#id'
+  end
+
+  # Wiki
+
   Given 'I go to wiki page' do
     click_link "Wiki"
     current_path.should == project_wiki_path(@project, "home")
diff --git a/spec/factories.rb b/spec/factories.rb
index 37436e53b95ad3168d3dbc718cf41598e4d81dc3..7fc2b7c5e97864a1077d76e0a420303d9819f506 100644
--- a/spec/factories.rb
+++ b/spec/factories.rb
@@ -34,6 +34,16 @@ FactoryGirl.define do
     creator
   end
 
+  # Generates a test repository from the repository stored under `spec/seed_project.tar.gz`.
+  # Once you run `rake gitlab:setup`, you can see what the repository looks like under `tmp/repositories/gitlabhq`.
+  # In order to modify files in the repository, you must untar the seed, modify and remake the tar.
+  # Before recompressing, do not forget to `git checkout master`.
+  # After recompressing, you need to run `RAILS_ENV=test bundle exec rake gitlab:setup` to regenerate the seeds under tmp.
+  #
+  # If you want to modify the repository only for an specific type of tests, e.g., markdown tests,
+  # consider using a feature branch to reduce the chances of collision with other tests.
+  # Create a new commit, and use the same commit message that you will use for the change in the main repo.
+  # Changing the commig message and SHA of branch `master` may break tests.
   factory :project, parent: :empty_project do
     path { 'gitlabhq' }
 
diff --git a/spec/helpers/gitlab_markdown_helper_spec.rb b/spec/helpers/gitlab_markdown_helper_spec.rb
index a445c18f0095f2c971fc5c397810ae2516649e96..7e98b7944f1e707e8e7fc070143572bc6c954bbe 100644
--- a/spec/helpers/gitlab_markdown_helper_spec.rb
+++ b/spec/helpers/gitlab_markdown_helper_spec.rb
@@ -454,7 +454,7 @@ describe GitlabMarkdownHelper do
 
     it "should handle relative urls in reference links for a directory in master" do
       actual = "[GitLab API doc directory][GitLab readmes]\n [GitLab readmes]: doc/api/\n"
-      expected = "<p><a href=\"/#{project.path_with_namespace}/tree/master/doc/api/\">GitLab API doc directory</a></p>\n"
+      expected = "<p><a href=\"/#{project.path_with_namespace}/tree/master/doc/api\">GitLab API doc directory</a></p>\n"
       markdown(actual).should match(expected)
     end
 
diff --git a/spec/seed_project.tar.gz b/spec/seed_project.tar.gz
index ee8c3f23c7019111d15bd62b8ed000229a6fa98e..92b9587e3f76bd27d26d910c49238a64caf93887 100644
Binary files a/spec/seed_project.tar.gz and b/spec/seed_project.tar.gz differ