diff --git a/Gemfile b/Gemfile
index 46ba460506b4896d4611a48cb6ebbef562c26d39..fb9df59e611fdfb8baaf613fa327ce83f6240749 100644
--- a/Gemfile
+++ b/Gemfile
@@ -263,3 +263,5 @@ group :production do
 end
 
 gem "newrelic_rpm"
+
+gem 'octokit', '3.7.0'
diff --git a/Gemfile.lock b/Gemfile.lock
index 4d4be5674dc3f351d2eb73e4087fc3cefaa98e16..cc46ad923421e21e6fb6025c18d5ab3de3f0cf4d 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -318,6 +318,8 @@ GEM
       jwt (~> 0.1.4)
       multi_json (~> 1.0)
       rack (~> 1.2)
+    octokit (3.7.0)
+      sawyer (~> 0.6.0, >= 0.5.3)
     omniauth (1.1.4)
       hashie (>= 1.2, < 3)
       rack
@@ -472,6 +474,9 @@ GEM
       sass (~> 3.2.0)
       sprockets (~> 2.8, <= 2.11.0)
       sprockets-rails (~> 2.0)
+    sawyer (0.6.0)
+      addressable (~> 2.3.5)
+      faraday (~> 0.8, < 0.10)
     sdoc (0.3.20)
       json (>= 1.1.3)
       rdoc (~> 3.10)
@@ -671,6 +676,7 @@ DEPENDENCIES
   mysql2
   newrelic_rpm
   nprogress-rails
+  octokit (= 3.7.0)
   omniauth (~> 1.1.3)
   omniauth-github
   omniauth-google-oauth2
diff --git a/app/controllers/github_imports_controller.rb b/app/controllers/github_imports_controller.rb
new file mode 100644
index 0000000000000000000000000000000000000000..97a2637b1eb4562210a4185028b69c343c822631
--- /dev/null
+++ b/app/controllers/github_imports_controller.rb
@@ -0,0 +1,75 @@
+class GithubImportsController < ApplicationController
+  before_filter :github_auth, except: :callback
+
+  rescue_from Octokit::Unauthorized, with: :github_unauthorized
+  
+  def callback
+    token = client.auth_code.get_token(params[:code]).token
+    current_user.github_access_token = token
+    current_user.save
+    redirect_to status_github_import_url
+  end
+
+  def status
+    @repos = octo_client.repos
+    octo_client.orgs.each do |org|
+      @repos += octo_client.repos(org.login)
+    end
+
+    @already_added_projects = current_user.created_projects.where(import_type: "github")
+    already_added_projects_names = @already_added_projects.pluck(:import_source)
+
+    @repos.reject!{|repo| already_added_projects_names.include? repo.full_name}
+  end
+
+  def create
+    @repo_id = params[:repo_id].to_i
+    repo = octo_client.repo(@repo_id)
+    target_namespace = params[:new_namespace].presence || repo.owner.login
+    existing_namespace = Namespace.find_by("path = ? OR name = ?", target_namespace, target_namespace)
+
+    if existing_namespace
+      if existing_namespace.owner == current_user
+        namespace = existing_namespace
+      else
+        @already_been_taken = true
+        @target_namespace = target_namespace
+        @project_name = repo.name
+        render and return
+      end
+    else
+      namespace = Group.create(name: target_namespace, path: target_namespace, owner: current_user)
+      namespace.add_owner(current_user)
+    end
+
+    Gitlab::Github::ProjectCreator.new(repo, namespace, current_user).execute
+  end
+
+  private
+
+  def client
+    @client ||= Gitlab::Github::Client.new.client
+  end
+
+  def octo_client
+    Octokit.auto_paginate = true
+    @octo_client ||= Octokit::Client.new(:access_token => current_user.github_access_token)
+  end
+
+  def github_auth
+    if current_user.github_access_token.blank?
+      go_to_gihub_for_permissions
+    end
+  end
+
+  def go_to_gihub_for_permissions
+    redirect_to client.auth_code.authorize_url({
+      redirect_uri: callback_github_import_url,
+      scope: "repo, user, user:email"
+    })
+  end
+
+  def github_unauthorized
+    go_to_gihub_for_permissions
+  end
+end
diff --git a/app/controllers/omniauth_callbacks_controller.rb b/app/controllers/omniauth_callbacks_controller.rb
index 3e984e5007ad6f55046b68ac07815e7b680a643e..442a1cf751820685602e82cc4f890f6195db7805 100644
--- a/app/controllers/omniauth_callbacks_controller.rb
+++ b/app/controllers/omniauth_callbacks_controller.rb
@@ -65,7 +65,7 @@ def handle_omniauth
         redirect_to omniauth_error_path(oauth['provider'], error: error_message) and return
       end
     end
