diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb
index e93a4e62244f33fbe1716ac00251ee8ee4cef1ad..8048e86fc3ad3b8570aff9f2e7fec6f1983b9832 100644
--- a/spec/models/project_spec.rb
+++ b/spec/models/project_spec.rb
@@ -73,9 +73,7 @@ describe Project, models: true do
 
     context 'after initialized' do
       it "has a project_feature" do
-        project = FactoryGirl.build(:project)
-
-        expect(project.project_feature.present?).to be_present
+        expect(Project.new.project_feature).to be_present
       end
     end
 
@@ -129,7 +127,7 @@ describe Project, models: true do
   end
 
   describe 'validation' do
-    let!(:project) { create(:project) }
+    let!(:project) { create(:empty_project) }
 
     it { is_expected.to validate_presence_of(:name) }
     it { is_expected.to validate_uniqueness_of(:name).scoped_to(:namespace_id) }
@@ -148,7 +146,7 @@ describe Project, models: true do
     it { is_expected.to validate_presence_of(:repository_storage) }
 
     it 'does not allow new projects beyond user limits' do
-      project2 = build(:project)
+      project2 = build(:empty_project)
       allow(project2).to receive(:creator).and_return(double(can_create_project?: false, projects_limit: 0).as_null_object)
       expect(project2).not_to be_valid
       expect(project2.errors[:limit_reached].first).to match(/Personal project creation is not allowed/)
@@ -157,7 +155,7 @@ describe Project, models: true do
     describe 'wiki path conflict' do
       context "when the new path has been used by the wiki of other Project" do
         it 'has an error on the name attribute' do
-          new_project = build_stubbed(:project, namespace_id: project.namespace_id, path: "#{project.path}.wiki")
+          new_project = build_stubbed(:empty_project, namespace_id: project.namespace_id, path: "#{project.path}.wiki")
 
           expect(new_project).not_to be_valid
           expect(new_project.errors[:name].first).to eq('has already been taken')
@@ -166,8 +164,8 @@ describe Project, models: true do
 
       context "when the new wiki path has been used by the path of other Project" do
         it 'has an error on the name attribute' do
-          project_with_wiki_suffix = create(:project, path: 'foo.wiki')
-          new_project = build_stubbed(:project, namespace_id: project_with_wiki_suffix.namespace_id, path: 'foo')
+          project_with_wiki_suffix = create(:empty_project, path: 'foo.wiki')
+          new_project = build_stubbed(:empty_project, namespace_id: project_with_wiki_suffix.namespace_id, path: 'foo')
 
           expect(new_project).not_to be_valid
           expect(new_project.errors[:name].first).to eq('has already been taken')
@@ -176,7 +174,7 @@ describe Project, models: true do
     end
 
     context 'repository storages inclussion' do
-      let(:project2) { build(:project, repository_storage: 'missing') }
+      let(:project2) { build(:empty_project, repository_storage: 'missing') }
 
       before do
         storages = { 'custom' => 'tmp/tests/custom_repositories' }
@@ -352,7 +350,7 @@ describe Project, models: true do
   end
 
   describe '#repository_storage_path' do
-    let(:project) { create(:project, repository_storage: 'custom') }
+    let(:project) { create(:empty_project, repository_storage: 'custom') }
 
     before do
       FileUtils.mkdir('tmp/tests/custom_repositories')
@@ -412,7 +410,7 @@ describe Project, models: true do
   describe 'last_activity methods' do
     let(:timestamp) { 2.hours.ago }
     # last_activity_at gets set to created_at upon creation
-    let(:project) { create(:project, created_at: timestamp, updated_at: timestamp) }
+    let(:project) { create(:empty_project, created_at: timestamp, updated_at: timestamp) }
 
     describe 'last_activity' do
       it 'alias last_activity to last_event' do
@@ -496,7 +494,7 @@ describe Project, models: true do
     context 'with namespace' do
       before do
         @group = create :group, name: 'gitlab'
