forked from elastic/elasticsearch
-
Notifications
You must be signed in to change notification settings - Fork 0
/
atomic_push.sh
executable file
·68 lines (52 loc) · 2.04 KB
/
atomic_push.sh
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
#!/usr/bin/env bash
set -e
if [ "$#" -eq 0 ]; then
printf 'Usage: %s <origin> <branch> <branch> ...\n' "$(basename "$0")"
exit 0;
fi
REMOTE="$1"
WORKING_DIR=$(pwd)
if ! git ls-remote --exit-code "${REMOTE}" > /dev/null 2>&1; then
echo >&2 "Remote '${REMOTE}' is not valid."
exit 1;
fi
if [ "$#" -lt 3 ]; then
echo >&2 "You must specify at least two branches to push."
exit 1;
fi
if ! git diff-index --quiet HEAD -- ; then
echo >&2 "Found uncommitted changes in working copy."
exit 1;
fi
ATOMIC_COMMIT_DATE="$(date)"
for BRANCH in "${@:2}"
do
echo "Validating branch '${BRANCH}'..."
# Validate that script arguments are valid local branch names
if ! git show-ref --verify --quiet "refs/heads/${BRANCH}"; then
echo >&2 "No such branch named '${BRANCH}'."
exit 1;
fi
# Determine if the branch is checked out to a worktree directory
WORKTREE_DIR=$(git worktree list | grep -F [${BRANCH}] | awk '{print $1}')
# If the branch is checked out to a worktree directory change directory to there
if [ -n "${WORKTREE_DIR}" -a "${WORKTREE_DIR}" != "${WORKING_DIR}" ]; then
echo "Switching to ${BRANCH} worktree in ${WORKTREE_DIR}";
cd ${WORKTREE_DIR}
fi
# Pull and rebase all branches to ensure we've incorporated any new upstream commits
git checkout --quiet ${BRANCH}
git pull "${REMOTE}" "${BRANCH}" --rebase --quiet
PENDING_COMMITS=$(git log ${REMOTE}/${BRANCH}..HEAD --oneline | grep "^.*$" -c || true)
# Ensure that there is exactly 1 unpushed commit in the branch
if [ "${PENDING_COMMITS}" -ne 1 ]; then
echo >&2 "Expected exactly 1 pending commit for branch '${BRANCH}' but ${PENDING_COMMITS} exist."
exit 1;
fi
# Amend HEAD commit to ensure all branch commit dates are the same
GIT_COMMITTER_DATE="${ATOMIC_COMMIT_DATE}" git commit --amend --no-edit --quiet
# Change back to original working directory if necessary
cd ${WORKING_DIR}
done
echo "Pushing to remote '${REMOTE}'..."
git push --atomic "${REMOTE}" "${@:2}"