def files(obj, commit='HEAD', skip_merge_commits=False):
    """Check the files of the commits."""
    from ..kwalitee import check_file, SUPPORTED_FILES
    from ..hooks import run
    options = obj.options
    repository = obj.repository

    if options.get('colors') is not False:
        colorama.init(autoreset=True)
        reset = colorama.Style.RESET_ALL
        yellow = colorama.Fore.YELLOW
        green = colorama.Fore.GREEN
        red = colorama.Fore.RED
    else:
        reset = yellow = green = red = ''

    try:
        sha = 'oid'
        commits = _pygit2_commits(commit, repository)
    except ImportError:
        try:
            sha = 'hexsha'
            commits = _git_commits(commit, repository)
        except ImportError:
            click.echo(
                'To use this feature, please install pygit2. GitPython will '
                'also work but is not recommended (python <= 2.7 only).',
                file=sys.stderr)
            click.exit(2)

    template = '{0}commit {{commit.{1}}}{2}\n\n'.format(yellow, sha, reset)
    template += '{message}{errors}\n'

    error_template = '\n{0}{{filename}}\n{1}{{errors}}{0}'.format(reset, red)
    no_errors = ['\n{0}Everything is OK.{1}'.format(green, reset)]
    msg_file_excluded = '\n{0}{{filename}} excluded.{1}'.format(yellow, reset)

    def _get_files_modified(commit):
        """Get the list of modified files that are Python or Jinja2."""
        cmd = "git show --no-commit-id --name-only --diff-filter=ACMRTUXB {0}"
        _, files_modified, _ = run(cmd.format(commit))

        extensions = [re.escape(ext)
                      for ext in list(SUPPORTED_FILES) + [".rst"]]
        test = "(?:{0})$".format("|".join(extensions))
        return list(filter(lambda f: re.search(test, f), files_modified))

    def _ensure_directory(filename):
        dir_ = os.path.dirname(filename)
        if not os.path.exists(dir_):
            os.makedirs(dir_)

    def _format_errors(args):
        filename, errors = args
        if errors is None:
            return msg_file_excluded.format(filename=filename)
        else:
            return error_template.format(filename=filename, errors='\n'.join(
                errors if len(errors) else no_errors))

    count = 0
    ident = '    '
    re_line = re.compile('^', re.MULTILINE)
    for commit in commits:
        if skip_merge_commits and _is_merge_commit(commit):
            continue
        message = commit.message
        commit_sha = getattr(commit, sha)
        tmpdir = mkdtemp()
        errors = {}
        try:
            for filename in _get_files_modified(commit):
                cmd = "git show {commit_sha}:{filename}"
                _, out, _ = run(cmd.format(commit_sha=commit_sha,
                                           filename=filename),
                                raw_output=True)

                destination = os.path.join(tmpdir, filename)
                _ensure_directory(destination)

                with open(destination, 'w+') as f:
                    f.write(out)

                errors[filename] = check_file(destination, **options)
        finally:
            shutil.rmtree(tmpdir, ignore_errors=True)

        message = re.sub(re_line, ident, message)
        if len(errors):
            count += 1
            errors = map(_format_errors, errors.items())
        else:
            errors = no_errors

        click.echo(template.format(commit=commit,
                                   message=message.encode('utf-8'),
                                   errors='\n'.join(errors)))

    if min(count, 1):
        raise click.Abort