diff options
90 files changed, 1734 insertions, 802 deletions
@@ -16,7 +16,7 @@ gem 'mysql2', '~> 0.4.5', group: :mysql gem 'pg', '~> 0.18.2', group: :postgres gem 'rugged', '~> 0.26.0' -gem 'grape-route-helpers', '~> 2.0.0' +gem 'grape-route-helpers', '~> 2.1.0' gem 'faraday', '~> 0.12' @@ -76,7 +76,7 @@ gem 'gollum-rugged_adapter', '~> 0.4.4', require: false gem 'github-linguist', '~> 4.7.0', require: 'linguist' # API -gem 'grape', '~> 0.19.2' +gem 'grape', '~> 1.0' gem 'grape-entity', '~> 0.6.0' gem 'rack-cors', '~> 0.4.0', require: 'rack/cors' @@ -144,8 +144,6 @@ end # State machine gem 'state_machines-activerecord', '~> 0.4.0' -# Run events after state machine commits -gem 'after_commit_queue', '~> 1.3.0' # Issue tags gem 'acts-as-taggable-on', '~> 4.0' diff --git a/Gemfile.lock b/Gemfile.lock index f7ad7bcbc6e..ae1df783a80 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -46,8 +46,6 @@ GEM ice_nine (~> 0.11.0) memoizable (~> 0.4.0) addressable (2.3.8) - after_commit_queue (1.3.0) - activerecord (>= 3.0) akismet (2.0.0) allocations (1.0.5) arel (6.0.4) @@ -342,12 +340,9 @@ GEM signet (~> 0.7) gpgme (2.0.13) mini_portile2 (~> 2.1) - grape (0.19.2) + grape (1.0.0) activesupport builder - hashie (>= 2.1.0) - multi_json (>= 1.3.2) - multi_xml (>= 0.5.2) mustermann-grape (~> 1.0.0) rack (>= 1.3.0) rack-accept @@ -355,11 +350,11 @@ GEM grape-entity (0.6.0) activesupport multi_json (>= 1.3.2) - grape-route-helpers (2.0.0) + grape-route-helpers (2.1.0) activesupport - grape (~> 0.16, >= 0.16.0) + grape (>= 0.16.0) rake - grpc (1.4.0) + grpc (1.4.5) google-protobuf (~> 3.1) googleauth (~> 0.5.1) haml (4.0.7) @@ -375,7 +370,7 @@ GEM thor tilt hashdiff (0.3.4) - hashie (3.5.5) + hashie (3.5.6) hashie-forbidden_attributes (0.1.1) hashie (>= 3.0) health_check (2.6.0) @@ -963,7 +958,6 @@ DEPENDENCIES activerecord_sane_schema_dumper (= 0.2) acts-as-taggable-on (~> 4.0) addressable (~> 2.3.8) - after_commit_queue (~> 1.3.0) akismet (~> 2.0) allocations (~> 1.0) asana (~> 0.6.0) @@ -1035,9 +1029,9 @@ DEPENDENCIES gon (~> 6.1.0) google-api-client (~> 0.8.6) gpgme - grape (~> 0.19.2) + grape (~> 1.0) grape-entity (~> 0.6.0) - grape-route-helpers (~> 2.0.0) + grape-route-helpers (~> 2.1.0) haml_lint (~> 0.26.0) hamlit (~> 2.6.1) hashie-forbidden_attributes diff --git a/app/assets/javascripts/groups_select.js b/app/assets/javascripts/groups_select.js index b5975295329..4d629bc6326 100644 --- a/app/assets/javascripts/groups_select.js +++ b/app/assets/javascripts/groups_select.js @@ -111,8 +111,7 @@ window.GroupsSelect = (function() { }; GroupsSelect.prototype.forceOverflow = function (e) { - const itemHeight = this.dropdown.querySelector('.select2-result:first-child').clientHeight; - this.dropdown.style.height = `${Math.floor(this.dropdown.scrollHeight - (itemHeight * 0.9))}px`; + this.dropdown.style.height = `${Math.floor(this.dropdown.scrollHeight)}px`; }; GroupsSelect.PER_PAGE = 20; diff --git a/app/assets/stylesheets/framework/dropdowns.scss b/app/assets/stylesheets/framework/dropdowns.scss index 1bb04b59a2a..958159b507a 100644 --- a/app/assets/stylesheets/framework/dropdowns.scss +++ b/app/assets/stylesheets/framework/dropdowns.scss @@ -743,6 +743,11 @@ border-radius: 0; padding: 8px 16px; + // make sure the text color is not overriden + &.text-danger { + @extend .text-danger; + } + &.is-focused, &:hover, &:active, diff --git a/app/assets/stylesheets/framework/lists.scss b/app/assets/stylesheets/framework/lists.scss index ab754f4a492..df2bf561194 100644 --- a/app/assets/stylesheets/framework/lists.scss +++ b/app/assets/stylesheets/framework/lists.scss @@ -132,6 +132,8 @@ ul.content-list { } .controls { + @include new-style-dropdown; + float: right; > .control-text { diff --git a/app/assets/stylesheets/framework/typography.scss b/app/assets/stylesheets/framework/typography.scss index 96409b10b99..0bd84c9e08c 100644 --- a/app/assets/stylesheets/framework/typography.scss +++ b/app/assets/stylesheets/framework/typography.scss @@ -18,7 +18,8 @@ background-color: $gray-lightest; } - img.js-lazy-loaded { + img.js-lazy-loaded, + img.emoji { min-width: inherit; min-height: inherit; background-color: inherit; diff --git a/app/assets/stylesheets/new_sidebar.scss b/app/assets/stylesheets/new_sidebar.scss index d078c8b956b..cee5b22adb9 100644 --- a/app/assets/stylesheets/new_sidebar.scss +++ b/app/assets/stylesheets/new_sidebar.scss @@ -103,7 +103,10 @@ $new-sidebar-collapsed-width: 50px; &.sidebar-icons-only { width: $new-sidebar-collapsed-width; - overflow-x: hidden; + + .nav-sidebar-inner-scroll { + overflow-x: hidden; + } .badge, .project-title { @@ -111,7 +114,11 @@ $new-sidebar-collapsed-width: 50px; } .nav-item-name { - opacity: 0; + display: none; + } + + .sidebar-top-level-items > li > a { + min-height: 44px; } } diff --git a/app/assets/stylesheets/pages/issuable.scss b/app/assets/stylesheets/pages/issuable.scss index 1dac38f2b6d..49839a9b528 100644 --- a/app/assets/stylesheets/pages/issuable.scss +++ b/app/assets/stylesheets/pages/issuable.scss @@ -260,7 +260,7 @@ padding-top: 10px; } - &:not(.issue-boards-sidebar):not([data-signed-in]) { + &:not(.issue-boards-sidebar):not([data-signed-in]):not([data-always-show-toggle]) { .issuable-sidebar-header { display: none; } diff --git a/app/models/concerns/referable.rb b/app/models/concerns/referable.rb index 10f4be72016..78ac4f324e7 100644 --- a/app/models/concerns/referable.rb +++ b/app/models/concerns/referable.rb @@ -25,6 +25,11 @@ module Referable to_reference(from_project) end + included do + alias_method :non_referable_inspect, :inspect + alias_method :inspect, :referable_inspect + end + def referable_inspect if respond_to?(:id) "#<#{self.class.name} id:#{id} #{to_reference(full: true)}>" @@ -33,10 +38,6 @@ module Referable end end - def inspect - referable_inspect - end - module ClassMethods # The character that prefixes the actual reference identifier # diff --git a/app/models/project.rb b/app/models/project.rb index 22b347cc8f9..be248bc99e1 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -60,7 +60,7 @@ class Project < ActiveRecord::Base end before_destroy :remove_private_deploy_keys - after_destroy :remove_pages + after_destroy -> { run_after_commit { remove_pages } } # update visibility_level of forks after_update :update_forks_visibility_level @@ -369,7 +369,10 @@ class Project < ActiveRecord::Base state :failed after_transition [:none, :finished, :failed] => :scheduled do |project, _| - project.run_after_commit { add_import_job } + project.run_after_commit do + job_id = add_import_job + update(import_jid: job_id) if job_id + end end after_transition started: :finished do |project, _| @@ -524,17 +527,26 @@ class Project < ActiveRecord::Base def add_import_job job_id = if forked? - RepositoryForkWorker.perform_async(id, forked_from_project.repository_storage_path, - forked_from_project.full_path, - self.namespace.full_path) + RepositoryForkWorker.perform_async(id, + forked_from_project.repository_storage_path, + forked_from_project.full_path, + self.namespace.full_path) else RepositoryImportWorker.perform_async(self.id) end + log_import_activity(job_id) + + job_id + end + + def log_import_activity(job_id, type: :import) + job_type = type.to_s.capitalize + if job_id - Rails.logger.info "Import job started for #{full_path} with job ID #{job_id}" + Rails.logger.info("#{job_type} job scheduled for #{full_path} with job ID #{job_id}.") else - Rails.logger.error "Import job failed to start for #{full_path}" + Rails.logger.error("#{job_type} job failed to create for #{full_path}.") end end @@ -543,6 +555,7 @@ class Project < ActiveRecord::Base ProjectCacheWorker.perform_async(self.id) end + update(import_error: nil) remove_import_data end @@ -1224,6 +1237,9 @@ class Project < ActiveRecord::Base # TODO: what to do here when not using Legacy Storage? Do we still need to rename and delay removal? def remove_pages + # Projects with a missing namespace cannot have their pages removed + return unless namespace + ::Projects::UpdatePagesConfigurationService.new(self).execute # 1. We rename pages to temporary directory diff --git a/app/models/user.rb b/app/models/user.rb index 0e2654ff757..02c3ab6654b 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -47,11 +47,6 @@ class User < ActiveRecord::Base devise :lockable, :recoverable, :rememberable, :trackable, :validatable, :omniauthable, :confirmable, :registerable - # devise overrides #inspect, so we manually use the Referable one - def inspect - referable_inspect - end - # Override Devise::Models::Trackable#update_tracked_fields! # to limit database writes to at most once every hour def update_tracked_fields!(request) diff --git a/app/views/admin/users/_user.html.haml b/app/views/admin/users/_user.html.haml index 4cf4a57ba18..ca6e43e091c 100644 --- a/app/views/admin/users/_user.html.haml +++ b/app/views/admin/users/_user.html.haml @@ -40,9 +40,10 @@ %li = link_to 'Remove user', admin_user_path(user), data: { confirm: "USER #{user.name} WILL BE REMOVED! Are you sure?" }, + class: 'text-danger', method: :delete %li = link_to 'Remove user and contributions', admin_user_path(user, hard_delete: true), data: { confirm: "USER #{user.name} WILL BE REMOVED! All issues, merge requests and comments authored by this user, and groups owned solely by them, will also be removed! Are you sure?" }, - class: 'btn btn-remove btn-block', + class: 'text-danger', method: :delete diff --git a/app/views/profiles/accounts/show.html.haml b/app/views/profiles/accounts/show.html.haml index ed079ed7dfb..5d778d67ae7 100644 --- a/app/views/profiles/accounts/show.html.haml +++ b/app/views/profiles/accounts/show.html.haml @@ -92,25 +92,24 @@ Update username %hr -- if signup_enabled? - .row.prepend-top-default - .col-lg-4.profile-settings-sidebar - %h4.prepend-top-0.danger-title - Remove account - .col-lg-8 - - if @user.can_be_removed? && can?(current_user, :destroy_user, @user) +.row.prepend-top-default + .col-lg-4.profile-settings-sidebar + %h4.prepend-top-0.danger-title + Remove account + .col-lg-8 + - if @user.can_be_removed? && can?(current_user, :destroy_user, @user) + %p + Deleting an account has the following effects: + = render 'users/deletion_guidance', user: current_user + = link_to 'Delete account', user_registration_path, data: { confirm: "REMOVE #{current_user.name}? Are you sure?" }, method: :delete, class: "btn btn-remove" + - else + - if @user.solo_owned_groups.present? %p - Deleting an account has the following effects: - = render 'users/deletion_guidance', user: current_user - = link_to 'Delete account', user_registration_path, data: { confirm: "REMOVE #{current_user.name}? Are you sure?" }, method: :delete, class: "btn btn-remove" + Your account is currently an owner in these groups: + %strong= @user.solo_owned_groups.map(&:name).join(', ') + %p + You must transfer ownership or delete these groups before you can delete your account. - else - - if @user.solo_owned_groups.present? - %p - Your account is currently an owner in these groups: - %strong= @user.solo_owned_groups.map(&:name).join(', ') - %p - You must transfer ownership or delete these groups before you can delete your account. - - else - %p - You don't have access to delete this user. + %p + You don't have access to delete this user. .append-bottom-default diff --git a/app/views/projects/_project_templates.html.haml b/app/views/projects/_project_templates.html.haml index 21baf35f2ac..97cf13df070 100644 --- a/app/views/projects/_project_templates.html.haml +++ b/app/views/projects/_project_templates.html.haml @@ -5,6 +5,6 @@ Blank - Gitlab::ProjectTemplate.all.each do |template| .btn - %input{ type: "radio", autocomplete: "off", name: "project_templates", id: template.name } + %input{ type: "radio", autocomplete: "off", name: "project[template_name]", id: template.name, value: template.name } = custom_icon(template.logo) = template.title diff --git a/app/views/projects/new.html.haml b/app/views/projects/new.html.haml index e3bbebbcf4c..647e0a772b1 100644 --- a/app/views/projects/new.html.haml +++ b/app/views/projects/new.html.haml @@ -25,7 +25,7 @@ .form-group = f.label :template_project, class: 'label-light' do Create from template - = link_to icon('question-circle'), help_page_path("public_access/public_access"), aria: { label: "What’s included in a template?" }, title: "What’s included in a template?", class: 'has-tooltip', data: { placement: 'top'} + = link_to icon('question-circle'), help_page_path("gitlab-basics/create-project"), target: '_blank', aria: { label: "What’s included in a template?" }, title: "What’s included in a template?", class: 'has-tooltip', data: { placement: 'top'} %div = render 'project_templates', f: f .second-column diff --git a/app/views/shared/_import_form.html.haml b/app/views/shared/_import_form.html.haml index 873179339dc..233d8c95eda 100644 --- a/app/views/shared/_import_form.html.haml +++ b/app/views/shared/_import_form.html.haml @@ -13,4 +13,4 @@ %li The import will time out after 15 minutes. For repositories that take longer, use a clone/push combination. %li - To migrate an SVN repository, check out #{link_to "this document", help_page_path('workflow/importing/migrating_from_svn')}. + To migrate an SVN repository, check out #{link_to "this document", help_page_path('user/project/import/svn')}. diff --git a/app/views/shared/milestones/_sidebar.html.haml b/app/views/shared/milestones/_sidebar.html.haml index 66ac8196f2f..40379f48393 100644 --- a/app/views/shared/milestones/_sidebar.html.haml +++ b/app/views/shared/milestones/_sidebar.html.haml @@ -1,7 +1,7 @@ - affix_offset = local_assigns.fetch(:affix_offset, "50") - project = local_assigns[:project] -%aside.right-sidebar.js-right-sidebar{ data: { "offset-top" => affix_offset, "spy" => "affix" }, class: sidebar_gutter_collapsed_class, 'aria-live' => 'polite' } +%aside.right-sidebar.js-right-sidebar{ data: { "offset-top" => affix_offset, "spy" => "affix", "always-show-toggle" => true }, class: sidebar_gutter_collapsed_class, 'aria-live' => 'polite' } .issuable-sidebar.milestone-sidebar .block.milestone-progress.issuable-sidebar-header %a.gutter-toggle.pull-right.js-sidebar-toggle{ role: "button", href: "#", "aria-label" => "Toggle sidebar" } diff --git a/app/workers/namespaceless_project_destroy_worker.rb b/app/workers/namespaceless_project_destroy_worker.rb index bfae0c77700..a9073742ff7 100644 --- a/app/workers/namespaceless_project_destroy_worker.rb +++ b/app/workers/namespaceless_project_destroy_worker.rb @@ -24,10 +24,6 @@ class NamespacelessProjectDestroyWorker unlink_fork(project) if project.forked? - # Override Project#remove_pages for this instance so it doesn't do anything - def project.remove_pages - end - project.destroy! end diff --git a/app/workers/repository_fork_worker.rb b/app/workers/repository_fork_worker.rb index a338523dc6b..cde5b45ad41 100644 --- a/app/workers/repository_fork_worker.rb +++ b/app/workers/repository_fork_worker.rb @@ -5,14 +5,17 @@ class RepositoryForkWorker include Gitlab::ShellAdapter include DedicatedSidekiqQueue + sidekiq_options status_expiration: StuckImportJobsWorker::IMPORT_JOBS_EXPIRATION + def perform(project_id, forked_from_repository_storage_path, source_path, target_path) + project = Project.find(project_id) + + return unless start_fork(project) + Gitlab::Metrics.add_event(:fork_repository, source_path: source_path, target_path: target_path) - project = Project.find(project_id) - project.import_start - result = gitlab_shell.fork_repository(forked_from_repository_storage_path, source_path, project.repository_storage_path, target_path) raise ForkError, "Unable to fork project #{project_id} for repository #{source_path} -> #{target_path}" unless result @@ -33,6 +36,13 @@ class RepositoryForkWorker private + def start_fork(project) + return true if project.import_start + + Rails.logger.info("Project #{project.full_path} was in inconsistent state (#{project.import_status}) while forking.") + false + end + def fail_fork(project, message) Rails.logger.error(message) project.mark_import_as_failed(message) diff --git a/app/workers/repository_import_worker.rb b/app/workers/repository_import_worker.rb index 6be541abd3e..2c2d1e8b91f 100644 --- a/app/workers/repository_import_worker.rb +++ b/app/workers/repository_import_worker.rb @@ -4,23 +4,18 @@ class RepositoryImportWorker include Sidekiq::Worker include DedicatedSidekiqQueue - sidekiq_options status_expiration: StuckImportJobsWorker::IMPORT_EXPIRATION - - attr_accessor :project, :current_user + sidekiq_options status_expiration: StuckImportJobsWorker::IMPORT_JOBS_EXPIRATION def perform(project_id) - @project = Project.find(project_id) - @current_user = @project.creator + project = Project.find(project_id) - project.import_start + return unless start_import(project) Gitlab::Metrics.add_event(:import_repository, - import_url: @project.import_url, - path: @project.full_path) - - project.update_columns(import_jid: self.jid, import_error: nil) + import_url: project.import_url, + path: project.full_path) - result = Projects::ImportService.new(project, current_user).execute + result = Projects::ImportService.new(project, project.creator).execute raise ImportError, result[:message] if result[:status] == :error project.repository.after_import @@ -37,6 +32,13 @@ class RepositoryImportWorker private + def start_import(project) + return true if project.import_start + + Rails.logger.info("Project #{project.full_path} was in inconsistent state (#{project.import_status}) while importing.") + false + end + def fail_import(project, message) project.mark_import_as_failed(message) end diff --git a/app/workers/stuck_import_jobs_worker.rb b/app/workers/stuck_import_jobs_worker.rb index bfc5e667bb6..f850e459cd9 100644 --- a/app/workers/stuck_import_jobs_worker.rb +++ b/app/workers/stuck_import_jobs_worker.rb @@ -2,36 +2,60 @@ class StuckImportJobsWorker include Sidekiq::Worker include CronjobQueue - IMPORT_EXPIRATION = 15.hours.to_i + IMPORT_JOBS_EXPIRATION = 15.hours.to_i def perform - stuck_projects.find_in_batches(batch_size: 500) do |group| + projects_without_jid_count = mark_projects_without_jid_as_failed! + projects_with_jid_count = mark_projects_with_jid_as_failed! + + Gitlab::Metrics.add_event(:stuck_import_jobs, + projects_without_jid_count: projects_without_jid_count, + projects_with_jid_count: projects_with_jid_count) + end + + private + + def mark_projects_without_jid_as_failed! + started_projects_without_jid.each do |project| + project.mark_import_as_failed(error_message) + end.count + end + + def mark_projects_with_jid_as_failed! + completed_jids_count = 0 + + started_projects_with_jid.find_in_batches(batch_size: 500) do |group| jids = group.map(&:import_jid) # Find the jobs that aren't currently running or that exceeded the threshold. - completed_jids = Gitlab::SidekiqStatus.completed_jids(jids) + completed_jids = Gitlab::SidekiqStatus.completed_jids(jids).to_set if completed_jids.any? - completed_ids = group.select { |project| completed_jids.include?(project.import_jid) }.map(&:id) + completed_jids_count += completed_jids.count + group.each do |project| + project.mark_import_as_failed(error_message) if completed_jids.include?(project.import_jid) + end - fail_batch!(completed_jids, completed_ids) + Rails.logger.info("Marked stuck import jobs as failed. JIDs: #{completed_jids.to_a.join(', ')}") end end - end - private + completed_jids_count + end - def stuck_projects - Project.select('id, import_jid').with_import_status(:started).where.not(import_jid: nil) + def started_projects + Project.with_import_status(:started) end - def fail_batch!(completed_jids, completed_ids) - Project.where(id: completed_ids).update_all(import_status: 'failed', import_error: error_message) + def started_projects_with_jid + started_projects.where.not(import_jid: nil) + end - Rails.logger.info("Marked stuck import jobs as failed. JIDs: #{completed_jids.join(', ')}") + def started_projects_without_jid + started_projects.where(import_jid: nil) end def error_message - "Import timed out. Import took longer than #{IMPORT_EXPIRATION} seconds" + "Import timed out. Import took longer than #{IMPORT_JOBS_EXPIRATION} seconds" end end diff --git a/changelogs/unreleased/35072-fix-pages-delete.yml b/changelogs/unreleased/35072-fix-pages-delete.yml new file mode 100644 index 00000000000..21af2bde201 --- /dev/null +++ b/changelogs/unreleased/35072-fix-pages-delete.yml @@ -0,0 +1,5 @@ +--- +title: Fix deleting GitLab Pages files when a project is removed +merge_request: 13631 +author: +type: fixed diff --git a/changelogs/unreleased/36087-users-cannot-delete-their-account.yml b/changelogs/unreleased/36087-users-cannot-delete-their-account.yml new file mode 100644 index 00000000000..9ba75d8b1d0 --- /dev/null +++ b/changelogs/unreleased/36087-users-cannot-delete-their-account.yml @@ -0,0 +1,5 @@ +--- +title: allow all users to delete their account +merge_request: 13636 +author: Jacopo Beschi @jacopo-beschi +type: changed diff --git a/changelogs/unreleased/issue_35580.yml b/changelogs/unreleased/issue_35580.yml new file mode 100644 index 00000000000..3a94e771e25 --- /dev/null +++ b/changelogs/unreleased/issue_35580.yml @@ -0,0 +1,4 @@ +--- +title: Fix project milestones import when projects belongs to a group +merge_request: +author: diff --git a/changelogs/unreleased/zj-upgrade-grape.yml b/changelogs/unreleased/zj-upgrade-grape.yml new file mode 100644 index 00000000000..daa6a234c07 --- /dev/null +++ b/changelogs/unreleased/zj-upgrade-grape.yml @@ -0,0 +1,5 @@ +--- +title: Upgrade grape to 1.0 +merge_request: +author: +type: other diff --git a/doc/README.md b/doc/README.md index 547541c4876..267487520cd 100644 --- a/doc/README.md +++ b/doc/README.md @@ -102,7 +102,7 @@ Manage your [repositories](user/project/repository/index.md) from the UI (user i ### Migrate and import your projects from other platforms -- [Importing to GitLab](workflow/importing/README.md): Import your projects from GitHub, Bitbucket, GitLab.com, FogBugz and SVN into GitLab. +- [Importing to GitLab](user/project/import/index.md): Import your projects from GitHub, Bitbucket, GitLab.com, FogBugz and SVN into GitLab. - [Migrating from SVN](workflow/importing/migrating_from_svn.md): Convert a SVN repository to Git and GitLab. ### Continuous Integration, Delivery, and Deployment diff --git a/doc/articles/index.md b/doc/articles/index.md index 3039faca411..1aa65504852 100644 --- a/doc/articles/index.md +++ b/doc/articles/index.md @@ -17,8 +17,8 @@ Explore GitLab's supported [authentications methods](../topics/authentication/in | Article title | Category | Publishing date | | :------------ | :------: | --------------: | | **LDAP** | -| [How to configure LDAP with GitLab CE](how_to_configure_ldap_gitlab_ce/index.md)| Admin guide | 2017/05/03 | -| [How to configure LDAP with GitLab EE](https://docs.gitlab.com/ee/articles/how_to_configure_ldap_gitlab_ee/) | Admin guide | 2017/05/03 | +| [How to configure LDAP with GitLab CE](how_to_configure_ldap_gitlab_ce/index.md)| Admin guide | 2017-05-03 | +| [How to configure LDAP with GitLab EE](https://docs.gitlab.com/ee/articles/how_to_configure_ldap_gitlab_ee/) | Admin guide | 2017-05-03 | ## Build, test, and deploy with GitLab CI/CD @@ -27,17 +27,17 @@ Build, test, and deploy the software you develop with [GitLab CI/CD](../ci/READM | Article title | Category | Publishing date | | :------------ | :------: | --------------: | | [How to deploy Maven projects to Artifactory with GitLab CI/CD](artifactory_and_gitlab/index.md) | Tutorial | 2017-08-15 | -| [Making CI Easier with GitLab](https://about.gitlab.com/2017/07/13/making-ci-easier-with-gitlab/) | Concepts | 2017/07/13 | -| [Dockerizing GitLab Review Apps](https://about.gitlab.com/2017/07/11/dockerizing-review-apps/) | Concepts | 2017/07/11 | -| [Continuous Integration: From Jenkins to GitLab Using Docker](https://about.gitlab.com/2017/07/27/docker-my-precious/) | Concepts | 2017/07/27 | -| [Continuous Delivery of a Spring Boot application with GitLab CI and Kubernetes](https://about.gitlab.com/2016/12/14/continuous-delivery-of-a-spring-boot-application-with-gitlab-ci-and-kubernetes/) | Tutorial | 2016/12/14 | -| [Setting up GitLab CI for Android projects](https://about.gitlab.com/2016/11/30/setting-up-gitlab-ci-for-android-projects/) | Tutorial | 2016/11/30 | -| [Automated Debian Package Build with GitLab CI](https://about.gitlab.com/2016/10/12/automated-debian-package-build-with-gitlab-ci/) | Tutorial | 2016/10/12 | -| [Building an Elixir Release into a Docker image using GitLab CI](https://about.gitlab.com/2016/08/11/building-an-elixir-release-into-docker-image-using-gitlab-ci-part-1/) | Tutorial | 2016/08/11 | -| [Continuous Delivery with GitLab and Convox](https://about.gitlab.com/2016/06/09/continuous-delivery-with-gitlab-and-convox/) | Technical overview | 2016/06/09 | -| [GitLab Container Registry](https://about.gitlab.com/2016/05/23/gitlab-container-registry/) | Technical overview | 2016/05/23 | -| [How to use GitLab CI and MacStadium to build your macOS or iOS projects](https://about.gitlab.com/2017/05/15/how-to-use-macstadium-and-gitlab-ci-to-build-your-macos-or-ios-projects/) | Technical overview | 2017/05/15 | -| [Setting up GitLab CI for iOS projects](https://about.gitlab.com/2016/03/10/setting-up-gitlab-ci-for-ios-projects/) | Tutorial | 2016/03/10 | +| [Making CI Easier with GitLab](https://about.gitlab.com/2017/07/13/making-ci-easier-with-gitlab/) | Concepts | 2017-07-13 | +| [Dockerizing GitLab Review Apps](https://about.gitlab.com/2017/07/11/dockerizing-review-apps/) | Concepts | 2017-07-11 | +| [Continuous Integration: From Jenkins to GitLab Using Docker](https://about.gitlab.com/2017/07/27/docker-my-precious/) | Concepts | 2017-07-27 | +| [Continuous Delivery of a Spring Boot application with GitLab CI and Kubernetes](https://about.gitlab.com/2016/12/14/continuous-delivery-of-a-spring-boot-application-with-gitlab-ci-and-kubernetes/) | Tutorial | 2016-12-14 | +| [Setting up GitLab CI for Android projects](https://about.gitlab.com/2016/11/30/setting-up-gitlab-ci-for-android-projects/) | Tutorial | 2016-11-30 | +| [Automated Debian Package Build with GitLab CI](https://about.gitlab.com/2016/10/12/automated-debian-package-build-with-gitlab-ci/) | Tutorial | 2016-10-12 | +| [Building an Elixir Release into a Docker image using GitLab CI](https://about.gitlab.com/2016/08/11/building-an-elixir-release-into-docker-image-using-gitlab-ci-part-1/) | Tutorial | 2016-08-11 | +| [Continuous Delivery with GitLab and Convox](https://about.gitlab.com/2016/06/09/continuous-delivery-with-gitlab-and-convox/) | Technical overview | 2016-06-09 | +| [GitLab Container Registry](https://about.gitlab.com/2016/05/23/gitlab-container-registry/) | Technical overview | 2016-05-23 | +| [How to use GitLab CI and MacStadium to build your macOS or iOS projects](https://about.gitlab.com/2017/05/15/how-to-use-macstadium-and-gitlab-ci-to-build-your-macos-or-ios-projects/) | Technical overview | 2017-05-15 | +| [Setting up GitLab CI for iOS projects](https://about.gitlab.com/2016/03/10/setting-up-gitlab-ci-for-ios-projects/) | Tutorial | 2016-03-10 | ## Git @@ -45,10 +45,11 @@ Learn how to use [Git with GitLab](../topics/git/index.md): | Article title | Category | Publishing date | | :------------ | :------: | --------------: | -| [Why Git is Worth the Learning Curve](https://about.gitlab.com/2017/05/17/learning-curve-is-the-biggest-challenge-developers-face-with-git/) | Concepts | 2017/05/17 | -| [How to install Git](how_to_install_git/index.md) | Tutorial | 2017/05/15 | -| [Getting Started with Git LFS](https://about.gitlab.com/2017/01/30/getting-started-with-git-lfs-tutorial/) | Tutorial | 2017/01/30 | -| [Git Tips & Tricks](https://about.gitlab.com/2016/12/08/git-tips-and-tricks/) | Technical overview | 2016/12/08 | +| [Numerous _undo_ possibilities in Git](numerous_undo_possibilities_in_git/index.md) | Tutorial | 2017-08-17 | +| [Why Git is Worth the Learning Curve](https://about.gitlab.com/2017/05/17/learning-curve-is-the-biggest-challenge-developers-face-with-git/) | Concepts | 2017-05-17 | +| [How to install Git](how_to_install_git/index.md) | Tutorial | 2017-05-15 | +| [Getting Started with Git LFS](https://about.gitlab.com/2017/01/30/getting-started-with-git-lfs-tutorial/) | Tutorial | 2017-01-30 | +| [Git Tips & Tricks](https://about.gitlab.com/2016/12/08/git-tips-and-tricks/) | Technical overview | 2016-12-08 | ## GitLab Pages @@ -57,21 +58,21 @@ Learn how to deploy a static website with [GitLab Pages](../user/project/pages/i | Article title | Category | Publishing date | | :------------ | :------: | --------------: | | **Series: GitLab Pages from A to Z:** | -| [- Part 1: Static sites and GitLab Pages domains](../user/project/pages/getting_started_part_one.md)| User guide | 2017/02/22 | -| [- Part 2: Quick start guide - Setting up GitLab Pages](../user/project/pages/getting_started_part_two.md)| User guide | 2017/02/22 | -| [- Part 3: Setting Up Custom Domains - DNS Records and SSL/TLS Certificates](../user/project/pages/getting_started_part_three.md)| User guide | 2017/02/22 | -| [- Part 4: Creating and tweaking `.gitlab-ci.yml` for GitLab Pages](../user/project/pages/getting_started_part_four.md)| User guide | 2017/02/22 | -| [Setting up GitLab Pages with CloudFlare Certificates](https://about.gitlab.com/2017/02/07/setting-up-gitlab-pages-with-cloudflare-certificates/) | Tutorial | 2017/02/07 | -| [Building a new GitLab Docs site with Nanoc, GitLab CI, and GitLab Pages](https://about.gitlab.com/2016/12/07/building-a-new-gitlab-docs-site-with-nanoc-gitlab-ci-and-gitlab-pages/) | Tutorial | 2016/12/07 | -| [Publish Code Coverage Report with GitLab Pages](https://about.gitlab.com/2016/11/03/publish-code-coverage-report-with-gitlab-pages/) | Tutorial | 2016/11/03 | -| [GitLab CI: Deployment & Environments](https://about.gitlab.com/2016/08/26/ci-deployment-and-environments/) | Tutorial | 2016/08/26 | -| [Posting to your GitLab Pages blog from iOS](https://about.gitlab.com/2016/08/19/posting-to-your-gitlab-pages-blog-from-ios/) | Tutorial | 2016/08/19 | +| [- Part 1: Static sites and GitLab Pages domains](../user/project/pages/getting_started_part_one.md)| User guide | 2017-02-22 | +| [- Part 2: Quick start guide - Setting up GitLab Pages](../user/project/pages/getting_started_part_two.md)| User guide | 2017-02-22 | +| [- Part 3: Setting Up Custom Domains - DNS Records and SSL/TLS Certificates](../user/project/pages/getting_started_part_three.md)| User guide | 2017-02-22 | +| [- Part 4: Creating and tweaking `.gitlab-ci.yml` for GitLab Pages](../user/project/pages/getting_started_part_four.md)| User guide | 2017-02-22 | +| [Setting up GitLab Pages with CloudFlare Certificates](https://about.gitlab.com/2017/02/07/setting-up-gitlab-pages-with-cloudflare-certificates/) | Tutorial | 2017-02-07 | +| [Building a new GitLab Docs site with Nanoc, GitLab CI, and GitLab Pages](https://about.gitlab.com/2016/12/07/building-a-new-gitlab-docs-site-with-nanoc-gitlab-ci-and-gitlab-pages/) | Tutorial | 2016-12-07 | +| [Publish Code Coverage Report with GitLab Pages](https://about.gitlab.com/2016/11/03/publish-code-coverage-report-with-gitlab-pages/) | Tutorial | 2016-11-03 | +| [GitLab CI: Deployment & Environments](https://about.gitlab.com/2016/08/26/ci-deployment-and-environments/) | Tutorial | 2016-08-26 | +| [Posting to your GitLab Pages blog from iOS](https://about.gitlab.com/2016/08/19/posting-to-your-gitlab-pages-blog-from-ios/) | Tutorial | 2016-08-19 | | **Series: Static Site Generator:** | -| [- Part 1: Dynamic vs Static Websites](https://about.gitlab.com/2016/06/03/ssg-overview-gitlab-pages-part-1-dynamic-x-static/) | Tutorial | 2016/06/03 | -| [- Part 2: Modern Static Site Generators](https://about.gitlab.com/2016/06/10/ssg-overview-gitlab-pages-part-2/) | Tutorial | 2016/06/10 | -| [- Part 3: Build any SSG site with GitLab Pages](https://about.gitlab.com/2016/06/17/ssg-overview-gitlab-pages-part-3-examples-ci/) | Tutorial | 2016/06/17 | -| [Securing your GitLab Pages with TLS and Let's Encrypt](https://about.gitlab.com/2016/04/11/tutorial-securing-your-gitlab-pages-with-tls-and-letsencrypt/) | Tutorial | 2016/04/11 | -| [Hosting on GitLab.com with GitLab Pages](https://about.gitlab.com/2016/04/07/gitlab-pages-setup/) | Tutorial | 2016/04/07 | +| [- Part 1: Dynamic vs Static Websites](https://about.gitlab.com/2016/06/03/ssg-overview-gitlab-pages-part-1-dynamic-x-static/) | Tutorial | 2016-06-03 | +| [- Part 2: Modern Static Site Generators](https://about.gitlab.com/2016/06/10/ssg-overview-gitlab-pages-part-2/) | Tutorial | 2016-06-10 | +| [- Part 3: Build any SSG site with GitLab Pages](https://about.gitlab.com/2016/06/17/ssg-overview-gitlab-pages-part-3-examples-ci/) | Tutorial | 2016-06-17 | +| [Securing your GitLab Pages with TLS and Let's Encrypt](https://about.gitlab.com/2016/04/11/tutorial-securing-your-gitlab-pages-with-tls-and-letsencrypt/) | Tutorial | 2016-04-11 | +| [Hosting on GitLab.com with GitLab Pages](https://about.gitlab.com/2016/04/07/gitlab-pages-setup/) | Tutorial | 2016-04-07 | ## Install and maintain GitLab @@ -79,10 +80,10 @@ Install, upgrade, integrate, migrate to GitLab: | Article title | Category | Publishing date | | :------------ | :------: | --------------: | -| [Video Tutorial: Idea to Production on Google Container Engine (GKE)](https://about.gitlab.com/2017/01/23/video-tutorial-idea-to-production-on-google-container-engine-gke/) | Tutorial | 2017/01/23 | -| [How to Setup a GitLab Instance on Microsoft Azure](https://about.gitlab.com/2016/07/13/how-to-setup-a-gitlab-instance-on-microsoft-azure/) | Tutorial | 2016/07/13 | -| [Get started with OpenShift Origin 3 and GitLab](openshift_and_gitlab/index.md) | Tutorial | 2016/06/28 | -| [Getting started with GitLab and DigitalOcean](https://about.gitlab.com/2016/04/27/getting-started-with-gitlab-and-digitalocean/) | Tutorial | 2016/04/27 | +| [Video Tutorial: Idea to Production on Google Container Engine (GKE)](https://about.gitlab.com/2017/01/23/video-tutorial-idea-to-production-on-google-container-engine-gke/) | Tutorial | 2017-01-23 | +| [How to Setup a GitLab Instance on Microsoft Azure](https://about.gitlab.com/2016/07/13/how-to-setup-a-gitlab-instance-on-microsoft-azure/) | Tutorial | 2016-07-13 | +| [Get started with OpenShift Origin 3 and GitLab](openshift_and_gitlab/index.md) | Tutorial | 2016-06-28 | +| [Getting started with GitLab and DigitalOcean](https://about.gitlab.com/2016/04/27/getting-started-with-gitlab-and-digitalocean/) | Tutorial | 2016-04-27 | ## Software development @@ -90,25 +91,25 @@ Explore the best of GitLab's software development's capabilities: | Article title | Category | Publishing date | | :------------ | :------: | --------------: | -| [Making CI Easier with GitLab](https://about.gitlab.com/2017/07/13/making-ci-easier-with-gitlab/) | Concepts | 2017/07/13 | -| [From 2/3 of the Self-Hosted Git Market, to the Next-Generation CI System, to Auto DevOps](https://about.gitlab.com/2017/06/29/whats-next-for-gitlab-ci/)| Concepts | 2017/06/29 | -| [Fast and Natural Continuous Integration with GitLab CI](https://about.gitlab.com/2017/05/22/fast-and-natural-continuous-integration-with-gitlab-ci/) | Concepts | 2017/05/22 | -| [Demo: Auto-Deploy from GitLab to an OpenShift Container Cluster](https://about.gitlab.com/2017/05/16/devops-containers-gitlab-openshift/) | Technical overview | 2017/05/16 | -| [Demo: GitLab Service Desk](https://about.gitlab.com/2017/05/09/demo-service-desk/) | Feature highlight | 2017/05/09 | -| [Demo: Mapping Work Versus Time, With Burndown Charts](https://about.gitlab.com/2017/04/25/mapping-work-to-do-versus-time-with-burndown-charts/) | Feature highlight | 2017/04/25 | -| [Demo: Cloud Native Development with GitLab](https://about.gitlab.com/2017/04/18/cloud-native-demo/) | Feature highlight | 2017/04/18 | -| [Demo: Mastering Code Review With GitLab](https://about.gitlab.com/2017/03/17/demo-mastering-code-review-with-gitlab/) | Feature highlight | 2017/03/17 | -| [In 13 minutes from Kubernetes to a complete application development tool](https://about.gitlab.com/2016/11/14/idea-to-production/) | Technical overview | 2016/11/14 | -| [GitLab Workflow, an Overview](https://about.gitlab.com/2016/10/25/gitlab-workflow-an-overview/) | Technical overview | 2016/10/25 | -| [Trends in Version Control Land: Microservices](https://about.gitlab.com/2016/08/16/trends-in-version-control-land-microservices/) | Concepts | 2016/08/16 | -| [Continuous Integration, Delivery, and Deployment with GitLab](https://about.gitlab.com/2016/08/05/continuous-integration-delivery-and-deployment-with-gitlab/) | Concepts | 2016/08/05 | -| [Trends in Version Control Land: Innersourcing](https://about.gitlab.com/2016/07/07/trends-version-control-innersourcing/) | Concepts | 2016/07/07 | -| [Tutorial: It's all connected in GitLab](https://about.gitlab.com/2016/03/08/gitlab-tutorial-its-all-connected/) | Technical overview | 2016/03/08 | +| [Making CI Easier with GitLab](https://about.gitlab.com/2017/07/13/making-ci-easier-with-gitlab/) | Concepts | 2017-07-13 | +| [From 2/3 of the Self-Hosted Git Market, to the Next-Generation CI System, to Auto DevOps](https://about.gitlab.com/2017/06/29/whats-next-for-gitlab-ci/)| Concepts | 2017-06-29 | +| [Fast and Natural Continuous Integration with GitLab CI](https://about.gitlab.com/2017/05/22/fast-and-natural-continuous-integration-with-gitlab-ci/) | Concepts | 2017-05-22 | +| [Demo: Auto-Deploy from GitLab to an OpenShift Container Cluster](https://about.gitlab.com/2017/05/16/devops-containers-gitlab-openshift/) | Technical overview | 2017-05-16 | +| [Demo: GitLab Service Desk](https://about.gitlab.com/2017/05/09/demo-service-desk/) | Feature highlight | 2017-05-09 | +| [Demo: Mapping Work Versus Time, With Burndown Charts](https://about.gitlab.com/2017/04/25/mapping-work-to-do-versus-time-with-burndown-charts/) | Feature highlight | 2017-04-25 | +| [Demo: Cloud Native Development with GitLab](https://about.gitlab.com/2017/04/18/cloud-native-demo/) | Feature highlight | 2017-04-18 | +| [Demo: Mastering Code Review With GitLab](https://about.gitlab.com/2017/03/17/demo-mastering-code-review-with-gitlab/) | Feature highlight | 2017-03-17 | +| [In 13 minutes from Kubernetes to a complete application development tool](https://about.gitlab.com/2016/11/14/idea-to-production/) | Technical overview | 2016-11-14 | +| [GitLab Workflow, an Overview](https://about.gitlab.com/2016/10/25/gitlab-workflow-an-overview/) | Technical overview | 2016-10-25 | +| [Trends in Version Control Land: Microservices](https://about.gitlab.com/2016/08/16/trends-in-version-control-land-microservices/) | Concepts | 2016-08-16 | +| [Continuous Integration, Delivery, and Deployment with GitLab](https://about.gitlab.com/2016/08/05/continuous-integration-delivery-and-deployment-with-gitlab/) | Concepts | 2016-08-05 | +| [Trends in Version Control Land: Innersourcing](https://about.gitlab.com/2016/07/07/trends-version-control-innersourcing/) | Concepts | 2016-07-07 | +| [Tutorial: It's all connected in GitLab](https://about.gitlab.com/2016/03/08/gitlab-tutorial-its-all-connected/) | Technical overview | 2016-03-08 | ## Technologies | Article title | Category | Publishing date | | :------------ | :------: | --------------: | -| [Why we are not leaving the cloud](https://about.gitlab.com/2017/03/02/why-we-are-not-leaving-the-cloud/) | Concepts | 2017/03/02 | -| [Why We Chose Vue.js](https://about.gitlab.com/2016/10/20/why-we-chose-vue/) | Concepts | 2016/10/20 | -| [Markdown Kramdown Tips & Tricks](https://about.gitlab.com/2016/07/19/markdown-kramdown-tips-and-tricks/) | Technical overview | 2016/07/19 | +| [Why we are not leaving the cloud](https://about.gitlab.com/2017/03/02/why-we-are-not-leaving-the-cloud/) | Concepts | 2017-03-02 | +| [Why We Chose Vue.js](https://about.gitlab.com/2016/10/20/why-we-chose-vue/) | Concepts | 2016-10-20 | +| [Markdown Kramdown Tips & Tricks](https://about.gitlab.com/2016/07/19/markdown-kramdown-tips-and-tricks/) | Technical overview | 2016-07-19 | diff --git a/doc/articles/numerous_undo_possibilities_in_git/img/branching.png b/doc/articles/numerous_undo_possibilities_in_git/img/branching.png Binary files differnew file mode 100644 index 00000000000..9a80c211c99 --- /dev/null +++ b/doc/articles/numerous_undo_possibilities_in_git/img/branching.png diff --git a/doc/articles/numerous_undo_possibilities_in_git/img/rebase_reset.png b/doc/articles/numerous_undo_possibilities_in_git/img/rebase_reset.png Binary files differnew file mode 100644 index 00000000000..ac7ea9ecddc --- /dev/null +++ b/doc/articles/numerous_undo_possibilities_in_git/img/rebase_reset.png diff --git a/doc/articles/numerous_undo_possibilities_in_git/img/revert.png b/doc/articles/numerous_undo_possibilities_in_git/img/revert.png Binary files differnew file mode 100644 index 00000000000..13b3a35ca45 --- /dev/null +++ b/doc/articles/numerous_undo_possibilities_in_git/img/revert.png diff --git a/doc/articles/numerous_undo_possibilities_in_git/index.md b/doc/articles/numerous_undo_possibilities_in_git/index.md new file mode 100644 index 00000000000..9f1239b8f88 --- /dev/null +++ b/doc/articles/numerous_undo_possibilities_in_git/index.md @@ -0,0 +1,497 @@ +# Numerous undo possibilities in Git + +> **Article [Type](../../development/writing_documentation.md#types-of-technical-articles):** tutorial || +> **Level:** intermediary || +> **Author:** [Crt Mori](https://gitlab.com/Letme) || +> **Publication date:** 2017/08/17 + +## Introduction + +In this tutorial, we will show you different ways of undoing your work in Git, for which +we will assume you have a basic working knowledge of. Check GitLab's +[Git documentation](../../topics/git/index.md#git-documentation) for reference. +Also, we will only provide some general info of the commands, which is enough +to get you started for the easy cases/examples, but for anything more advanced please refer to the [Git book](https://git-scm.com/book/en/v2). + +We will explain a few different techniques to undo your changes based on the stage +of the change in your current development. Also, keep in mind that [nothing in +Git is really deleted.][git-autoclean-ref] +This means that until Git automatically cleans detached commits (which cannot be +accessed by branch or tag) it will be possible to view them with `git reflog` command +and access them with direct commit-id. Read more about _[redoing the undo](#redoing-the-undo)_ on the section below. + +This guide is organized depending on the [stage of development][git-basics] +where you want to undo your changes from and if they were shared with other developers +or not. Because Git is tracking changes a created or edited file is in the unstaged state +(if created it is untracked by Git). After you add it to a repository (`git add`) you put +a file into the **staged** state, which is then committed (`git commit`) to your +local repository. After that, file can be shared with other developers (`git push`). +Here's what we'll cover in this tutorial: + + - [Undo local changes](#undo-local-changes) which were not pushed to remote repository + + - Before you commit, in both unstaged and staged state + - After you committed + + - Undo changes after they are pushed to remote repository + + - [Without history modification](#undo-remote-changes-without-changing-history) (preferred way) + - [With history modification](#undo-remote-changes-with-modifying-history) (requires + coordination with team and force pushes). + + - [Usecases when modifying history is generally acceptable](#where-modifying-history-is-generally-acceptable) + - [How to modify history](#how-modifying-history-is-done) + - [How to remove sensitive information from repository](#deleting-sensitive-information-from-commits) + + +### Branching strategy + +[Git][git-official] is a de-centralized version control system, which means that beside regular +versioning of the whole repository, it has possibilities to exchange changes +with other repositories. To avoid chaos with +[multiple sources of truth][git-distributed], various +development workflows have to be followed, and it depends on your internal +workflow how certain changes or commits can be undone or changed. +[GitLab Flow][gitlab-flow] provides a good +balance between developers clashing with each other while +developing the same feature and cooperating seamlessly, but it does not enable +joined development of the same feature by multiple developers by default. +When multiple developers develop the same feature on the same branch, clashing +with every synchronization is unavoidable, but a proper or chosen Git Workflow will +prevent that anything is lost or out of sync when feature is complete. You can also +read through this blog post on [Git Tips & Tricks][gitlab-git-tips-n-tricks] +to learn how to easily **do** things in Git. + + +## Undo local changes + +Until you push your changes to any remote repository, they will only affect you. +That broadens your options on how to handle undoing them. Still, local changes +can be on various stages and each stage has a different approach on how to tackle them. + + +### Unstaged local changes (before you commit) + +When a change is made, but it is not added to the staged tree, Git itself +proposes a solution to discard changes to certain file. + +Suppose you edited a file to change the content using your favorite editor: + +```shell +vim <file> +``` + +Since you did not `git add <file>` to staging, it should be under unstaged files (or +untracked if file was created). You can confirm that with: + +```shell +$ git status +On branch master +Your branch is up-to-date with 'origin/master'. +Changes not staged for commit: + (use "git add <file>..." to update what will be committed) + (use "git checkout -- <file>..." to discard changes in working directory) + + modified: <file> +no changes added to commit (use "git add" and/or "git commit -a") +``` + +At this point there are 3 options to undo the local changes you have: + + - Discard all local changes, but save them for possible re-use [later](#quickly-save-local-changes) + + ```shell + git stash + ``` + + - Discarding local changes (permanently) to a file + + ```shell + git checkout -- <file> + ``` + + - Discard all local changes to all files permanently + + ```shell + git reset --hard + ``` + + +Before executing `git reset --hard`, keep in mind that there is also a way to +just temporary store the changes without committing them using `git stash`. +This command resets the changes to all files, but it also saves them in case +you would like to apply them at some later time. You can read more about it in +[section below](#quickly-save-local-changes). + +### Quickly save local changes + +You are working on a feature when a boss drops by with an urgent task. Since your +feature is not complete, but you need to swap to another branch, you can use +`git stash` to save what you had done, swap to another branch, commit, push, +test, then get back to previous feature branch, do `git stash pop` and continue +where you left. + +The example above shows that discarding all changes is not always a preferred option, +but Git provides a way to save them for later, while resetting the repository to state without +them. This is achieved by Git stashing command `git stash`, which in fact saves your +current work and runs `git reset --hard`, but it also has various +additional options like: + + - `git stash save`, which enables including temporary commit message, which will help you identify changes, among with other options + - `git stash list`, which lists all previously stashed commits (yes, there can be more) that were not `pop`ed + - `git stash pop`, which redoes previously stashed changes and removes them from stashed list + - `git stash apply`, which redoes previously stashed changes, but keeps them on stashed list + +### Staged local changes (before you commit) + +Let's say you have added some files to staging, but you want to remove them from the +current commit, yet you want to retain those changes - just move them outside +of the staging tree. You also have an option to discard all changes with +`git reset --hard` or think about `git stash` [as described earlier.](#quickly-save-local-changes) + +Lets start the example by editing a file, with your favorite editor, to change the +content and add it to staging + +``` +vim <file> +git add <file> +``` + +The file is now added to staging as confirmed by `git status` command: + +```shell +$ git status +On branch master +Your branch is up-to-date with 'origin/master'. +Changes to be committed: + (use "git reset HEAD <file>..." to unstage) + + new file: <file> +``` + +Now you have 4 options to undo your changes: + + - Unstage the file to current commit (HEAD) + + ```shell + git reset HEAD <file> + ``` + + - Unstage everything - retain changes + + ```shell + git reset + ``` + + - Discard all local changes, but save them for [later](#quickly-save-local-changes) + + ```shell + git stash + ``` + + - Discard everything permanently + + ```shell + git reset --hard + ``` + +## Committed local changes + +Once you commit, your changes are recorded by the version control system. +Because you haven't pushed to your remote repository yet, your changes are +still not public (or shared with other developers). At this point, undoing +things is a lot easier, we have quite some workaround options. Once you push +your code, you'll have less options to troubleshoot your work. + +### Without modifying history + +Through the development process some of the previously committed changes do not +fit anymore in the end solution, or are source of the bugs. Once you find the +commit which triggered bug, or once you have a faulty commit, you can simply +revert it with `git revert commit-id`. This command inverts (swaps) the additions and +deletions in that commit, so that it does not modify history. Retaining history +can be helpful in future to notice that some changes have been tried +unsuccessfully in the past. + +In our example we will assume there are commits `A`,`B`,`C`,`D`,`E` committed in this order: `A-B-C-D-E`, +and `B` is the commit you want to undo. There are many different ways to identify commit +`B` as bad, one of them is to pass a range to `git bisect` command. The provided range includes +last known good commit (we assume `A`) and first known bad commit (where bug was detected - we will assume `E`). + +```shell +git bisect A..E +``` + +Bisect will provide us with commit-id of the middle commit to test, and then guide us +through simple bisection process. You can read more about it [in official Git Tools][git-debug] +In our example we will end up with commit `B`, that introduced bug/error. We have +4 options on how to remove it (or part of it) from our repository. + +- Undo (swap additions and deletions) changes introduced by commit `B`. + + ```shell + git revert commit-B-id + ``` + +- Undo changes on a single file or directory from commit `B`, but retain them in the staged state + + ```shell + git checkout commit-B-id <file> + ``` + +- Undo changes on a single file or directory from commit `B`, but retain them in the unstaged state + + ```shell + git reset commit-B-id <file> + ``` + + - There is one command we also must not forget: **creating a new branch** + from the point where changes are not applicable or where the development has hit a + dead end. For example you have done commits `A-B-C-D` on your feature-branch + and then you figure `C` and `D` are wrong. At this point you either reset to `B` + and do commit `F` (which will cause problems with pushing and if forced pushed also with other developers) + since branch now looks `A-B-F`, which clashes with what other developers have locally (you will + [change history](#with-history-modification)), or you simply checkout commit `B` create + a new branch and do commit `F`. In the last case, everyone else can still do their work while you + have your new way to get it right and merge it back in later. Alternatively, with GitLab, + you can [cherry-pick](../../user/project/merge_requests/cherry_pick_changes.md#cherry-picking-a-commit) + that commit into a new merge request. + +  + + ```shell + git checkout commit-B-id + git checkout -b new-path-of-feature + # Create <commit F> + git commit -a + ``` + +### With history modification + +There is one command for history modification and that is `git rebase`. Command +provides interactive mode (`-i` flag) which enables you to: + + - **reword** commit messages (there is also `git commit --amend` for editing + last commit message) + - **edit** the commit content (changes introduced by commit) and message + - **squash** multiple commits into a single one, and have a custom or aggregated + commit message + - **drop** commits - simply delete them + - and few more options + +Let us check few examples. Again there are commits `A-B-C-D` where you want to +delete commit `B`. + +- Rebase the range from current commit D to A: + + ```shell + git rebase -i A + ``` + +- Command opens your favorite editor where you write `drop` in front of commit + `B`, but you leave default `pick` with all other commits. Save and exit the + editor to perform a rebase. Remember: if you want to cancel delete whole + file content before saving and exiting the editor + +In case you want to modify something introduced in commit `B`. + +- Rebase the range from current commit D to A: + + ```shell + git rebase -i A + ``` + +- Command opens your favorite text editor where you write `edit` in front of commit + `B`, but leave default `pick` with all other commits. Save and exit the editor to + perform a rebase + +- Now do your edits and commit changes: + + ```shell + git commit -a + ``` + +You can find some more examples in [below section where we explain how to modify +history](#how-modifying-history-is-done) + + +### Redoing the Undo + +Sometimes you realize that the changes you undid were useful and you want them +back. Well because of first paragraph you are in luck. Command `git reflog` +enables you to *recall* detached local commits by referencing or applying them +via commit-id. Although, do not expect to see really old commits in reflog, because +Git regularly [cleans the commits which are *unreachable* by branches or tags][git-autoclean-ref]. + +To view repository history and to track older commits you can use below command: + +```shell +$ git reflog show + +# Example output: +b673187 HEAD@{4}: merge 6e43d5987921bde189640cc1e37661f7f75c9c0b: Merge made by the 'recursive' strategy. +eb37e74 HEAD@{5}: rebase -i (finish): returning to refs/heads/master +eb37e74 HEAD@{6}: rebase -i (pick): Commit C +97436c6 HEAD@{7}: rebase -i (start): checkout 97436c6eec6396c63856c19b6a96372705b08b1b +... +88f1867 HEAD@{12}: commit: Commit D +97436c6 HEAD@{13}: checkout: moving from 97436c6eec6396c63856c19b6a96372705b08b1b to test +97436c6 HEAD@{14}: checkout: moving from master to 97436c6 +05cc326 HEAD@{15}: commit: Commit C +6e43d59 HEAD@{16}: commit: Commit B +``` + +Output of command shows repository history. In first column there is commit-id, +in following column, number next to `HEAD` indicates how many commits ago something +was made, after that indicator of action that was made (commit, rebase, merge, ...) +and then on end description of that action. + +## Undo remote changes without changing history + +This topic is roughly same as modifying committed local changes without modifying +history. **It should be the preferred way of undoing changes on any remote repository +or public branch.** Keep in mind that branching is the best solution when you want +to retain the history of faulty development, yet start anew from certain point. Branching +enables you to include the existing changes in new development (by merging) and +it also provides a clear timeline and development structure. + + + +If you want to revert changes introduced in certain `commit-id` you can simply +revert that `commit-id` (swap additions and deletions) in newly created commit: +You can do this with + +```shell +git revert commit-id +``` + +or creating a new branch: + +```shell +git checkout commit-id +git checkout -b new-path-of-feature +``` + +## Undo remote changes with modifying history + +This is useful when you want to *hide* certain things - like secret keys, +passwords, SSH keys, etc. It is and should not be used to hide mistakes, as +it will make it harder to debug in case there are some other bugs. The main +reason for this is that you loose the real development progress. **Also keep in +mind that, even with modified history, commits are just detached and can still be +accessed through commit-id** - at least until all repositories perform +the cleanup of detached commits (happens automatically). + + + +### Where modifying history is generally acceptable + +Modified history breaks the development chain of other developers, as changed +history does not have matching commits'ids. For that reason it should not +be used on any public branch or on branch that *might* be used by other +developers. When contributing to big open source repositories (e.g. [GitLab CE][gitlab-ce]), +it is acceptable to *squash* commits into a single one, to present +a nicer history of your contribution. +Keep in mind that this also removes the comments attached to certain commits +in merge requests, so if you need to retain traceability in GitLab, then +modifying history is not acceptable. +A feature-branch of a merge request is a public branch and might be used by +other developers, but project process and rules might allow or require +you to use `git rebase` (command that changes history) to reduce number of +displayed commits on target branch after reviews are done (for example +GitLab). There is a `git merge --squash` command which does exactly that +(squashes commits on feature-branch to a single commit on target branch +at merge). + +>**Note:** +Never modify the commit history of `master` or shared branch + +### How modifying history is done + +After you know what you want to modify (how far in history or how which range of +old commits), use `git rebase -i commit-id`. This command will then display all the commits from +current version to chosen commit-id and allow modification, squashing, deletion +of that commits. + +```shell +$ git rebase -i commit1-id..commit3-id +pick <commit1-id> <commit1-commit-message> +pick <commit2-id> <commit2-commit-message> +pick <commit3-id> <commit3-commit-message> + +# Rebase commit1-id..commit3-id onto <commit4-id> (3 command(s)) +# +# Commands: +# p, pick = use commit +# r, reword = use commit, but edit the commit message +# e, edit = use commit, but stop for amending +# s, squash = use commit, but meld into previous commit +# f, fixup = like "squash", but discard this commit's log message +# x, exec = run command (the rest of the line) using shell +# d, drop = remove commit +# +# These lines can be re-ordered; they are executed from top to bottom. +# +# If you remove a line here THAT COMMIT WILL BE LOST. +# +# However, if you remove everything, the rebase will be aborted. +# +# Note that empty commits are commented out +``` + +>**Note:** +It is important to notice that comment from the output clearly states that, if +you decide to abort, then do not just close your editor (as that will in-fact +modify history), but remove all uncommented lines and save. + +That is one of the reasons why `git rebase` should be used carefully on +shared and remote branches. But don't worry, there will be nothing broken until +you push back to the remote repository (so you can freely explore the +different outcomes locally). + +```shell +# Modify history from commit-id to HEAD (current commit) +git rebase -i commit-id +``` + +### Deleting sensitive information from commits + +Git also enables you to delete sensitive information from your past commits and +it does modify history in the progress. That is why we have included it in this +section and not as a standalone topic. To do so, you should run the +`git filter-branch`, which enables you to rewrite history with +[certain filters][git-filters-manual]. +This command uses rebase to modify history and if you want to remove certain +file from history altogether use: + +```shell +git filter-branch --tree-filter 'rm filename' HEAD +``` + +Since `git filter-branch` command might be slow on big repositories, there are +tools that can use some of Git specifics to enable faster execution of common +tasks (which is exactly what removing sensitive information file is about). +An alternative is [BFG Repo-cleaner][bfg-repo-cleaner]. Keep in mind that these +tools are faster because they do not provide a same fully feature set as `git filter-branch` +does, but focus on specific usecases. + +## Conclusion + +There are various options of undoing your work with any version control system, but +because of de-centralized nature of Git, these options are multiplied (or limited) +depending on the stage of your process. Git also enables rewriting history, but that +should be avoided as it might cause problems when multiple developers are +contributing to the same codebase. + +<!-- Identifiers, in alphabetical order --> + +[bfg-repo-cleaner]: https://rtyley.github.io/bfg-repo-cleaner/ +[git-autoclean-ref]: https://git-scm.com/book/en/v2/Git-Internals-Maintenance-and-Data-Recovery +[git-basics]: https://git-scm.com/book/en/v2/Git-Basics-Recording-Changes-to-the-Repository +[git-debug]: https://git-scm.com/book/en/v2/Git-Tools-Debugging-with-Git +[git-distributed]: https://git-scm.com/about/distributed +[git-filters-manual]: https://git-scm.com/docs/git-filter-branch#_options +[git-official]: https://git-scm.com/ +[gitlab-ce]: https://gitlab.com/gitlab-org/gitlab-ce/blob/master/CONTRIBUTING.md#contribution-acceptance-criteria +[gitlab-flow]: https://about.gitlab.com/2014/09/29/gitlab-flow/ +[gitlab-git-tips-n-tricks]: https://about.gitlab.com/2016/12/08/git-tips-and-tricks/ diff --git a/doc/ci/docker/using_docker_images.md b/doc/ci/docker/using_docker_images.md index d3433594eb7..dc5313c5597 100644 --- a/doc/ci/docker/using_docker_images.md +++ b/doc/ci/docker/using_docker_images.md @@ -117,7 +117,7 @@ following these rules: created (requires GitLab Runner v1.1.0 or higher) To override the default behavior, you can -[specify a service alias](#available-settings-for-services-entry). +[specify a service alias](#available-settings-for-services). ## Define `image` and `services` from `.gitlab-ci.yml` @@ -183,8 +183,7 @@ test: ## Extended Docker configuration options -> **Note:** -This feature requires GitLab 9.4 and GitLab Runner 9.4 or higher. +> Introduced in GitLab and GitLab Runner 9.4. When configuring the `image` or `services` entries, you can use a string or a map as options: @@ -221,28 +220,29 @@ For example, the following two definitions are equal: ### Available settings for `image` -> **Note:** -This feature requires GitLab 9.4 and GitLab Runner 9.4 or higher. +> Introduced in GitLab and GitLab Runner 9.4. -| Setting | Required | Description | -|------------|----------|-------------| -| `name` | yes, when used with any other option | Full name of the image that should be used. It should contain the Registry part if needed. | -| `entrypoint` | no | Command or script that should be executed as the container's entrypoint. It will be translated to Docker's `--entrypoint` option while creating the container. The syntax is similar to [`Dockerfile`'s `ENTRYPOINT`][entrypoint] directive, where each shell token is a separate string in the array. | +| Setting | Required | GitLab version | Description | +|------------|----------|----------------| ----------- | +| `name` | yes, when used with any other option | 9.4 |Full name of the image that should be used. It should contain the Registry part if needed. | +| `entrypoint` | no | 9.4 |Command or script that should be executed as the container's entrypoint. It will be translated to Docker's `--entrypoint` option while creating the container. The syntax is similar to [`Dockerfile`'s `ENTRYPOINT`][entrypoint] directive, where each shell token is a separate string in the array. | ### Available settings for `services` -> **Note:** -This feature requires GitLab 9.4 and GitLab Runner 9.4 or higher. +> Introduced in GitLab and GitLab Runner 9.4. -| Setting | Required | Description | -|------------|----------|-------------| -| `name` | yes, when used with any other option | Full name of the image that should be used. It should contain the Registry part if needed. | -| `entrypoint` | no | Command or script that should be executed as the container's entrypoint. It will be translated to Docker's `--entrypoint` option while creating the container. The syntax is similar to [`Dockerfile`'s `ENTRYPOINT`][entrypoint] directive, where each shell token is a separate string in the array. | -| `command` | no | Command or script that should be used as the container's command. It will be translated to arguments passed to Docker after the image's name. The syntax is similar to [`Dockerfile`'s `CMD`][cmd] directive, where each shell token is a separate string in the array. | -| `alias` | no | Additional alias that can be used to access the service from the job's container. Read [Accessing the services](#accessing-the-services) for more information. | +| Setting | Required | GitLab version | Description | +|------------|----------|----------------| ----------- | +| `name` | yes, when used with any other option | 9.4 | Full name of the image that should be used. It should contain the Registry part if needed. | +| `entrypoint` | no | 9.4 |Command or script that should be executed as the container's entrypoint. It will be translated to Docker's `--entrypoint` option while creating the container. The syntax is similar to [`Dockerfile`'s `ENTRYPOINT`][entrypoint] directive, where each shell token is a separate string in the array. | +| `command` | no | 9.4 |Command or script that should be used as the container's command. It will be translated to arguments passed to Docker after the image's name. The syntax is similar to [`Dockerfile`'s `CMD`][cmd] directive, where each shell token is a separate string in the array. | +| `alias` | no | 9.4 |Additional alias that can be used to access the service from the job's container. Read [Accessing the services](#accessing-the-services) for more information. | ### Starting multiple services from the same image +> Introduced in GitLab and GitLab Runner 9.4. Read more about the [extended +configuration options](#extended-docker-configuration-options). + Before the new extended Docker configuration options, the following configuration would not work properly: @@ -274,6 +274,9 @@ in `.gitlab-ci.yml` file. ### Setting a command for the service +> Introduced in GitLab and GitLab Runner 9.4. Read more about the [extended +configuration options](#extended-docker-configuration-options). + Let's assume you have a `super/sql:latest` image with some SQL database inside it and you would like to use it as a service for your job. Let's also assume that this image doesn't start the database process while starting @@ -313,6 +316,9 @@ As you can see, the syntax of `command` is similar to [Dockerfile's `CMD`][cmd]. ### Overriding the entrypoint of an image +> Introduced in GitLab and GitLab Runner 9.4. Read more about the [extended +configuration options](#extended-docker-configuration-options). + Let's assume you have a `super/sql:experimental` image with some SQL database inside it and you would like to use it as a base image for your job because you want to execute some tests with this database binary. Let's also assume that diff --git a/doc/gitlab-basics/create-project.md b/doc/gitlab-basics/create-project.md index 2513f4b420a..b4b77a2f94b 100644 --- a/doc/gitlab-basics/create-project.md +++ b/doc/gitlab-basics/create-project.md @@ -1,5 +1,9 @@ # How to create a project in GitLab +>**Notes:** +- For a list of words that are not allowed to be used as project names see the + [reserved names][reserved]. + 1. In your dashboard, click the green **New project** button or use the plus icon in the upper right corner of the navigation bar. @@ -25,4 +29,12 @@ 1. Click **Create project**. +## From a template + +To kickstart your development GitLab projects can be started from a template. +For example, one of the templates included is Ruby on Rails. When filling out the +form for new projects, click the 'Ruby on Rails' button. During project creation, +this will import a Ruby on Rails template with GitLab CI preconfigured. + [import it]: ../workflow/importing/README.md +[reserved]: ../user/reserved_names.md diff --git a/doc/topics/git/index.md b/doc/topics/git/index.md index 604f9375714..df56f031970 100644 --- a/doc/topics/git/index.md +++ b/doc/topics/git/index.md @@ -22,6 +22,7 @@ We've gathered some resources to help you to get the best from Git with GitLab. - [Cherry-picking a commit](../../user/project/merge_requests/cherry_pick_changes.md#cherry-picking-a-commit) - [Squashing commits](../../workflow/gitlab_flow.md#squashing-commits-with-rebase) - **Articles:** + - [Numerous _undo_ possibilities in Git](../../articles/numerous_undo_possibilities_in_git/index.md) - [How to install Git](../../articles/how_to_install_git/index.md) - [Git Tips & Tricks](https://about.gitlab.com/2016/12/08/git-tips-and-tricks/) - [Eight Tips to help you work better with Git](https://about.gitlab.com/2015/02/19/8-tips-to-help-you-work-better-with-git/) diff --git a/doc/user/group/index.md b/doc/user/group/index.md index ceec8b74373..9e168e830e5 100644 --- a/doc/user/group/index.md +++ b/doc/user/group/index.md @@ -57,6 +57,10 @@ By doing so: ## Create a new group +> **Notes:** +- For a list of words that are not allowed to be used as group names see the + [reserved names][reserved]. + You can create a group in GitLab from: 1. The Groups page: expand the left menu, click **Groups**, and click the green button **New group**: @@ -213,4 +217,5 @@ for the group (GitLab admins only, available in [GitLab Enterprise Edition Start - **Pipelines quota**: keep track of the [pipeline quota](../admin_area/settings/continuous_integration.md) for the group [permissions]: ../permissions.md#permissions -[ee]: https://about.gitlab.com/products/
\ No newline at end of file +[ee]: https://about.gitlab.com/products/ +[reserved]: ../reserved_names.md diff --git a/doc/user/group/subgroups/index.md b/doc/user/group/subgroups/index.md index 5724dcfab48..d2478aea4bd 100644 --- a/doc/user/group/subgroups/index.md +++ b/doc/user/group/subgroups/index.md @@ -83,10 +83,7 @@ structure. - You need to be an Owner of a group in order to be able to create a subgroup. For more information check the [permissions table][permissions]. - For a list of words that are not allowed to be used as group names see the - [`path_regex.rb` file][reserved] under the `TOP_LEVEL_ROUTES`, `PROJECT_WILDCARD_ROUTES` and `GROUP_ROUTES` lists: - - `TOP_LEVEL_ROUTES`: are names that are reserved as usernames or top level groups - - `PROJECT_WILDCARD_ROUTES`: are names that are reserved for child groups or projects. - - `GROUP_ROUTES`: are names that are reserved for all groups or projects. + [reserved names][reserved]. To create a subgroup: @@ -175,5 +172,5 @@ Here's a list of what you can't do with subgroups: [ce-2772]: https://gitlab.com/gitlab-org/gitlab-ce/issues/2772 [permissions]: ../../permissions.md#group -[reserved]: https://gitlab.com/gitlab-org/gitlab-ce/blob/master/lib/gitlab/path_regex.rb +[reserved]: ../../reserved_names.md [issue]: https://gitlab.com/gitlab-org/gitlab-ce/issues/30472#note_27747600 diff --git a/doc/user/project/import/bitbucket.md b/doc/user/project/import/bitbucket.md new file mode 100644 index 00000000000..b22c7db0047 --- /dev/null +++ b/doc/user/project/import/bitbucket.md @@ -0,0 +1,62 @@ +# Import your project from Bitbucket to GitLab + +Import your projects from Bitbucket to GitLab with minimal effort. + +## Overview + +>**Note:** +The [Bitbucket integration][bb-import] must be first enabled in order to be +able to import your projects from Bitbucket. Ask your GitLab administrator +to enable this if not already. + +- At its current state, the Bitbucket importer can import: + - the repository description (GitLab 7.7+) + - the Git repository data (GitLab 7.7+) + - the issues (GitLab 7.7+) + - the issue comments (GitLab 8.15+) + - the pull requests (GitLab 8.4+) + - the pull request comments (GitLab 8.15+) + - the milestones (GitLab 8.15+) + - the wiki (GitLab 8.15+) +- References to pull requests and issues are preserved (GitLab 8.7+) +- Repository public access is retained. If a repository is private in Bitbucket + it will be created as private in GitLab as well. + + +## How it works + +When issues/pull requests are being imported, the Bitbucket importer tries to find +the Bitbucket author/assignee in GitLab's database using the Bitbucket ID. For this +to work, the Bitbucket author/assignee should have signed in beforehand in GitLab +and **associated their Bitbucket account**. If the user is not +found in GitLab's database, the project creator (most of the times the current +user that started the import process) is set as the author, but a reference on +the issue about the original Bitbucket author is kept. + +The importer will create any new namespaces (groups) if they don't exist or in +the case the namespace is taken, the repository will be imported under the user's +namespace that started the import process. + +## Importing your Bitbucket repositories + +1. Sign in to GitLab and go to your dashboard. +1. Click on **New project**. + +  + +1. Click on the "Bitbucket" button + +  + +1. Grant GitLab access to your Bitbucket account + +  + +1. Click on the projects that you'd like to import or **Import all projects**. + You can also select the namespace under which each project will be + imported. + +  + +[bb-import]: ../../../integration/bitbucket.md +[social sign-in]: ../../profile/account/social_sign_in.md diff --git a/doc/user/project/import/fogbugz.md b/doc/user/project/import/fogbugz.md new file mode 100644 index 00000000000..17222c53675 --- /dev/null +++ b/doc/user/project/import/fogbugz.md @@ -0,0 +1,28 @@ +# Import your project from FogBugz to GitLab + +It only takes a few simple steps to import your project from FogBugz. +The importer will import all of your cases and comments with original case +numbers and timestamps. You will also have the opportunity to map FogBugz +users to GitLab users. + +1. From your GitLab dashboard click 'New project' +1. Click on the 'FogBugz' button + +  + +1. Enter your FogBugz URL, email address, and password. + +  + +1. Create mapping from FogBugz users to GitLab users. + +  + +1. Select the projects you wish to import by clicking the Import buttons + +  + +1. Once the import has finished click the link to take you to the project +dashboard. Follow the directions to push your existing repository. + +  diff --git a/doc/user/project/import/gitea.md b/doc/user/project/import/gitea.md new file mode 100644 index 00000000000..f5746a0fb31 --- /dev/null +++ b/doc/user/project/import/gitea.md @@ -0,0 +1,77 @@ +# Import your project from Gitea to GitLab + +Import your projects from Gitea to GitLab with minimal effort. + +## Overview + +>**Note:** +This requires Gitea `v1.0.0` or newer. + +- At its current state, Gitea importer can import: + - the repository description (GitLab 8.15+) + - the Git repository data (GitLab 8.15+) + - the issues (GitLab 8.15+) + - the pull requests (GitLab 8.15+) + - the milestones (GitLab 8.15+) + - the labels (GitLab 8.15+) +- Repository public access is retained. If a repository is private in Gitea + it will be created as private in GitLab as well. + +## How it works + +Since Gitea is currently not an OAuth provider, author/assignee cannot be mapped +to users in your GitLab's instance. This means that the project creator (most of +the times the current user that started the import process) is set as the author, +but a reference on the issue about the original Gitea author is kept. + +The importer will create any new namespaces (groups) if they don't exist or in +the case the namespace is taken, the repository will be imported under the user's +namespace that started the import process. + +## Importing your Gitea repositories + +The importer page is visible when you create a new project. + + + +Click on the **Gitea** link and the import authorization process will start. + + + +### Authorize access to your repositories using a personal access token + +With this method, you will perform a one-off authorization with Gitea to grant +GitLab access your repositories: + +1. Go to <https://you-gitea-instance/user/settings/applications> (replace + `you-gitea-instance` with the host of your Gitea instance). +1. Click **Generate New Token**. +1. Enter a token description. +1. Click **Generate Token**. +1. Copy the token hash. +1. Go back to GitLab and provide the token to the Gitea importer. +1. Hit the **List Your Gitea Repositories** button and wait while GitLab reads + your repositories' information. Once done, you'll be taken to the importer + page to select the repositories to import. + +### Select which repositories to import + +After you've authorized access to your Gitea repositories, you will be +redirected to the Gitea importer page. + +From there, you can see the import statuses of your Gitea repositories. + +- Those that are being imported will show a _started_ status, +- those already successfully imported will be green with a _done_ status, +- whereas those that are not yet imported will have an **Import** button on the + right side of the table. + +If you want, you can import all your Gitea projects in one go by hitting +**Import all projects** in the upper left corner. + + + +--- + +You can also choose a different name for the project and a different namespace, +if you have the privileges to do so. diff --git a/doc/user/project/import/github.md b/doc/user/project/import/github.md new file mode 100644 index 00000000000..016f98966e3 --- /dev/null +++ b/doc/user/project/import/github.md @@ -0,0 +1,122 @@ +# Import your project from GitHub to GitLab + +Import your projects from GitHub to GitLab with minimal effort. + +## Overview + +>**Note:** +If you are an administrator you can enable the [GitHub integration][gh-import] +in your GitLab instance sitewide. This configuration is optional, users will +still be able to import their GitHub repositories with a +[personal access token][gh-token]. + +>**Note:** +Administrators of a GitLab instance (Community or Enterprise Edition) can also +use the [GitHub rake task][gh-rake] to import projects from GitHub without the +constrains of a Sidekiq worker. + +- At its current state, GitHub importer can import: + - the repository description (GitLab 7.7+) + - the Git repository data (GitLab 7.7+) + - the issues (GitLab 7.7+) + - the pull requests (GitLab 8.4+) + - the wiki pages (GitLab 8.4+) + - the milestones (GitLab 8.7+) + - the labels (GitLab 8.7+) + - the release note descriptions (GitLab 8.12+) +- References to pull requests and issues are preserved (GitLab 8.7+) +- Repository public access is retained. If a repository is private in GitHub + it will be created as private in GitLab as well. + +## How it works + +When issues/pull requests are being imported, the GitHub importer tries to find +the GitHub author/assignee in GitLab's database using the GitHub ID. For this +to work, the GitHub author/assignee should have signed in beforehand in GitLab +and **associated their GitHub account**. If the user is not +found in GitLab's database, the project creator (most of the times the current +user that started the import process) is set as the author, but a reference on +the issue about the original GitHub author is kept. + +The importer will create any new namespaces (groups) if they don't exist or in +the case the namespace is taken, the repository will be imported under the user's +namespace that started the import process. + +## Importing your GitHub repositories + +The importer page is visible when you create a new project. + + + +Click on the **GitHub** link and the import authorization process will start. +There are two ways to authorize access to your GitHub repositories: + +1. [Using the GitHub integration][gh-integration] (if it's enabled by your + GitLab administrator). This is the preferred way as it's possible to + preserve the GitHub authors/assignees. Read more in the [How it works](#how-it-works) + section. +1. [Using a personal access token][gh-token] provided by GitHub. + + + +### Authorize access to your repositories using the GitHub integration + +If the [GitHub integration][gh-import] is enabled by your GitLab administrator, +you can use it instead of the personal access token. + +1. First you may want to connect your GitHub account to GitLab in order for + the username mapping to be correct. +1. Once you connect GitHub, click the **List your GitHub repositories** button + and you will be redirected to GitHub for permission to access your projects. +1. After accepting, you'll be automatically redirected to the importer. + +You can now go on and [select which repositories to import](#select-which-repositories-to-import). + +### Authorize access to your repositories using a personal access token + +>**Note:** +For a proper author/assignee mapping for issues and pull requests, the +[GitHub integration][gh-integration] should be used instead of the +[personal access token][gh-token]. If the GitHub integration is enabled by your +GitLab administrator, it should be the preferred method to import your repositories. +Read more in the [How it works](#how-it-works) section. + +If you are not using the GitHub integration, you can still perform a one-off +authorization with GitHub to grant GitLab access your repositories: + +1. Go to <https://github.com/settings/tokens/new>. +1. Enter a token description. +1. Check the `repo` scope. +1. Click **Generate token**. +1. Copy the token hash. +1. Go back to GitLab and provide the token to the GitHub importer. +1. Hit the **List Your GitHub Repositories** button and wait while GitLab reads + your repositories' information. Once done, you'll be taken to the importer + page to select the repositories to import. + +### Select which repositories to import + +After you've authorized access to your GitHub repositories, you will be +redirected to the GitHub importer page. + +From there, you can see the import statuses of your GitHub repositories. + +- Those that are being imported will show a _started_ status, +- those already successfully imported will be green with a _done_ status, +- whereas those that are not yet imported will have an **Import** button on the + right side of the table. + +If you want, you can import all your GitHub projects in one go by hitting +**Import all projects** in the upper left corner. + + + +--- + +You can also choose a different name for the project and a different namespace, +if you have the privileges to do so. + +[gh-import]: ../../../integration/github.md "GitHub integration" +[gh-rake]: ../../../administration/raketasks/github_import.md "GitHub rake task" +[gh-integration]: #authorize-access-to-your-repositories-using-the-github-integration +[gh-token]: #authorize-access-to-your-repositories-using-a-personal-access-token diff --git a/doc/user/project/import/gitlab_com.md b/doc/user/project/import/gitlab_com.md new file mode 100644 index 00000000000..3b37da67a5b --- /dev/null +++ b/doc/user/project/import/gitlab_com.md @@ -0,0 +1,20 @@ +# Project importing from GitLab.com to your private GitLab instance + +You can import your existing GitLab.com projects to your GitLab instance. But keep in mind that it is possible only if +GitLab support is enabled on your GitLab instance. +You can read more about GitLab support [here](http://docs.gitlab.com/ce/integration/gitlab.html) +To get to the importer page you need to go to "New project" page. + +>**Note:** +If you are interested in importing Wiki and Merge Request data to your new +instance, you'll need to follow the instructions for [project export](../settings/import_export.md) + + + +Click on the "Import projects from GitLab.com" link and you will be redirected to GitLab.com +for permission to access your projects. After accepting, you'll be automatically redirected to the importer. + + + +To import a project, you can simple click "Import". The importer will import your repository and issues. +Once the importer is done, a new GitLab project will be created with your imported data. diff --git a/doc/workflow/importing/img/bitbucket_import_grant_access.png b/doc/user/project/import/img/bitbucket_import_grant_access.png Binary files differindex 429904e621d..429904e621d 100644 --- a/doc/workflow/importing/img/bitbucket_import_grant_access.png +++ b/doc/user/project/import/img/bitbucket_import_grant_access.png diff --git a/doc/workflow/importing/img/bitbucket_import_new_project.png b/doc/user/project/import/img/bitbucket_import_new_project.png Binary files differindex 8ed528c2f09..8ed528c2f09 100644 --- a/doc/workflow/importing/img/bitbucket_import_new_project.png +++ b/doc/user/project/import/img/bitbucket_import_new_project.png diff --git a/doc/workflow/importing/img/bitbucket_import_select_project.png b/doc/user/project/import/img/bitbucket_import_select_project.png Binary files differindex 1bca6166ec8..1bca6166ec8 100644 --- a/doc/workflow/importing/img/bitbucket_import_select_project.png +++ b/doc/user/project/import/img/bitbucket_import_select_project.png diff --git a/doc/workflow/importing/fogbugz_importer/fogbugz_import_finished.png b/doc/user/project/import/img/fogbugz_import_finished.png Binary files differindex 62c5c86c9b3..62c5c86c9b3 100644 --- a/doc/workflow/importing/fogbugz_importer/fogbugz_import_finished.png +++ b/doc/user/project/import/img/fogbugz_import_finished.png diff --git a/doc/workflow/importing/fogbugz_importer/fogbugz_import_login.png b/doc/user/project/import/img/fogbugz_import_login.png Binary files differindex 96bce70b74d..96bce70b74d 100644 --- a/doc/workflow/importing/fogbugz_importer/fogbugz_import_login.png +++ b/doc/user/project/import/img/fogbugz_import_login.png diff --git a/doc/workflow/importing/fogbugz_importer/fogbugz_import_select_fogbogz.png b/doc/user/project/import/img/fogbugz_import_select_fogbogz.png Binary files differindex b26c652e382..b26c652e382 100644 --- a/doc/workflow/importing/fogbugz_importer/fogbugz_import_select_fogbogz.png +++ b/doc/user/project/import/img/fogbugz_import_select_fogbogz.png diff --git a/doc/workflow/importing/fogbugz_importer/fogbugz_import_select_project.png b/doc/user/project/import/img/fogbugz_import_select_project.png Binary files differindex ccc82f9d4cd..ccc82f9d4cd 100644 --- a/doc/workflow/importing/fogbugz_importer/fogbugz_import_select_project.png +++ b/doc/user/project/import/img/fogbugz_import_select_project.png diff --git a/doc/workflow/importing/fogbugz_importer/fogbugz_import_user_map.png b/doc/user/project/import/img/fogbugz_import_user_map.png Binary files differindex 28ff55a8d89..28ff55a8d89 100644 --- a/doc/workflow/importing/fogbugz_importer/fogbugz_import_user_map.png +++ b/doc/user/project/import/img/fogbugz_import_user_map.png diff --git a/doc/workflow/importing/gitlab_importer/importer.png b/doc/user/project/import/img/gitlab_importer.png Binary files differindex 27d42eb492e..27d42eb492e 100644 --- a/doc/workflow/importing/gitlab_importer/importer.png +++ b/doc/user/project/import/img/gitlab_importer.png diff --git a/doc/workflow/importing/gitlab_importer/new_project_page.png b/doc/user/project/import/img/gitlab_new_project_page.png Binary files differindex c673724f436..c673724f436 100644 --- a/doc/workflow/importing/gitlab_importer/new_project_page.png +++ b/doc/user/project/import/img/gitlab_new_project_page.png diff --git a/doc/workflow/importing/img/import_projects_from_gitea_new_import.png b/doc/user/project/import/img/import_projects_from_gitea_new_import.png Binary files differindex a3f603cbd0a..a3f603cbd0a 100644 --- a/doc/workflow/importing/img/import_projects_from_gitea_new_import.png +++ b/doc/user/project/import/img/import_projects_from_gitea_new_import.png diff --git a/doc/workflow/importing/img/import_projects_from_github_importer.png b/doc/user/project/import/img/import_projects_from_github_importer.png Binary files differindex d8effaf6075..d8effaf6075 100644 --- a/doc/workflow/importing/img/import_projects_from_github_importer.png +++ b/doc/user/project/import/img/import_projects_from_github_importer.png diff --git a/doc/workflow/importing/img/import_projects_from_github_select_auth_method.png b/doc/user/project/import/img/import_projects_from_github_select_auth_method.png Binary files differindex 1ccb38a815e..1ccb38a815e 100644 --- a/doc/workflow/importing/img/import_projects_from_github_select_auth_method.png +++ b/doc/user/project/import/img/import_projects_from_github_select_auth_method.png diff --git a/doc/workflow/importing/img/import_projects_from_new_project_page.png b/doc/user/project/import/img/import_projects_from_new_project_page.png Binary files differindex 97ca30b2087..97ca30b2087 100644 --- a/doc/workflow/importing/img/import_projects_from_new_project_page.png +++ b/doc/user/project/import/img/import_projects_from_new_project_page.png diff --git a/doc/user/project/import/index.md b/doc/user/project/import/index.md new file mode 100644 index 00000000000..06e8c81ef06 --- /dev/null +++ b/doc/user/project/import/index.md @@ -0,0 +1,20 @@ +# Migrating projects to a GitLab instance + +1. [From Bitbucket.org](bitbucket.md) +1. [From GitHub.com of GitHub Enterprise](github.md) +1. [From GitLab.com](gitlab_com.md) +1. [From FogBugz](fogbugz.md) +1. [From Gitea](gitea.md) +1. [From SVN](svn.md) + +In addition to the specific migration documentation above, you can import any +Git repository via HTTP from the New Project page. Be aware that if the +repository is too large the import can timeout. + +## Migrating from self-hosted GitLab to GitLab.com + +You can copy your repos by changing the remote and pushing to the new server, +but issues and merge requests can't be imported. + +If you want to retain all metadata like issues and merge requests, you can use +the [import/export feature](../settings/import_export.md). diff --git a/doc/user/project/import/svn.md b/doc/user/project/import/svn.md new file mode 100644 index 00000000000..7a3628a39d7 --- /dev/null +++ b/doc/user/project/import/svn.md @@ -0,0 +1,183 @@ +# Migrating from SVN to GitLab + +Subversion (SVN) is a central version control system (VCS) while +Git is a distributed version control system. There are some major differences +between the two, for more information consult your favorite search engine. + +## Overview + +There are two approaches to SVN to Git migration: + +1. [Git/SVN Mirror](#smooth-migration-with-a-gitsvn-mirror-using-subgit) which: + - Makes the GitLab repository to mirror the SVN project. + - Git and SVN repositories are kept in sync; you can use either one. + - Smoothens the migration process and allows to manage migration risks. + +1. [Cut over migration](#cut-over-migration-with-svn2git) which: + - Translates and imports the existing data and history from SVN to Git. + - Is a fire and forget approach, good for smaller teams. + +## Smooth migration with a Git/SVN mirror using SubGit + +[SubGit](https://subgit.com) is a tool for a smooth, stress-free SVN to Git +migration. It creates a writable Git mirror of a local or remote Subversion +repository and that way you can use both Subversion and Git as long as you like. +It requires access to your GitLab server as it talks with the Git repositories +directly in a filesystem level. + +### SubGit prerequisites + +1. Install Oracle JRE 1.8 or newer. On Debian-based Linux distributions you can + follow [this article](http://www.webupd8.org/2012/09/install-oracle-java-8-in-ubuntu-via-ppa.html). +1. Download SubGit from https://subgit.com/download/. +1. Unpack the downloaded SubGit zip archive to the `/opt` directory. The `subgit` + command will be available at `/opt/subgit-VERSION/bin/subgit`. + +### SubGit configuration + +The first step to mirror you SVN repository in GitLab is to create a new empty +project which will be used as a mirror. For Omnibus installations the path to +the repository will be located at +`/var/opt/gitlab/git-data/repositories/USER/REPO.git` by default. For +installations from source, the default repository directory will be +`/home/git/repositories/USER/REPO.git`. For convenience, assign this path to a +variable: + +``` +GIT_REPO_PATH=/var/opt/gitlab/git-data/repositories/USER/REPOS.git +``` + +SubGit will keep this repository in sync with a remote SVN project. For +convenience, assign your remote SVN project URL to a variable: + +``` +SVN_PROJECT_URL=http://svn.company.com/repos/project +``` + +Next you need to run SubGit to set up a Git/SVN mirror. Make sure the following +`subgit` command is ran on behalf of the same user that keeps ownership of +GitLab Git repositories (by default `git`): + +``` +subgit configure --layout auto $SVN_PROJECT_URL $GIT_REPO_PATH +``` + +Adjust authors and branches mappings, if necessary. Open with your favorite +text editor: + +``` +edit $GIT_REPO_PATH/subgit/authors.txt +edit $GIT_REPO_PATH/subgit/config +``` + +For more information regarding the SubGit configuration options, refer to +[SubGit's documentation](https://subgit.com/documentation.html) website. + +### Initial translation + +Now that SubGit has configured the Git/SVN repos, run `subgit` to perform the +initial translation of existing SVN revisions into the Git repository: + +``` +subgit install $GIT_REPO_PATH +``` + +After the initial translation is completed, the Git repository and the SVN +project will be kept in sync by `subgit` - new Git commits will be translated to +SVN revisions and new SVN revisions will be translated to Git commits. Mirror +works transparently and does not require any special commands. + +If you would prefer to perform one-time cut over migration with `subgit`, use +the `import` command instead of `install`: + +``` +subgit import $GIT_REPO_PATH +``` + +### SubGit licensing + +Running SubGit in a mirror mode requires a +[registration](https://subgit.com/pricing.html). Registration is free for open +source, academic and startup projects. + +We're currently working on deeper GitLab/SubGit integration. You may track our +progress at [this issue](https://gitlab.com/gitlab-org/gitlab-ee/issues/990). + +### SubGit support + +For any questions related to SVN to GitLab migration with SubGit, you can +contact the SubGit team directly at [support@subgit.com](mailto:support@subgit.com). + +## Cut over migration with svn2git + +If you are currently using an SVN repository, you can migrate the repository +to Git and GitLab. We recommend a hard cut over - run the migration command once +and then have all developers start using the new GitLab repository immediately. +Otherwise, it's hard to keep changing in sync in both directions. The conversion +process should be run on a local workstation. + +Install `svn2git`. On all systems you can install as a Ruby gem if you already +have Ruby and Git installed. + +```bash +sudo gem install svn2git +``` + +On Debian-based Linux distributions you can install the native packages: + +```bash +sudo apt-get install git-core git-svn ruby +``` + +Optionally, prepare an authors file so `svn2git` can map SVN authors to Git authors. +If you choose not to create the authors file then commits will not be attributed +to the correct GitLab user. Some users may not consider this a big issue while +others will want to ensure they complete this step. If you choose to map authors +you will be required to map every author that is present on changes in the SVN +repository. If you don't, the conversion will fail and you will have to update +the author file accordingly. The following command will search through the +repository and output a list of authors. + +```bash +svn log --quiet | grep -E "r[0-9]+ \| .+ \|" | cut -d'|' -f2 | sed 's/ //g' | sort | uniq +``` + +Use the output from the last command to construct the authors file. +Create a file called `authors.txt` and add one mapping per line. + +``` +janedoe = Jane Doe <janedoe@example.com> +johndoe = John Doe <johndoe@example.com> +``` + +If your SVN repository is in the standard format (trunk, branches, tags, +not nested) the conversion is simple. For a non-standard repository see +[svn2git documentation](https://github.com/nirvdrum/svn2git). The following +command will checkout the repository and do the conversion in the current +working directory. Be sure to create a new directory for each repository before +running the `svn2git` command. The conversion process will take some time. + +```bash +svn2git https://svn.example.com/path/to/repo --authors /path/to/authors.txt +``` + +If your SVN repository requires a username and password add the +`--username <username>` and `--password <password` flags to the above command. +`svn2git` also supports excluding certain file paths, branches, tags, etc. See +[svn2git documentation](https://github.com/nirvdrum/svn2git) or run +`svn2git --help` for full documentation on all of the available options. + +Create a new GitLab project, where you will eventually push your converted code. +Copy the SSH or HTTP(S) repository URL from the project page. Add the GitLab +repository as a Git remote and push all the changes. This will push all commits, +branches and tags. + +```bash +git remote add origin git@gitlab.com:<group>/<project>.git +git push --all origin +git push --tags origin +``` + +## Contribute to this guide +We welcome all contributions that would expand this guide with instructions on +how to migrate from SVN and other version control systems. diff --git a/doc/user/project/index.md b/doc/user/project/index.md index 0dd0faf35e9..ba6ac2797b3 100644 --- a/doc/user/project/index.md +++ b/doc/user/project/index.md @@ -90,11 +90,11 @@ from your fork to the upstream project ## Import or export a project -- Import a project from: - - [GitHub to GitLab](../../workflow/importing/import_projects_from_github.md) - - [BitBucket to GitLab](../../workflow/importing/import_projects_from_bitbucket.md) - - [Gitea to GitLab](../../workflow/importing/import_projects_from_gitea.md) - - [FogBugz to GitLab](../../workflow/importing/import_projects_from_fogbugz.md) +- [Import a project](import/index.md) from: + - [GitHub to GitLab](import/github.md) + - [BitBucket to GitLab](import/bitbucket.md) + - [Gitea to GitLab](import/gitea.md) + - [FogBugz to GitLab](import/fogbugz.md) - [Export a project from GitLab](settings/import_export.md#exporting-a-project-and-its-data) - [Importing and exporting projects between GitLab instances](settings/import_export.md) diff --git a/doc/user/reserved_names.md b/doc/user/reserved_names.md new file mode 100644 index 00000000000..50ec99be48b --- /dev/null +++ b/doc/user/reserved_names.md @@ -0,0 +1,109 @@ +# Reserved project and group names + +Not all project & group names are allowed because they would conflict with +existing routes used by GitLab. + +For a list of words that are not allowed to be used as group or project names, see the +[`path_regex.rb` file][reserved] under the `TOP_LEVEL_ROUTES`, `PROJECT_WILDCARD_ROUTES` and `GROUP_ROUTES` lists: +- `TOP_LEVEL_ROUTES`: are names that are reserved as usernames or top level groups +- `PROJECT_WILDCARD_ROUTES`: are names that are reserved for child groups or projects. +- `GROUP_ROUTES`: are names that are reserved for all groups or projects. + +## Reserved project names + +It is currently not possible to create a project with the following names: + +- - +- badges +- blame +- blob +- builds +- commits +- create +- create_dir +- edit +- environments/folders +- files +- find_file +- gitlab-lfs/objects +- info/lfs/objects +- new +- preview +- raw +- refs +- tree +- update +- wikis + +## Reserved group names + +Currently the following names are reserved as top level groups: + +- 503.html +- - +- .well-known +- 404.html +- 422.html +- 500.html +- 502.html +- abuse_reports +- admin +- api +- apple-touch-icon-precomposed.png +- apple-touch-icon.png +- files +- assets +- autocomplete +- ci +- dashboard +- deploy.html +- explore +- favicon.ico +- groups +- header_logo_dark.png +- header_logo_light.png +- health_check +- help +- import +- invites +- jwt +- koding +- notification_settings +- oauth +- profile +- projects +- public +- robots.txt +- s +- search +- sent_notifications +- slash-command-logo.png +- snippets +- u +- unicorn_test +- unsubscribes +- uploads +- users + +These group names are unavailable as subgroup names: + +- - +- activity +- analytics +- audit_events +- avatar +- edit +- group_members +- hooks +- issues +- labels +- ldap +- ldap_group_links +- merge_requests +- milestones +- notification_setting +- pipeline_quota +- projects +- subgroups + +[reserved]: https://gitlab.com/gitlab-org/gitlab-ce/blob/master/lib/gitlab/path_regex.rb diff --git a/doc/workflow/importing/README.md b/doc/workflow/importing/README.md index 2d91bee0e94..f753708ad89 100644 --- a/doc/workflow/importing/README.md +++ b/doc/workflow/importing/README.md @@ -1,17 +1 @@ -# Migrating projects to a GitLab instance
-
-1. [Bitbucket](import_projects_from_bitbucket.md)
-1. [GitHub](import_projects_from_github.md)
-1. [GitLab.com](import_projects_from_gitlab_com.md)
-1. [FogBugz](import_projects_from_fogbugz.md)
-1. [Gitea](import_projects_from_gitea.md)
-1. [SVN](migrating_from_svn.md)
-
-In addition to the specific migration documentation above, you can import any
-Git repository via HTTP from the New Project page. Be aware that if the
-repository is too large the import can timeout.
-
-### Migrating from self-hosted GitLab to GitLab.com
-
-You can copy your repos by changing the remote and pushing to the new server;
-but issues and merge requests can't be imported.
+This document was moved to a [new location](../../user/project/import/index.md).
diff --git a/doc/workflow/importing/import_projects_from_bitbucket.md b/doc/workflow/importing/import_projects_from_bitbucket.md index f3c636ed1d5..248c3990372 100644 --- a/doc/workflow/importing/import_projects_from_bitbucket.md +++ b/doc/workflow/importing/import_projects_from_bitbucket.md @@ -1,62 +1 @@ -# Import your project from Bitbucket to GitLab
-
-Import your projects from Bitbucket to GitLab with minimal effort.
-
-## Overview
-
->**Note:**
-The [Bitbucket integration][bb-import] must be first enabled in order to be
-able to import your projects from Bitbucket. Ask your GitLab administrator
-to enable this if not already.
-
-- At its current state, the Bitbucket importer can import:
- - the repository description (GitLab 7.7+)
- - the Git repository data (GitLab 7.7+)
- - the issues (GitLab 7.7+)
- - the issue comments (GitLab 8.15+)
- - the pull requests (GitLab 8.4+)
- - the pull request comments (GitLab 8.15+)
- - the milestones (GitLab 8.15+)
- - the wiki (GitLab 8.15+)
-- References to pull requests and issues are preserved (GitLab 8.7+)
-- Repository public access is retained. If a repository is private in Bitbucket
- it will be created as private in GitLab as well.
-
-
-## How it works
-
-When issues/pull requests are being imported, the Bitbucket importer tries to find
-the Bitbucket author/assignee in GitLab's database using the Bitbucket ID. For this
-to work, the Bitbucket author/assignee should have signed in beforehand in GitLab
-and **associated their Bitbucket account**. If the user is not
-found in GitLab's database, the project creator (most of the times the current
-user that started the import process) is set as the author, but a reference on
-the issue about the original Bitbucket author is kept.
-
-The importer will create any new namespaces (groups) if they don't exist or in
-the case the namespace is taken, the repository will be imported under the user's
-namespace that started the import process.
-
-## Importing your Bitbucket repositories
-
-1. Sign in to GitLab and go to your dashboard.
-1. Click on **New project**.
-
- 
-
-1. Click on the "Bitbucket" button
-
- 
-
-1. Grant GitLab access to your Bitbucket account
-
- 
-
-1. Click on the projects that you'd like to import or **Import all projects**.
- You can also select the namespace under which each project will be
- imported.
-
- 
-
-[bb-import]: ../../integration/bitbucket.md
-[social sign-in]: ../../user/profile/account/social_sign_in.md
+This document was moved to a [new location](../../user/project/import/bitbucket.md).
diff --git a/doc/workflow/importing/import_projects_from_fogbugz.md b/doc/workflow/importing/import_projects_from_fogbugz.md index 71af0f9ea44..050746e2b4d 100644 --- a/doc/workflow/importing/import_projects_from_fogbugz.md +++ b/doc/workflow/importing/import_projects_from_fogbugz.md @@ -1,29 +1 @@ -# Import your project from FogBugz to GitLab - -It only takes a few simple steps to import your project from FogBugz. -The importer will import all of your cases and comments with original case -numbers and timestamps. You will also have the opportunity to map FogBugz -users to GitLab users. - -* From your GitLab dashboard click 'New project' - -* Click on the 'FogBugz' button - - - -* Enter your FogBugz URL, email address, and password. - - - -* Create mapping from FogBugz users to GitLab users. - - - -* Select the projects you wish to import by clicking the Import buttons - - - -* Once the import has finished click the link to take you to the project -dashboard. Follow the directions to push your existing repository. - - +This document was moved to a [new location](../../user/project/import/fogbugz.md). diff --git a/doc/workflow/importing/import_projects_from_gitea.md b/doc/workflow/importing/import_projects_from_gitea.md index f5746a0fb31..cb90c490b0f 100644 --- a/doc/workflow/importing/import_projects_from_gitea.md +++ b/doc/workflow/importing/import_projects_from_gitea.md @@ -1,77 +1 @@ -# Import your project from Gitea to GitLab - -Import your projects from Gitea to GitLab with minimal effort. - -## Overview - ->**Note:** -This requires Gitea `v1.0.0` or newer. - -- At its current state, Gitea importer can import: - - the repository description (GitLab 8.15+) - - the Git repository data (GitLab 8.15+) - - the issues (GitLab 8.15+) - - the pull requests (GitLab 8.15+) - - the milestones (GitLab 8.15+) - - the labels (GitLab 8.15+) -- Repository public access is retained. If a repository is private in Gitea - it will be created as private in GitLab as well. - -## How it works - -Since Gitea is currently not an OAuth provider, author/assignee cannot be mapped -to users in your GitLab's instance. This means that the project creator (most of -the times the current user that started the import process) is set as the author, -but a reference on the issue about the original Gitea author is kept. - -The importer will create any new namespaces (groups) if they don't exist or in -the case the namespace is taken, the repository will be imported under the user's -namespace that started the import process. - -## Importing your Gitea repositories - -The importer page is visible when you create a new project. - - - -Click on the **Gitea** link and the import authorization process will start. - - - -### Authorize access to your repositories using a personal access token - -With this method, you will perform a one-off authorization with Gitea to grant -GitLab access your repositories: - -1. Go to <https://you-gitea-instance/user/settings/applications> (replace - `you-gitea-instance` with the host of your Gitea instance). -1. Click **Generate New Token**. -1. Enter a token description. -1. Click **Generate Token**. -1. Copy the token hash. -1. Go back to GitLab and provide the token to the Gitea importer. -1. Hit the **List Your Gitea Repositories** button and wait while GitLab reads - your repositories' information. Once done, you'll be taken to the importer - page to select the repositories to import. - -### Select which repositories to import - -After you've authorized access to your Gitea repositories, you will be -redirected to the Gitea importer page. - -From there, you can see the import statuses of your Gitea repositories. - -- Those that are being imported will show a _started_ status, -- those already successfully imported will be green with a _done_ status, -- whereas those that are not yet imported will have an **Import** button on the - right side of the table. - -If you want, you can import all your Gitea projects in one go by hitting -**Import all projects** in the upper left corner. - - - ---- - -You can also choose a different name for the project and a different namespace, -if you have the privileges to do so. +This document was moved to a [new location](../../user/project/import/gitea.md). diff --git a/doc/workflow/importing/import_projects_from_github.md b/doc/workflow/importing/import_projects_from_github.md index 8ed1d98d05b..13639feaa04 100644 --- a/doc/workflow/importing/import_projects_from_github.md +++ b/doc/workflow/importing/import_projects_from_github.md @@ -1,122 +1 @@ -# Import your project from GitHub to GitLab
-
-Import your projects from GitHub to GitLab with minimal effort.
-
-## Overview
-
->**Note:**
-If you are an administrator you can enable the [GitHub integration][gh-import]
-in your GitLab instance sitewide. This configuration is optional, users will
-still be able to import their GitHub repositories with a
-[personal access token][gh-token].
-
->**Note:**
-Administrators of a GitLab instance (Community or Enterprise Edition) can also
-use the [GitHub rake task][gh-rake] to import projects from GitHub without the
-constrains of a Sidekiq worker.
-
-- At its current state, GitHub importer can import:
- - the repository description (GitLab 7.7+)
- - the Git repository data (GitLab 7.7+)
- - the issues (GitLab 7.7+)
- - the pull requests (GitLab 8.4+)
- - the wiki pages (GitLab 8.4+)
- - the milestones (GitLab 8.7+)
- - the labels (GitLab 8.7+)
- - the release note descriptions (GitLab 8.12+)
-- References to pull requests and issues are preserved (GitLab 8.7+)
-- Repository public access is retained. If a repository is private in GitHub
- it will be created as private in GitLab as well.
-
-## How it works
-
-When issues/pull requests are being imported, the GitHub importer tries to find
-the GitHub author/assignee in GitLab's database using the GitHub ID. For this
-to work, the GitHub author/assignee should have signed in beforehand in GitLab
-and **associated their GitHub account**. If the user is not
-found in GitLab's database, the project creator (most of the times the current
-user that started the import process) is set as the author, but a reference on
-the issue about the original GitHub author is kept.
-
-The importer will create any new namespaces (groups) if they don't exist or in
-the case the namespace is taken, the repository will be imported under the user's
-namespace that started the import process.
-
-## Importing your GitHub repositories
-
-The importer page is visible when you create a new project.
-
-
-
-Click on the **GitHub** link and the import authorization process will start.
-There are two ways to authorize access to your GitHub repositories:
-
-1. [Using the GitHub integration][gh-integration] (if it's enabled by your
- GitLab administrator). This is the preferred way as it's possible to
- preserve the GitHub authors/assignees. Read more in the [How it works](#how-it-works)
- section.
-1. [Using a personal access token][gh-token] provided by GitHub.
-
-
-
-### Authorize access to your repositories using the GitHub integration
-
-If the [GitHub integration][gh-import] is enabled by your GitLab administrator,
-you can use it instead of the personal access token.
-
-1. First you may want to connect your GitHub account to GitLab in order for
- the username mapping to be correct.
-1. Once you connect GitHub, click the **List your GitHub repositories** button
- and you will be redirected to GitHub for permission to access your projects.
-1. After accepting, you'll be automatically redirected to the importer.
-
-You can now go on and [select which repositories to import](#select-which-repositories-to-import).
-
-### Authorize access to your repositories using a personal access token
-
->**Note:**
-For a proper author/assignee mapping for issues and pull requests, the
-[GitHub integration][gh-integration] should be used instead of the
-[personal access token][gh-token]. If the GitHub integration is enabled by your
-GitLab administrator, it should be the preferred method to import your repositories.
-Read more in the [How it works](#how-it-works) section.
-
-If you are not using the GitHub integration, you can still perform a one-off
-authorization with GitHub to grant GitLab access your repositories:
-
-1. Go to <https://github.com/settings/tokens/new>.
-1. Enter a token description.
-1. Check the `repo` scope.
-1. Click **Generate token**.
-1. Copy the token hash.
-1. Go back to GitLab and provide the token to the GitHub importer.
-1. Hit the **List Your GitHub Repositories** button and wait while GitLab reads
- your repositories' information. Once done, you'll be taken to the importer
- page to select the repositories to import.
-
-### Select which repositories to import
-
-After you've authorized access to your GitHub repositories, you will be
-redirected to the GitHub importer page.
-
-From there, you can see the import statuses of your GitHub repositories.
-
-- Those that are being imported will show a _started_ status,
-- those already successfully imported will be green with a _done_ status,
-- whereas those that are not yet imported will have an **Import** button on the
- right side of the table.
-
-If you want, you can import all your GitHub projects in one go by hitting
-**Import all projects** in the upper left corner.
-
-
-
----
-
-You can also choose a different name for the project and a different namespace,
-if you have the privileges to do so.
-
-[gh-import]: ../../integration/github.md "GitHub integration"
-[gh-rake]: ../../administration/raketasks/github_import.md "GitHub rake task"
-[gh-integration]: #authorize-access-to-your-repositories-using-the-github-integration
-[gh-token]: #authorize-access-to-your-repositories-using-a-personal-access-token
+This document was moved to a [new location](../../user/project/import/github.md).
diff --git a/doc/workflow/importing/import_projects_from_gitlab_com.md b/doc/workflow/importing/import_projects_from_gitlab_com.md index b27125a44de..df4c180919a 100644 --- a/doc/workflow/importing/import_projects_from_gitlab_com.md +++ b/doc/workflow/importing/import_projects_from_gitlab_com.md @@ -1,21 +1 @@ -# Project importing from GitLab.com to your private GitLab instance - -You can import your existing GitLab.com projects to your GitLab instance. But keep in mind that it is possible only if -GitLab support is enabled on your GitLab instance. -You can read more about GitLab support [here](http://docs.gitlab.com/ce/integration/gitlab.html) -To get to the importer page you need to go to "New project" page. - ->**Note:** -If you are interested in importing Wiki and Merge Request data to your new instance, you'll need to follow the instructions for [project export](../../user/project/settings/import_export.md) - - - -Click on the "Import projects from GitLab.com" link and you will be redirected to GitLab.com -for permission to access your projects. After accepting, you'll be automatically redirected to the importer. - - - - - -To import a project, you can simple click "Import". The importer will import your repository and issues. -Once the importer is done, a new GitLab project will be created with your imported data.
\ No newline at end of file +This document was moved to a [new location](../../user/project/import/gitlab_com.md). diff --git a/doc/workflow/importing/migrating_from_svn.md b/doc/workflow/importing/migrating_from_svn.md index 7a3628a39d7..81df3fbcdbb 100644 --- a/doc/workflow/importing/migrating_from_svn.md +++ b/doc/workflow/importing/migrating_from_svn.md @@ -1,183 +1 @@ -# Migrating from SVN to GitLab - -Subversion (SVN) is a central version control system (VCS) while -Git is a distributed version control system. There are some major differences -between the two, for more information consult your favorite search engine. - -## Overview - -There are two approaches to SVN to Git migration: - -1. [Git/SVN Mirror](#smooth-migration-with-a-gitsvn-mirror-using-subgit) which: - - Makes the GitLab repository to mirror the SVN project. - - Git and SVN repositories are kept in sync; you can use either one. - - Smoothens the migration process and allows to manage migration risks. - -1. [Cut over migration](#cut-over-migration-with-svn2git) which: - - Translates and imports the existing data and history from SVN to Git. - - Is a fire and forget approach, good for smaller teams. - -## Smooth migration with a Git/SVN mirror using SubGit - -[SubGit](https://subgit.com) is a tool for a smooth, stress-free SVN to Git -migration. It creates a writable Git mirror of a local or remote Subversion -repository and that way you can use both Subversion and Git as long as you like. -It requires access to your GitLab server as it talks with the Git repositories -directly in a filesystem level. - -### SubGit prerequisites - -1. Install Oracle JRE 1.8 or newer. On Debian-based Linux distributions you can - follow [this article](http://www.webupd8.org/2012/09/install-oracle-java-8-in-ubuntu-via-ppa.html). -1. Download SubGit from https://subgit.com/download/. -1. Unpack the downloaded SubGit zip archive to the `/opt` directory. The `subgit` - command will be available at `/opt/subgit-VERSION/bin/subgit`. - -### SubGit configuration - -The first step to mirror you SVN repository in GitLab is to create a new empty -project which will be used as a mirror. For Omnibus installations the path to -the repository will be located at -`/var/opt/gitlab/git-data/repositories/USER/REPO.git` by default. For -installations from source, the default repository directory will be -`/home/git/repositories/USER/REPO.git`. For convenience, assign this path to a -variable: - -``` -GIT_REPO_PATH=/var/opt/gitlab/git-data/repositories/USER/REPOS.git -``` - -SubGit will keep this repository in sync with a remote SVN project. For -convenience, assign your remote SVN project URL to a variable: - -``` -SVN_PROJECT_URL=http://svn.company.com/repos/project -``` - -Next you need to run SubGit to set up a Git/SVN mirror. Make sure the following -`subgit` command is ran on behalf of the same user that keeps ownership of -GitLab Git repositories (by default `git`): - -``` -subgit configure --layout auto $SVN_PROJECT_URL $GIT_REPO_PATH -``` - -Adjust authors and branches mappings, if necessary. Open with your favorite -text editor: - -``` -edit $GIT_REPO_PATH/subgit/authors.txt -edit $GIT_REPO_PATH/subgit/config -``` - -For more information regarding the SubGit configuration options, refer to -[SubGit's documentation](https://subgit.com/documentation.html) website. - -### Initial translation - -Now that SubGit has configured the Git/SVN repos, run `subgit` to perform the -initial translation of existing SVN revisions into the Git repository: - -``` -subgit install $GIT_REPO_PATH -``` - -After the initial translation is completed, the Git repository and the SVN -project will be kept in sync by `subgit` - new Git commits will be translated to -SVN revisions and new SVN revisions will be translated to Git commits. Mirror -works transparently and does not require any special commands. - -If you would prefer to perform one-time cut over migration with `subgit`, use -the `import` command instead of `install`: - -``` -subgit import $GIT_REPO_PATH -``` - -### SubGit licensing - -Running SubGit in a mirror mode requires a -[registration](https://subgit.com/pricing.html). Registration is free for open -source, academic and startup projects. - -We're currently working on deeper GitLab/SubGit integration. You may track our -progress at [this issue](https://gitlab.com/gitlab-org/gitlab-ee/issues/990). - -### SubGit support - -For any questions related to SVN to GitLab migration with SubGit, you can -contact the SubGit team directly at [support@subgit.com](mailto:support@subgit.com). - -## Cut over migration with svn2git - -If you are currently using an SVN repository, you can migrate the repository -to Git and GitLab. We recommend a hard cut over - run the migration command once -and then have all developers start using the new GitLab repository immediately. -Otherwise, it's hard to keep changing in sync in both directions. The conversion -process should be run on a local workstation. - -Install `svn2git`. On all systems you can install as a Ruby gem if you already -have Ruby and Git installed. - -```bash -sudo gem install svn2git -``` - -On Debian-based Linux distributions you can install the native packages: - -```bash -sudo apt-get install git-core git-svn ruby -``` - -Optionally, prepare an authors file so `svn2git` can map SVN authors to Git authors. -If you choose not to create the authors file then commits will not be attributed -to the correct GitLab user. Some users may not consider this a big issue while -others will want to ensure they complete this step. If you choose to map authors -you will be required to map every author that is present on changes in the SVN -repository. If you don't, the conversion will fail and you will have to update -the author file accordingly. The following command will search through the -repository and output a list of authors. - -```bash -svn log --quiet | grep -E "r[0-9]+ \| .+ \|" | cut -d'|' -f2 | sed 's/ //g' | sort | uniq -``` - -Use the output from the last command to construct the authors file. -Create a file called `authors.txt` and add one mapping per line. - -``` -janedoe = Jane Doe <janedoe@example.com> -johndoe = John Doe <johndoe@example.com> -``` - -If your SVN repository is in the standard format (trunk, branches, tags, -not nested) the conversion is simple. For a non-standard repository see -[svn2git documentation](https://github.com/nirvdrum/svn2git). The following -command will checkout the repository and do the conversion in the current -working directory. Be sure to create a new directory for each repository before -running the `svn2git` command. The conversion process will take some time. - -```bash -svn2git https://svn.example.com/path/to/repo --authors /path/to/authors.txt -``` - -If your SVN repository requires a username and password add the -`--username <username>` and `--password <password` flags to the above command. -`svn2git` also supports excluding certain file paths, branches, tags, etc. See -[svn2git documentation](https://github.com/nirvdrum/svn2git) or run -`svn2git --help` for full documentation on all of the available options. - -Create a new GitLab project, where you will eventually push your converted code. -Copy the SSH or HTTP(S) repository URL from the project page. Add the GitLab -repository as a Git remote and push all the changes. This will push all commits, -branches and tags. - -```bash -git remote add origin git@gitlab.com:<group>/<project>.git -git push --all origin -git push --tags origin -``` - -## Contribute to this guide -We welcome all contributions that would expand this guide with instructions on -how to migrate from SVN and other version control systems. +This document was moved to a [new location](../../user/project/import/svn.md). diff --git a/lib/after_commit_queue.rb b/lib/after_commit_queue.rb new file mode 100644 index 00000000000..b67575a3ac2 --- /dev/null +++ b/lib/after_commit_queue.rb @@ -0,0 +1,30 @@ +module AfterCommitQueue + extend ActiveSupport::Concern + + included do + after_commit :_run_after_commit_queue + after_rollback :_clear_after_commit_queue + end + + def run_after_commit(method = nil, &block) + _after_commit_queue << proc { self.send(method) } if method + _after_commit_queue << block if block + true + end + + protected + + def _run_after_commit_queue + while action = _after_commit_queue.pop + self.instance_eval(&action) + end + end + + def _after_commit_queue + @after_commit_queue ||= [] + end + + def _clear_after_commit_queue + _after_commit_queue.clear + end +end diff --git a/lib/api/helpers.rb b/lib/api/helpers.rb index 3582ed81b0f..b56fd2388b3 100644 --- a/lib/api/helpers.rb +++ b/lib/api/helpers.rb @@ -290,7 +290,7 @@ module API def uploaded_file(field, uploads_path) if params[field] - bad_request!("#{field} is not a file") unless params[field].respond_to?(:filename) + bad_request!("#{field} is not a file") unless params[field][:filename] return params[field] end diff --git a/lib/api/jobs.rb b/lib/api/jobs.rb index 8a67de10bca..a40018b214e 100644 --- a/lib/api/jobs.rb +++ b/lib/api/jobs.rb @@ -16,9 +16,9 @@ module API case scope when String [scope] - when Hashie::Mash + when ::Hash scope.values - when Hashie::Array + when ::Array scope else ['unknown'] diff --git a/lib/api/templates.rb b/lib/api/templates.rb index 0fc13b35d5b..f70bc0622b7 100644 --- a/lib/api/templates.rb +++ b/lib/api/templates.rb @@ -57,7 +57,7 @@ module API end get "templates/licenses" do options = { - featured: declared(params).popular.present? ? true : nil + featured: declared(params)[:popular].present? ? true : nil } licences = ::Kaminari.paginate_array(Licensee::License.all(options)) present paginate(licences), with: Entities::RepoLicense @@ -71,7 +71,7 @@ module API requires :name, type: String, desc: 'The name of the template' end get "templates/licenses/:name", requirements: { name: /[\w\.-]+/ } do - not_found!('License') unless Licensee::License.find(declared(params).name) + not_found!('License') unless Licensee::License.find(declared(params)[:name]) template = parsed_license_template @@ -102,7 +102,7 @@ module API requires :name, type: String, desc: 'The name of the template' end get "templates/#{template_type}/:name" do - new_template = klass.find(declared(params).name) + new_template = klass.find(declared(params)[:name]) render_response(template_type, new_template) end diff --git a/lib/api/v3/builds.rb b/lib/api/v3/builds.rb index 93ad9eb26b8..c189d486f50 100644 --- a/lib/api/v3/builds.rb +++ b/lib/api/v3/builds.rb @@ -16,7 +16,7 @@ module API coerce_with: ->(scope) { if scope.is_a?(String) [scope] - elsif scope.is_a?(Hashie::Mash) + elsif scope.is_a?(::Hash) scope.values else ['unknown'] diff --git a/lib/api/v3/templates.rb b/lib/api/v3/templates.rb index 4c577a8d2b7..2a2fb59045c 100644 --- a/lib/api/v3/templates.rb +++ b/lib/api/v3/templates.rb @@ -59,7 +59,7 @@ module API end get route do options = { - featured: declared(params).popular.present? ? true : nil + featured: declared(params)[:popular].present? ? true : nil } present Licensee::License.all(options), with: ::API::Entities::RepoLicense end @@ -76,7 +76,7 @@ module API requires :name, type: String, desc: 'The name of the template' end get route, requirements: { name: /[\w\.-]+/ } do - not_found!('License') unless Licensee::License.find(declared(params).name) + not_found!('License') unless Licensee::License.find(declared(params)[:name]) template = parsed_license_template @@ -111,7 +111,7 @@ module API requires :name, type: String, desc: 'The name of the template' end get route do - new_template = klass.find(declared(params).name) + new_template = klass.find(declared(params)[:name]) render_response(template_type, new_template) end diff --git a/lib/gitlab/gitaly_client/blob_service.rb b/lib/gitlab/gitaly_client/blob_service.rb index 7ea8e8d0857..a250eb75bd4 100644 --- a/lib/gitlab/gitaly_client/blob_service.rb +++ b/lib/gitlab/gitaly_client/blob_service.rb @@ -13,10 +13,17 @@ module Gitlab ) response = GitalyClient.call(@gitaly_repo.storage_name, :blob_service, :get_blob, request) - blob = response.first - return unless blob.oid.present? + data = '' + blob = nil + response.each do |msg| + if blob.nil? + blob = msg + end - data = response.reduce(blob.data.dup) { |memo, msg| memo << msg.data.dup } + data << msg.data + end + + return nil if blob.oid.blank? Gitlab::Git::Blob.new( id: blob.oid, diff --git a/lib/gitlab/gitaly_client/commit_service.rb b/lib/gitlab/gitaly_client/commit_service.rb index 93268d9f33c..b36e81278d6 100644 --- a/lib/gitlab/gitaly_client/commit_service.rb +++ b/lib/gitlab/gitaly_client/commit_service.rb @@ -60,15 +60,21 @@ module Gitlab ) response = GitalyClient.call(@repository.storage, :commit_service, :tree_entry, request) - entry = response.first - return unless entry.oid.present? - if entry.type == :BLOB - rest_of_data = response.reduce("") { |memo, msg| memo << msg.data } - entry.data += rest_of_data + entry = nil + data = '' + response.each do |msg| + if entry.nil? + entry = msg + + break unless entry.type == :BLOB + end + + data << msg.data end + entry.data = data - entry + entry unless entry.oid.blank? end def tree_entries(repository, revision, path) diff --git a/lib/gitlab/import_export/project_tree_restorer.rb b/lib/gitlab/import_export/project_tree_restorer.rb index 84ab1977dfa..cbc8d170936 100644 --- a/lib/gitlab/import_export/project_tree_restorer.rb +++ b/lib/gitlab/import_export/project_tree_restorer.rb @@ -1,6 +1,9 @@ module Gitlab module ImportExport class ProjectTreeRestorer + # Relations which cannot have both group_id and project_id at the same time + RESTRICT_PROJECT_AND_GROUP = %i(milestones).freeze + def initialize(user:, shared:, project:) @path = File.join(shared.export_path, 'project.json') @user = user @@ -118,9 +121,11 @@ module Gitlab end def create_relation(relation, relation_hash_list) + relation_type = relation.to_sym + relation_array = [relation_hash_list].flatten.map do |relation_hash| - Gitlab::ImportExport::RelationFactory.create(relation_sym: relation.to_sym, - relation_hash: parsed_relation_hash(relation_hash), + Gitlab::ImportExport::RelationFactory.create(relation_sym: relation_type, + relation_hash: parsed_relation_hash(relation_hash, relation_type), members_mapper: members_mapper, user: @user, project: restored_project) @@ -129,8 +134,16 @@ module Gitlab relation_hash_list.is_a?(Array) ? relation_array : relation_array.first end - def parsed_relation_hash(relation_hash) - relation_hash.merge!('group_id' => restored_project.group.try(:id), 'project_id' => restored_project.id) + def parsed_relation_hash(relation_hash, relation_type) + if RESTRICT_PROJECT_AND_GROUP.include?(relation_type) + params = {} + params['group_id'] = restored_project.group.try(:id) if relation_hash['group_id'] + params['project_id'] = restored_project.id if relation_hash['project_id'] + else + params = { 'group_id' => restored_project.group.try(:id), 'project_id' => restored_project.id } + end + + relation_hash.merge(params) end end end diff --git a/lib/gitlab/sidekiq_status.rb b/lib/gitlab/sidekiq_status.rb index ca8d3271541..a0a2769cf9e 100644 --- a/lib/gitlab/sidekiq_status.rb +++ b/lib/gitlab/sidekiq_status.rb @@ -90,9 +90,14 @@ module Gitlab # # Returns an array of completed JIDs def self.completed_jids(job_ids) - Sidekiq.redis do |redis| - job_ids.reject { |jid| redis.exists(key_for(jid)) } + statuses = job_status(job_ids) + + completed = [] + job_ids.zip(statuses).each do |job_id, status| + completed << job_id unless status end + + completed end def self.key_for(jid) diff --git a/spec/features/help_pages_spec.rb b/spec/features/help_pages_spec.rb index bd4f233cba9..93be3b066ee 100644 --- a/spec/features/help_pages_spec.rb +++ b/spec/features/help_pages_spec.rb @@ -50,7 +50,7 @@ describe 'Help Pages' do it 'hides the version check image if the image request fails' do # We use '--load-images=yes' with poltergeist so the image fails to load - expect(find('.js-version-status-badge', visible: false)).not_to be_visible + expect(page).to have_selector('.js-version-status-badge', visible: false) end end diff --git a/spec/features/profile_spec.rb b/spec/features/profile_spec.rb index 672022304da..f183dd8cb75 100644 --- a/spec/features/profile_spec.rb +++ b/spec/features/profile_spec.rb @@ -7,9 +7,8 @@ describe 'Profile account page' do sign_in(user) end - describe 'when signup is enabled' do + describe 'when I delete my account' do before do - stub_application_setting(signup_enabled: true) visit profile_account_path end @@ -21,18 +20,6 @@ describe 'Profile account page' do end end - describe 'when signup is disabled' do - before do - stub_application_setting(signup_enabled: false) - visit profile_account_path - end - - it 'does not have option to remove account' do - expect(page).not_to have_content('Remove account') - expect(current_path).to eq(profile_account_path) - end - end - describe 'when I reset private token' do before do visit profile_account_path diff --git a/spec/features/projects_spec.rb b/spec/features/projects_spec.rb index d3d7915bebf..baf3d29e6c5 100644 --- a/spec/features/projects_spec.rb +++ b/spec/features/projects_spec.rb @@ -18,7 +18,7 @@ feature 'Project' do click_button "Create project" end - expect(page).to have_content 'This project Loading..' + expect(page).to have_content template.name end end diff --git a/spec/lib/after_commit_queue_spec.rb b/spec/lib/after_commit_queue_spec.rb new file mode 100644 index 00000000000..6e7c2ec2363 --- /dev/null +++ b/spec/lib/after_commit_queue_spec.rb @@ -0,0 +1,15 @@ +require 'spec_helper' + +describe AfterCommitQueue do + it 'runs after transaction is committed' do + called = false + test_proc = proc { called = true } + + project = build(:project) + project.run_after_commit(&test_proc) + + project.save + + expect(called).to be true + end +end diff --git a/spec/lib/gitlab/background_migration/migrate_events_to_push_event_payloads_spec.rb b/spec/lib/gitlab/background_migration/migrate_events_to_push_event_payloads_spec.rb index 87f45619e7a..0d5fffa38ff 100644 --- a/spec/lib/gitlab/background_migration/migrate_events_to_push_event_payloads_spec.rb +++ b/spec/lib/gitlab/background_migration/migrate_events_to_push_event_payloads_spec.rb @@ -210,7 +210,11 @@ describe Gitlab::BackgroundMigration::MigrateEventsToPushEventPayloads::Event do end end -describe Gitlab::BackgroundMigration::MigrateEventsToPushEventPayloads do +## +# The background migration relies on a temporary table, hence we're migrating +# to a specific version of the database where said table is still present. +# +describe Gitlab::BackgroundMigration::MigrateEventsToPushEventPayloads, :migration, schema: 20170608152748 do let(:migration) { described_class.new } let(:project) { create(:project_empty_repo) } let(:author) { create(:user) } @@ -229,21 +233,6 @@ describe Gitlab::BackgroundMigration::MigrateEventsToPushEventPayloads do ) end - # The background migration relies on a temporary table, hence we're migrating - # to a specific version of the database where said table is still present. - before :all do - ActiveRecord::Migration.verbose = false - - ActiveRecord::Migrator - .migrate(ActiveRecord::Migrator.migrations_paths, 20170608152748) - end - - after :all do - ActiveRecord::Migrator.migrate(ActiveRecord::Migrator.migrations_paths) - - ActiveRecord::Migration.verbose = true - end - describe '#perform' do it 'returns if data should not be migrated' do allow(migration).to receive(:migrate?).and_return(false) diff --git a/spec/lib/gitlab/import_export/project.light.json b/spec/lib/gitlab/import_export/project.light.json index a78836c3c34..2d8f3d4a566 100644 --- a/spec/lib/gitlab/import_export/project.light.json +++ b/spec/lib/gitlab/import_export/project.light.json @@ -2,6 +2,20 @@ "description": "Nisi et repellendus ut enim quo accusamus vel magnam.", "visibility_level": 10, "archived": false, + "milestones": [ + { + "id": 1, + "title": "test milestone", + "project_id": 8, + "description": "test milestone", + "due_date": null, + "created_at": "2016-06-14T15:02:04.415Z", + "updated_at": "2016-06-14T15:02:04.415Z", + "state": "active", + "iid": 1, + "group_id": null + } + ], "labels": [ { "id": 2, @@ -14,20 +28,6 @@ "description": "", "type": "ProjectLabel", "priorities": [ - ] - }, - { - "id": 3, - "title": "test3", - "color": "#428bca", - "group_id": 8, - "created_at": "2016-07-22T08:55:44.161Z", - "updated_at": "2016-07-22T08:55:44.161Z", - "template": false, - "description": "", - "project_id": null, - "type": "GroupLabel", - "priorities": [ { "id": 1, "project_id": 5, @@ -39,10 +39,80 @@ ] } ], + "issues": [ + { + "id": 1, + "title": "Fugiat est minima quae maxime non similique.", + "assignee_id": null, + "project_id": 8, + "author_id": 1, + "created_at": "2017-07-07T18:13:01.138Z", + "updated_at": "2017-08-15T18:37:40.807Z", + "branch_name": null, + "description": "Quam totam fuga numquam in eveniet.", + "state": "opened", + "iid": 20, + "updated_by_id": 1, + "confidential": false, + "deleted_at": null, + "due_date": null, + "moved_to_id": null, + "lock_version": null, + "time_estimate": 0, + "closed_at": null, + "last_edited_at": null, + "last_edited_by_id": null, + "group_milestone_id": null, + "label_links": [ + { + "id": 11, + "label_id": 6, + "target_id": 1, + "target_type": "Issue", + "created_at": "2017-08-15T18:37:40.795Z", + "updated_at": "2017-08-15T18:37:40.795Z", + "label": { + "id": 6, + "title": "group label", + "color": "#A8D695", + "project_id": null, + "created_at": "2017-08-15T18:37:19.698Z", + "updated_at": "2017-08-15T18:37:19.698Z", + "template": false, + "description": "", + "group_id": 5, + "type": "GroupLabel", + "priorities": [] + } + }, + { + "id": 11, + "label_id": 2, + "target_id": 1, + "target_type": "Issue", + "created_at": "2017-08-15T18:37:40.795Z", + "updated_at": "2017-08-15T18:37:40.795Z", + "label": { + "id": 6, + "title": "project label", + "color": "#A8D695", + "project_id": null, + "created_at": "2017-08-15T18:37:19.698Z", + "updated_at": "2017-08-15T18:37:19.698Z", + "template": false, + "description": "", + "group_id": 5, + "type": "ProjectLabel", + "priorities": [] + } + } + ] + } + ], "snippets": [ ], "hooks": [ ] -}
\ No newline at end of file +} diff --git a/spec/lib/gitlab/import_export/project_tree_restorer_spec.rb b/spec/lib/gitlab/import_export/project_tree_restorer_spec.rb index 7ee0e22f28d..956f1d56eb4 100644 --- a/spec/lib/gitlab/import_export/project_tree_restorer_spec.rb +++ b/spec/lib/gitlab/import_export/project_tree_restorer_spec.rb @@ -183,7 +183,8 @@ describe Gitlab::ImportExport::ProjectTreeRestorer do let(:restored_project_json) { project_tree_restorer.restore } before do - allow(ImportExport).to receive(:project_filename).and_return('project.light.json') + project_tree_restorer.instance_variable_set(:@path, "spec/lib/gitlab/import_export/project.light.json") + allow(shared).to receive(:export_path).and_return('spec/lib/gitlab/import_export/') end @@ -195,7 +196,7 @@ describe Gitlab::ImportExport::ProjectTreeRestorer do restored_project_json - expect(shared.errors.first).not_to include('test') + expect(shared.errors.first).to be_nil end end end @@ -219,15 +220,42 @@ describe Gitlab::ImportExport::ProjectTreeRestorer do end before do + project_tree_restorer.instance_variable_set(:@path, "spec/lib/gitlab/import_export/project.light.json") + restored_project_json end - it 'has group labels' do - expect(GroupLabel.count).to eq(1) + it 'correctly restores project' do + expect(restored_project_json).to be_truthy + expect(shared.errors).to be_empty + end + + it 'has labels' do + expect(project.labels.count).to eq(2) + end + + it 'creates group label' do + expect(project.group.labels.count).to eq(1) end it 'has label priorities' do - expect(GroupLabel.first.priorities).not_to be_empty + expect(project.labels.first.priorities).not_to be_empty + end + + it 'has milestones' do + expect(project.milestones.count).to eq(1) + end + + it 'has issue' do + expect(project.issues.count).to eq(1) + expect(project.issues.first.labels.count).to eq(2) + end + + it 'has issue with group label and project label' do + labels = project.issues.first.labels + + expect(labels.where(type: "GroupLabel").count).to eq(1) + expect(labels.where(type: "ProjectLabel").count).to eq(1) end end end diff --git a/spec/migrations/README.md b/spec/migrations/README.md index 05d4f35db72..45cf25b96de 100644 --- a/spec/migrations/README.md +++ b/spec/migrations/README.md @@ -28,6 +28,14 @@ The `after` hook will migrate the database **up** and reinstitutes the latest schema version, so that the process does not affect subsequent specs and ensures proper isolation. +## Testing a class that is not an ActiveRecord::Migration + +In order to test a class that is not a migration itself, you will need to +manually provide a required schema version. Please add a `schema` tag to a +context that you want to switch the database schema within. + +Example: `describe SomeClass, :migration, schema: 20170608152748`. + ## Available helpers Use `table` helper to create a temporary `ActiveRecord::Base` derived model @@ -80,8 +88,6 @@ end ## Best practices -1. Use only one test example per migration unless there is a good reason to -use more. 1. Note that this type of tests do not run within the transaction, we use a truncation database cleanup strategy. Do not depend on transaction being present. diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb index eba71ba2f72..5e60511f3a8 100644 --- a/spec/models/project_spec.rb +++ b/spec/models/project_spec.rb @@ -1610,8 +1610,7 @@ describe Project do it 'imports a project' do expect_any_instance_of(RepositoryImportWorker).to receive(:perform).and_call_original - project.import_schedule - + expect { project.import_schedule }.to change { project.import_jid } expect(project.reload.import_status).to eq('finished') end end @@ -1624,6 +1623,13 @@ describe Project do allow(Projects::HousekeepingService).to receive(:new) { housekeeping_service } end + it 'resets project import_error' do + error_message = 'Some error' + mirror = create(:project_empty_repo, :import_started, import_error: error_message) + + expect { mirror.import_finish }.to change { mirror.import_error }.from(error_message).to(nil) + end + it 'performs housekeeping when an import of a fresh project is completed' do project = create(:project_empty_repo, :import_started, import_type: :github) @@ -1730,17 +1736,21 @@ describe Project do end describe '#add_import_job' do + let(:import_jid) { '123' } + context 'forked' do let(:forked_project_link) { create(:forked_project_link, :forked_to_empty_project) } let(:forked_from_project) { forked_project_link.forked_from_project } let(:project) { forked_project_link.forked_to_project } it 'schedules a RepositoryForkWorker job' do - expect(RepositoryForkWorker).to receive(:perform_async) - .with(project.id, forked_from_project.repository_storage_path, - forked_from_project.disk_path, project.namespace.full_path) + expect(RepositoryForkWorker).to receive(:perform_async).with( + project.id, + forked_from_project.repository_storage_path, + forked_from_project.disk_path, + project.namespace.full_path).and_return(import_jid) - project.add_import_job + expect(project.add_import_job).to eq(import_jid) end end @@ -1748,9 +1758,8 @@ describe Project do it 'schedules a RepositoryImportWorker job' do project = create(:project, import_url: generate(:url)) - expect(RepositoryImportWorker).to receive(:perform_async).with(project.id) - - project.add_import_job + expect(RepositoryImportWorker).to receive(:perform_async).with(project.id).and_return(import_jid) + expect(project.add_import_job).to eq(import_jid) end end end @@ -2311,6 +2320,44 @@ describe Project do end end + describe '#remove_pages' do + let(:project) { create(:project) } + let(:namespace) { project.namespace } + let(:pages_path) { project.pages_path } + + around do |example| + FileUtils.mkdir_p(pages_path) + begin + example.run + ensure + FileUtils.rm_rf(pages_path) + end + end + + it 'removes the pages directory' do + expect_any_instance_of(Projects::UpdatePagesConfigurationService).to receive(:execute) + expect_any_instance_of(Gitlab::PagesTransfer).to receive(:rename_project).and_return(true) + expect(PagesWorker).to receive(:perform_in).with(5.minutes, :remove, namespace.full_path, anything) + + project.remove_pages + end + + it 'is a no-op when there is no namespace' do + project.update_column(:namespace_id, nil) + + expect_any_instance_of(Projects::UpdatePagesConfigurationService).not_to receive(:execute) + expect_any_instance_of(Gitlab::PagesTransfer).not_to receive(:rename_project) + + project.remove_pages + end + + it 'is run when the project is destroyed' do + expect(project).to receive(:remove_pages).and_call_original + + project.destroy + end + end + describe '#forks_count' do it 'returns the number of forks' do project = build(:project) diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 3eea39d4bf4..c10197ff651 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -132,17 +132,12 @@ RSpec.configure do |config| Sidekiq.redis(&:flushall) end - config.before(:example, :migration) do - ActiveRecord::Migrator - .migrate(migrations_paths, previous_migration.version) - - reset_column_in_migration_models + config.before(:each, :migration) do + schema_migrate_down! end - config.after(:example, :migration) do - ActiveRecord::Migrator.migrate(migrations_paths) - - reset_column_in_migration_models + config.after(:context, :migration) do + schema_migrate_up! end config.around(:each, :nested_groups) do |example| diff --git a/spec/support/db_cleaner.rb b/spec/support/db_cleaner.rb index 7f5769209bb..b0f520d08e8 100644 --- a/spec/support/db_cleaner.rb +++ b/spec/support/db_cleaner.rb @@ -20,7 +20,7 @@ RSpec.configure do |config| end config.before(:each, :migration) do - DatabaseCleaner.strategy = :truncation + DatabaseCleaner.strategy = :truncation, { cache_tables: false } end config.before(:each) do diff --git a/spec/support/migrations_helpers.rb b/spec/support/migrations_helpers.rb index aabdad13047..255b3d96a62 100644 --- a/spec/support/migrations_helpers.rb +++ b/spec/support/migrations_helpers.rb @@ -31,6 +31,35 @@ module MigrationsHelpers end end + def migration_schema_version + self.class.metadata[:schema] || previous_migration.version + end + + def schema_migrate_down! + disable_migrations_output do + ActiveRecord::Migrator.migrate(migrations_paths, + migration_schema_version) + end + + reset_column_in_migration_models + end + + def schema_migrate_up! + disable_migrations_output do + ActiveRecord::Migrator.migrate(migrations_paths) + end + + reset_column_in_migration_models + end + + def disable_migrations_output + ActiveRecord::Migration.verbose = false + + yield + ensure + ActiveRecord::Migration.verbose = true + end + def migrate! ActiveRecord::Migrator.up(migrations_paths) do |migration| migration.name == described_class.name diff --git a/spec/workers/repository_import_worker_spec.rb b/spec/workers/repository_import_worker_spec.rb index ca904e512ac..100dfc32bbe 100644 --- a/spec/workers/repository_import_worker_spec.rb +++ b/spec/workers/repository_import_worker_spec.rb @@ -22,8 +22,8 @@ describe RepositoryImportWorker do it 'hide the credentials that were used in the import URL' do error = %q{remote: Not Found fatal: repository 'https://user:pass@test.com/root/repoC.git/' not found } + project.update_attributes(import_jid: '123') expect_any_instance_of(Projects::ImportService).to receive(:execute).and_return({ status: :error, message: error }) - allow(subject).to receive(:jid).and_return('123') expect do subject.perform(project.id) diff --git a/spec/workers/stuck_import_jobs_worker_spec.rb b/spec/workers/stuck_import_jobs_worker_spec.rb index 2f5b685a332..a82eb54ffe4 100644 --- a/spec/workers/stuck_import_jobs_worker_spec.rb +++ b/spec/workers/stuck_import_jobs_worker_spec.rb @@ -8,29 +8,29 @@ describe StuckImportJobsWorker do allow_any_instance_of(Gitlab::ExclusiveLease).to receive(:try_obtain).and_return(exclusive_lease_uuid) end - describe 'long running import' do - let(:project) { create(:project, import_jid: '123', import_status: 'started') } + describe 'with started import_status' do + let(:project) { create(:project, :import_started, import_jid: '123') } - before do - allow(Gitlab::SidekiqStatus).to receive(:completed_jids).and_return(['123']) - end + describe 'long running import' do + it 'marks the project as failed' do + allow(Gitlab::SidekiqStatus).to receive(:completed_jids).and_return(['123']) - it 'marks the project as failed' do - expect { worker.perform }.to change { project.reload.import_status }.to('failed') + expect { worker.perform }.to change { project.reload.import_status }.to('failed') + end end - end - describe 'running import' do - let(:project) { create(:project, import_jid: '123', import_status: 'started') } - - before do - allow(Gitlab::SidekiqStatus).to receive(:completed_jids).and_return([]) - end + describe 'running import' do + it 'does not mark the project as failed' do + allow(Gitlab::SidekiqStatus).to receive(:completed_jids).and_return([]) - it 'does not mark the project as failed' do - worker.perform + expect { worker.perform }.not_to change { project.reload.import_status } + end - expect(project.reload.import_status).to eq('started') + describe 'import without import_jid' do + it 'marks the project as failed' do + expect { worker.perform }.to change { project.reload.import_status }.to('failed') + end + end end end end |