Skip to content

Instantly share code, notes, and snippets.

@jbradberry
Last active June 21, 2024 01:37
Show Gist options
  • Save jbradberry/ab47ba6f8567473f06bd4015020c3ef5 to your computer and use it in GitHub Desktop.
Save jbradberry/ab47ba6f8567473f06bd4015020c3ef5 to your computer and use it in GitHub Desktop.
Re-number Django migrations during a rebase, use like `$ git rebase -i devel --exec "python3 rebase_migrations.py"`
from collections import defaultdict
from pathlib import Path
import re
import subprocess
changed_files = subprocess.check_output("git diff-tree --no-commit-id --name-status -r HEAD", shell=True)
changed_status = [line.split('\t') for line in changed_files.decode('utf-8').rstrip('\n').split('\n')]
changed_migrations = {fname for status, fname in changed_status
if '/migrations/' in fname and Path(fname).name[0].isdigit() and status != 'D'}
if changed_migrations:
print("Changed migrations: {}".format(changed_migrations))
migrations = defaultdict(list)
for m in sorted(changed_migrations):
migrations[Path(m).parent].append(m)
for d, S in migrations.items():
existing_migrations = sorted(
f for f in Path(d).iterdir()
if f.is_file() and f.name[0].isdigit() and f.name.endswith('.py') and str(f) not in S
)
existing_numbers = [int(f.name[:4], base=10) for f in existing_migrations]
for m in S:
migration = Path(m)
num = int(migration.name[:4], base=10)
if num in existing_numbers:
with open(m) as f:
contents = f.read()
print('git rm', m)
subprocess.check_output(['git', 'rm', m])
updated = re.sub(
r'{:04d}_[a-zA-Z0-9_]*'.format(num - 1),
max(existing_migrations).name[:-3],
contents
)
migration = d / '{:04d}{}'.format(max(existing_numbers) + 1, migration.name[4:])
with migration.open('w') as f:
f.write(updated)
print('git add', str(migration))
subprocess.check_output(['git', 'add', str(migration)])
existing_migrations.append(migration)
existing_numbers.append(num)
subprocess.check_output("git commit --amend --no-edit", shell=True)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment