def __init__(
        self,
        path: Optional[PathLike] = None,
        odbt: Type[LooseObjectDB] = GitCmdObjectDB,
        search_parent_directories: bool = False,
        expand_vars: bool = True,
    ) -> None:
        R"""Create a new :class:`Repo` instance.

        :param path:
            The path to either the worktree directory or the .git directory itself::

                repo = Repo("/Users/mtrier/Development/git-python")
                repo = Repo("/Users/mtrier/Development/git-python.git")
                repo = Repo("~/Development/git-python.git")
                repo = Repo("$REPOSITORIES/Development/git-python.git")
                repo = Repo(R"C:\Users\mtrier\Development\git-python\.git")

            - In *Cygwin*, `path` may be a ``cygdrive/...`` prefixed path.
            - If `path` is ``None`` or an empty string, :envvar:`GIT_DIR` is used. If
              that environment variable is absent or empty, the current directory is
              used.

        :param odbt:
            Object DataBase type - a type which is constructed by providing the
            directory containing the database objects, i.e. ``.git/objects``. It will be
            used to access all object data.

        :param search_parent_directories:
            If ``True``, all parent directories will be searched for a valid repo as
            well.

            Please note that this was the default behaviour in older versions of
            GitPython, which is considered a bug though.

        :raise git.exc.InvalidGitRepositoryError:

        :raise git.exc.NoSuchPathError:

        :return:
            :class:`Repo`
        """

        epath = path or os.getenv("GIT_DIR")
        if not epath:
            epath = os.getcwd()
        if Git.is_cygwin():
            # Given how the tests are written, this seems more likely to catch Cygwin
            # git used from Windows than Windows git used from Cygwin. Therefore
            # changing to Cygwin-style paths is the relevant operation.
            epath = cygpath(str(epath))

        epath = epath or path or os.getcwd()
        if not isinstance(epath, str):
            epath = str(epath)
        if expand_vars and re.search(self.re_envvars, epath):
            warnings.warn(
                "The use of environment variables in paths is deprecated"
                + "\nfor security reasons and may be removed in the future!!",
                stacklevel=1,
            )
        epath = expand_path(epath, expand_vars)
        if epath is not None:
            if not os.path.exists(epath):
                raise NoSuchPathError(epath)

        # Walk up the path to find the `.git` dir.
        curpath = epath
        git_dir = None
        while curpath:
            # ABOUT osp.NORMPATH
            # It's important to normalize the paths, as submodules will otherwise
            # initialize their repo instances with paths that depend on path-portions
            # that will not exist after being removed. It's just cleaner.
            if is_git_dir(curpath):
                git_dir = curpath
                # from man git-config : core.worktree
                # Set the path to the root of the working tree. If GIT_COMMON_DIR
                # environment variable is set, core.worktree is ignored and not used for
                # determining the root of working tree. This can be overridden by the
                # GIT_WORK_TREE environment variable. The value can be an absolute path
                # or relative to the path to the .git directory, which is either
                # specified by GIT_DIR, or automatically discovered. If GIT_DIR is
                # specified but none of GIT_WORK_TREE and core.worktree is specified,
                # the current working directory is regarded as the top level of your
                # working tree.
                self._working_tree_dir = os.path.dirname(git_dir)
                if os.environ.get("GIT_COMMON_DIR") is None:
                    gitconf = self._config_reader("repository", git_dir)
                    if gitconf.has_option("core", "worktree"):
                        self._working_tree_dir = gitconf.get("core", "worktree")
                if "GIT_WORK_TREE" in os.environ:
                    self._working_tree_dir = os.getenv("GIT_WORK_TREE")
                break

            dotgit = osp.join(curpath, ".git")
            sm_gitpath = find_submodule_git_dir(dotgit)
            if sm_gitpath is not None:
                git_dir = osp.normpath(sm_gitpath)

            sm_gitpath = find_submodule_git_dir(dotgit)
            if sm_gitpath is None:
                sm_gitpath = find_worktree_git_dir(dotgit)

            if sm_gitpath is not None:
                git_dir = expand_path(sm_gitpath, expand_vars)
                self._working_tree_dir = curpath
                break

            if not search_parent_directories:
                break
            curpath, tail = osp.split(curpath)
            if not tail:
                break
        # END while curpath

        if git_dir is None:
            raise InvalidGitRepositoryError(epath)
        self.git_dir = git_dir

        self._bare = False
        try:
            self._bare = self.config_reader("repository").getboolean("core", "bare")
        except Exception:
            # Let's not assume the option exists, although it should.
            pass

        try:
            common_dir = (Path(self.git_dir) / "commondir").read_text().splitlines()[0].strip()
            self._common_dir = osp.join(self.git_dir, common_dir)
        except OSError:
            self._common_dir = ""

        # Adjust the working directory in case we are actually bare - we didn't know
        # that in the first place.
        if self._bare:
            self._working_tree_dir = None
        # END working dir handling

        self.working_dir: PathLike = self._working_tree_dir or self.common_dir
        self.git = self.GitCommandWrapperType(self.working_dir)

        # Special handling, in special times.
        rootpath = osp.join(self.common_dir, "objects")
        if issubclass(odbt, GitCmdObjectDB):
            self.odb = odbt(rootpath, self.git)
        else:
            self.odb = odbt(rootpath)
Create a new :class:`Repo` instance.

        :param path:
            The path to either the worktree directory or the .git directory itself::

                repo = Repo("/Users/mtrier/Development/git-python")
                repo = Repo("/Users/mtrier/Development/git-python.git")
                repo = Repo("~/Development/git-python.git")
                repo = Repo("$REPOSITORIES/Development/git-python.git")
                repo = Repo(R"C:\Users\mtrier\Development\git-python\.git")

            - In *Cygwin*, `path` may be a ``cygdrive/...`` prefixed path.
            - If `path` is ``None`` or an empty string, :envvar:`GIT_DIR` is used. If
              that environment variable is absent or empty, the current directory is
              used.

        :param odbt:
            Object DataBase type - a type which is constructed by providing the
            directory containing the database objects, i.e. ``.git/objects``. It will be
            used to access all object data.

        :param search_parent_directories:
            If ``True``, all parent directories will be searched for a valid repo as
            well.

            Please note that this was the default behaviour in older versions of
            GitPython, which is considered a bug though.

        :raise git.exc.InvalidGitRepositoryError:

        :raise git.exc.NoSuchPathError:

        :return:
            :class:`Repo`
        
git/repo/base.py