Skip to content

Conversation

@bitfehler
Copy link

These commands modify the version table without actually running any migrations. The command names are taken from alembic, but other frameworks also support this under different names (repair, force, ...), see #938.

The stamp command simply sets the database version to that of the latest available migration, where as the stamp-to command allows to specify a version (including 0). Stamping can both increase and decrease the database version.

Fixes: #938

These commands modify the version table without actually running any
migrations. The command names are taken from alembic [1], but other
frameworks also support this under different names (repair, force, ...),
see pressly#938.

The `stamp` command simply sets the database version to that of the
latest available migration, where as the `stamp-to` command allows to
specify a version (including 0). Stamping can both increase and decrease
the database version.

[1]: https://alembic.sqlalchemy.org/en/latest/api/commands.html#alembic.command.stamp

Fixes: pressly#938
@bitfehler
Copy link
Author

Hi there, thank you for your work on goose! We really like it and are in the process of migrating over from alembic, hence the choice of command naming. However, I'd be totally open to give these commands any other name 🙂 we'd just be super happy to see this functionality added to goose!

I have tested the functionality with a simple project, and it handled all of the cases I could think of. However, this was my first time looking at goose internals, so I may have missed a bunch of stuff. If you'd be up for including this functionality at all I am happy to spend time refining this PR to your liking!

Thanks again!

@masonk
Copy link

masonk commented Sep 10, 2025

This would be great to have. I just found out that my team has been manually inserting and deleting from the goose table for want of this functionality.

As it stands there is not a well lit path for taking an existing DB and putting it under the management of goose.

@mfridman
Copy link
Collaborator

I don't particularly like the term goose stamp; I prefer something like goose repair, which suggests a more internal process within goose.

Also, stamp may be too close to a future goose apply command that allows you to apply a specific version (equivalent to Provider.ApplyVersion).

@mfridman
Copy link
Collaborator

Looking a bit more at this PR, I don't think we need all the checks. I believe what users want is a crude command to modify the goose table irrespective of any migration(s) data. E.g.,

# zero version manually

goose repair add --version=0
goose repair delete --version=0

# some other value
goose repair add --version=121

Now, there are 2 other bits of the goose table: id (typically auto-incrementing) and timestamp. But users would not be able to do this:

goose repair add --version=121 --timestamp="2019-11-14T00:55:31.820Z" --id=891

Maybe to start, we add --version and revisit the other 2 fields if/when it comes up.

Does this sound reasonable?

@masonk
Copy link

masonk commented Sep 11, 2025 via email

@mfridman
Copy link
Collaborator

One thing which isn’t clear is whether --version 121 marks everything up to 121 or exactly 121. All of my use-cases want up-to and down-to semantics

It'd be exactly 121.

I'm curious about your use case for up/down-to semantics. When migrating from another tool that's currently at version 121, the typical approach would be:

  • Roll up existing migrations into a single file (e.g., 00121_initial.sql)
  • Mark the goose table as starting from 121
  • New migrations continue from 122

What's your specific scenario where you need the range behavior instead of targeting exact versions?

ps. this is how I approached it in a system where I swapped golang-migrate for goose. Maybe there's a world where the command works like

goose repair insert --version=121 --include-all

Where --include-all would provide the functionality you're looking for.


As I typed this out, I realized the use case is probably keeping migrations as separate files rather than rolling them up. With something like --include-all (up-to semantics), the migration file layout would map cleanly to the database versions.

@masonk
Copy link

masonk commented Sep 12, 2025

Correct - my basic idea is that if want goose to take over a DB that is already at version 121, I could write this:

goose mark 121

And goose now knows that DDLs 1-121 have been applied.

Something you wrote makes me think that I didn't understand how goose works. What would it mean for version 121 to be applied but not versions 1-120? I didn't think that would be a valid system state. If it is, then perhaps there's no need for up-to semantics.

@mfridman
Copy link
Collaborator

mfridman commented Sep 12, 2025

You're absolutely right in that if you have migration files 1-120 and the goose table is marked at 121 then goose will raise an "missing migrations detected" error:

goose run: error: found 120 missing migrations before current version 121:
        version 1: migrations/00001_foo.sql
        version 2: migrations/00002_bar.sql
[...]

So in those situations, you definitely want up-to semantics so that all migrations considered missing would be marked as having been applied.

I've never run into this because I always dump the schema (e.g., #278 (comment)) and don't bother maintaining existing file order.

Hopefully, this sheds some light on my use case.

TL;DR - I think we need to support both cases.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Feature request: Allow "mark as applied"

3 participants