Using a timestamp in a migration system doesn't really solve the problem at edge cases though: the time-based ordering of migration file
creation may differ from the time-based ordering of migration
application, especially accounting for different git branches, and different DB environments (prod, staging, dev DBs for each developer).
The canonical problem is two engineers with branches that each add a new column to the end of the same table. It's easy to end up with schema drift between environments, or cases where executing the migrations in alphabetical order yields a different result than executing them in git history order. You can add various guard rails and band-aids to catch this, but it's ugly.
In contrast, declarative schema management systems inherently avoid this situation. For example, if two engineers try to add a new column to the end of the same table, one of them will get a git merge conflict -- exactly like if two branches in an application code repo tried to edit the same line of a function.