rollback
The rollback
command rolls back changes made to the database based on the specified tag.
Uses
The rollback
command is typically used to revert all changes that were made to the database after the tag you specify.
Command behavior
When you run rollback
, Liquibase will roll back sequentially all the deployed changes until it reaches the tag row in the DATABASECHANGELOG table. For example, you can use the rollback
command when you want to undo a series of changes made to your database related to a specific tag such as a numbered release. If you have tags for release 1
, release 2
, and release 3
, and need to make a correction in release 2
, the rollback
command will rollback release 3
first.
You must specify a tag with the tag
command or the tagDatabase
Change Type in your changelog file for rollback
to work. If Liquibase cannot find your tag, it halts and displays the following message:
rollback: Unexpected error running Liquibase: Could not find tag 'doesntexist' in the database
Tip: Before running this command, it is a best practice to run tag-exists
to check whether your tag syntax is correct. It is also a best practice to copy+paste the name of the tag into the CLI so that you are less likely to misspell it.
The following image shows that if we deploy the createTable C
changeset and run the rollback --tag=version1
command to revert changes, Liquibase will roll back only createTable C
value:
In Liquibase Pro 4.27.0 and later, you can automatically generate a database Rollback Report summarizing this command.
Impact
Using the rollback
command comes with risks to your database, so it's important to look for potential unintended consequences before executing this command. You can do this with the rollback-sql command.
Syntax
To run the rollback
command, specify the driver, classpath, and URL in the Liquibase properties file. For more information, see Create and Configure a liquibase.properties File. You can also specify these properties in your command line.
Also, before running the rollback
command, you need to know the following:
- If the tag name is unknown to you, you can find it in the DATABASECHANGELOG table.
- If you don't have any tags specified, you can run the tag command. If you run the
tag
command to mark the current database state or release, your tag will be applied to the last row in the DATABASECHANGELOG table. - If you use the tagDatabase Change Type to create a tag changeset in the changelog file and want to roll back changes applied after this tag, the
rollback
command will remove all changes made after this tag row and the tag row. - If you run the
tag
command, deploy changesets, and then add thetagDatabase
Change Type in your changelog file, your changes and the tag row created by thetagDatabase
Change Type will be removed till the command reaches the tag specified with therollback
command.
liquibase rollback --tag=myTag --changelog-file=example-changelog.xml
Note: The --tag=myTag
syntax was added in Liquibase 4.4. If you use an older version, specify your tag as a positional argument: <command> myTag
.
Command parameters
Attribute | Definition | Requirement |
---|---|---|
|
The root changelog |
Required |
|
The tag identifying which tagged changesets in the changelog to evaluate. Specify as |
Required |
|
The JDBC database connection URL. See Using JDBC URL in Liquibase. |
Required |
|
Fully-qualified class which specifies a |
Optional |
|
Path to a properties file for the |
Optional |
|
Specifies the changeset contexts to match. Contexts are tags you can add to changesets to control which changesets are executed in any particular migration run. Note: If you use Liquibase 4.23.0 or earlier, use the syntax |
Optional |
|
Name of the default catalog to use for the database connection |
Optional |
|
Name of the default schema to use for the database connection. If Tip: In Liquibase v4.23.0+, camelCase for Note: The syntax |
Optional |
|
The JDBC driver class |
Optional |
|
The JDBC driver properties file |
Optional |
|
Specifies the changeset labels to match. Labels are tags you can add to changesets to control which changesets will be executed in any migration run. |
Optional |
|
Password to connect to the target database. Tip: It is a best practice to store sensitive data in a Secrets Management tool with Liquibase Pro. |
Optional |
|
Enables a report at the command level. Overrides the global argument |
Optional |
|
Specifies the name of the report file at the command level. Overrides the global argument |
Optional |
|
Specifies the file path to the report file at the command level. Overrides the global argument |
Optional |
|
The path to the script to use to perform the rollback. Only needed if the rollback is not already defined in the changelog, and if it is not a rollback statement that is automatically generated by Liquibase. |
Optional |
|
Tag version to use for multiple occurrences of a tag. Valid values are |
Optional |
|
Username to connect to the target database. Tip: It is a best practice to store sensitive data in a Secrets Management tool with Liquibase Pro. |
Optional |
Attribute | Definition | Requirement |
---|---|---|
|
The root changelog |
Required |
|
The tag identifying which tagged changesets in the changelog to evaluate. Specify as |
Required |
|
The JDBC database connection URL. See Using JDBC URL in Liquibase. |
Required |
|
Fully-qualified class which specifies a |
Optional |
|
Path to a properties file for the |
Optional |
|
Specifies the changeset contexts to match. Contexts are tags you can add to changesets to control which changesets are executed in any particular migration run. Note: If you use Liquibase 4.23.0 or earlier, use the syntax |
Optional |
|
Name of the default catalog to use for the database connection |
Optional |
|
Name of the default schema to use for the database connection. If Tip: In Liquibase v4.23.0+, camelCase for Note: The syntax |
Optional |
|
The JDBC driver class |
Optional |
|
The JDBC driver properties file |
Optional |
|
Specifies the changeset labels to match. Labels are tags you can add to changesets to control which changesets will be executed in any migration run. |
Optional |
|
Password to connect to the target database. Tip: It is a best practice to store sensitive data in a Secrets Management tool with Liquibase Pro. |
Optional |
|
Enables a report at the command level. Overrides the global argument |
Optional |
|
Specifies the name of the report file at the command level. Overrides the global argument |
Optional |
|
Specifies the file path to the report file at the command level. Overrides the global argument |
Optional |
|
The path to the script to use to perform the rollback. Only needed if the rollback is not already defined in the changelog, and if it is not a rollback statement that is automatically generated by Liquibase. |
Optional |
|
Tag version to use for multiple occurrences of a tag. Valid values are |
Optional |
|
Username to connect to the target database. Tip: It is a best practice to store sensitive data in a Secrets Management tool with Liquibase Pro. |
Optional |
Attribute | Definition | Requirement |
---|---|---|
|
The root changelog |
Required |
|
The tag identifying which tagged changesets in the changelog to evaluate. Specify as |
Required |
|
The JDBC database connection URL. See Using JDBC URL in Liquibase. |
Required |
|
Fully-qualified class which specifies a |
Optional |
|
Path to a properties file for the |
Optional |
|
Specifies the changeset contexts to match. Contexts are tags you can add to changesets to control which changesets are executed in any particular migration run. Note: If you use Liquibase 4.23.0 or earlier, use the syntax |
Optional |
|
Name of the default catalog to use for the database connection |
Optional |
|
Name of the default schema to use for the database connection. If Tip: In Liquibase v4.23.0+, camelCase for Note: The syntax |
Optional |
|
The JDBC driver class |
Optional |
|
The JDBC driver properties file |
Optional |
|
Specifies the changeset labels to match. Labels are tags you can add to changesets to control which changesets will be executed in any migration run. |
Optional |
|
Password to connect to the target database. Tip: It is a best practice to store sensitive data in a Secrets Management tool with Liquibase Pro. |
Optional |
|
Enables a report at the command level. Overrides the global argument |
Optional |
|
Specifies the name of the report file at the command level. Overrides the global argument |
Optional |
|
Specifies the file path to the report file at the command level. Overrides the global argument |
Optional |
|
The path to the script to use to perform the rollback. Only needed if the rollback is not already defined in the changelog, and if it is not a rollback statement that is automatically generated by Liquibase. |
Optional |
|
Tag version to use for multiple occurrences of a tag. Valid values are |
Optional |
|
Username to connect to the target database. Tip: It is a best practice to store sensitive data in a Secrets Management tool with Liquibase Pro. |
Optional |
Attribute | Definition | Requirement |
---|---|---|
|
The root changelog |
Required |
|
The tag identifying which tagged changesets in the changelog to evaluate. Specify as |
Required |
|
The JDBC database connection URL. See Using JDBC URL in Liquibase. |
Required |
|
Fully-qualified class which specifies a |
Optional |
|
Path to a properties file for the |
Optional |
|
Specifies the changeset contexts to match. Contexts are tags you can add to changesets to control which changesets are executed in any particular migration run. Note: If you use Liquibase 4.23.0 or earlier, use the syntax |
Optional |
|
Name of the default catalog to use for the database connection |
Optional |
|
Name of the default schema to use for the database connection. If Tip: In Liquibase v4.23.0+, camelCase for Note: The syntax |
Optional |
|
The JDBC driver class |
Optional |
|
The JDBC driver properties file |
Optional |
|
Specifies the changeset labels to match. Labels are tags you can add to changesets to control which changesets will be executed in any migration run. |
Optional |
|
Password to connect to the target database. Tip: It is a best practice to store sensitive data in a Secrets Management tool with Liquibase Pro. |
Optional |
|
Enables a report at the command level. Overrides the global argument |
Optional |
|
Specifies the name of the report file at the command level. Overrides the global argument |
Optional |
|
Specifies the file path to the report file at the command level. Overrides the global argument |
Optional |
|
The path to the script to use to perform the rollback. Only needed if the rollback is not already defined in the changelog, and if it is not a rollback statement that is automatically generated by Liquibase. |
Optional |
|
Tag version to use for multiple occurrences of a tag. Valid values are |
Optional |
|
Username to connect to the target database. Tip: It is a best practice to store sensitive data in a Secrets Management tool with Liquibase Pro. |
Optional |
Attribute | Definition | Requirement |
---|---|---|
|
The root changelog |
Required |
|
The tag identifying which tagged changesets in the changelog to evaluate. Specify as |
Required |
|
The JDBC database connection URL. See Using JDBC URL in Liquibase. |
Required |
|
Fully-qualified class which specifies a |
Optional |
|
Path to a properties file for the |
Optional |
|
Specifies the changeset contexts to match. Contexts are tags you can add to changesets to control which changesets are executed in any particular migration run. Note: If you use Liquibase 4.23.0 or earlier, use the syntax |
Optional |
|
Name of the default catalog to use for the database connection |
Optional |
|
Name of the default schema to use for the database connection. If Tip: In Liquibase v4.23.0+, camelCase for Note: The syntax |
Optional |
|
The JDBC driver class |
Optional |
|
The JDBC driver properties file |
Optional |
|
Specifies the changeset labels to match. Labels are tags you can add to changesets to control which changesets will be executed in any migration run. |
Optional |
|
Password to connect to the target database. Tip: It is a best practice to store sensitive data in a Secrets Management tool with Liquibase Pro. |
Optional |
|
Enables a report at the command level. Overrides the global argument |
Optional |
|
Specifies the name of the report file at the command level. Overrides the global argument |
Optional |
|
Specifies the file path to the report file at the command level. Overrides the global argument |
Optional |
|
The path to the script to use to perform the rollback. Only needed if the rollback is not already defined in the changelog, and if it is not a rollback statement that is automatically generated by Liquibase. |
Optional |
|
Tag version to use for multiple occurrences of a tag. Valid values are |
Optional |
|
Username to connect to the target database. Tip: It is a best practice to store sensitive data in a Secrets Management tool with Liquibase Pro. |
Optional |
Note: The username
and password
attributes are not required for connections and systems which use alternate means of authentication. Also, you can specify database credentials as part of the url
attribute.
rollback
functionality
For more information, see Liquibase Rollback Workflow and Automatic and Custom Rollbacks.
Custom rollbacks
Liquibase cannot automatically roll back all Change Types. For example, Liquibase cannot automatically roll back dropTable
changes because the inverse SQL could be more than one statement.
In these cases, you must specify custom rollback syntax in your changelog for every changeset that you might want to roll back. This way, when you run the rollback
command, Liquibase knows what to do.
Note: When rolling back stored logic, Liquibase does not restore the previously stored version. Instead, Liquibase rolls back to the exact file/code specified in the custom rollback.
Note: Liquibase does not support automatic rollback for any Formatted SQL changesets. To roll back Formatted SQL changes, you must always specify a custom rollback.
--changeset liquibaseuser:1
create table testTable ( id int primary key, name varchar(255) );
--rollback drop table testTable;
--changeset liquibaseuser:2
insert into testTable values ('1','The First', 'Country')
insert into testTable values ('2','The Second', 'Country2')
--rollback delete from testTable where id='1'
--rollback delete from testTable where id='2'
In Liquibase 4.19.0 and later, you can specify multiple rollback statements in a block comment:
--changeset liquibaseuser:2
insert into testTable values ('1','The First', 'Country')
insert into testTable values ('2','The Second', 'Country2')
/* liquibase rollback
rollback delete from testTable where id='1'
rollback delete from testTable where id='2'
*/
In Liquibase 4.26.0 and later, you can use a rollbackSqlFile
statement to specify rollback SQL for a changeset in a separate file:
--changeset liquibase-user:1
DROP PROCEDURE hello_world;
--rollbackSqlFile path:release_1.0/rollback_45895.sql
In your rollbackSqlFile
statement, you can specify parameters to change the behavior of your rollback, such as a unique end delimiter. For more information, see Example Changelogs: SQL Format.
databaseChangeLog:
- changeSet:
id: 2
author: liquibaseuser
changes:
- dropTable:
tableName: person
rollback:
createTable:
catalogName: cat
columns:
- column:
name: address
type: varchar(255)
remarks: A String
schemaName: public
tableName: person
For more information, see Example Changelogs: YAML Format.
{
"databaseChangeLog": [
{
"changeSet": {
"id": "2",
"author": "liquibaseuser",
"changes": [
{
"dropTable": {
"tableName": "person"
}
}
],
"rollback": [
{
"createTable": {
"catalogName": "cat",
"columns": [
{
"column": {
"name": "address",
"type": "varchar(255)"
}
}
],
"remarks": "A String",
"schemaName": "public",
"tableName": "person"
}
}
]
}
}
]
}
For more information, see Example Changelogs: JSON Format.
<databaseChangeLog
xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext"
xmlns:pro="http://www.liquibase.org/xml/ns/pro"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog
http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-latest.xsd
http://www.liquibase.org/xml/ns/dbchangelog-ext
http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-ext.xsd
http://www.liquibase.org/xml/ns/pro
http://www.liquibase.org/xml/ns/pro/liquibase-pro-latest.xsd">
<changeSet author="liquibaseuser" id="2">
<dropTable tableName="person"/>
<rollback>
<createTable catalogName="department"
remarks="A String"
schemaName="public"
tableName="person"
<column name="address" type="varchar(255)"/>
</createTable>
</rollback>
</changeSet>
</databaseChangeLog>
For more information, see Example Changelogs: XML Format.
Override default rollback commands
The <rollback>
tag describes how to roll back a change using SQL statements, Change Types, or a reference to a previous changeset. You can use any Change Type in the <rollback>
element, such as dropTable, sql, and sqlFile:
- changeSet:
id: 1
author: liquibaseuser
changes:
- createTable:
tableName: testTable
columns:
- column:
name: id
rollback:
- dropTable:
tableName: testTable
{
"changeSet": {
"id": 1,
"author": "liquibaseuser",
"changes": [
{
"createTable": {
"tableName": "testTable"
}
}
],
"rollback": [
{
"dropTable": {
"tableName": "testTable"
}
}
]
}
}
<changeSet id="1" author="liquibaseuser">
<createTable tableName="testTable">
<column name="id" type="int"/>
</createTable>
<rollback>
<dropTable tableName="testTable"/>
</rollback>
</changeSet>
Alternatively, you can have raw SQL in the content part of the <rollback>
element. For example:
<changeSet id="1" author="liquibaseuser">
<createTable tableName="testTable">
<column name="id" type="int"/>
</createTable>
<rollback>
drop table testTable
</rollback>
</changeSet>
Liquibase treats the raw SQL within <rollback>
the same as in the <sql>
Change Type, with stripComments
set to true
, splitStatements
set to true
, and endDelimiter
set to ;
. For more details, see the XML example from the sql documentation.
Multiple rollbacks
You can also specify multiple Change Types within a single <rollback>
statement or across multiple <rollback>
statements:
- changeSet:
id: multiRollbackTest
author: liquibaseuser
changes:
- createTable:
tableName: multiRollback1
columns:
- column:
name: id
- createTable:
tableName: multiRollback2
columns:
- column:
name: id
- createTable:
tableName: multiRollback3
columns:
- column:
name: id
rollback:
- dropTable:
tableName: multiRollback1
- dropTable:
tableName: multiRollback2
rollback:
- dropTable:
tableName: multiRollback3
{
"changeSet": {
"id": multiRollbackTest,
"author": "liquibaseuser",
"changes": [
{
"createTable": {
"tableName": "multiRollback1",
"columns": [
{
"column": {
"name": "id"
}
}
]
},
"createTable": {
"tableName": "multiRollback2"
"columns": [
{
"column": {
"name": "id"
}
}
]
},
"createTable": {
"tableName": "multiRollback3"
"columns": [
{
"column": {
"name": "id"
}
}
]
}
}
],
"rollback": [
{
"dropTable": {
"tableName": "multiRollback1"
},
"dropTable": {
"tableName": "multiRollback2"
}
}
],
"rollback": [
{
"dropTable": {
"tableName": "multiRollback3"
}
}
],
}
}
Change Type syntax:
<changeSet id="multiRollbackTest" author="liquibaseuser">
<createTable tableName="multiRollback1">
<column name="id" type="int"/>
</createTable>
<createTable tableName="multiRollback2">
<column name="id" type="int"/>
</createTable>
<createTable tableName="multiRollback3">
<column name="id" type="int"/>
</createTable>
<rollback>
<dropTable tableName="multiRollback1"/>
<dropTable tableName="multiRollback2"/>
</rollback>
<rollback>
<dropTable tableName="multiRollback3"/>
</rollback>
</changeSet>
Raw SQL:
<changeSet id="multiRollbackTest" author="liquibaseuser">
<createTable tableName="multiRollback1">
<column name="id" type="int"/>
</createTable>
<createTable tableName="multiRollback2">
<column name="id" type="int"/>
</createTable>
<createTable tableName="multiRollback3">
<column name="id" type="int"/>
</createTable>
<rollback>
drop table multiRollback1;
drop table multiRollback2;
</rollback>
<rollback>drop table multiRollback3</rollback>
</changeSet>
Directly reference changeset
The following example shows how you can use a <rollback>
tag to reference the changeset that originally created a statement. This example uses changeset 2
to implement rollback logic against changeset 1
:
--changeset liquibaseuser:1
create table testTable ( id int primary key, name varchar(255) );
--changeset liquibaseuser:2
--rollback drop table testTable;
--rollback changesetId:1 changesetAuthor:liquibaseuser changesetPath:optional/path/to/myChangeLog.sql
- changeSet:
id: 1
author: liquibaseuser
changes:
- createTable:
tableName: testTable
columns:
- column:
name: id
- changeSet:
id: 2
author: liquibaseuser
rollback:
- dropTable:
tableName: testTable
changesetId: 1
changesetAuthor: liquibaseuser
changesetpath: optional/path/to/myChangeLog.yaml
{
"changeSet": {
"id": 1,
"author": "liquibaseuser",
"changes": [
{
"createTable": {
"tableName": "testTable",
"columns": [
{
"column": {
"name": "id",
"type": "varchar(255)"
}
}
]
}
}
]
{
"changeSet": {
"id": 2,
"author": "liquibaseuser",
"rollback": [
{
"dropTable": {
"tableName": "testTable"
}
},
"changesetId": "1",
"changesetAuthor": "liquibaseuser",
"changesetPath": "optional/path/to/myChangeLog.json"
]
}
}
<changeSet id="1" author="liquibaseuser">
<createTable tableName="testTable"/>
<column name="id" type="varchar(255)"/>
</createTable>
</changeSet>
<changeSet id="2" author="liquibaseuser">
<dropTable tableName="testTable"/>
<rollback changesetId="1" changesetAuthor="liquibaseuser" changesetPath="optional/path/to/myChangeLog.xml"/>
</changeSet>
Empty rollback statements
If you do not want to revert a change in a rollback mode, use either the keyword empty
or the keyword not required
inside the rollback
tag. In XML, YAML, and JSON changelogs, you can also use an empty string inside the rollback
tag.
--changeset liquibaseuser:1
create table testTable ( id int primary key, name varchar(255) );
--rollback empty
- changeSet:
id: 1
author: liquibase
changes:
- createTable:
tableName: testTable
columns:
- column:
name: id
type: int
rollback: empty
You can also use an empty string (rollback: ""
).
{
"changeSet": {
"id": 1,
"author": "example",
"changes": [
{
"createTable": {
"tableName": "testTable",
"columns": [
{
"column": {
"name": "id",
"type": "int"
}
}
]
}
}
],
"rollback": "empty"
}
}
You can also use an empty string ("rollback": ""
).
<changeSet id="3" author="liquibaseuser">
<createTable tableName="testTable">
<column name="id" type="int"/>
</createTable>
<rollback>empty</rollback>
</changeSet>
You can also use an empty string (<rollback></rollback>
) or a self-closing-tag (<rollback/>
).
Note: The empty
and output
Change Types support automatic rollbacks.
When successful, the rollback
command produces the following output:
Liquibase Version: 4.9.1
Rolling Back Changeset: example-changelog.sql::2::Amber.Williams
Rolling Back Changeset: example-changelog.sql::1::Amber.Williams
Liquibase command 'rollback' was executed successfully.
Liquibase: Rollback has been successful.