---
id: lint
slug: /versioned/lint
title: Verifying migration safety
---

import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';

The `atlas migrate lint` command enables team members to work together on database schemas, ensuring they are synchronized
and avoid stepping on each other's toes. Atlas analyzes new schema changes in the migration directory that might
be dangerous, violate best practices, or break the team's policies. Learn more about [Atlas's analyzers](/lint/analyzers).

While this command is commonly used locally, migration linting is frequently incorporated into CI pipelines, allowing
teams to detect changes early before merging them into the main branch. Learn more on how to integrate Atlas into
your [GitHub Actions](/cloud/setup-ci) or [GitLab](/guides/ci-platforms/gitlab) CI pipelines.

### Flags

When using `migrate lint` to analyze migrations, users must supply multiple parameters:
* `--dev-url` - [URL](/concepts/url) to a [Dev-database](/concepts/dev-database) that will be used
 to simulate the changes and verify their correctness.
* `--dir` - URL of the migration directory, by default it is `file://migrations`, e.g a
 directory named `migrations` in the current working directory.
* `--web` / `-w` (optional) - open the lint report in the browser.

### Changeset detection

When we run the `lint` command, we need to instruct Atlas on how to decide which set of migration files to analyze.
Currently, three ways are supported. Let's go over them one by one:

#### Compare against the latest state of the migration directory

Teams that have connected their project to Atlas Cloud (see [setup](/cloud/setup-ci) for more details), can simply run
the following command to analyze the changes detected by comparing the **local state** of the migration directory
to the **latest state**, as defined in Atlas Cloud. For example, either by running `atlas migrate push` or by connecting
it to a CI pipeline.

<Tabs>
<TabItem value="mysql" label="MySQL">

```shell
atlas migrate lint \
  --dev-url "docker://mysql/8/dev" \
  -w
```

</TabItem>
<TabItem value="maria" label="MariaDB">

```shell
atlas migrate lint \
  --dev-url "docker://mariadb/latest/dev" \
  -w
```

</TabItem>
<TabItem value="postgres" label="PostgreSQL">

```shell
atlas migrate lint \
  --dev-url "docker://postgres/15/test?search_path=public" \
  -w
```

</TabItem>
<TabItem value="sqlite" label="SQLite">

```shell
atlas migrate lint \
  --dev-url "sqlite://file?mode=memory" \
  -w
```

</TabItem>
</Tabs>

:::info Preventing non-additive changes
By using this method, Atlas warns you if your local migration directory is not up-to-date with the latest state
of the project and rebasing is required. For example, while working on a feature branch, another team member might have
pushed a new migration file to the main branch.
:::

Here is an example of how a report of `atlas migrate lint` looks like:

