summaryrefslogtreecommitdiff
path: root/doc
diff options
context:
space:
mode:
Diffstat (limited to 'doc')
-rw-r--r--doc/api/commits.md3
-rw-r--r--doc/api/notes.md1
-rw-r--r--doc/api/project_snippets.md1
-rw-r--r--doc/api/users.md2
-rw-r--r--doc/ci/api/README.md88
-rw-r--r--doc/ci/api/builds.md118
-rw-r--r--doc/ci/api/commits.md108
-rw-r--r--doc/ci/api/projects.md149
-rw-r--r--doc/ci/api/runners.md71
-rw-r--r--doc/development/README.md1
-rw-r--r--doc/development/sql.md219
-rw-r--r--doc/hooks/custom_hooks.md2
-rw-r--r--doc/install/installation.md11
-rw-r--r--doc/integration/README.md31
-rw-r--r--doc/integration/ldap.md22
-rw-r--r--doc/integration/saml.md38
-rw-r--r--doc/integration/slack.md12
-rw-r--r--doc/markdown/markdown.md1
-rw-r--r--doc/project_services/jira.md13
-rw-r--r--doc/update/8.4-to-8.5.md3
-rw-r--r--doc/update/patch_versions.md6
-rw-r--r--doc/update/upgrader.md2
-rw-r--r--doc/web_hooks/web_hooks.md1
-rw-r--r--doc/workflow/lfs/lfs_administration.md8
-rw-r--r--doc/workflow/lfs/manage_large_binaries_with_git_lfs.md85
25 files changed, 493 insertions, 503 deletions
diff --git a/doc/api/commits.md b/doc/api/commits.md
index e4d436b8e52..6341440c58b 100644
--- a/doc/api/commits.md
+++ b/doc/api/commits.md
@@ -213,8 +213,7 @@ Example response:
## Commit status
-Since GitLab 8.1, this is the new commit status API. The documentation in
-[ci/api/commits](../ci/api/commits.md) is deprecated.
+Since GitLab 8.1, this is the new commit status API.
### Get the status of a commit
diff --git a/doc/api/notes.md b/doc/api/notes.md
index d4d63e825ab..85d4f0bafa2 100644
--- a/doc/api/notes.md
+++ b/doc/api/notes.md
@@ -145,7 +145,6 @@ Parameters:
"state": "active",
"created_at": "2013-09-30T13:46:01Z"
},
- "expires_at": null,
"updated_at": "2013-10-02T07:34:20Z",
"created_at": "2013-10-02T07:34:20Z"
}
diff --git a/doc/api/project_snippets.md b/doc/api/project_snippets.md
index a7acf37b5bc..fb802102e3a 100644
--- a/doc/api/project_snippets.md
+++ b/doc/api/project_snippets.md
@@ -51,7 +51,6 @@ Parameters:
"state": "active",
"created_at": "2012-05-23T08:00:58Z"
},
- "expires_at": null,
"updated_at": "2012-06-28T10:52:04Z",
"created_at": "2012-06-28T10:52:04Z"
}
diff --git a/doc/api/users.md b/doc/api/users.md
index b7fc903825e..82c57a2fd43 100644
--- a/doc/api/users.md
+++ b/doc/api/users.md
@@ -151,6 +151,8 @@ Parameters:
"name": "John Smith",
"state": "active",
"created_at": "2012-05-23T08:00:58Z",
+ "confirmed_at": "2012-05-23T08:00:58Z",
+ "last_sign_in_at": "2015-03-23T08:00:58Z",
"bio": null,
"skype": "",
"linkedin": "",
diff --git a/doc/ci/api/README.md b/doc/ci/api/README.md
index cf9710ede57..aea808007fc 100644
--- a/doc/ci/api/README.md
+++ b/doc/ci/api/README.md
@@ -1,86 +1,22 @@
# GitLab CI API
-## Resources
-
-- [Projects](projects.md)
-- [Runners](runners.md)
-- [Commits](commits.md)
-- [Builds](builds.md)
-
-
-## Authentication
-
-GitLab CI API uses different types of authentication depends on what API you use.
-Each API document has section with information about authentication you need to use.
-
-GitLab CI API has 4 authentication methods:
-
-* GitLab user token & GitLab url
-* GitLab CI project token
-* GitLab CI runners registration token
-* GitLab CI runner token
-
-
-### Authentication #1: GitLab user token & GitLab url
-
-Authentication is done by
-sending the `private-token` of a valid user and the `url` of an
-authorized GitLab instance via a query string along with the API
-request:
-
- GET http://gitlab.example.com/ci/api/v1/projects?private_token=QVy1PB7sTxfy4pqfZM1U&url=http://demo.gitlab.com/
+## Purpose
-If preferred, you may instead send the `private-token` as a header in
-your request:
+Main purpose of GitLab CI API is to provide necessary data and context for
+GitLab CI Runners.
- curl --header "PRIVATE-TOKEN: QVy1PB7sTxfy4pqfZM1U" "http://gitlab.example.com/ci/api/v1/projects?url=http://demo.gitlab.com/"
+For consumer API take a look at this [documentation](../../api/README.md) where
+you will find all relevant information.
+## API Prefix
-### Authentication #2: GitLab CI project token
+Current CI API prefix is `/ci/api/v1`.
-Each project in GitLab CI has it own token.
-It can be used to get project commits and builds information.
-You can use project token only for certain project.
+You need to prepend this prefix to all examples in this documentation, like:
-### Authentication #3: GitLab CI runners registration token
+ GET /ci/api/v1/builds/:id/artifacts
-This token is not persisted and is generated on each application start.
-It can be used only for registering new runners in system. You can find it on
-GitLab CI Runners web page https://gitlab-ci.example.com/admin/runners
-
-### Authentication #4: GitLab CI runner token
-
-Every GitLab CI runner has it own token that allow it to receive and update
-GitLab CI builds. This token exists of internal purposes and should be used only
-by runners
-
-## JSON
-
-All API requests are serialized using JSON. You don't need to specify
-`.json` at the end of API URL.
-
-## Status codes
-
-The API is designed to return different status codes according to context and action. In this way if a request results in an error the caller is able to get insight into what went wrong, e.g. status code `400 Bad Request` is returned if a required attribute is missing from the request. The following list gives an overview of how the API functions generally behave.
-
-API request types:
-
-- `GET` requests access one or more resources and return the result as JSON
-- `POST` requests return `201 Created` if the resource is successfully created and return the newly created resource as JSON
-- `GET`, `PUT` and `DELETE` return `200 OK` if the resource is accessed, modified or deleted successfully, the (modified) result is returned as JSON
-- `DELETE` requests are designed to be idempotent, meaning a request a resource still returns `200 OK` even it was deleted before or is not available. The reasoning behind it is the user is not really interested if the resource existed before or not.
-
-The following list shows the possible return codes for API requests.
-
-Return values:
+## Resources
-- `200 OK` - The `GET`, `PUT` or `DELETE` request was successful, the resource(s) itself is returned as JSON
-- `201 Created` - The `POST` request was successful and the resource is returned as JSON
-- `400 Bad Request` - A required attribute of the API request is missing, e.g. the title of an issue is not given
-- `401 Unauthorized` - The user is not authenticated, a valid user token is necessary, see above
-- `403 Forbidden` - The request is not allowed, e.g. the user is not allowed to delete a project
-- `404 Not Found` - A resource could not be accessed, e.g. an ID for a resource could not be found
-- `405 Method Not Allowed` - The request is not supported
-- `409 Conflict` - A conflicting resource already exists, e.g. creating a project with a name that already exists
-- `422 Unprocessable` - The entity could not be processed
-- `500 Server Error` - While handling the request something went wrong on the server side
+- [Builds](builds.md)
+- [Runners](runners.md)
diff --git a/doc/ci/api/builds.md b/doc/ci/api/builds.md
index 018ca22dbbd..d100e261178 100644
--- a/doc/ci/api/builds.md
+++ b/doc/ci/api/builds.md
@@ -1,85 +1,73 @@
# Builds API
-This API used by runners to receive and update builds.
+API used by runners to receive and update builds.
-__Authentication is done by runner token__
+_**Note:** This API is intended to be used only by Runners as their own
+communication channel. For the consumer API see the
+[Builds API](../../api/builds.md)._
+
+## Authentication
+
+This API uses two types of authentication:
+
+1. Unique runner's token
+
+ Token assigned to runner after it has been registered.
+
+2. Using build authorization token
+
+ This is project's CI token that can be found in Continuous Integration
+ project settings.
+
+ Build authorization token can be passed as a parameter or a value of
+ `BUILD-TOKEN` header. This method are interchangeable.
## Builds
### Runs oldest pending build by runner
- POST /ci/builds/register
+ POST /ci/api/v1/builds/register
Parameters:
- * `token` (required) - The unique token of runner
-
-Returns:
-
-```json
-{
- "id": 48584,
- "ref": "0.1.1",
- "tag": true,
- "sha": "d63117656af6ff57d99e50cc270f854691f335ad",
- "status": "success",
- "name": "pages",
- "token": "9dd60b4f1a439d1765357446c1084c",
- "stage": "test",
- "project_id": 479,
- "project_name": "test",
- "commands": "echo commands",
- "repo_url": "http://gitlab-ci-token:token@gitlab.example/group/test.git",
- "before_sha": "0000000000000000000000000000000000000000",
- "allow_git_fetch": false,
- "options": {
- "image": "docker:image",
- "artifacts": {
- "paths": [
- "public"
- ]
- },
- "cache": {
- "paths": [
- "vendor"
- ]
- }
- },
- "timeout": 3600,
- "variables": [
- {
- "key": "CI_BUILD_TAG",
- "value": "0.1.1",
- "public": true
- }
- ],
- "depends_on_builds": [
- {
- "id": 48584,
- "ref": "0.1.1",
- "tag": true,
- "sha": "d63117656af6ff57d99e50cc270f854691f335ad",
- "status": "success",
- "name": "build",
- "token": "9dd60b4f1a439d1765357446c1084c",
- "stage": "build",
- "project_id": 479,
- "project_name": "test",
- "artifacts_file": {
- "filename": "artifacts.zip",
- "size": 0
- }
- }
- ]
-}
-```
+ * `token` (required) - Unique runner token
+
### Update details of an existing build
- PUT /ci/builds/:id
+ PUT /ci/api/v1/builds/:id
Parameters:
* `id` (required) - The ID of a project
+ * `token` (required) - Unique runner token
* `state` (optional) - The state of a build
* `trace` (optional) - The trace of a build
+
+### Upload artifacts to build
+
+ POST /ci/api/v1/builds/:id/artifacts
+
+Parameters:
+
+ * `id` (required) - The ID of a build
+ * `token` (required) - The build authorization token
+ * `file` (required) - Artifacts file
+
+### Download the artifacts file from build
+
+ GET /ci/api/v1/builds/:id/artifacts
+
+Parameters:
+
+ * `id` (required) - The ID of a build
+ * `token` (required) - The build authorization token
+
+### Remove the artifacts file from build
+
+ DELETE /ci/api/v1/builds/:id/artifacts
+
+Parameters:
+
+ * ` id` (required) - The ID of a build
+ * `token` (required) - The build authorization token
diff --git a/doc/ci/api/commits.md b/doc/ci/api/commits.md
deleted file mode 100644
index 871de7abcce..00000000000
--- a/doc/ci/api/commits.md
+++ /dev/null
@@ -1,108 +0,0 @@
-# Commits API
-
-**DEPRECATED**
-
-Since GitLab 8.1, there is a new commit status API. Please see the [revised
-documentation](../../api/commits.md#commit-status).
-
----
-
-__Authentication is done by GitLab CI project token__
-
-## Commits
-
-### Retrieve all commits per project
-
-Get list of commits per project
-
- GET /ci/commits
-
-Parameters:
-
- * `project_id` (required) - The ID of a project
- * `project_token` (requires) - Project token
- * `page` (optional)
- * `per_page` (optional) - items per request (default is 20)
-
-Returns:
-
-```json
-[{
- "id": 3,
- "ref": "master",
- "sha": "65617dfc36761baa1f46a7006f2a88916f7f56cf",
- "project_id": 2,
- "before_sha": "96906f2bceb04c7323f8514aa5ad8cb1313e2898",
- "created_at": "2014-11-05T09:46:35.247Z",
- "status": "success",
- "finished_at": "2014-11-05T09:46:44.254Z",
- "duration": 5.062692165374756,
- "git_commit_message": "wow\n",
- "git_author_name": "Administrator",
- "git_author_email": "admin@example.com",
- "builds": [{
- "id": 7,
- "project_id": 2,
- "ref": "master",
- "status": "success",
- "finished_at": "2014-11-05T09:46:44.254Z",
- "created_at": "2014-11-05T09:46:35.259Z",
- "updated_at": "2014-11-05T09:46:44.255Z",
- "sha": "65617dfc36761baa1f46a7006f2a88916f7f56cf",
- "started_at": "2014-11-05T09:46:39.192Z",
- "before_sha": "96906f2bceb04c7323f8514aa5ad8cb1313e2898",
- "runner_id": 1,
- "coverage": null,
- "commit_id": 3
- }]
-}]
-```
-
-### Create commit
-
-Inform GitLab CI about new commit you want it to build.
-
-__If commit already exists in GitLab CI it will not be created__
-
-
- POST /ci/commits
-
-Parameters:
-
- * `project_id` (required) - The ID of a project
- * `project_token` (requires) - Project token
- * `data` (required) - Push data. For example see comment in `lib/api/commits.rb`
-
-Returns:
-
-```json
-{
- "id": 3,
- "ref": "master",
- "sha": "65617dfc36761baa1f46a7006f2a88916f7f56cf",
- "project_id": 2,
- "before_sha": "96906f2bceb04c7323f8514aa5ad8cb1313e2898",
- "created_at": "2014-11-05T09:46:35.247Z",
- "status": "success",
- "finished_at": "2014-11-05T09:46:44.254Z",
- "duration": 5.062692165374756,
- "git_commit_message": "wow\n",
- "git_author_name": "Administrator",
- "git_author_email": "admin@example.com",
- "builds": [{
- "id": 7,
- "project_id": 2,
- "ref": "master",
- "status": "success",
- "finished_at": "2014-11-05T09:46:44.254Z",
- "created_at": "2014-11-05T09:46:35.259Z",
- "updated_at": "2014-11-05T09:46:44.255Z",
- "sha": "65617dfc36761baa1f46a7006f2a88916f7f56cf",
- "started_at": "2014-11-05T09:46:39.192Z",
- "before_sha": "96906f2bceb04c7323f8514aa5ad8cb1313e2898",
- "runner_id": 1,
- "coverage": null,
- "commit_id": 3
- }]
-}
-```
diff --git a/doc/ci/api/projects.md b/doc/ci/api/projects.md
deleted file mode 100644
index fe6b1c01352..00000000000
--- a/doc/ci/api/projects.md
+++ /dev/null
@@ -1,149 +0,0 @@
-# Projects API
-
-This API is intended to aid in the setup and configuration of
-projects on GitLab CI.
-
-__Authentication is done by GitLab user token & GitLab url__
-
-## Projects
-
-### List Authorized Projects
-
-Lists all projects that the authenticated user has access to.
-
-```
-GET /ci/projects
-```
-
-Returns:
-
-```json
-[
- {
- "id" : 271,
- "name" : "gitlabhq",
- "timeout" : 1800,
- "token" : "iPWx6WM4lhHNedGfBpPJNP",
- "default_ref" : "master",
- "gitlab_url" : "http://demo.gitlabhq.com/gitlab/gitlab-shell",
- "path" : "gitlab/gitlab-shell",
- "always_build" : false,
- "polling_interval" : null,
- "public" : false,
- "ssh_url_to_repo" : "git@demo.gitlab.com:gitlab/gitlab-shell.git",
- "gitlab_id" : 3
- },
- {
- "id" : 272,
- "name" : "gitlab-ci",
- "timeout" : 1800,
- "token" : "iPWx6WM4lhHNedGfBpPJNP",
- "default_ref" : "master",
- "gitlab_url" : "http://demo.gitlabhq.com/gitlab/gitlab-shell",
- "path" : "gitlab/gitlab-shell",
- "always_build" : false,
- "polling_interval" : null,
- "public" : false,
- "ssh_url_to_repo" : "git@demo.gitlab.com:gitlab/gitlab-shell.git",
- "gitlab_id" : 4
- }
-]
-```
-
-### List Owned Projects
-
-Lists all projects that the authenticated user owns.
-
-```
-GET /ci/projects/owned
-```
-
-Returns:
-
-```json
-[
- {
- "id" : 272,
- "name" : "gitlab-ci",
- "timeout" : 1800,
- "token" : "iPWx6WM4lhHNedGfBpPJNP",
- "default_ref" : "master",
- "gitlab_url" : "http://demo.gitlabhq.com/gitlab/gitlab-shell",
- "path" : "gitlab/gitlab-shell",
- "always_build" : false,
- "polling_interval" : null,
- "public" : false,
- "ssh_url_to_repo" : "git@demo.gitlab.com:gitlab/gitlab-shell.git",
- "gitlab_id" : 4
- }
-]
-```
-
-### Single Project
-
-Returns information about a single project for which the user is
-authorized.
-
- GET /ci/projects/:id
-
-Parameters:
-
- * `id` (required) - The ID of the GitLab CI project
-
-### Create Project
-
-Creates a GitLab CI project using GitLab project details.
-
- POST /ci/projects
-
-Parameters:
-
- * `name` (required) - The name of the project
- * `gitlab_id` (required) - The ID of the project on the GitLab instance
- * `default_ref` (optional) - The branch to run on (default to `master`)
-
-### Update Project
-
-Updates a GitLab CI project using GitLab project details that the
-authenticated user has access to.
-
- PUT /ci/projects/:id
-
-Parameters:
-
- * `name` - The name of the project
- * `default_ref` - The branch to run on (default to `master`)
-
-### Remove Project
-
-Removes a GitLab CI project that the authenticated user has access to.
-
- DELETE /ci/projects/:id
-
-Parameters:
-
- * `id` (required) - The ID of the GitLab CI project
-
-### Link Project to Runner
-
-Links a runner to a project so that it can make builds (only via
-authorized user).
-
- POST /ci/projects/:id/runners/:runner_id
-
-Parameters:
-
- * `id` (required) - The ID of the GitLab CI project
- * `runner_id` (required) - The ID of the GitLab CI runner
-
-### Remove Project from Runner
-
-Removes a runner from a project so that it can not make builds (only
-via authorized user).
-
- DELETE /ci/projects/:id/runners/:runner_id
-
-Parameters:
-
- * `id` (required) - The ID of the GitLab CI project
- * `runner_id` (required) - The ID of the GitLab CI runner \ No newline at end of file
diff --git a/doc/ci/api/runners.md b/doc/ci/api/runners.md
index e9033aeacd5..2f01da4bd76 100644
--- a/doc/ci/api/runners.md
+++ b/doc/ci/api/runners.md
@@ -1,81 +1,46 @@
# Runners API
+API used by runners to register and delete themselves.
+
_**Note:** This API is intended to be used only by Runners as their own
communication channel. For the consumer API see the
[new Runners API](../../api/runners.md)._
-## Runners
-
-### Retrieve all runners
+## Authentication
-__Authentication is done by GitLab user token & GitLab url__
+This API uses two types of authentication:
-Used to get information about all runners registered on the GitLab CI
-instance.
+1. Unique runner's token
- GET /ci/runners
+ Token assigned to runner after it has been registered.
-Returns:
+2. Using runners' registration token
-```json
-[
- {
- "id" : 85,
- "token" : "12b68e90394084703135"
- },
- {
- "id" : 86,
- "token" : "76bf894e969364709864"
- },
-]
-```
+ This is a token that can be found in project's settings.
+ It can be also found in Admin area » Runners settings.
-### Register a new runner
+ There are two types of tokens you can pass - shared runner registration
+ token or project specific registration token.
+## Runners
-__Authentication is done with a Shared runner registration token or a project Specific runner registration token__
+### Register a new runner
Used to make GitLab CI aware of available runners.
- POST /ci/runners/register
+ POST /ci/api/v1/runners/register
Parameters:
- * `token` (required) - The registration token. It is 2 types of token you can pass here.
+ * `token` (required) - Registration token
-1. Shared runner registration token
-2. Project specific registration token
-
-Returns:
-
-```json
-{
- "id" : 85,
- "token" : "12b68e90394084703135"
-}
-```
### Delete a runner
+Used to remove runner.
-__Authentication is done by runner token__
-
-Used to removing runners.
-
- DELETE /ci/runners/delete
+ DELETE /ci/api/v1/runners/delete
Parameters:
- * `token` (required) - The runner token.
-
-Returns:
-
-```json
-{
- "id" : 1,
- "token" : "d14963981a428f70121777e50643d1",
- "created_at" : "2015-02-26T11:39:39.232Z",
- "updated_at" : "2015-02-26T11:39:39.232Z",
- "description" : "awesome runner"
-}
-```
+ * `token` (required) - Unique runner token
diff --git a/doc/development/README.md b/doc/development/README.md
index b9a0d81e5ba..f5c3107ff44 100644
--- a/doc/development/README.md
+++ b/doc/development/README.md
@@ -9,4 +9,5 @@
- [Rake tasks](rake_tasks.md) for development
- [Shell commands](shell_commands.md) in the GitLab codebase
- [Sidekiq debugging](sidekiq_debugging.md)
+- [SQL guidelines](sql.md) for SQL guidelines
- [UI guide](ui_guide.md) for building GitLab with existing css styles and elements
diff --git a/doc/development/sql.md b/doc/development/sql.md
new file mode 100644
index 00000000000..23fd7604957
--- /dev/null
+++ b/doc/development/sql.md
@@ -0,0 +1,219 @@
+# SQL Query Guidelines
+
+This document describes various guidelines to follow when writing SQL queries,
+either using ActiveRecord/Arel or raw SQL queries.
+
+## Using LIKE Statements
+
+The most common way to search for data is using the `LIKE` statement. For
+example, to get all issues with a title starting with "WIP:" you'd write the
+following query:
+
+```sql
+SELECT *
+FROM issues
+WHERE title LIKE 'WIP:%';
+```
+
+On PostgreSQL the `LIKE` statement is case-sensitive. On MySQL this depends on
+the case-sensitivity of the collation, which is usually case-insensitive. To
+perform a case-insensitive `LIKE` on PostgreSQL you have to use `ILIKE` instead.
+This statement in turn isn't supported on MySQL.
+
+To work around this problem you should write `LIKE` queries using Arel instead
+of raw SQL fragments as Arel automatically uses `ILIKE` on PostgreSQL and `LIKE`
+on MySQL. This means that instead of this:
+
+```ruby
+Issue.where('title LIKE ?', 'WIP:%')
+```
+
+You'd write this instead:
+
+```ruby
+Issue.where(Issue.arel_table[:title].matches('WIP:%'))
+```
+
+Here `matches` generates the correct `LIKE` / `ILIKE` statement depending on the
+database being used.
+
+If you need to chain multiple `OR` conditions you can also do this using Arel:
+
+```ruby
+table = Issue.arel_table
+
+Issue.where(table[:title].matches('WIP:%').or(table[:foo].matches('WIP:%')))
+```
+
+For PostgreSQL this produces:
+
+```sql
+SELECT *
+FROM issues
+WHERE (title ILIKE 'WIP:%' OR foo ILIKE 'WIP:%')
+```
+
+In turn for MySQL this produces:
+
+```sql
+SELECT *
+FROM issues
+WHERE (title LIKE 'WIP:%' OR foo LIKE 'WIP:%')
+```
+
+## LIKE & Indexes
+
+Neither PostgreSQL nor MySQL use any indexes when using `LIKE` / `ILIKE` with a
+wildcard at the start. For example, this will not use any indexes:
+
+```sql
+SELECT *
+FROM issues
+WHERE title ILIKE '%WIP:%';
+```
+
+Because the value for `ILIKE` starts with a wildcard the database is not able to
+use an index as it doesn't know where to start scanning the indexes.
+
+MySQL provides no known solution to this problem. Luckily PostgreSQL _does_
+provide a solution: trigram GIN indexes. These indexes can be created as
+follows:
+
+```sql
+CREATE INDEX [CONCURRENTLY] index_name_here
+ON table_name
+USING GIN(column_name gin_trgm_ops);
+```
+
+The key here is the `GIN(column_name gin_trgm_ops)` part. This creates a [GIN
+index][gin-index] with the operator class set to `gin_trgm_ops`. These indexes
+_can_ be used by `ILIKE` / `LIKE` and can lead to greatly improved performance.
+One downside of these indexes is that they can easily get quite large (depending
+on the amount of data indexed).
+
+To keep naming of these indexes consistent please use the following naming
+pattern:
+
+ index_TABLE_on_COLUMN_trigram
+
+For example, a GIN/trigram index for `issues.title` would be called
+`index_issues_on_title_trigram`.
+
+Due to these indexes taking quite some time to be built they should be built
+concurrently. This can be done by using `CREATE INDEX CONCURRENTLY` instead of
+just `CREATE INDEX`. Concurrent indexes can _not_ be created inside a
+transaction. Transactions for migrations can be disabled using the following
+pattern:
+
+```ruby
+class MigrationName < ActiveRecord::Migration
+ disable_ddl_transaction!
+end
+```
+
+For example:
+
+```ruby
+class AddUsersLowerUsernameEmailIndexes < ActiveRecord::Migration
+ disable_ddl_transaction!
+
+ def up
+ return unless Gitlab::Database.postgresql?
+
+ execute 'CREATE INDEX CONCURRENTLY index_on_users_lower_username ON users (LOWER(username));'
+ execute 'CREATE INDEX CONCURRENTLY index_on_users_lower_email ON users (LOWER(email));'
+ end
+
+ def down
+ return unless Gitlab::Database.postgresql?
+
+ remove_index :users, :index_on_users_lower_username
+ remove_index :users, :index_on_users_lower_email
+ end
+end
+```
+
+## Plucking IDs
+
+This can't be stressed enough: **never** use ActiveRecord's `pluck` to pluck a
+set of values into memory only to use them as an argument for another query. For
+example, this will make the database **very** sad:
+
+```ruby
+projects = Project.all.pluck(:id)
+
+MergeRequest.where(source_project_id: projects)
+```
+
+Instead you can just use sub-queries which perform far better:
+
+```ruby
+MergeRequest.where(source_project_id: Project.all.select(:id))
+```
+
+The _only_ time you should use `pluck` is when you actually need to operate on
+the values in Ruby itself (e.g. write them to a file). In almost all other cases
+you should ask yourself "Can I not just use a sub-query?".
+
+## Use UNIONs
+
+UNIONs aren't very commonly used in most Rails applications but they're very
+powerful and useful. In most applications queries tend to use a lot of JOINs to
+get related data or data based on certain criteria, but JOIN performance can
+quickly deteriorate as the data involved grows.
+
+For example, if you want to get a list of projects where the name contains a
+value _or_ the name of the namespace contains a value most people would write
+the following query:
+
+```sql
+SELECT *
+FROM projects
+JOIN namespaces ON namespaces.id = projects.namespace_id
+WHERE projects.name ILIKE '%gitlab%'
+OR namespaces.name ILIKE '%gitlab%';
+```
+
+Using a large database this query can easily take around 800 milliseconds to
+run. Using a UNION we'd write the following instead:
+
+```sql
+SELECT projects.*
+FROM projects
+WHERE projects.name ILIKE '%gitlab%'
+
+UNION
+
+SELECT projects.*
+FROM projects
+JOIN namespaces ON namespaces.id = projects.namespace_id
+WHERE namespaces.name ILIKE '%gitlab%';
+```
+
+This query in turn only takes around 15 milliseconds to complete while returning
+the exact same records.
+
+This doesn't mean you should start using UNIONs everywhere, but it's something
+to keep in mind when using lots of JOINs in a query and filtering out records
+based on the joined data.
+
+GitLab comes with a `Gitlab::SQL::Union` class that can be used to build a UNION
+of multiple `ActiveRecord::Relation` objects. You can use this class as
+follows:
+
+```ruby
+union = Gitlab::SQL::Union.new([projects, more_projects, ...])
+
+Project.from("(#{union.to_sql}) projects")
+```
+
+## Ordering by Creation Date
+
+When ordering records based on the time they were created you can simply order
+by the `id` column instead of ordering by `created_at`. Because IDs are always
+unique and incremented in the order that rows are created this will produce the
+exact same results. This also means there's no need to add an index on
+`created_at` to ensure consistent performance as `id` is already indexed by
+default.
+
+[gin-index]: http://www.postgresql.org/docs/current/static/gin.html
diff --git a/doc/hooks/custom_hooks.md b/doc/hooks/custom_hooks.md
index 0f2665a3bf7..5a4b2f43ba7 100644
--- a/doc/hooks/custom_hooks.md
+++ b/doc/hooks/custom_hooks.md
@@ -2,7 +2,7 @@
**Note: Custom git hooks must be configured on the filesystem of the GitLab
server. Only GitLab server administrators will be able to complete these tasks.
-Please explore webhooks as an option if you do not have filesystem access. For a user configurable Git Hooks interface, please see [GitLab Enterprise Edition Git Hooks](http://doc.gitlab.com/ee/git_hooks/git_hooks.html).**
+Please explore [web hooks](doc/web_hooks/web_hooks.md) as an option if you do not have filesystem access. For a user configurable Git Hooks interface, please see [GitLab Enterprise Edition Git Hooks](http://doc.gitlab.com/ee/git_hooks/git_hooks.html).**
Git natively supports hooks that are executed on different actions.
Examples of server-side git hooks include pre-receive, post-receive, and update.
diff --git a/doc/install/installation.md b/doc/install/installation.md
index c1787a7c6a8..0fd54be58b0 100644
--- a/doc/install/installation.md
+++ b/doc/install/installation.md
@@ -467,12 +467,15 @@ NOTE: Supply `SANITIZE=true` environment variable to `gitlab:check` to omit proj
### Initial Login
-Visit YOUR_SERVER in your web browser for your first GitLab login. The setup has created a default admin account for you. You can use it to log in:
+Visit YOUR_SERVER in your web browser for your first GitLab login.
- root
- 5iveL!fe
+If you didn't [provide a root password during setup](#initialize-database-and-activate-advanced-features),
+you'll be redirected to a password reset screen to provide the password for the
+initial administrator account. Enter your desired password and you'll be
+redirected back to the login screen.
-**Important Note:** On login you'll be prompted to change the password.
+The default account's username is **root**. Provide the password you created
+earlier and login. After login you can change the username if you wish.
**Enjoy!**
diff --git a/doc/integration/README.md b/doc/integration/README.md
index 281eea8363d..7c8f785a61f 100644
--- a/doc/integration/README.md
+++ b/doc/integration/README.md
@@ -39,3 +39,34 @@ please see the [project_services directory][projects-code].
[jenkins]: http://doc.gitlab.com/ee/integration/jenkins.html
[Project Service]: ../project_services/project_services.md
[projects-code]: https://gitlab.com/gitlab-org/gitlab-ce/tree/master/app/models/project_services
+
+## SSL certificate errors
+
+When trying to integrate GitLab with services that are using self-signed certificates,
+it is very likely that SSL certificate errors will occur on different parts of the
+application, most likely Sidekiq. There are 2 approaches you can take to solve this:
+
+1. Add the root certificate to the trusted chain of the OS.
+1. If using Omnibus, you can add the certificate to GitLab's trusted certificates.
+
+**OS main trusted chain**
+
+This [resource](http://kb.kerio.com/product/kerio-connect/server-configuration/ssl-certificates/adding-trusted-root-certificates-to-the-server-1605.html)
+has all the information you need to add a certificate to the main trusted chain.
+
+This [answer](http://superuser.com/questions/437330/how-do-you-add-a-certificate-authority-ca-to-ubuntu)
+at SuperUser also has relevant information.
+
+**Omnibus Trusted Chain**
+
+It is enough to concatenate the certificate to the main trusted certificate:
+
+```bash
+cat jira.pem >> /opt/gitlab/embedded/ssl/certs/cacert.pem
+```
+
+After that restart GitLab with:
+
+```bash
+sudo gitlab-ctl restart
+```
diff --git a/doc/integration/ldap.md b/doc/integration/ldap.md
index f256477196b..cf1f98492ea 100644
--- a/doc/integration/ldap.md
+++ b/doc/integration/ldap.md
@@ -204,3 +204,25 @@ When setting `method: ssl`, the underlying authentication method used by
`omniauth-ldap` is `simple_tls`. This method establishes TLS encryption with
the LDAP server before any LDAP-protocol data is exchanged but no validation of
the LDAP server's SSL certificate is performed.
+
+## Troubleshooting
+
+### Invalid credentials when logging in
+
+Make sure the user you are binding with has enough permissions to read the user's
+tree and traverse it.
+
+Also make sure that the `user_filter` is not blocking otherwise valid users.
+
+To make sure that the LDAP settings are correct and GitLab can see your users,
+execute the following command:
+
+
+```bash
+# For Omnibus installations
+sudo gitlab-rake gitlab:ldap:check
+
+# For installations from source
+sudo -u git -H bundle exec rake gitlab:ldap:check RAILS_ENV=production
+```
+
diff --git a/doc/integration/saml.md b/doc/integration/saml.md
index c84113556cd..148c4ac1886 100644
--- a/doc/integration/saml.md
+++ b/doc/integration/saml.md
@@ -133,12 +133,16 @@ will be returned to GitLab and will be signed in.
## Troubleshooting
+### 500 error after login
+
If you see a "500 error" in GitLab when you are redirected back from the SAML sign in page,
this likely indicates that GitLab could not get the email address for the SAML user.
Make sure the IdP provides a claim containing the user's email address, using claim name
`email` or `mail`.
+### Redirect back to login screen with no evident error
+
If after signing in into your SAML server you are redirected back to the sign in page and
no error is displayed, check your `production.log` file. It will most likely contain the
message `Can't verify CSRF token authenticity`. This means that there is an error during
@@ -147,4 +151,36 @@ the SAML request, but this error never reaches GitLab due to the CSRF check.
To bypass this you can add `skip_before_action :verify_authenticity_token` to the
`omniauth_callbacks_controller.rb` file. This will allow the error to hit GitLab,
where it can then be seen in the usual logs, or as a flash message in the login
-screen. \ No newline at end of file
+screen.
+
+### Invalid audience
+
+This error means that the IdP doesn't recognize GitLab as a valid sender and
+receiver of SAML requests. Make sure to add the GitLab callback URL to the approved
+audiences of the IdP server.
+
+### Missing claims
+
+The IdP server needs to pass certain information in order for GitLab to either
+create an account, or match the login information to an existing account. `email`
+is the minimum amount of information that needs to be passed. If the IdP server
+is not providing this information, all SAML requests will fail.
+
+Make sure this information is provided.
+
+### Key validation error, Digest mismatch or Fingerprint mismatch
+
+These errors all come from a similar place, the SAML certificate. SAML requests
+need to be validated using a fingerprint, a certificate or a validator.
+
+For this you need take the following into account:
+
+- If no certificate is provided in the settings, a fingerprint or fingerprint
+ validator needs to be provided and the response from the server must contain
+ a certificate (`<ds:KeyInfo><ds:X509Data><ds:X509Certificate>`)
+- If a certificate is provided in the settings, it is no longer necessary for
+ the request to contain one. In this case the fingerprint or fingerprint
+ validators are optional
+
+Make sure that one of the above described scenarios is valid, or the requests will
+fail with one of the mentioned errors. \ No newline at end of file
diff --git a/doc/integration/slack.md b/doc/integration/slack.md
index ecbe0d3e887..f6ba80f46d5 100644
--- a/doc/integration/slack.md
+++ b/doc/integration/slack.md
@@ -2,19 +2,11 @@
## On Slack
-To enable Slack integration you must create an Incoming WebHooks integration on Slack;
+To enable Slack integration you must create an Incoming WebHooks integration on Slack:
1. [Sign in to Slack](https://slack.com/signin)
-1. Select **Apps & Custom Integrations** from the dropdown next to your team name.
-
-1. Click the **Configure** link (right-upper corner).
-
-1. Select the **Custom integrations** tab.
-
-1. Click the **Incoming WebHooks** row.
-
-1. Click the **Add configuration** button.
+1. Visit [Incoming WebHooks](https://my.slack.com/services/new/incoming-webhook/)
1. Choose the channel name you want to send notifications to.
diff --git a/doc/markdown/markdown.md b/doc/markdown/markdown.md
index c400cdac64d..cbf57db5684 100644
--- a/doc/markdown/markdown.md
+++ b/doc/markdown/markdown.md
@@ -207,6 +207,7 @@ GFM also recognizes certain cross-project references:
| `namespace/project$123` | snippet |
| `namespace/project@9ba12248` | specific commit |
| `namespace/project@9ba12248...b19a04f5` | commit range comparison |
+| `namespace/project~"Some label"` | issues with given label |
## Task Lists
diff --git a/doc/project_services/jira.md b/doc/project_services/jira.md
index 7c12557a321..27170c1eb19 100644
--- a/doc/project_services/jira.md
+++ b/doc/project_services/jira.md
@@ -219,3 +219,16 @@ You can see from the above image that there are four references to GitLab:
[JIRA Core]: https://www.atlassian.com/software/jira/core "The JIRA Core website"
[jira-ce]: https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/2146 "MR - Backport JIRA service"
[8_3_post]: https://about.gitlab.com/2015/12/22/gitlab-8-3-released/ "GitLab 8.3 release post"
+
+## Troubleshooting
+
+### GitLab is unable to comment on a ticket
+
+Make sure that the user you set up for GitLab to communicate with JIRA has the
+correct access permission to post comments on a ticket and to also transition the
+ticket, if you'd like GitLab to also take care of closing them.
+
+### GitLab is unable to close a ticket
+
+Make sure the the `Transition ID` you set within the JIRA settings matches the
+one your project needs to close a ticket.
diff --git a/doc/update/8.4-to-8.5.md b/doc/update/8.4-to-8.5.md
index 408a17ac348..0a9cb5683e7 100644
--- a/doc/update/8.4-to-8.5.md
+++ b/doc/update/8.4-to-8.5.md
@@ -64,6 +64,9 @@ sudo -u git -H bundle install --without postgres development test --deployment
# PostgreSQL installations (note: the line below states '--without mysql')
sudo -u git -H bundle install --without mysql development test --deployment
+# Optional: clean up old gems
+sudo -u git -H bundle clean
+
# Run database migrations
sudo -u git -H bundle exec rake db:migrate RAILS_ENV=production
diff --git a/doc/update/patch_versions.md b/doc/update/patch_versions.md
index a10e62877ba..f446ed0a35b 100644
--- a/doc/update/patch_versions.md
+++ b/doc/update/patch_versions.md
@@ -62,7 +62,13 @@ sudo -u git -H bundle install --without development test mysql --deployment
# MySQL
sudo -u git -H bundle install --without development test postgres --deployment
+# Optional: clean up old gems
+sudo -u git -H bundle clean
+
+# Run database migrations
sudo -u git -H bundle exec rake db:migrate RAILS_ENV=production
+
+# Clean up assets and cache
sudo -u git -H bundle exec rake assets:clean assets:precompile cache:clear RAILS_ENV=production
```
diff --git a/doc/update/upgrader.md b/doc/update/upgrader.md
index fd0327686b1..5fa39ef1b0a 100644
--- a/doc/update/upgrader.md
+++ b/doc/update/upgrader.md
@@ -4,7 +4,7 @@
Although deprecated, if someone wants to make this script into a gem or otherwise improve it merge requests are welcome.
-*Make sure you view this [upgrade guide from the 'master' branch](../../../master/doc/update/upgrader.md) for the most up to date instructions.*
+*Make sure you view this [upgrade guide from the 'master' branch](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/doc/update/upgrader.md) for the most up to date instructions.*
GitLab Upgrader - a ruby script that allows you easily upgrade GitLab to latest minor version.
diff --git a/doc/web_hooks/web_hooks.md b/doc/web_hooks/web_hooks.md
index b82306bd1da..e2b53c45ab1 100644
--- a/doc/web_hooks/web_hooks.md
+++ b/doc/web_hooks/web_hooks.md
@@ -582,7 +582,6 @@ X-Gitlab-Event: Note Hook
"created_at": "2015-04-09 02:40:38 UTC",
"updated_at": "2015-04-09 02:40:38 UTC",
"file_name": "test.rb",
- "expires_at": null,
"type": "ProjectSnippet",
"visibility_level": 0
}
diff --git a/doc/workflow/lfs/lfs_administration.md b/doc/workflow/lfs/lfs_administration.md
index 5076b2697a3..36cb9da2380 100644
--- a/doc/workflow/lfs/lfs_administration.md
+++ b/doc/workflow/lfs/lfs_administration.md
@@ -9,7 +9,8 @@ Documentation on how to use Git LFS are under [Managing large binary files with
## Configuration
-Git LFS objects can be large in size. By default, they are stored on the server GitLab is installed on.
+Git LFS objects can be large in size. By default, they are stored on the server
+GitLab is installed on.
There are two configuration options to help GitLab server administrators:
@@ -37,5 +38,8 @@ In `config/gitlab.yml`:
## Known limitations
-* Currently, storing GitLab Git LFS objects on a non-local storage (like S3 buckets) is not supported
+* Currently, storing GitLab Git LFS objects on a non-local storage (like S3 buckets)
+ is not supported
* Currently, removing LFS objects from GitLab Git LFS storage is not supported
+* LFS authentications via SSH is not supported for the time being
+* Only compatible with the GitLFS client versions 1.1.0 or 1.0.2.
diff --git a/doc/workflow/lfs/manage_large_binaries_with_git_lfs.md b/doc/workflow/lfs/manage_large_binaries_with_git_lfs.md
index b59e92cb317..ba91685a20b 100644
--- a/doc/workflow/lfs/manage_large_binaries_with_git_lfs.md
+++ b/doc/workflow/lfs/manage_large_binaries_with_git_lfs.md
@@ -1,17 +1,21 @@
# Git LFS
-Managing large files such as audio, video and graphics files has always been one of the shortcomings of Git.
-The general recommendation is to not have Git repositories larger than 1GB to preserve performance.
+Managing large files such as audio, video and graphics files has always been one
+of the shortcomings of Git. The general recommendation is to not have Git repositories
+larger than 1GB to preserve performance.
-GitLab already supports [managing large files with git annex](http://doc.gitlab.com/ee/workflow/git_annex.html) (EE only), however in certain
-environments it is not always convenient to use different commands to differentiate between the large files and regular ones.
+GitLab already supports [managing large files with git annex](http://doc.gitlab.com/ee/workflow/git_annex.html)
+(EE only), however in certain environments it is not always convenient to use
+different commands to differentiate between the large files and regular ones.
-Git LFS makes this simpler for the end user by removing the requirement to learn new commands.
+Git LFS makes this simpler for the end user by removing the requirement to
+learn new commands.
## How it works
-Git LFS client talks with the GitLab server over HTTPS. It uses HTTP Basic Authentication to authorize client requests.
-Once the request is authorized, Git LFS client receives instructions from where to fetch or where to push the large file.
+Git LFS client talks with the GitLab server over HTTPS. It uses HTTP Basic Authentication
+to authorize client requests. Once the request is authorized, Git LFS client receives
+instructions from where to fetch or where to push the large file.
## GitLab server configuration
@@ -24,15 +28,19 @@ Documentation for GitLab instance administrators is under [LFS administration do
## Known limitations
-* Git LFS v1 original API is not supported since it was deprecated early in LFS development
+* Git LFS v1 original API is not supported since it was deprecated early in LFS
+ development
* When SSH is set as a remote, Git LFS objects still go through HTTPS
-* Any Git LFS request will ask for HTTPS credentials to be provided so good Git credentials store is recommended
-* Git LFS always assumes HTTPS so if you have GitLab server on HTTP you will have to add the URL to Git config manually (see #troubleshooting)
+* Any Git LFS request will ask for HTTPS credentials to be provided so good Git
+ credentials store is recommended
+* Git LFS always assumes HTTPS so if you have GitLab server on HTTP you will have
+ to add the URL to Git config manually (see #troubleshooting)
## Using Git LFS
-Lets take a look at the workflow when you need to check large files into your Git repository with Git LFS:
-For example, if you want to upload a very large file and check it into your Git repository:
+Lets take a look at the workflow when you need to check large files into your Git
+repository with Git LFS. For example, if you want to upload a very large file and
+check it into your Git repository:
```bash
git clone git@gitlab.example.com:group/project.git
@@ -40,7 +48,8 @@ git lfs init # initialize the Git LFS project project
git lfs track "*.iso" # select the file extensions that you want to treat as large files
```
-Once a certain file extension is marked for tracking as a LFS object you can use Git as usual without having to redo the command to track a file with the same extension:
+Once a certain file extension is marked for tracking as a LFS object you can use
+Git as usual without having to redo the command to track a file with the same extension:
```bash
cp ~/tmp/debian.iso ./ # copy a large file into the current directory
@@ -49,13 +58,17 @@ git commit -am "Added Debian iso" # commit the file meta data
git push origin master # sync the git repo and large file to the GitLab server
```
-Cloning the repository works the same as before. Git automatically detects the LFS-tracked files and clones them via HTTP. If you performed the git clone command with a SSH URL, you have to enter your GitLab credentials for HTTP authentication.
+Cloning the repository works the same as before. Git automatically detects the
+LFS-tracked files and clones them via HTTP. If you performed the git clone
+command with a SSH URL, you have to enter your GitLab credentials for HTTP
+authentication.
```bash
git clone git@gitlab.example.com:group/project.git
```
-If you already cloned the repository and you want to get the latest LFS object that are on the remote repository, eg. from branch `master`:
+If you already cloned the repository and you want to get the latest LFS object
+that are on the remote repository, eg. from branch `master`:
```bash
git lfs fetch master
@@ -73,8 +86,8 @@ Check if you have permissions to push to the project or fetch from the project.
* Project is not allowed to access the LFS object
-LFS object you are trying to push to the project or fetch from the project is not available to the project anymore.
-Probably the object was removed from the server.
+LFS object you are trying to push to the project or fetch from the project is not
+available to the project anymore. Probably the object was removed from the server.
* Local git repository is using deprecated LFS API
@@ -89,16 +102,26 @@ git lfs logs last
If the status `error 501` is shown, it is because:
-* Git LFS support is not enabled on the GitLab server. Check with your GitLab administrator why Git LFS is not enabled on the server. See [LFS administration documentation](lfs_administration.md) for instructions on how to enable LFS support.
+* Git LFS support is not enabled on the GitLab server. Check with your GitLab
+ administrator why Git LFS is not enabled on the server. See
+ [LFS administration documentation](lfs_administration.md) for instructions
+ on how to enable LFS support.
-* Git LFS client version is not supported by GitLab server. Check your Git LFS version with `git lfs version`. Check the Git config of the project for traces of deprecated API with `git lfs -l`. If `batch = false` is set in the config, remove the line and try to update your Git LFS client. Only version 1.0.1 and newer are supported.
+* Git LFS client version is not supported by GitLab server. Check your Git LFS
+ version with `git lfs version`. Check the Git config of the project for traces
+ of deprecated API with `git lfs -l`. If `batch = false` is set in the config,
+ remove the line and try to update your Git LFS client. Only version 1.0.1 and
+ newer are supported.
### getsockopt: connection refused
-If you push a LFS object to a project and you receive an error similar to: `Post <URL>/info/lfs/objects/batch: dial tcp IP: getsockopt: connection refused`,
-the LFS client is trying to reach GitLab through HTTPS. However, your GitLab instance is being served on HTTP.
+If you push a LFS object to a project and you receive an error similar to:
+`Post <URL>/info/lfs/objects/batch: dial tcp IP: getsockopt: connection refused`,
+the LFS client is trying to reach GitLab through HTTPS. However, your GitLab
+instance is being served on HTTP.
-This behaviour is caused by Git LFS using HTTPS connections by default when a `lfsurl` is not set in the Git config.
+This behaviour is caused by Git LFS using HTTPS connections by default when a
+`lfsurl` is not set in the Git config.
To prevent this from happening, set the lfs url in project Git config:
@@ -109,18 +132,24 @@ git config --add lfs.url "http://gitlab.example.com/group/project.git/info/lfs/o
### Credentials are always required when pushing an object
-Given that Git LFS uses HTTP Basic Authentication to authenticate the user pushing the LFS object on every push for every object, user HTTPS credentials are required.
+Given that Git LFS uses HTTP Basic Authentication to authenticate the user pushing
+the LFS object on every push for every object, user HTTPS credentials are required.
-By default, Git has support for remembering the credentials for each repository you use. This is described in [Git credentials man pages](https://git-scm.com/docs/gitcredentials).
+By default, Git has support for remembering the credentials for each repository
+you use. This is described in [Git credentials man pages](https://git-scm.com/docs/gitcredentials).
-For example, you can tell Git to remember the password for a period of time in which you expect to push the objects:
+For example, you can tell Git to remember the password for a period of time in
+which you expect to push the objects:
```bash
git config --global credential.helper 'cache --timeout=3600'
```
-This will remember the credentials for an hour after which Git operations will require re-authentication.
+This will remember the credentials for an hour after which Git operations will
+require re-authentication.
-If you are using OS X you can use `osxkeychain` to store and encrypt your credentials. For Windows, you can use `wincred` or Microsoft's [Git Credential Manager for Windows](https://github.com/Microsoft/Git-Credential-Manager-for-Windows/releases).
+If you are using OS X you can use `osxkeychain` to store and encrypt your credentials.
+For Windows, you can use `wincred` or Microsoft's [Git Credential Manager for Windows](https://github.com/Microsoft/Git-Credential-Manager-for-Windows/releases).
-More details about various methods of storing the user credentials can be found on [Git Credential Storage documentation](https://git-scm.com/book/en/v2/Git-Tools-Credential-Storage). \ No newline at end of file
+More details about various methods of storing the user credentials can be found
+on [Git Credential Storage documentation](https://git-scm.com/book/en/v2/Git-Tools-Credential-Storage). \ No newline at end of file