diff --git a/.travis.yml b/.travis.yml
index d39e7f9..dc863a8 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,5 +1,7 @@
 language: scala
 sudo: true
+jdk: 
+  - oraclejdk8
 script:
   - sbt test
 before_script:
@@ -14,40 +16,3 @@
     - $HOME/.coursier
     - $HOME/.embedmysql
     - $HOME/.embedpostgresql
-matrix:
-  include:
-  - jdk: oraclejdk8
-    addons:
-      apt:
-        packages:
-        - libaio1
-  - dist: trusty
-    group: edge
-    sudo: required
-    jdk: oraclejdk9
-    addons:
-      apt:
-        packages:
-        - libaio1
-    before_install:
-    - cd ~
-    - JDK9_URL=`curl http://jdk.java.net/9/ | grep "lin64JDK" | grep "tar.gz\"" | sed -e "s/\"/ /g" | awk '{print $5}'`
-    - wget -O jdk-9_linux-x64_bin.tar.gz $JDK9_URL
-    - tar -xzf jdk-9_linux-x64_bin.tar.gz
-    - cd -
-    script:
-    # https://github.com/sbt/sbt/pull/2951
-    - git clone https://github.com/retronym/java9-rt-export
-    - cd java9-rt-export/
-    - git checkout 1019a2873d057dd7214f4135e84283695728395d
-    - jdk_switcher use oraclejdk8
-    - sbt package
-#    - jdk_switcher use oraclejdk9
-    - export JAVA_HOME=~/jdk-9
-    - PATH=$JAVA_HOME/bin:$PATH
-    - java -version
-    - mkdir -p $HOME/.sbt/0.13/java9-rt-ext; java -jar target/java9-rt-export-*.jar $HOME/.sbt/0.13/java9-rt-ext/rt.jar
-    - jar tf $HOME/.sbt/0.13/java9-rt-ext/rt.jar | grep java/lang/Object
-    - cd ..
-    - wget https://raw.githubusercontent.com/paulp/sbt-extras/9ade5fa54914ca8aded44105bf4b9a60966f3ccd/sbt && chmod +x ./sbt
-    - ./sbt -Dscala.ext.dirs=$HOME/.sbt/0.13/java9-rt-ext test
diff --git a/src/main/scala/ScalatraBootstrap.scala b/src/main/scala/ScalatraBootstrap.scala
index 7bc40ca..80e3a58 100644
--- a/src/main/scala/ScalatraBootstrap.scala
+++ b/src/main/scala/ScalatraBootstrap.scala
@@ -25,11 +25,9 @@
     context.getFilterRegistration("gitAuthenticationFilter").addMappingForUrlPatterns(EnumSet.allOf(classOf[DispatcherType]), true, "/git/*")
     context.addFilter("apiAuthenticationFilter", new ApiAuthenticationFilter)
     context.getFilterRegistration("apiAuthenticationFilter").addMappingForUrlPatterns(EnumSet.allOf(classOf[DispatcherType]), true, "/api/v3/*")
-    context.addFilter("ghCompatRepositoryAccessFilter", new GHCompatRepositoryAccessFilter)
-    context.getFilterRegistration("ghCompatRepositoryAccessFilter").addMappingForUrlPatterns(EnumSet.allOf(classOf[DispatcherType]), true, "/*")
 
     // Register controllers
-    context.mount(new AnonymousAccessController, "/*")
+    context.mount(new PreProcessController, "/*")
 
     context.addFilter("pluginControllerFilter", new PluginControllerFilter)
     context.getFilterRegistration("pluginControllerFilter").addMappingForUrlPatterns(EnumSet.allOf(classOf[DispatcherType]), true, "/*")
