async function add({
  fs: _fs,
  dir,
  gitdir = join(dir, '.git'),
  filepath,
  cache = {},
  force = false,
  parallel = true,
}) {
  try {
    assertParameter('fs', _fs)
    assertParameter('dir', dir)
    assertParameter('gitdir', gitdir)
    assertParameter('filepath', filepath)

    const fs = new FileSystem(_fs)
    await GitIndexManager.acquire({ fs, gitdir, cache }, async index => {
      const config = await GitConfigManager.get({ fs, gitdir })
      const autocrlf = await config.get('core.autocrlf')
      return addToIndex({
        dir,
        gitdir,
        fs,
        filepath,
        index,
        force,
        parallel,
        autocrlf,
      })
    })
  } catch (err) {
    err.caller = 'git.add'
    throw err
  }
}
Add a file to the git index (aka staging area)

@param {object} args
@param {FsClient} args.fs - a file system implementation
@param {string} args.dir - The [working tree](dir-vs-gitdir.md) directory path
@param {string} [args.gitdir=join(dir, '.git')] - [required] The [git directory](dir-vs-gitdir.md) path
@param {string|string[]} args.filepath - The path to the file to add to the index
@param {object} [args.cache] - a [cache](cache.md) object
@param {boolean} [args.force=false] - add to index even if matches gitignore. Think `git add --force`
@param {boolean} [args.parallel=false] - process each input file in parallel. Parallel processing will result in more memory consumption but less process time

@returns {Promise<void>} Resolves successfully once the git index has been updated

@example
await fs.promises.writeFile('/tutorial/README.md', `# TEST`)
await git.add({ fs, dir: '/tutorial', filepath: 'README.md' })
console.log('done')