-        @project = create(:project, name: 'gitlabhq', namespace: @group)
+        @project = create(:empty_project, name: 'gitlabhq', namespace: @group)
       end
 
       it { expect(@project.to_param).to eq('gitlabhq') }
@@ -522,7 +520,7 @@ describe Project, models: true do
   end
 
   describe '#repository' do
-    let(:project) { create(:project) }
+    let(:project) { create(:project, :repository) }
 
     it 'returns valid repo' do
       expect(project.repository).to be_kind_of(Repository)
@@ -530,20 +528,22 @@ describe Project, models: true do
   end
 
   describe '#default_issues_tracker?' do
-    let(:project) { create(:project) }
-    let(:ext_project) { create(:redmine_project) }
-
     it "is true if used internal tracker" do
+      project = build(:empty_project)
+
       expect(project.default_issues_tracker?).to be_truthy
     end
 
     it "is false if used other tracker" do
-      expect(ext_project.default_issues_tracker?).to be_falsey
+      # NOTE: The current nature of this factory requires persistence
+      project = create(:redmine_project)
+
+      expect(project.default_issues_tracker?).to be_falsey
     end
   end
 
   describe '#external_issue_tracker' do
-    let(:project) { create(:project) }
+    let(:project) { create(:empty_project) }
     let(:ext_project) { create(:redmine_project) }
 
     context 'on existing projects with no value for has_external_issue_tracker' do
@@ -578,7 +578,7 @@ describe Project, models: true do
   end
 
   describe '#cache_has_external_issue_tracker' do
-    let(:project) { create(:project, has_external_issue_tracker: nil) }
+    let(:project) { create(:empty_project, has_external_issue_tracker: nil) }
 
     it 'stores true if there is any external_issue_tracker' do
       services = double(:service, external_issue_trackers: [RedmineService.new])
@@ -600,9 +600,9 @@ describe Project, models: true do
   end
 
   describe '#has_wiki?' do
-    let(:no_wiki_project)       { create(:project, wiki_access_level: ProjectFeature::DISABLED, has_external_wiki: false) }
-    let(:wiki_enabled_project)  { create(:project) }
-    let(:external_wiki_project) { create(:project, has_external_wiki: true) }
+    let(:no_wiki_project)       { create(:empty_project, wiki_access_level: ProjectFeature::DISABLED, has_external_wiki: false) }
+    let(:wiki_enabled_project)  { create(:empty_project) }
+    let(:external_wiki_project) { create(:empty_project, has_external_wiki: true) }
 
     it 'returns true if project is wiki enabled or has external wiki' do
       expect(wiki_enabled_project).to have_wiki
@@ -612,7 +612,7 @@ describe Project, models: true do
   end
 
   describe '#external_wiki' do
-    let(:project) { create(:project) }
+    let(:project) { create(:empty_project) }
 
     context 'with an active external wiki' do
       before do
@@ -663,7 +663,7 @@ describe Project, models: true do
   end
 
   describe '#open_branches' do
-    let(:project) { create(:project) }
+    let(:project) { create(:project, :repository) }
 
     before do
       project.protected_branches.create(name: 'master')
@@ -685,7 +685,7 @@ describe Project, models: true do
     it 'counts stars from multiple users' do
       user1 = create :user
       user2 = create :user
-      project = create :project, :public
+      project = create(:empty_project, :public)
 
       expect(project.star_count).to eq(0)
 
@@ -707,8 +707,8 @@ describe Project, models: true do
 
     it 'counts stars on the right project' do
       user = create :user
-      project1 = create :project, :public
-      project2 = create :project, :public
+      project1 = create(:empty_project, :public)
+      project2 = create(:empty_project, :public)
 
       expect(project1.star_count).to eq(0)
       expect(project2.star_count).to eq(0)
@@ -740,7 +740,7 @@ describe Project, models: true do
   end
 
   describe '#avatar_type' do
-    let(:project) { create(:project) }
+    let(:project) { create(:empty_project) }
 
     it 'is true if avatar is image' do
       project.update_attribute(:avatar, 'uploads/avatar.png')