-  rescue ForbiddenAction => e
+  rescue Gitlab::OAuth::ForbiddenAction => e
     flash[:notice] = e.message
     redirect_to new_user_session_path
   end
diff --git a/app/helpers/projects_helper.rb b/app/helpers/projects_helper.rb
index e489d431e84927f109a63e046dee690d73ae6f12..39d6be06383fe89768b0720092afa3b3b1ecb920 100644
--- a/app/helpers/projects_helper.rb
+++ b/app/helpers/projects_helper.rb
@@ -237,4 +237,20 @@ def hidden_pass_url(original_url)
     result.password = '*****' if result.password.present?
     result
   end
+
+  def project_status_css_class(status)
+    case status
+    when "started"
+      "active"
+    when "failed"
+      "danger"
+    when "finished"
+      "success"
+    end
+  end
+
+  def github_import_enabled?
+    Gitlab.config.omniauth.enabled && enabled_oauth_providers.include?(:github)
+  end
 end
+
diff --git a/app/views/github_imports/create.js.haml b/app/views/github_imports/create.js.haml
new file mode 100644
index 0000000000000000000000000000000000000000..e354c2da4dd117422a42389c72457ee9673662ca
--- /dev/null
+++ b/app/views/github_imports/create.js.haml
@@ -0,0 +1,18 @@
+- if @already_been_taken
+  :plain
+    target_field = $("tr#repo_#{@repo_id} .import-target")
+    origin_target = target_field.text()
+    project_name = "#{@project_name}"
+    origin_namespace = "#{@target_namespace}"
+    target_field.empty()
+    target_field.append("<p class='alert alert-danger'>This namespace already been taken! Please choose another one</p>")
+    target_field.append("<input type='text' name='target_namespace' />")
+    target_field.append("/" + project_name)
+    target_field.data("project_name", project_name)
+    target_field.find('input').prop("value", origin_namespace)
+- else
+  :plain
+    $("table.import-jobs tbody").prepend($("tr#repo_#{@repo_id}"))
+    $("tr#repo_#{@repo_id}").addClass("active").find(".import-actions").text("started")
+
+  
\ No newline at end of file
diff --git a/app/views/github_imports/status.html.haml b/app/views/github_imports/status.html.haml
new file mode 100644
index 0000000000000000000000000000000000000000..6a196cae39d31cf83289d4513767b8d2e4e248c1
--- /dev/null
+++ b/app/views/github_imports/status.html.haml
@@ -0,0 +1,41 @@
+%h3.page-title
+  Import repositories from github
+
+%hr
+%h4
+  Select projects you want to import.
+  
+%table.table.table-bordered.import-jobs
+  %thead
+    %tr
+      %th From GitHub
+      %th To GitLab
+      %th Status
+  %tbody
+    - @already_added_projects.each do |repo|
+      %tr{id: "repo_#{repo.id}", class: "#{project_status_css_class(repo.import_status)}"}
+        %td= repo.import_source
+        %td= repo.name_with_namespace
+        %td= repo.human_import_status_name
+    
+    - @repos.each do |repo|
+      %tr{id: "repo_#{repo.id}"}
+        %td= repo.full_name
+        %td.import-target 
+          = repo.full_name
+        %td.import-actions
+          = button_tag "Add", class: "btn btn-add-to-import"
+        
+
+:coffeescript
+  $(".btn-add-to-import").click () ->
+    new_namespace = null
+    tr = $(this).closest("tr")
+    id = tr.attr("id").replace("repo_", "")
+    if tr.find(".import-target input").length > 0
+      new_namespace = tr.find(".import-target input").prop("value")
+      tr.find(".import-target").empty().append(new_namespace + "/" + tr.find(".import-target").data("project_name"))
+    $.post "#{github_import_url}", {repo_id: id, new_namespace: new_namespace}, dataType: 'script'
+
+
+        
diff --git a/app/views/projects/new.html.haml b/app/views/projects/new.html.haml
index f320a2b505ee4381a5cf6b6eb3b4a9de28707e61..88c1f725703c6ff11a345cdac60d2d1daaebaac0 100644
--- a/app/views/projects/new.html.haml
+++ b/app/views/projects/new.html.haml
@@ -39,7 +39,15 @@
                 %br
                 The import will time out after 4 minutes. For big repositories, use a clone/push combination.
                 For SVN repositories, check #{link_to "this migrating from SVN doc.", "http://doc.gitlab.com/ce/workflow/migrating_from_svn.html"}
