docs: def lint(ctx):
      """ Lints a git repository [default command] """
      lint_config = ctx.obj[0]
      msg_filename = ctx.obj[3]
  
      # Let's determine where our input data is coming from:
      # Order of precedence:
      # 1. Any data specified via --msg-filename
      # 2. Any data sent to stdin
      # 3. Fallback to reading from local repository
      stdin_input = get_stdin_data()
      if msg_filename:
          LOG.debug("Attempting to read from --msg-filename.")
          gitcontext = GitContext.from_commit_msg(ustr(msg_filename.read()))
      elif stdin_input:
          LOG.debug("No --msg-filename flag. Attempting to read from stdin.")
          gitcontext = GitContext.from_commit_msg(stdin_input)
      else:
          LOG.debug("No --msg-filename flag, no or empty data passed to stdin. Attempting to read from the local repo.")
          gitcontext = GitContext.from_local_repository(lint_config.target, ctx.obj[2])
  
      number_of_commits = len(gitcontext.commits)
      # Exit if we don't have commits in the specified range. Use a 0 exit code, since a popular use-case is one
      # where users are using --commits in a check job to check the commit messages inside a CI job. By returning 0, we
      # ensure that these jobs don't fail if for whatever reason the specified commit range is empty.
      if number_of_commits == 0:
          LOG.debug(u'No commits in range "%s"', ctx.obj[2])
          ctx.exit(0)
  
      general_config_builder = ctx.obj[1]
      last_commit = gitcontext.commits[-1]
  
      # Let's get linting!
      first_violation = True
      exit_code = 0
      for commit in gitcontext.commits:
          # Build a config_builder taking into account the commit specific config (if any)
          config_builder = general_config_builder.clone()
          config_builder.set_config_from_commit(commit)
  
          # Create a deepcopy from the original config, so we have a unique config object per commit
          # This is important for configuration rules to be able to modifying the config on a per commit basis
          commit_config = config_builder.build(copy.deepcopy(lint_config))
  
          # Actually do the linting
          linter = GitLinter(commit_config)
          violations = linter.lint(commit)
          # exit code equals the total number of violations in all commits
          exit_code += len(violations)
          if violations:
              # Display the commit hash & new lines intelligently
              if number_of_commits > 1 and commit.sha:
                  linter.display.e(u"{0}Commit {1}:".format(
                      "\n" if not first_violation or commit is last_commit else "",
                      commit.sha[:10]
                  ))
              linter.print_violations(violations)
              first_violation = False
  
      # cap actual max exit code because bash doesn't like exit codes larger than 255:
      # http://tldp.org/LDP/abs/html/exitcodes.html
      exit_code = min(MAX_VIOLATION_ERROR_CODE, exit_code)
      LOG.debug("Exit Code = %s", exit_code)
      ctx.exit(exit_code)