@@ -756,7 +756,7 @@ describe Project, models: true do
   describe '#avatar_url' do
     subject { project.avatar_url }
 
-    let(:project) { create(:project) }
+    let(:project) { create(:empty_project) }
 
     context 'When avatar file is uploaded' do
       before do
@@ -791,7 +791,7 @@ describe Project, models: true do
   end
 
   describe '#pipeline_for' do
-    let(:project) { create(:project) }
+    let(:project) { create(:project, :repository) }
     let!(:pipeline) { create_pipeline }
 
     shared_examples 'giving the correct pipeline' do
@@ -825,7 +825,7 @@ describe Project, models: true do
   end
 
   describe '#builds_enabled' do
-    let(:project) { create :project }
+    let(:project) { create(:empty_project) }
 
     subject { project.builds_enabled }
 
@@ -877,7 +877,7 @@ describe Project, models: true do
   end
 
   describe '.visible_to_user' do
-    let!(:project) { create(:project, :private) }
+    let!(:project) { create(:empty_project, :private) }
     let!(:user)    { create(:user) }
 
     subject { described_class.visible_to_user(user) }
@@ -975,7 +975,7 @@ describe Project, models: true do
   end
 
   describe '#visibility_level_allowed?' do
-    let(:project) { create(:project, :internal) }
+    let(:project) { create(:empty_project, :internal) }
 
     context 'when checking on non-forked project' do
       it { expect(project.visibility_level_allowed?(Gitlab::VisibilityLevel::PRIVATE)).to be_truthy }
@@ -984,8 +984,8 @@ describe Project, models: true do
     end
 
     context 'when checking on forked project' do
-      let(:project)        { create(:project, :internal) }
-      let(:forked_project) { create(:project, forked_from_project: project) }
+      let(:project)        { create(:empty_project, :internal) }
+      let(:forked_project) { create(:empty_project, forked_from_project: project) }
 
       it { expect(forked_project.visibility_level_allowed?(Gitlab::VisibilityLevel::PRIVATE)).to be_truthy }
       it { expect(forked_project.visibility_level_allowed?(Gitlab::VisibilityLevel::INTERNAL)).to be_truthy }
@@ -994,7 +994,7 @@ describe Project, models: true do
   end
 
   describe '.search' do
-    let(:project) { create(:project, description: 'kitten mittens') }
+    let(:project) { create(:empty_project, description: 'kitten mittens') }
 
     it 'returns projects with a matching name' do
       expect(described_class.search(project.name)).to eq([project])
@@ -1052,7 +1052,7 @@ describe Project, models: true do
   end
 
   describe '#rename_repo' do
-    let(:project) { create(:project) }
+    let(:project) { create(:project, :repository) }
     let(:gitlab_shell) { Gitlab::Shell.new }
 
     before do
@@ -1102,7 +1102,7 @@ describe Project, models: true do
   end
 
   describe '#expire_caches_before_rename' do
-    let(:project) { create(:project) }
+    let(:project) { create(:project, :repository) }
     let(:repo)    { double(:repo, exists?: true) }
     let(:wiki)    { double(:wiki, exists?: true) }
 
@@ -1123,7 +1123,7 @@ describe Project, models: true do
   end
 
   describe '.search_by_title' do
-    let(:project) { create(:project, name: 'kittens') }
+    let(:project) { create(:empty_project, name: 'kittens') }
 
     it 'returns projects with a matching name' do
       expect(described_class.search_by_title(project.name)).to eq([project])
@@ -1142,8 +1142,8 @@ describe Project, models: true do
     let(:private_group)    { create(:group, visibility_level: 0)  }
     let(:internal_group)   { create(:group, visibility_level: 10) }
 
