Clean up maintenance scripts (#2550)

- Factor update into a separate script. It's pretty verbose.
- Fetch the base branch for doing comparisons in merge scripts.
- Have uniform error handling for missing `gh`
- Some other consistency between the scripts.
- Turn of `set -x`. Current script messaging is better than that
  gets us.

Example PRs created by these scripts (because testing in prod
is the only testing):
https://github.com/google/iree/pull/2554
https://github.com/google/iree/pull/2555
https://github.com/google/iree/pull/2553
diff --git a/scripts/git/bazel_to_cmake.sh b/scripts/git/bazel_to_cmake.sh
index e5738fa..bd7fb79 100755
--- a/scripts/git/bazel_to_cmake.sh
+++ b/scripts/git/bazel_to_cmake.sh
@@ -26,32 +26,14 @@
 # - Requires that the working directory be clean. Will abort otherwise.
 
 set -e
-set -x
 set -o pipefail
 
+export UPSTREAM_REMOTE="${UPSTREAM_REMOTE:-upstream}"
 BASE_BRANCH="${1:-google}"
 PR_BRANCH="bazel-to-cmake-fix"
-UPSTREAM_REMOTE="${UPSTREAM_REMOTE:-upstream}"
 FORK_REMOTE="${FORK_REMOTE:-origin}"
 
-if [[ -n "$(git status --porcelain)" ]]; then
-  echo "Working directory not clean. Aborting"
-  git status
-  exit 1
-fi
-if ! git symbolic-ref -q HEAD; then
-  echo "In a detached HEAD state. Aborting"
-  git status
-  exit 1
-fi
-git checkout "${BASE_BRANCH?}"
-git pull "${UPSTREAM_REMOTE?}" "${BASE_BRANCH?}" --ff-only
-git submodule update --init
-if [[ -n "$(git status --porcelain)" ]]; then
-  echo "Working directory not clean after sync. Aborting"
-  git status
-  exit 1
-fi
+./scripts/git/git_update.sh "${BASE_BRANCH?}"
 git checkout -B "${PR_BRANCH?}"
 ./build_tools/bazel_to_cmake/bazel_to_cmake.py
 
@@ -63,4 +45,14 @@
 
 git commit -am "${TITLE?}"
 git push -f "${FORK_REMOTE}" "${PR_BRANCH?}"
+
+if [[ -z "$(which gh)" ]]; then
+  echo "gh not found on path."
+  echo "Have you installed the GitHub CLI (https://github.com/cli/cli)?"
+  echo "Cannot create PR. Branch ${PR_BRANCH?} pushed, but aborting."
+  echo "You can manually create a PR using the generated body:"
+  echo "${BODY?}"
+  exit 1
+fi
+
 gh pr create --title="${TITLE?}" --body="${BODY?}" --base="${BASE_BRANCH?}"
diff --git a/scripts/git/git_update.sh b/scripts/git/git_update.sh
new file mode 100755
index 0000000..56fab02
--- /dev/null
+++ b/scripts/git/git_update.sh
@@ -0,0 +1,52 @@
+#!/bin/bash
+
+# Copyright 2020 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# Checks out and updates the specified branch to match the corresponding branch
+# on UPSTREAM_REMOTE (default "upstream")
+#
+# - Requires that the local branch is a pristine (potentially stale) copy of the
+#   same branch on the configured UPSTREAM_REMOTE.
+# - Requires that the working directory be clean. Will abort otherwise.
+
+set -e
+set -o pipefail
+
+BRANCH="$1"
+UPSTREAM_REMOTE="${UPSTREAM_REMOTE:-upstream}"
+
+if [[ -z "$BRANCH" ]]; then
+  echo "Must specify a branch to update for git_update.sh"
+  exit 1
+fi
+
+if [[ -n "$(git status --porcelain)" ]]; then
+    echo "Working directory not clean. Aborting"
+    git status
+    exit 1
+fi
+if ! git symbolic-ref -q HEAD; then
+    echo "In a detached HEAD state. Aborting"
+    git status
+    exit 1
+fi
+git checkout "${BRANCH?}"
+git pull "${UPSTREAM_REMOTE?}" "${BRANCH?}" --ff-only
+git submodule update --init
+if [[ -n "$(git status --porcelain)" ]]; then
+    echo "Working directory not clean after update"
+    git status
+    exit 1
+fi
diff --git a/scripts/git/google_to_main.sh b/scripts/git/google_to_main.sh
index 0ec91a7..ebd34bd 100755
--- a/scripts/git/google_to_main.sh
+++ b/scripts/git/google_to_main.sh
@@ -25,47 +25,35 @@
 #   (default "upstream").
 # - Requires that the working directory be clean. Will abort otherwise.
 
-set -x
 set -e
 set -o pipefail
 
 GREEN_COMMIT="${1:-google}"
 
+export UPSTREAM_REMOTE="${UPSTREAM_REMOTE:-upstream}"
 PR_BRANCH="${PR_BRANCH:-google-to-main}"
-UPSTREAM_REMOTE="${UPSTREAM_REMOTE:-upstream}"
 FORK_REMOTE="${FORK_REMOTE:-origin}"
 
-if [[ -n "$(git status --porcelain)" ]]; then
-  echo "Working directory not clean. Aborting"
-  git status
-  exit 1
-fi
-if ! git symbolic-ref -q HEAD; then
-  echo "In a detached HEAD state. Aborting"
-  git status
-  exit 1
-fi
-git checkout google
-git pull "${UPSTREAM_REMOTE?}" google --ff-only
-git submodule update --init
-if [[ -n "$(git status --porcelain)" ]]; then
-  echo "Working directory not clean after sync. Aborting"
-  git status
-  exit 1
-fi
+./scripts/git/git_update.sh google
 if [[ "${GREEN_COMMIT}" != "google" ]]; then
   git checkout "${GREEN_COMMIT?}"
   git submodule update
 fi
+
 git checkout -B "${PR_BRANCH?}"
 git push -f "${FORK_REMOTE?}" "${PR_BRANCH?}"
+
+TITLE="Merge google -> main"
+
+git fetch "${UPSTREAM_REMOTE?}" main
+BODY="$(git log ${UPSTREAM_REMOTE?}/main.. --decorate=no --pretty='format:* %h %<(80,trunc)%s')"
+
 if [[ -z "$(which gh)" ]]; then
   echo "gh not found on path."
   echo "Have you installed the GitHub CLI (https://github.com/cli/cli)?"
-  echo "Cannot create PR. Branch ${BRANCH?} pushed, but aborting."
+  echo "Cannot create PR. Branch ${PR_BRANCH?} pushed, but aborting."
+  echo "You can manually create a PR using the generated body:"
+  echo "${BODY?}"
   exit 1
 fi
-gh pr create \
-    --base main \
-    --title="Merge google -> main" \
-    --body="$(git log main.. --decorate=no --pretty='format:* %h %<(80,trunc)%s')"
+gh pr create --base main --title="${TITLE?}" --body="${BODY?}"
diff --git a/scripts/git/main_to_google.sh b/scripts/git/main_to_google.sh
index 53c2513..980cb3a 100755
--- a/scripts/git/main_to_google.sh
+++ b/scripts/git/main_to_google.sh
@@ -25,47 +25,35 @@
 #   (default "upstream").
 # - Requires that the working directory be clean. Will abort otherwise.
 
-set -x
 set -e
 set -o pipefail
 
 GREEN_COMMIT="${1:-main}"
 
+export UPSTREAM_REMOTE="${UPSTREAM_REMOTE:-upstream}"
 PR_BRANCH="${PR_BRANCH:-main-to-google}"
-UPSTREAM_REMOTE="${UPSTREAM_REMOTE:-upstream}"
 FORK_REMOTE="${FORK_REMOTE:-origin}"
 
-if [[ -n "$(git status --porcelain)" ]]; then
-  echo "Working directory not clean. Aborting"
-  git status
-  exit 1
-fi
-if ! git symbolic-ref -q HEAD; then
-  echo "In a detached HEAD state. Aborting"
-  git status
-  exit 1
-fi
-git checkout main
-git pull "${UPSTREAM_REMOTE?}" main --ff-only
-git submodule update --init
-if [[ -n "$(git status --porcelain)" ]]; then
-  echo "Working directory not clean after sync. Aborting"
-  git status
-  exit 1
-fi
+./scripts/git/git_update.sh main
 if [[ "${GREEN_COMMIT}" != "main" ]]; then
   git checkout "${GREEN_COMMIT?}"
   git submodule update
 fi
+
 git checkout -B "${PR_BRANCH?}"
 git push -f "${FORK_REMOTE?}" "${PR_BRANCH?}"
+
+TITLE="Merge main -> google"
+
+git fetch "${UPSTREAM_REMOTE?}" google
+BODY="$(git log ${UPSTREAM_REMOTE?}/google.. --decorate=no --pretty='format:* %h %<(80,trunc)%s')"
+
 if [[ -z "$(which gh)" ]]; then
   echo "gh not found on path."
   echo "Have you installed the GitHub CLI (https://github.com/cli/cli)?"
-  echo "Cannot create PR. Branch ${BRANCH?} pushed, but aborting."
+  echo "Cannot create PR. Branch ${PR_BRANCH?} pushed, but aborting."
+  echo "You can manually create a PR using the generated body:"
+  echo "${BODY?}"
   exit 1
 fi
-gh pr create \
-    --base google \
-    --title="Merge main -> google" \
-    --body="$(git log google.. --decorate=no --pretty='format:* %h %<(80,trunc)%s')"
+gh pr create --base google --title="${TITLE?}" --body="${BODY?}"
diff --git a/scripts/git/update_tf_submodule.sh b/scripts/git/update_tf_submodule.sh
index a3aac63..0f61a9c 100755
--- a/scripts/git/update_tf_submodule.sh
+++ b/scripts/git/update_tf_submodule.sh
@@ -30,34 +30,16 @@
 #   TENSORFLOW_COMMIT is REMOTE and the trimmed commit sha otherwise.
 
 set -e
-set -x
 set -o pipefail
 
+export UPSTREAM_REMOTE="${UPSTREAM_REMOTE:-upstream}"
 TENSORFLOW_COMMIT="${1:-REMOTE}"
 PR_BRANCH="tf-submodule-update"
 BASE_BRANCH="${1:-google}"
-UPSTREAM_REMOTE="${UPSTREAM_REMOTE:-upstream}"
 FORK_REMOTE="${FORK_REMOTE:-origin}"
 TF_COMMIT_NICKNAME=""
 
-if [[ -n "$(git status --porcelain)" ]]; then
-  echo "Working directory not clean. Aborting"
-  git status
-  exit 1
-fi
-if ! git symbolic-ref -q HEAD; then
-  echo "In a detached HEAD state. Aborting"
-  git status
-  exit 1
-fi
-git checkout "${BASE_BRANCH?}"
-git pull "${UPSTREAM_REMOTE?}" "${BASE_BRANCH?}" --ff-only
-git submodule update --init
-if [[ -n "$(git status --porcelain)" ]]; then
-  echo "Working directory not clean after sync. Aborting"
-  git status
-  exit 1
-fi
+./scripts/git/git_update.sh "${BASE_BRANCH?}"
 git checkout -B "${PR_BRANCH?}"
 
 CMD="./scripts/git/update_tf_llvm_submodules.py --llvm_commit=KEEP --update_build_files=true --tensorflow_commit=${TENSORFLOW_COMMIT?}"
@@ -83,4 +65,13 @@
 
 git commit -am "${TITLE?}"
 git push -f "${FORK_REMOTE?}" "${PR_BRANCH?}"
+
+if [[ -z "$(which gh)" ]]; then
+  echo "gh not found on path."
+  echo "Have you installed the GitHub CLI (https://github.com/cli/cli)?"
+  echo "Cannot create PR. Branch ${PR_BRANCH?} pushed, but aborting."
+  echo "You can manually create a PR using the generated body:"
+  echo "${BODY?}"
+  exit 1
+fi
 gh pr create --title="${TITLE?}" --body="${BODY?}" --base="${BASE_BRANCH?}"