Migration path from HABTM to has_many :through

In Ruby on Rails there are two fundamental approaches for N:M associations: has_and_belongs_to_many and has_many :through. Both have their advantages and disadvantages. That means both types are relevant likewise.
But the story adheres tenaciously, that has_many :through is to preferred generally, because of its flexibility. Sure, it is more flexible in some terms. The has_many :through model can be provided with additional attributes without changing the association itself. However the flexibility is not necessary in each case. Essentially has_and_belongs_to_many is more lightweight and leaves a smaller footprint.
Worrying about a possibly necessary structural change should never be the reason for a decision in favour of has_many :through. Angst is always a bad adviser.
By all means the migration from a has_and_belongs_to_many to a has_many :through association is as easy and natural as the following example.
Basically there are users having many addresses and each address can have many users:

2. Set the has_many :through association

The old HABTM association has to be renamed temporarily, for the reason of setting the has_many :through association unambiguously (one end of the relationship is sufficient). That makes the model up for copying the data (association links):

It absolutely makes sense to migrate the association table data in batches. By default find_each fetches 1000 records, but the batch size depends on the specific use case.
The migration process so far can be deployed. Clearing the deprecated HABTM relationships should be executed in a second deploy.

5. Dropping the HABTM table and relationship

The migration file for dropping the obsolete HABTM table should be migrated In a second deploy:

Conclusion

The process of migrating a has_and_belongs_to_many to a has_many :through relationship looks more extensive than it actually is. But some steps are necessary anyway, if there was a decision in favour of the has_many :through association in the first place. Actually it merely comes with additional effort for migrating the links (association data). However separating the migration path into 2 isolated deploys is necessary, due to copying the existing links.
Basically HABTM is the association of choice, unless there is a reasonable chance, that the relationship will have additional attributes. It is because a dedicated HABTM relationship comes with higher performance and a migration towards a has_many :through relationship is unproblematic, if ever necessary at all.