-      %hr
+      
+      - if github_import_enabled?
+        .project-import.form-group
+          .col-sm-2
+          .col-sm-10
+            %i.fa.fa-bars
+            = link_to "Import projects from github", status_github_import_path
+
+      %hr.prepend-botton-10
 
       .form-group
         = f.label :description, class: 'control-label' do
diff --git a/app/workers/repository_import_worker.rb b/app/workers/repository_import_worker.rb
index 01586150cd2c2974b0db6a473a0f6c8276dc6be7..0bcc42bc62c8d9781556814b503841552eab4950 100644
--- a/app/workers/repository_import_worker.rb
+++ b/app/workers/repository_import_worker.rb
@@ -10,7 +10,13 @@ def perform(project_id)
                                project.path_with_namespace,
                                project.import_url)
 
-    if result
+    if project.import_type == 'github'
+      result_of_data_import = Gitlab::Github::Importer.new(project).execute
+    else
+      result_of_data_import = true
+    end
+
+    if result && result_of_data_import
       project.import_finish
       project.save
       project.satellite.create unless project.satellite.exists?
diff --git a/config/routes.rb b/config/routes.rb
index d36540024aaca2975ae0f3aea7c684bb10b340c2..fc82926abb167d4f6d450cfadf7f4acd188cb11d 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -51,6 +51,14 @@
   end
   get "/s/:username" => "snippets#user_index", as: :user_snippets, constraints: { username: /.*/ }
 
+  #
+  # Github importer area
+  #
+  resource :github_import, only: [:create, :new] do
+    get :status
+    get :callback
+  end
+
   #
   # Explroe area
   #
diff --git a/db/migrate/20141223135007_add_import_data_to_project_table.rb b/db/migrate/20141223135007_add_import_data_to_project_table.rb
new file mode 100644
index 0000000000000000000000000000000000000000..5db78f94cc978c3a06511aa76ff6ccd9339bf58a
--- /dev/null
+++ b/db/migrate/20141223135007_add_import_data_to_project_table.rb
@@ -0,0 +1,8 @@
+class AddImportDataToProjectTable < ActiveRecord::Migration
+  def change
+    add_column :projects, :import_type, :string
+    add_column :projects, :import_source, :string
+
+    add_column :users, :github_access_token, :string
+  end
+end
diff --git a/db/schema.rb b/db/schema.rb
index cb945e71665acb5a3f81ae461451a7a2d0368a9e..b87b7d05509027759782f1767d49bfe1be219f39 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -314,6 +314,8 @@
     t.string   "import_status"
     t.float    "repository_size",        default: 0.0
     t.integer  "star_count",             default: 0,        null: false
+    t.string   "import_type"
+    t.string   "import_source"
   end
 
   add_index "projects", ["creator_id"], name: "index_projects_on_creator_id", using: :btree
@@ -411,6 +413,7 @@
     t.integer  "notification_level",       default: 1,     null: false
     t.datetime "password_expires_at"
     t.integer  "created_by_id"
+    t.datetime "last_credential_check_at"
     t.string   "avatar"
     t.string   "confirmation_token"
     t.datetime "confirmed_at"
@@ -418,7 +421,7 @@
     t.string   "unconfirmed_email"
     t.boolean  "hide_no_ssh_key",          default: false
     t.string   "website_url",              default: "",    null: false
-    t.datetime "last_credential_check_at"
+    t.string   "github_access_token"
   end
 
   add_index "users", ["admin"], name: "index_users_on_admin", using: :btree
