def update(self, recursive=False, init=True, to_latest_revision=False, progress=None, dry_run=False,
               force=False, keep_going=False):
        if self.repo.bare:
            return self
        # END pass in bare mode

        if progress is None:
            progress = UpdateProgress()
        # END handle progress
        prefix = ''
        if dry_run:
            prefix = "DRY-RUN: "
        # END handle prefix

        # to keep things plausible in dry-run mode
        if dry_run:
            mrepo = None
        # END init mrepo

        try:
            # ASSURE REPO IS PRESENT AND UPTODATE
            #####################################
            try:
                mrepo = self.module()
                rmts = mrepo.remotes
                len_rmts = len(rmts)
                for i, remote in enumerate(rmts):
                    op = FETCH
                    if i == 0:
                        op |= BEGIN
                    # END handle start

                    progress.update(op, i, len_rmts, prefix + "Fetching remote %s of submodule %r"
                                    % (remote, self.name))
                    #===============================
                    if not dry_run:
                        remote.fetch(progress=progress)
                    # END handle dry-run
                    #===============================
                    if i == len_rmts - 1:
                        op |= END
                    # END handle end
                    progress.update(op, i, len_rmts, prefix + "Done fetching remote of submodule %r" % self.name)
                # END fetch new data
            except InvalidGitRepositoryError:
                if not init:
                    return self
                # END early abort if init is not allowed

                # there is no git-repository yet - but delete empty paths
                checkout_module_abspath = self.abspath
                if not dry_run and os.path.isdir(checkout_module_abspath):
                    try:
                        os.rmdir(checkout_module_abspath)
                    except OSError:
                        raise OSError("Module directory at %r does already exist and is non-empty"
                                      % checkout_module_abspath)
                    # END handle OSError
                # END handle directory removal

                # don't check it out at first - nonetheless it will create a local
                # branch according to the remote-HEAD if possible
                progress.update(BEGIN | CLONE, 0, 1, prefix + "Cloning url '%s' to '%s' in submodule %r" %
                                (self.url, checkout_module_abspath, self.name))
                if not dry_run:
                    mrepo = self._clone_repo(self.repo, self.url, self.path, self.name, n=True)
                # END handle dry-run
                progress.update(END | CLONE, 0, 1, prefix + "Done cloning to %s" % checkout_module_abspath)

                if not dry_run:
                    # see whether we have a valid branch to checkout
                    try:
                        # find  a remote which has our branch - we try to be flexible
                        remote_branch = find_first_remote_branch(mrepo.remotes, self.branch_name)
                        local_branch = mkhead(mrepo, self.branch_path)

                        # have a valid branch, but no checkout - make sure we can figure
                        # that out by marking the commit with a null_sha
                        local_branch.set_object(util.Object(mrepo, self.NULL_BIN_SHA))
                        # END initial checkout + branch creation

                        # make sure HEAD is not detached
                        mrepo.head.set_reference(local_branch, logmsg="submodule: attaching head to %s" % local_branch)
                        mrepo.head.ref.set_tracking_branch(remote_branch)
                    except IndexError:
                        log.warn("Failed to checkout tracking branch %s", self.branch_path)
                    # END handle tracking branch

                    # NOTE: Have to write the repo config file as well, otherwise
                    # the default implementation will be offended and not update the repository
                    # Maybe this is a good way to assure it doesn't get into our way, but
                    # we want to stay backwards compatible too ... . Its so redundant !
                    writer = self.repo.config_writer()
                    writer.set_value(sm_section(self.name), 'url', self.url)
                    writer.release()
                # END handle dry_run
            # END handle initalization

            # DETERMINE SHAS TO CHECKOUT
            ############################
            binsha = self.binsha
            hexsha = self.hexsha
            if mrepo is not None:
                # mrepo is only set if we are not in dry-run mode or if the module existed
                is_detached = mrepo.head.is_detached
            # END handle dry_run

            if mrepo is not None and to_latest_revision:
                msg_base = "Cannot update to latest revision in repository at %r as " % mrepo.working_dir
                if not is_detached:
                    rref = mrepo.head.ref.tracking_branch()
                    if rref is not None:
                        rcommit = rref.commit
                        binsha = rcommit.binsha
                        hexsha = rcommit.hexsha
                    else:
                        log.error("%s a tracking branch was not set for local branch '%s'", msg_base, mrepo.head.ref)
                    # END handle remote ref
                else:
                    log.error("%s there was no local tracking branch", msg_base)
                # END handle detached head
            # END handle to_latest_revision option

            # update the working tree
            # handles dry_run
            if mrepo is not None and mrepo.head.commit.binsha != binsha:
                # We must assure that our destination sha (the one to point to) is in the future of our current head.
                # Otherwise, we will reset changes that might have been done on the submodule, but were not yet pushed
                # We also handle the case that history has been rewritten, leaving no merge-base. In that case
                # we behave conservatively, protecting possible changes the user had done
                may_reset = True
                if mrepo.head.commit.binsha != self.NULL_BIN_SHA:
                    base_commit = mrepo.merge_base(mrepo.head.commit, hexsha)
                    if len(base_commit) == 0 or base_commit[0].hexsha == hexsha:
                        if force:
                            msg = "Will force checkout or reset on local branch that is possibly in the future of"
                            msg += "the commit it will be checked out to, effectively 'forgetting' new commits"
                            log.debug(msg)
                        else:
                            msg = "Skipping %s on branch '%s' of submodule repo '%s' as it contains un-pushed commits"
                            msg %= (is_detached and "checkout" or "reset", mrepo.head, mrepo)
                            log.info(msg)
                            may_reset = False
                        # end handle force
                    # end handle if we are in the future

                    if may_reset and not force and mrepo.is_dirty(index=True, working_tree=True, untracked_files=True):
                        raise RepositoryDirtyError(mrepo, "Cannot reset a dirty repository")
                    # end handle force and dirty state
                # end handle empty repo

                # end verify future/past
                progress.update(BEGIN | UPDWKTREE, 0, 1, prefix +
                                "Updating working tree at %s for submodule %r to revision %s"
                                % (self.path, self.name, hexsha))

                if not dry_run and may_reset:
                    if is_detached:
                        # NOTE: for now we force, the user is no supposed to change detached
                        # submodules anyway. Maybe at some point this becomes an option, to
                        # properly handle user modifications - see below for future options
                        # regarding rebase and merge.
                        mrepo.git.checkout(hexsha, force=force)
                    else:
                        mrepo.head.reset(hexsha, index=True, working_tree=True)
                    # END handle checkout
                # if we may reset/checkout
                progress.update(END | UPDWKTREE, 0, 1, prefix + "Done updating working tree for submodule %r"
                                % self.name)
            # END update to new commit only if needed
        except Exception as err:
            if not keep_going:
                raise
            log.error(str(err))
        # end handle keep_going

        # HANDLE RECURSION
        ##################
        if recursive:
            # in dry_run mode, the module might not exist
            if mrepo is not None:
                for submodule in self.iter_items(self.module()):
                    submodule.update(recursive, init, to_latest_revision, progress=progress, dry_run=dry_run,
                                     force=force, keep_going=keep_going)
                # END handle recursive update
            # END handle dry run
        # END for each submodule

        return self
Update the repository of this submodule to point to the checkout
dataset/ETHPy150Open gitpython-developers/GitPython/git/objects/submodule/base.py/Submodule.update