diff --git a/.gitignore b/.gitignore
index b1f4229925a5b26d15661f051facf19f5e0cdb6c..72abdd52ab9caa9efb2f9830d19615572860765c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -2,7 +2,7 @@
 .rbx/
 db/*.sqlite3
 db/*.sqlite3-journal
-log/*.log
+log/*.log*
 tmp/
 .sass-cache/
 coverage/*
diff --git a/VERSION b/VERSION
index 87db9036a822108fd68f9be0ad2186f2760e1155..ee74734aa2258df77aa09402d55798a1e2e55212 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-4.1.0rc1
+4.1.0
diff --git a/app/controllers/profiles_controller.rb b/app/controllers/profiles_controller.rb
index 1d1efb16f042c0cef0c3200756b660715553b4bf..051a6664519c265e201fc00a244a9881211504ea 100644
--- a/app/controllers/profiles_controller.rb
+++ b/app/controllers/profiles_controller.rb
@@ -51,7 +51,9 @@ class ProfilesController < ApplicationController
   end
 
   def update_username
-    @user.update_attributes(username: params[:user][:username])
+    if @user.can_change_username?
+      @user.update_attributes(username: params[:user][:username])
+    end
 
     respond_to do |format|
       format.js
diff --git a/app/models/repository.rb b/app/models/repository.rb
index 6bfdf2255f2b812b7132ec7331660f7ef06d1047..9032905ce9a7b3f39248489476d581374d144629 100644
--- a/app/models/repository.rb
+++ b/app/models/repository.rb
@@ -151,7 +151,7 @@ class Repository
     return nil unless commit
 
     # Build file path
-    file_name = self.path_with_namespace + "-" + commit.id.to_s + ".tar.gz"
+    file_name = self.path_with_namespace.gsub("/","_") + "-" + commit.id.to_s + ".tar.gz"
     storage_path = Rails.root.join("tmp", "repositories")
     file_path = File.join(storage_path, file_name)
 
diff --git a/app/models/user.rb b/app/models/user.rb
index 35a693fdb1c0beb4d58591af2685805fabfb4757..d66ce41128617e3121d043d59210a8bc6690a58f 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -215,6 +215,10 @@ class User < ActiveRecord::Base
     keys.count == 0
   end
 
+  def can_change_username?
+    Gitlab.config.gitlab.username_changing_enabled
+  end
+
   def can_create_project?
     projects_limit > personal_projects.count
   end
diff --git a/app/views/profiles/account.html.haml b/app/views/profiles/account.html.haml
index 522e45e637a390a25a7a58e3d64c0291799b50be..ea9bcb648def5b9940d9b8ba1e47367ac886c321 100644
--- a/app/views/profiles/account.html.haml
+++ b/app/views/profiles/account.html.haml
@@ -53,28 +53,29 @@
 
 
 
-%fieldset.update-username
-  %legend
-    Username
-    %small.cred.right
-      Changing your username can have unintended side effects!
-  = form_for @user, url: update_username_profile_path,  method: :put, remote: true do |f|
-    .padded
-      = f.label :username
-      .input
-        = f.text_field :username, required: true
-        &nbsp;
-        %span.loading-gif.hide= image_tag "ajax_loader.gif"
-        %span.update-success.cgreen.hide
-          %i.icon-ok
-          Saved
-        %span.update-failed.cred.hide
-          %i.icon-remove
-          Failed
-        %ul.cred
-          %li It will change web url for personal projects.
-          %li It will change the git path to repositories for personal projects.
-      .input
-        = f.submit 'Save username', class: "btn save-btn"
+- if current_user.can_change_username?
+  %fieldset.update-username
+    %legend
+      Username
+      %small.cred.right
+        Changing your username can have unintended side effects!
+    = form_for @user, url: update_username_profile_path,  method: :put, remote: true do |f|
+      .padded
+        = f.label :username
+        .input
+          = f.text_field :username, required: true
+          &nbsp;
+          %span.loading-gif.hide= image_tag "ajax_loader.gif"
+          %span.update-success.cgreen.hide
+            %i.icon-ok
+            Saved
+          %span.update-failed.cred.hide
+            %i.icon-remove
+            Failed
+          %ul.cred
+            %li It will change web url for personal projects.
+            %li It will change the git path to repositories for personal projects.
+        .input
+          = f.submit 'Save username', class: "btn save-btn"
 
 
diff --git a/config/gitlab.yml.example b/config/gitlab.yml.example
index b2dccbe3d4c9a4062300d26a3b0ddd9aa3332d07..4b2f69ab5fe79ba752e8cad437e2a2e9938a2a5d 100644
--- a/config/gitlab.yml.example
+++ b/config/gitlab.yml.example
@@ -35,6 +35,7 @@ gitlab:
   ## Project settings
   default_projects_limit: 10
   # signup_enabled: true          # default: false - Account passwords are not sent via the email if signup is enabled.
+  # username_changing_enabled: false # default: true - User can change her username/namespace
 
 ## Gravatar
 gravatar:
diff --git a/config/initializers/1_settings.rb b/config/initializers/1_settings.rb
index a1afa5b22c4f434b5fd1ff65ace51c387f7fa307..0334b35ec9185d951aff2be1e7c93db14da84cc9 100644
--- a/config/initializers/1_settings.rb
+++ b/config/initializers/1_settings.rb
@@ -53,6 +53,7 @@ Settings.gitlab['support_email']  ||= Settings.gitlab.email_from
 Settings.gitlab['url']        ||= Settings.send(:build_gitlab_url)
 Settings.gitlab['user']       ||= 'gitlab'
 Settings.gitlab['signup_enabled'] ||= false
+Settings.gitlab['username_changing_enabled'] = true if Settings.gitlab['username_changing_enabled'].nil?
 
 Settings['gravatar'] ||= Settingslogic.new({})
 Settings.gravatar['enabled']      = true if Settings.gravatar['enabled'].nil?
diff --git a/doc/install/installation.md b/doc/install/installation.md
index 27c87ec825f737466cca9fe935229b6c7ab39dce..aa3137d1d597e70643c02f3953c2d7e60a6115af 100644
--- a/doc/install/installation.md
+++ b/doc/install/installation.md
@@ -149,7 +149,7 @@ Fix the directory permissions for the repositories:
     sudo chown -R git:git /home/git/repositories/
 
 
-## Add domains to list to the list of known hosts
+## Add domains to the list of known hosts
 
     sudo -u gitlab -H ssh git@localhost
     sudo -u gitlab -H ssh git@YOUR_DOMAIN_NAME
@@ -190,10 +190,10 @@ See `doc/install/databases.md`
     cd /home/gitlab/gitlab
    
     # Checkout to stable release
-    sudo -u gitlab -H git checkout 4-0-stable
+    sudo -u gitlab -H git checkout 4-1-stable
 
 **Note:**
-You can change `4-0-stable` to `master` if you want the *bleeding edge* version, but
+You can change `4-1-stable` to `master` if you want the *bleeding edge* version, but
 do so with caution!
 
 ## Configure it
@@ -267,7 +267,7 @@ used for the `email.from` setting in `config/gitlab.yml`)
 
 Download the init script (will be /etc/init.d/gitlab):
 
-    sudo curl --output /etc/init.d/gitlab https://raw.github.com/gitlabhq/gitlab-recipes/master/init.d/gitlab
+    sudo curl --output /etc/init.d/gitlab https://raw.github.com/gitlabhq/gitlab-recipes/4-1-stable/init.d/gitlab
     sudo chmod +x /etc/init.d/gitlab
 
 Make GitLab start on boot:
@@ -292,7 +292,7 @@ However there are still a few steps left.
 
     sudo service gitlab start
     # or
-    sudo /etc/init.d/gitlab restart
+    sudo /etc/init.d/gitlab start
 
 
 # 7. Nginx
@@ -302,13 +302,13 @@ If you can't or don't want to use Nginx as your web server, have a look at the
 "Advanced Setup Tips" section.
 
 ## Installation
-    sudo apt-get install nginx
+    sudo apt-get -y install nginx
 
 ## Site Configuration
 
 Download an example site config:
 
-    sudo curl --output /etc/nginx/sites-available/gitlab https://raw.github.com/gitlabhq/gitlab-recipes/master/nginx/gitlab
+    sudo curl --output /etc/nginx/sites-available/gitlab https://raw.github.com/gitlabhq/gitlab-recipes/4-1-stable/nginx/gitlab
     sudo ln -s /etc/nginx/sites-available/gitlab /etc/nginx/sites-enabled/gitlab
 
 Make sure to edit the config file to match your setup:
diff --git a/lib/gitlab/backend/gitolite_config.rb b/lib/gitlab/backend/gitolite_config.rb
index 7d59ddae0c85bc74697866437d2c0f60b7082ff9..1783b2c37b4e08692cd7a7519f02494e3b8ad809 100644
--- a/lib/gitlab/backend/gitolite_config.rb
+++ b/lib/gitlab/backend/gitolite_config.rb
@@ -87,7 +87,9 @@ module Gitlab
     end
 
     def destroy_project(project)
-      FileUtils.rm_rf(project.repository.path_to_repo)
+      if project.repository
+        FileUtils.rm_rf(project.repository.path_to_repo)
+      end
       conf.rm_repo(project.path_with_namespace)
     end
 
diff --git a/lib/tasks/gitlab/check.rake b/lib/tasks/gitlab/check.rake
index 826b78ec5b1bc8ff175efa78704215aab5f773ba..00068abfa02151eaa863164eb373e27d310553b6 100644
--- a/lib/tasks/gitlab/check.rake
+++ b/lib/tasks/gitlab/check.rake
@@ -142,7 +142,7 @@ namespace :gitlab do
         return
       end
 
-      recipe_content = `curl https://raw.github.com/gitlabhq/gitlab-recipes/master/init.d/gitlab 2>/dev/null`
+      recipe_content = `curl https://raw.github.com/gitlabhq/gitlab-recipes/4-1-stable/init.d/gitlab 2>/dev/null`
       script_content = File.read(script_path)
 
       if recipe_content == script_content
@@ -780,21 +780,25 @@ namespace :gitlab do
       Project.find_each(batch_size: 100) do |project|
         print "#{project.name_with_namespace.yellow} ... "
 
-        correct_options = options.map do |name, value|
-          run("git --git-dir=\"#{project.repository.path_to_repo}\" config --get #{name}").try(:chomp) == value
-        end
-
-        if correct_options.all?
-          puts "ok".green
+        if project.empty_repo?
+          puts "repository is empty".magenta
         else
-          puts "wrong or missing".red
-          try_fixing_it(
-            sudo_gitlab("bundle exec rake gitlab:gitolite:update_repos")
-          )
-          for_more_information(
-            "doc/raketasks/maintenance.md"
-          )
-          fix_and_rerun
+          correct_options = options.map do |name, value|
+            run("git --git-dir=\"#{project.repository.path_to_repo}\" config --get #{name}").try(:chomp) == value
+          end
+
+          if correct_options.all?
+            puts "ok".green
+          else
+            puts "wrong or missing".red
+            try_fixing_it(
+              sudo_gitlab("bundle exec rake gitlab:gitolite:update_repos")
+            )
+            for_more_information(
+              "doc/raketasks/maintenance.md"
+            )
+            fix_and_rerun
+          end
         end
       end
     end
@@ -820,32 +824,37 @@ namespace :gitlab do
 
       Project.find_each(batch_size: 100) do |project|
         print "#{project.name_with_namespace.yellow} ... "
-        project_hook_file = File.join(project.repository.path_to_repo, "hooks", hook_file)
 
-        unless File.exists?(project_hook_file)
-          puts "missing".red
-          try_fixing_it(
-            "sudo -u #{gitolite_ssh_user} ln -sf #{gitolite_hook_file} #{project_hook_file}"
-          )
-          for_more_information(
-            "lib/support/rewrite-hooks.sh"
-          )
-          fix_and_rerun
-          next
-        end
-
-        if File.lstat(project_hook_file).symlink? &&
-            File.realpath(project_hook_file) == File.realpath(gitolite_hook_file)
-          puts "ok".green
+        if project.empty_repo?
+          puts "repository is empty".magenta
         else
-          puts "not a link to Gitolite's hook".red
-          try_fixing_it(
-            "sudo -u #{gitolite_ssh_user} ln -sf #{gitolite_hook_file} #{project_hook_file}"
-          )
-          for_more_information(
-            "lib/support/rewrite-hooks.sh"
-          )
-          fix_and_rerun
+          project_hook_file = File.join(project.repository.path_to_repo, "hooks", hook_file)
+
+          unless File.exists?(project_hook_file)
+            puts "missing".red
+            try_fixing_it(
+              "sudo -u #{gitolite_ssh_user} ln -sf #{gitolite_hook_file} #{project_hook_file}"
+            )
+            for_more_information(
+              "lib/support/rewrite-hooks.sh"
+            )
+            fix_and_rerun
+            next
+          end
+
+          if File.lstat(project_hook_file).symlink? &&
+              File.realpath(project_hook_file) == File.realpath(gitolite_hook_file)
+            puts "ok".green
+          else
+            puts "not a link to Gitolite's hook".red
+            try_fixing_it(
+              "sudo -u #{gitolite_ssh_user} ln -sf #{gitolite_hook_file} #{project_hook_file}"
+            )
+            for_more_information(
+              "lib/support/rewrite-hooks.sh"
+            )
+            fix_and_rerun
+          end
         end
       end
     end
diff --git a/lib/tasks/gitlab/import.rake b/lib/tasks/gitlab/import.rake
index 4bf9110508ed41a12ba25d6517364a45daa5f681..29e5847b81ee5156bf7f39d04049fa0b6679978c 100644
--- a/lib/tasks/gitlab/import.rake
+++ b/lib/tasks/gitlab/import.rake
@@ -42,9 +42,10 @@ namespace :gitlab do
 
           project_params = {
             :name => path,
+            :namespace_id => Namespace.global_id,
           }
 
-          project = Project.create_by_user(project_params, user)
+          project = Projects::CreateContext.new(user, project_params).execute
 
           if project.valid?
             puts " * Created #{project.name} (#{repo_name})".green