diff --git a/lib/gitlab/github/client.rb b/lib/gitlab/github/client.rb
new file mode 100644
index 0000000000000000000000000000000000000000..c6935a0b0ba93916a7e8408743e31c93345688e1
--- /dev/null
+++ b/lib/gitlab/github/client.rb
@@ -0,0 +1,29 @@
+module Gitlab
+  module Github
+    class Client
+      attr_reader :client
+
+      def initialize
+        @client = ::OAuth2::Client.new(
+          config.app_id,
+          config.app_secret,
+          github_options
+        )
+      end
+
+      private
+
+      def config
+        Gitlab.config.omniauth.providers.select{|provider| provider.name == "github"}.first
+      end
+
+      def github_options
+        {
+          :site => 'https://api.github.com',
+          :authorize_url => 'https://github.com/login/oauth/authorize',
+          :token_url => 'https://github.com/login/oauth/access_token'
+        }
+      end
+    end
+  end
+end
diff --git a/lib/gitlab/github/importer.rb b/lib/gitlab/github/importer.rb
new file mode 100644
index 0000000000000000000000000000000000000000..c72a1c25e9e49e7eb8e192d155a37aab5d6eddf0
--- /dev/null
+++ b/lib/gitlab/github/importer.rb
@@ -0,0 +1,48 @@
+module Gitlab
+  module Github
+    class Importer
+      attr_reader :project
+
+      def initialize(project)
+        @project = project
+      end
+
+      def execute
+        client = octo_client(project.creator.github_access_token)
+       
+        #Issues && Comments
+        client.list_issues(project.import_source, state: :all).each do |issue|
+          if issue.pull_request.nil?
+            body = "*Created by: #{issue.user.login}*\n\n#{issue.body}"
+            
+            if issue.comments > 0
+              body += "\n\n\n**Imported comments:**\n"
+              client.issue_comments(project.import_source, issue.number).each do |c|
+                body += "\n\n*By #{c.user.login} on #{c.created_at}*\n\n#{c.body}"
+              end
+            end
+
+            project.issues.create!(
+              description: body, 
+              title: issue.title,
+              state: issue.state == 'closed' ? 'closed' : 'opened',
+              author_id: gl_user_id(project, issue.user.id)
+            )
+          end
+        end
+      end
+
+      private
+
+      def octo_client(access_token)
+        ::Octokit.auto_paginate = true
+        ::Octokit::Client.new(:access_token => access_token)
+      end
+
+      def gl_user_id(project, github_id)
+        user = User.joins(:identities).find_by("identities.extern_uid = ?", github_id.to_s)
+        (user && user.id) || project.creator_id
+      end
+    end
+  end
+end
diff --git a/lib/gitlab/github/project_creator.rb b/lib/gitlab/github/project_creator.rb
new file mode 100644
index 0000000000000000000000000000000000000000..682ef389e443770a760f5c77476efed79385be00
--- /dev/null
+++ b/lib/gitlab/github/project_creator.rb
@@ -0,0 +1,37 @@
+module Gitlab
+  module Github
+    class ProjectCreator
+      attr_reader :repo, :namespace, :current_user
+
+      def initialize(repo, namespace, current_user)
+        @repo = repo
+        @namespace = namespace
+        @current_user = current_user
+      end
+
+      def execute
+        @project = Project.new(
+          name: repo.name,
+          path: repo.name,
+          description: repo.description,
+          namespace: namespace,
+          creator: current_user,
+          visibility_level: repo.private ? Gitlab::VisibilityLevel::PRIVATE : Gitlab::VisibilityLevel::PUBLIC,
+          import_type: "github",
+          import_source: repo.full_name,
+          import_url: repo.clone_url.sub("https://", "https://#{current_user.github_access_token}@")
+        )
+
+        if @project.save!
+          @project.reload
+
+          if @project.import_failed?
+            @project.import_retry
+          else
+            @project.import_start
+          end
+        end
+      end
+    end
+  end
+end
diff --git a/lib/gitlab/regex.rb b/lib/gitlab/regex.rb
index c4d0d85b7f58903e4171d8602857aae16622f445..cf6e260f25750be6200f4b4b8030102cf5c6e991 100644
--- a/lib/gitlab/regex.rb
+++ b/lib/gitlab/regex.rb
@@ -11,7 +11,7 @@ def username_regex_message
     end
 
     def project_name_regex
-      /\A[a-zA-Z0-9_][a-zA-Z0-9_\-\. ]*\z/
+      /\A[a-zA-Z0-9_.][a-zA-Z0-9_\-\. ]*\z/
     end
 
     def project_regex_message