-    let(:private_project)  { create :project, :private, group: private_group }
-    let(:internal_project) { create :project, :internal, group: internal_group }
+    let(:private_project)  { create :empty_project, :private, group: private_group }
+    let(:internal_project) { create :empty_project, :internal, group: internal_group }
 
     context 'when group is private project can not be internal' do
       it { expect(private_project.visibility_level_allowed?(Gitlab::VisibilityLevel::INTERNAL)).to be_falsey }
@@ -1155,7 +1155,7 @@ describe Project, models: true do
   end
 
   describe '#create_repository' do
-    let(:project) { create(:project) }
+    let(:project) { create(:project, :repository) }
     let(:shell) { Gitlab::Shell.new }
 
     before do
@@ -1197,7 +1197,7 @@ describe Project, models: true do
 
   describe '#protected_branch?' do
     context 'existing project' do
-      let(:project) { create(:project) }
+      let(:project) { create(:project, :repository) }
 
       it 'returns true when the branch matches a protected branch via direct match' do
         create(:protected_branch, project: project, name: "foo")
@@ -1381,7 +1381,7 @@ describe Project, models: true do
              name: name)
     end
 
-    let(:project) { create(:project) }
+    let(:project) { create(:project, :repository) }
     let(:pipeline) { create_pipeline }
 
     context 'with many builds' do
@@ -1461,7 +1461,7 @@ describe Project, models: true do
     end
 
     context 'not forked' do
-      let(:project) { create(:project) }
+      let(:project) { create(:empty_project) }
 
       it 'schedules a RepositoryImportWorker job' do
         expect(RepositoryImportWorker).to receive(:perform_async).with(project.id)
@@ -1472,19 +1472,19 @@ describe Project, models: true do
   end
 
   describe '#gitlab_project_import?' do
-    subject(:project) { build(:project, import_type: 'gitlab_project') }
+    subject(:project) { build(:empty_project, import_type: 'gitlab_project') }
 
     it { expect(project.gitlab_project_import?).to be true }
   end
 
   describe '#gitea_import?' do
-    subject(:project) { build(:project, import_type: 'gitea') }
+    subject(:project) { build(:empty_project, import_type: 'gitea') }
 
     it { expect(project.gitea_import?).to be true }
   end
 
   describe '#lfs_enabled?' do
-    let(:project) { create(:project) }
+    let(:project) { create(:empty_project) }
 
     shared_examples 'project overrides group' do
       it 'returns true when enabled in project' do
@@ -1546,7 +1546,7 @@ describe Project, models: true do
   end
 
   describe '#change_head' do
-    let(:project) { create(:project) }
+    let(:project) { create(:project, :repository) }
 
     it 'calls the before_change_head and after_change_head methods' do
       expect(project.repository).to receive(:before_change_head)
@@ -1574,7 +1574,7 @@ describe Project, models: true do
   end
 
   describe '#pushes_since_gc' do
-    let(:project) { create(:project) }
+    let(:project) { create(:empty_project) }
 
     after do
       project.reset_pushes_since_gc
@@ -1596,7 +1596,7 @@ describe Project, models: true do
   end
 
   describe '#increment_pushes_since_gc' do
-    let(:project) { create(:project) }
+    let(:project) { create(:empty_project) }
 
     after do
       project.reset_pushes_since_gc
@@ -1610,7 +1610,7 @@ describe Project, models: true do
   end
 
   describe '#reset_pushes_since_gc' do
-    let(:project) { create(:project) }
+    let(:project) { create(:empty_project) }
 
     after do
       project.reset_pushes_since_gc
@@ -1626,7 +1626,7 @@ describe Project, models: true do
   end
 
   describe '#environments_for' do
-    let(:project) { create(:project) }
+    let(:project) { create(:project, :repository) }
     let(:environment) { create(:environment, project: project) }
 
     context 'tagged deployment' do
@@ -1678,7 +1678,7 @@ describe Project, models: true do
   end
 
   describe '#environments_recently_updated_on_branch' do
-    let(:project) { create(:project) }
+    let(:project) { create(:project, :repository) }
     let(:environment) { create(:environment, project: project) }
 
     context 'when last deployment to environment is the most recent one' do