1
This commit is contained in:
142
push-git.sh
Normal file
142
push-git.sh
Normal file
@@ -0,0 +1,142 @@
|
||||
#!/usr/bin/env sh
|
||||
#
|
||||
# 这个脚本用于一键提交并推送当前 Git 仓库。
|
||||
#
|
||||
# 使用命令案例:
|
||||
# sh push-git.sh "提交说明"
|
||||
# chmod +x push-git.sh && ./push-git.sh "提交说明"
|
||||
# ./push-git.sh -m "提交说明" --pull-rebase
|
||||
# ./push-git.sh -m "提交说明" --dry-run
|
||||
#
|
||||
# 这个脚本做的事情:
|
||||
# 1. 自动进入脚本所在 Git 仓库根目录,并检查当前分支和远程仓库。
|
||||
# 2. 如果存在本地改动,执行 git add -A 和 git commit -m "提交说明"。
|
||||
# 3. 按当前分支推送到远程仓库;首次推送会自动设置 upstream。
|
||||
|
||||
set -eu
|
||||
|
||||
SCRIPT_DIR="$(CDPATH= cd -- "$(dirname -- "$0")" && pwd)"
|
||||
REMOTE="origin"
|
||||
MESSAGE=""
|
||||
PULL_REBASE=0
|
||||
NO_VERIFY=0
|
||||
DRY_RUN=0
|
||||
|
||||
usage() {
|
||||
cat <<'EOF'
|
||||
Usage:
|
||||
./push-git.sh "commit message"
|
||||
./push-git.sh -m "commit message" [--pull-rebase] [--dry-run]
|
||||
|
||||
Options:
|
||||
-m, --message MESSAGE Commit message.
|
||||
-r, --remote REMOTE Git remote name. Default: origin.
|
||||
--pull-rebase Run git pull --rebase before pushing.
|
||||
--no-verify Skip git commit hooks.
|
||||
--dry-run Print commands without running them.
|
||||
-h, --help Show this help.
|
||||
EOF
|
||||
}
|
||||
|
||||
die() {
|
||||
echo "Error: $*" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
run() {
|
||||
echo "git $*"
|
||||
if [ "$DRY_RUN" -eq 1 ]; then
|
||||
return 0
|
||||
fi
|
||||
|
||||
git "$@"
|
||||
}
|
||||
|
||||
while [ "$#" -gt 0 ]; do
|
||||
case "$1" in
|
||||
-m|--message)
|
||||
[ "$#" -ge 2 ] || die "$1 requires a value"
|
||||
MESSAGE="$2"
|
||||
shift 2
|
||||
;;
|
||||
-r|--remote)
|
||||
[ "$#" -ge 2 ] || die "$1 requires a value"
|
||||
REMOTE="$2"
|
||||
shift 2
|
||||
;;
|
||||
--pull-rebase)
|
||||
PULL_REBASE=1
|
||||
shift
|
||||
;;
|
||||
--no-verify)
|
||||
NO_VERIFY=1
|
||||
shift
|
||||
;;
|
||||
--dry-run)
|
||||
DRY_RUN=1
|
||||
shift
|
||||
;;
|
||||
-h|--help)
|
||||
usage
|
||||
exit 0
|
||||
;;
|
||||
--)
|
||||
shift
|
||||
break
|
||||
;;
|
||||
-*)
|
||||
die "unknown option: $1"
|
||||
;;
|
||||
*)
|
||||
if [ -z "$MESSAGE" ]; then
|
||||
MESSAGE="$1"
|
||||
else
|
||||
MESSAGE="$MESSAGE $1"
|
||||
fi
|
||||
shift
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
REPO_ROOT="$(git -C "$SCRIPT_DIR" rev-parse --show-toplevel)"
|
||||
cd "$REPO_ROOT"
|
||||
|
||||
BRANCH="$(git rev-parse --abbrev-ref HEAD)"
|
||||
[ -n "$BRANCH" ] && [ "$BRANCH" != "HEAD" ] || die "detached HEAD detected; checkout a branch before pushing"
|
||||
|
||||
git remote get-url "$REMOTE" >/dev/null || die "remote not found: $REMOTE"
|
||||
|
||||
STATUS="$(git status --porcelain)"
|
||||
if [ -n "$STATUS" ]; then
|
||||
if [ -z "$MESSAGE" ]; then
|
||||
if [ "$DRY_RUN" -eq 1 ]; then
|
||||
MESSAGE="<commit message>"
|
||||
else
|
||||
printf "Commit message: "
|
||||
IFS= read -r MESSAGE
|
||||
fi
|
||||
fi
|
||||
|
||||
[ -n "$MESSAGE" ] || die "commit message is required when there are local changes"
|
||||
|
||||
run add -A
|
||||
|
||||
if [ "$NO_VERIFY" -eq 1 ]; then
|
||||
run commit -m "$MESSAGE" --no-verify
|
||||
else
|
||||
run commit -m "$MESSAGE"
|
||||
fi
|
||||
else
|
||||
echo "No local file changes to commit."
|
||||
fi
|
||||
|
||||
if [ "$PULL_REBASE" -eq 1 ]; then
|
||||
run fetch "$REMOTE"
|
||||
run pull --rebase "$REMOTE" "$BRANCH"
|
||||
fi
|
||||
|
||||
if git rev-parse --abbrev-ref --symbolic-full-name '@{u}' >/dev/null 2>&1; then
|
||||
run push "$REMOTE" "$BRANCH"
|
||||
else
|
||||
run push -u "$REMOTE" "$BRANCH"
|
||||
fi
|
||||
Reference in New Issue
Block a user