diff --git a/src/main/scala/gitbucket/core/controller/AnonymousAccessController.scala b/src/main/scala/gitbucket/core/controller/AnonymousAccessController.scala
deleted file mode 100644
index 180b164..0000000
--- a/src/main/scala/gitbucket/core/controller/AnonymousAccessController.scala
+++ /dev/null
@@ -1,14 +0,0 @@
-package gitbucket.core.controller
-
-class AnonymousAccessController extends AnonymousAccessControllerBase
-
-trait AnonymousAccessControllerBase extends ControllerBase {
-  get(!context.settings.allowAnonymousAccess, context.loginAccount.isEmpty) {
-    if(!context.currentPath.startsWith("/assets") && !context.currentPath.startsWith("/signin") &&
-      !context.currentPath.startsWith("/register")) {
-      Unauthorized()
-    } else {
-      pass()
-    }
-  }
-}
diff --git a/src/main/scala/gitbucket/core/controller/PreProcessController.scala b/src/main/scala/gitbucket/core/controller/PreProcessController.scala
new file mode 100644
index 0000000..1c5d263
--- /dev/null
+++ b/src/main/scala/gitbucket/core/controller/PreProcessController.scala
@@ -0,0 +1,40 @@
+package gitbucket.core.controller
+
+import org.scalatra.MovedPermanently
+
+class PreProcessController extends PreProcessControllerBase
+
+trait PreProcessControllerBase extends ControllerBase {
+
+  /**
+   * Provides GitHub compatible URLs for Git client.
+   *
+   * <ul>
+   *   <li>git clone http://localhost:8080/owner/repo</li>
+   *   <li>git clone http://localhost:8080/owner/repo.git</li>
+   * </ul>
+   *
+   * @see https://git-scm.com/book/en/v2/Git-Internals-Transfer-Protocols
+   */
+  get("/*/*/info/refs") {
+    val query = Option(request.getQueryString).map("?" + _).getOrElse("")
+    halt(MovedPermanently(baseUrl + "/git" + request.getRequestURI + query))
+  }
+
+  /**
+   * Filter requests from anonymous users.
+   *
+   * If anonymous access is allowed, pass all requests.
+   * But if it's not allowed, demands authentication except some paths.
+   */
+  get(!context.settings.allowAnonymousAccess, context.loginAccount.isEmpty) {
+    if(!context.currentPath.startsWith("/assets") && !context.currentPath.startsWith("/signin") &&
+      !context.currentPath.startsWith("/register")) {
+      Unauthorized()
+    } else {
+      pass()
+    }
+  }
+
+
+}
diff --git a/src/main/scala/gitbucket/core/servlet/GHCompatRepositoryAccessFilter.scala b/src/main/scala/gitbucket/core/servlet/GHCompatRepositoryAccessFilter.scala
deleted file mode 100644
index 0a19060..0000000
--- a/src/main/scala/gitbucket/core/servlet/GHCompatRepositoryAccessFilter.scala
+++ /dev/null
@@ -1,38 +0,0 @@
-package gitbucket.core.servlet
-
-import javax.servlet._
-import javax.servlet.http.{HttpServletRequest, HttpServletResponse}
-
-import gitbucket.core.service.SystemSettingsService
-
-/**
-  * A controller to provide GitHub compatible URL for Git clients.
-  */
-class GHCompatRepositoryAccessFilter extends Filter with SystemSettingsService {
-
-  /**
-    * Pattern of GitHub compatible repository URL.
-    * <code>/:user/:repo.git/</code>
-    */
-  private val githubRepositoryPattern = """^/[^/]+/[^/]+\.git/.*""".r
-
-  override def init(filterConfig: FilterConfig) = {}
-
-  override def doFilter(req: ServletRequest, res: ServletResponse, chain: FilterChain) = {
-    implicit val request = req.asInstanceOf[HttpServletRequest]
-    val agent = request.getHeader("USER-AGENT")
-    val response = res.asInstanceOf[HttpServletResponse]
-    val requestPath = request.getRequestURI.substring(request.getContextPath.length)
-    val queryString = if (request.getQueryString != null) "?" + request.getQueryString else ""
-
-    requestPath match {
-      case githubRepositoryPattern() if agent != null && agent.toLowerCase.indexOf("git") >= 0 =>
-        response.sendRedirect(baseUrl + "/git" + requestPath + queryString)
-      case _ =>
-        chain.doFilter(req, res)
-    }
-  }
-
-  override def destroy() = {}
-
-}