code: def git_rollback_on_error(gitroot_path, branch="master"):
      def run(*cmdline, **kwargs):
          """Run subprocess with cwd in sympy_doc"""
          print()
          print("Running: $ " + " ".join(cmdline))
          print()
          return subprocess.run(
              cmdline, cwd=gitroot_path, check=True, **kwargs
          )
  
      unclean_msg = (
          "The git repo should be completely clean before running this"
      )
  
      try:
          run("git", "diff", "--exit-code")  # Error if tree is unclean
      except subprocess.CalledProcessError:
          raise ValueError(unclean_msg)
      if run("git", "clean", "-n", stdout=subprocess.PIPE).stdout:
          raise ValueError(unclean_msg)
  
      run("git", "checkout", branch)
      run("git", "pull")
  
      bsha_start = run(
          "git", "rev-parse", "HEAD", stdout=subprocess.PIPE
      ).stdout
      sha_start = bsha_start.strip().decode("ascii")
  
      try:
          yield run
      except Exception as e:
          run("git", "reset", "--hard", sha_start)
          raise e from None
  
file_path: sympy/release/update_docs.py
imports: import json
  import subprocess
  import sys
  from os.path import join, splitext, basename
  from contextlib import contextmanager
  from tempfile import TemporaryDirectory
  from zipfile import ZipFile
  from shutil import copytree
label_desc: Use image node_id 3 for calling a global function with example usage: git_rollback_on_error(gitroot_path, branch) and returns: subprocess