git-filter-repo/contrib/filter-repo-demos/signed-off-by
Elijah Newren 320c85f941 filter-repo: improve support for partial history rewrites
Partial history rewrites were possible before with the (previously
hidden) --refs flag, but the defaults were wrong.  That could be worked
around with the --source or --target flags, but that disabled --no-data
for fast-export and thus slowed things down, and also would require
overridding --replace-refs.  And the defaults for --source and --target
may diverge further from what is wanted/needed for partial history
rewrites in the future.

So, add --partial as a first-class supported option with scary
documentation about how it permits mixing new and old history.  Make
--refs imply that flag.  Make the behavioral similarities (in regards to
which steps are skipped) between --source, --target, and --partial more
clear.  Add relevant documentation to round it out.

Signed-off-by: Elijah Newren <newren@gmail.com>
2019-10-17 18:55:09 -07:00

66 lines
2.4 KiB
Python
Executable File

#!/usr/bin/env python3
"""
This is a simple program that will add Signed-off-by: tags to a range of
commits. Example usage, to add a signed-off-by trailer to every commit that
is not in next but is in any of master, develop, or maint:
signed-off-by master develop maint ^next
More likely called as:
signed-off-by master~4..master
There's no real reason to use this script since `rebase --signoff` exists;
it's mostly just a demonstration of what could be done.
"""
"""
Please see the
***** API BACKWARD COMPATIBILITY CAVEAT *****
near the top of git-filter-repo.
"""
import argparse
import re
import subprocess
try:
import git_filter_repo as fr
except ImportError:
raise SystemExit("Error: Couldn't find git_filter_repo.py. Did you forget to make a symlink to git-filter-repo named git_filter_repo.py or did you forget to put the latter in your PYTHONPATH?")
parser = argparse.ArgumentParser(
description="Add 'Signed-off-by:' tags to a range of commits")
parser.add_argument('rev_list_args', metavar='rev-list args',
nargs=argparse.REMAINDER,
help=("Range of commits (need to include ref tips) to work on"))
myargs = parser.parse_args()
user_name = subprocess.check_output('git config user.name'.split()).rstrip()
user_email = subprocess.check_output('git config user.email'.split()).rstrip()
trailer = b'Signed-off-by: %s <%s>' % (user_name, user_email)
def add_signed_off_by_trailer(commit, metadata):
if trailer in commit.message:
return
# We want to add the trailer, but we want it to be separated from any
# existing paragraphs by a blank line. However, if the commit message
# already ends with trailers, then we want all trailers to be on adjacent
# lines.
if not commit.message.endswith(b'\n'):
commit.message += b'\n'
lastline = commit.message.splitlines()[-1]
if not re.match(b'[A-Za-z0-9-_]*: ', lastline):
commit.message += b'\n'
commit.message += trailer
# Setting source and target to anything prevents:
# * remapping origin remote tracking branches to regular branches
# * deletion of the origin remote
# * nuking unused refs
# * nuking reflogs
# * repacking
# so we cheat and set source and target both to '.'
args = fr.FilteringOptions.parse_args(['--force',
'--refs'] + myargs.rev_list_args)
args.refs = myargs.rev_list_args
filter = fr.RepoFilter(args, commit_callback=add_signed_off_by_trailer)
filter.run()