def _fetch_project(self):
        """
        Clones the project if necessary, fetches from the remote repo and resets to the requested commit
        """
        # If shallow_clones is set to True, then we need to specify the --depth=1 argument to all git fetch
        # and clone invocations.
        git_clone_fetch_depth_arg = ''
        if Configuration['shallow_clones']:
            git_clone_fetch_depth_arg = '--depth=1'

        existing_repo_is_shallow = os.path.isfile(os.path.join(self._repo_directory, '.git', 'shallow'))

        # If we disable shallow clones, but the existing repo is shallow, we must re-clone non-shallowly.
        if not Configuration['shallow_clones'] and existing_repo_is_shallow and os.path.exists(self._repo_directory):
            shutil.rmtree(self._repo_directory)
            fs.create_dir(self._repo_directory, self.DIRECTORY_PERMISSIONS)

        # Clone the repo if it doesn't exist
        try:
            self._execute_git_command_in_repo_and_raise_on_failure('rev-parse')  # rev-parse succeeds if repo exists
        except __HOLE__:
            self._logger.notice('No valid repo in "{}". Cloning fresh from "{}".', self._repo_directory, self._url)
            self._execute_git_command_in_repo_and_raise_on_failure(
                git_command='clone {} {} {}'. format(git_clone_fetch_depth_arg, self._url, self._repo_directory),
                error_msg='Could not clone repo.'
            )

        # Must add the --update-head-ok in the scenario that the current branch of the working directory
        # is equal to self._branch, otherwise the git fetch will exit with a non-zero exit code.
        self._execute_git_command_in_repo_and_raise_on_failure(
            git_command='fetch {} --update-head-ok {} {}'.format(git_clone_fetch_depth_arg, self._remote, self._branch),
            error_msg='Could not fetch specified branch "{}" from remote "{}".'.format(self._branch, self._remote)
        )

        # Validate and convert the user-specified hash/refspec to a full git hash
        fetch_head_hash = self._execute_git_command_in_repo_and_raise_on_failure(
            git_command='rev-parse FETCH_HEAD',
            error_msg='Could not rev-parse FETCH_HEAD of {} to a commit hash.'.format(self._branch)
        ).strip()

        # Save this hash as a local ref. Named local refs are necessary for slaves to fetch correctly from the master.
        # The local ref will be passed on to slaves instead of the user-specified branch.
        self._local_ref = 'refs/clusterrunner/{}'.format(fetch_head_hash)
        self._execute_git_command_in_repo_and_raise_on_failure(
            git_command='update-ref {} {}'.format(self._local_ref, fetch_head_hash),
            error_msg='Could not update local ref.'
        )

        # The '--' argument acts as a delimiter to differentiate values that can be "tree-ish" or a "path"
        self._execute_git_command_in_repo_and_raise_on_failure(
            git_command='reset --hard {} --'.format(fetch_head_hash),
            error_msg='Could not reset Git repo.'
        )

        self._execute_git_command_in_repo_and_raise_on_failure(
            git_command='clean -dfx',
            error_msg='Could not clean Git repo.'
        )
dataset/ETHPy150Open box/ClusterRunner/app/project_type/git.py/Git._fetch_project