def run(*args, out: nil, err: nil, normalize:, chomp:, merge:, chdir: nil, timeout: nil)
      git_cmd = build_git_cmd(args)
      begin
        result = ProcessExecuter.run(env, *git_cmd, out: out, err: err, merge:, chdir: (chdir || :not_set), timeout: timeout, raise_errors: false)
      rescue ProcessExecuter::Command::ProcessIOError => e
        raise Git::ProcessIOError.new(e.message), cause: e.exception.cause
      end
      process_result(result, normalize, chomp, timeout)
    end
Execute a git command, wait for it to finish, and return the result

NORMALIZATION

The command output is returned as a Unicde string containing the binary output
from the command. If the binary output is not valid UTF-8, the output will
cause problems because the encoding will be invalid.

Normalization is a process that trys to convert the binary output to a valid
UTF-8 string. It uses the `rchardet` gem to detect the encoding of the binary
output and then converts it to UTF-8.

Normalization is not enabled by default. Pass `normalize: true` to Git::CommandLine#run
to enable it. Normalization will only be performed on stdout and only if the `out:`` option
is nil or is a StringIO object. If the out: option is set to a file or other IO object,
the normalize option will be ignored.

@example Run a command and return the output
cli.run('version') #=> "git version 2.39.1\n"

@example The args array should be splatted into the parameter list
args = %w[log -n 1 --oneline]
cli.run(*args) #=> "f5baa11 beginning of Ruby/Git project\n"

@example Run a command and return the chomped output
cli.run('version', chomp: true) #=> "git version 2.39.1"

@example Run a command and without normalizing the output
cli.run('version', normalize: false) #=> "git version 2.39.1\n"

@example Capture stdout in a temporary file
require 'tempfile'
tempfile = Tempfile.create('git') do |file|
cli.run('version', out: file)
file.rewind
file.read #=> "git version 2.39.1\n"
end

@example Capture stderr in a StringIO object
require 'stringio'
stderr = StringIO.new
begin
cli.run('log', 'nonexistent-branch', err: stderr)
rescue Git::FailedError => e
stderr.string #=> "unknown revision or path not in the working tree.\n"
end

@param args [Array<String>] the command line arguements to pass to git

This array should be splatted into the parameter list.

@param out [#write, nil] the object to write stdout to or nil to ignore stdout

If this is a 'StringIO' object, then `stdout_writer.string` will be returned.

In general, only specify a `stdout_writer` object when you want to redirect
stdout to a file or some other object that responds to `#write`. The default
behavior will return the output of the command.

@param err [#write] the object to write stderr to or nil to ignore stderr

If this is a 'StringIO' object and `merged_output` is `true`, then
`stderr_writer.string` will be merged into the output returned by this method.

@param normalize [Boolean] whether to normalize the output to a valid encoding

@param chomp [Boolean] whether to chomp the output

@param merge [Boolean] whether to merge stdout and stderr in the string returned

@param chdir [String] the directory to run the command in

@param timeout [Numeric, nil] the maximum seconds to wait for the command to complete

If timeout is zero, the timeout will not be enforced.

If the command times out, it is killed via a `SIGKILL` signal and `Git::TimeoutError` is raised.

If the command does not respond to SIGKILL, it will hang this method.

@return [Git::CommandLineResult] the output of the command

This result of running the command.

@raise [ArgumentError] if `args` is not an array of strings

@raise [Git::SignaledError] if the command was terminated because of an uncaught signal

@raise [Git::FailedError] if the command returned a non-zero exitstatus

@raise [Git::ProcessIOError] if an exception was raised while collecting subprocess output

@raise [Git::TimeoutError] if the command times out