![CI for schema changes](https://atlasgo.io/uploads/lint-report-non-additive.png)


#### Analyze the latest N migration files

Users can instruct Atlas to analyze the latest N migration files by running `atlas migrate lint --latest N`:

<Tabs>
<TabItem value="mysql" label="MySQL">

```shell
atlas migrate lint \
  --dev-url "docker://mysql/8/dev" \
  --latest 1
```

</TabItem>
<TabItem value="maria" label="MariaDB">

```shell
atlas migrate lint \
  --dev-url "docker://mariadb/latest/dev" \
  --latest 1
```

</TabItem>
<TabItem value="postgres" label="PostgreSQL">

```shell
atlas migrate lint \
  --dev-url "docker://postgres/15/test?search_path=public" \
  --latest 1
```

</TabItem>
<TabItem value="sqlite" label="SQLite">

```shell
atlas migrate lint \
  --dev-url "sqlite://file?mode=memory" \
  --latest 1
```

</TabItem>
</Tabs>

Similarly to the previous method, the `-w`/`--web` can be used to open the report in the browser, see the changes in ERD
format, and more.

#### Compare against a specific branch

Users can instruct Atlas to detect which changes to analyze by comparing the current branch to a specific branch.
For example, in order to analyze the changes between the current branch and the `main` branch, and open the report in the
browser, run the following command:

<Tabs>
<TabItem value="mysql" label="MySQL">

```shell
atlas migrate lint \
  --dev-url "docker://mysql/8/dev" \
  --git-base "master" \
  -w
```

</TabItem>
<TabItem value="maria" label="MariaDB">

```shell
atlas migrate lint \
  --dev-url "docker://mariadb/latest/dev" \
  --git-base "master" \
  -w
```

</TabItem>
<TabItem value="postgres" label="PostgreSQL">

```shell
atlas migrate lint \
  --dev-url "docker://postgres/15/test?search_path=public" \
  --git-base "master" \
  -w
```

</TabItem>
<TabItem value="sqlite" label="SQLite">

```shell
atlas migrate lint \
  --dev-url "sqlite://file?mode=memory" \
  --git-base "master" \
  -w
```

</TabItem>
</Tabs>

### `nolint` directive

Annotating a statement with the `--atlas:nolint` directive allows excluding it from the analysis reporting. For example:

<Tabs
defaultValue="all-changes"
values={[
{label: 'All changes', value: 'all-changes'},
{label: 'Class of changes', value: 'by-name'},
{label: 'Specific checks', value: 'by-check'},
{label: 'File level', value: 'file-level'},
]}>
<TabItem value="all-changes">

Using `--atlas:nolint` excludes the annotated statement from all linters.

```sql
//highlight-next-line
-- atlas:nolint
ALTER TABLE `t1` DROP COLUMN `c1`, ADD COLUMN `d1` varchar(255) NOT NULL;

//highlight-next-line
--atlas:nolint
ALTER TABLE `t2` DROP COLUMN `c2`, ADD COLUMN `d2` varchar(255) NOT NULL;

//highlight-next-line
/*atlas:nolint*/
ALTER TABLE `t3` DROP COLUMN `c3`, ADD COLUMN `d3` varchar(255) NOT NULL;

//highlight-next-line
#atlas:nolint
ALTER TABLE `t4` DROP COLUMN `c4`, ADD COLUMN `d4` varchar(255) NOT NULL;
```

</TabItem>
<TabItem value="by-name">

Using `--atlas:nolint [names...]` excludes reporting specific analyzers for the annotated statements.

```sql
//highlight-next-line
-- Ignore reporting destructive changes.
//highlight-next-line
-- atlas:nolint destructive
ALTER TABLE `t1` DROP COLUMN `c1`, ADD COLUMN `d1` varchar(255) NOT NULL;

//highlight-next-line
-- Ignore reporting destructive and data-dependent changes.
//highlight-next-line
--atlas:nolint destructive data_depend
ALTER TABLE `t2` DROP COLUMN `c2`, ADD COLUMN `d2` varchar(255) NOT NULL;

//highlight-next-line
/*atlas:nolint data_depend*/
ALTER TABLE `t3` DROP COLUMN `c3`, ADD COLUMN `d3` varchar(255) NOT NULL;

//highlight-next-line
#atlas:nolint destructive data_depend
ALTER TABLE `t4` DROP COLUMN `c4`, ADD COLUMN `d4` varchar(255) NOT NULL;
```

</TabItem>

<TabItem value="by-check">

Using `--atlas:nolint [checks...]` excludes reporting specific [checks](../lint/analyzers.mdx#checks) for the annotated
statement.

```sql
//highlight-next-line
-- atlas:nolint DS103 MY101
ALTER TABLE `t1` DROP COLUMN `c1`, ADD COLUMN `d1` varchar(255) NOT NULL;
```

</TabItem>


<TabItem value="file-level">

The `--atlas:nolint` directive can be used to exclude the whole file (given at top) from analysis, or to exclude specific
statements in the file from specific [checks](../lint/analyzers.mdx#checks) or analyzers.

```sql
//highlight-next-line
-- atlas:nolint

ALTER TABLE `t1` DROP COLUMN `c1`, ADD COLUMN `d1` varchar(255) NOT NULL;

DROP TABLE `t2`;
```

Skip a specific analyzer for all statements in the file:

```sql
//highlight-next-line
-- atlas:nolint destructive

ALTER TABLE `t1` DROP COLUMN `c1`, ADD COLUMN `d1` varchar(255) NOT NULL;

DROP TABLE `t2`;
```

:::note
File directives are located at the top of the file and should not be associated with any statement. Hence, double new
lines are used to separate file directives from its content.
:::

</TabItem>
</Tabs>

### Open in the browser

In order to open the migration linting report in the browser, you first need to be logged in to Atlas, then use one of
the example commands above with the `-w`/`--web` flag. For example:

<Tabs>
<TabItem value="mysql" label="MySQL">

```shell
atlas login
```

```shell
atlas migrate lint \
  --dev-url "docker://mysql/8/dev" \
  --latest 1 \
  -w
```

</TabItem>
<TabItem value="maria" label="MariaDB">

```shell
atlas login
```

```shell
atlas migrate lint \
  --dev-url "docker://mariadb/latest/dev" \
  --latest 1 \
  -w
```

</TabItem>
<TabItem value="postgres" label="PostgreSQL">

```shell
atlas login
```

```shell
atlas migrate lint \
  --dev-url "docker://postgres/15/test?search_path=public" \
  --latest 1 \
  -w
```

</TabItem>
<TabItem value="sqlite" label="SQLite">

```shell
atlas login
```

```shell
atlas migrate lint \
  --dev-url "sqlite://file?mode=memory" \
  --latest 1 \
  -w
```

</TabItem>
</Tabs>

<details><summary>Screenshot example</summary>

![CI for schema changes](https://atlasgo.io/uploads/lint-report-non-additive.png)

</details>

### Output

Users may supply a [Go template](https://pkg.go.dev/text/template) string as the `--format` parameter to
format the output of the `lint` command.

### Reference

[CLI Command Reference](/cli-reference#atlas-migrate-lint)