diff --git a/spec/controllers/github_imports_controller_spec.rb b/spec/controllers/github_imports_controller_spec.rb
new file mode 100644
index 0000000000000000000000000000000000000000..f1d2df8411aa29a077a671be668d412a835bb40e
--- /dev/null
+++ b/spec/controllers/github_imports_controller_spec.rb
@@ -0,0 +1,64 @@
+require 'spec_helper'
+
+describe GithubImportsController do
+  let(:user) { create(:user, github_access_token: 'asd123') }
+
+  before do
+    sign_in(user)
+  end
+
+  describe "GET callback" do
+    it "updates access token" do
+      token = "asdasd12345"
+      Gitlab::Github::Client.any_instance.stub_chain(:client, :auth_code, :get_token, :token).and_return(token)
+
+      get :callback
+      
+      user.reload.github_access_token.should == token
+      controller.should redirect_to(status_github_import_url)
+    end
+  end
+
+  describe "GET status" do
+    before do
+      @repo = OpenStruct.new(login: 'vim', full_name: 'asd/vim')
+    end
+
+    it "assigns variables" do
+      @project = create(:project, import_type: 'github', creator_id: user.id)
+      controller.stub_chain(:octo_client, :repos).and_return([@repo])
+      controller.stub_chain(:octo_client, :orgs).and_return([])
+
+      get :status
+
+      expect(assigns(:already_added_projects)).to eq([@project])
+      expect(assigns(:repos)).to eq([@repo])
+    end
+
+    it "does not show already added project" do
+      @project = create(:project, import_type: 'github', creator_id: user.id, import_source: 'asd/vim')
+      controller.stub_chain(:octo_client, :repos).and_return([@repo])
+      controller.stub_chain(:octo_client, :orgs).and_return([])
+
+      get :status
+
+      expect(assigns(:already_added_projects)).to eq([@project])
+      expect(assigns(:repos)).to eq([])
+    end
+  end
+
+  describe "POST create" do
+    before do
+      @repo = OpenStruct.new(login: 'vim', full_name: 'asd/vim', owner: OpenStruct.new(login: "john"))
+    end
+
+    it "takes already existing namespace" do
+      namespace = create(:namespace, name: "john", owner: user)
+      Gitlab::Github::ProjectCreator.should_receive(:new).with(@repo, namespace, user).
+        and_return(double(execute: true))
+      controller.stub_chain(:octo_client, :repo).and_return(@repo)
+
+      post :create, format: :js
+    end
+  end
+end
diff --git a/spec/helpers/projects_helper_spec.rb b/spec/helpers/projects_helper_spec.rb
index 114058e3095ef6bfc29dc476a5527dd5a1b872ca..2146b0b138335cc6f2d13766cf8ae75e6c6ce82c 100644
--- a/spec/helpers/projects_helper_spec.rb
+++ b/spec/helpers/projects_helper_spec.rb
@@ -20,4 +20,13 @@
           "<option value=\"gitlab\">GitLab</option>"
     end
   end
+
+  describe "#project_status_css_class" do
+    it "returns appropriate class" do
+      project_status_css_class("started").should == "active"
+      project_status_css_class("failed").should == "danger"
+      project_status_css_class("finished").should == "success"
+    end
+
+  end
 end
diff --git a/spec/lib/gitlab/github/project_creator.rb b/spec/lib/gitlab/github/project_creator.rb
new file mode 100644
index 0000000000000000000000000000000000000000..0bade5619a512eb6b2277904bb5a262c48e517b9
--- /dev/null
+++ b/spec/lib/gitlab/github/project_creator.rb
@@ -0,0 +1,25 @@
+require 'spec_helper'
+
+describe Gitlab::Github::ProjectCreator do
+  let(:user) { create(:user, github_access_token: "asdffg") }
+  let(:repo) { OpenStruct.new(
+    login: 'vim',
+    name: 'vim',
+    private: true,
+    full_name: 'asd/vim',
+    clone_url: "https://gitlab.com/asd/vim.git",
+    owner: OpenStruct.new(login: "john"))
+  }
+  let(:namespace){ create(:namespace) }
+
+  it 'creates project' do
+    Project.any_instance.stub(:add_import_job)
+    
+    project_creator = Gitlab::Github::ProjectCreator.new(repo, namespace, user)
+    project_creator.execute
+    project = Project.last
+    
+    project.import_url.should ==  "https://asdffg@gitlab.com/asd/vim.git"
+    project.visibility_level.should == Gitlab::VisibilityLevel::PRIVATE
+  end
+end