我通常至少有3个远程分支:master、staging和production。我有3个本地分支来跟踪这些远程分支。
更新我所有的本地分支是乏味的:
git fetch --all
git rebase origin/master
git checkout staging
git rebase origin/staging
git checkout production
git rebase origin/production
我很想做一个“git pull -all”,但我还没能让它工作。它似乎做了一个“fetch -all”,然后更新(快进或合并)当前工作的分支,但不包括其他本地分支。
我仍然需要手动切换到每个本地分支并进行更新。
以上答案都没有考虑存在多个工作树的可能性。使用git update-ref或git branch -f更新当前在其他工作树中签出的分支会产生意想不到的副作用。
考虑一下我处理工作树的解决方案:
#! /usr/bin/env bash
set -euo pipefail
# Read the default remote from config, defaulting to "origin".
DEFAULT_REMOTE=$(git config --default origin --get clone.defaultRemoteName)
# Use first argument as remote name, fallback to default.
REMOTE=${1:-$DEFAULT_REMOTE}
# Resolve the rev that HEAD points at, so that we can give it
# a special treatment.
HEAD_REV=$(git rev-parse HEAD)
# Format that allows us to easily grep for local branches that are behind,
# and have an upstream at $REMOTE.
FORMAT="%(upstream:trackshort)%(upstream:remotename)|%(refname:short)"
# Get a list of revs that are checked out. We don't want to
# update refs that are pointing at them.
set +e
WORKTREE_REVS=$(git worktree list --porcelain | grep -Po "HEAD \K(.+)" | grep -v "$HEAD_REV")
set -e
git fetch $REMOTE
for BRANCH in $(git for-each-ref refs/heads --format="$FORMAT" | grep -Po "<$REMOTE\|\K(.+)")
do
BRANCH_REV=$(git rev-parse $BRANCH)
if [ "$BRANCH_REV" = "$HEAD_REV" ]
then
# This branch is currently checked out "here". Forward it carefully.
set +e
git merge --no-autostash --ff-only $BRANCH@{u}
set -e
elif grep -q "$BRANCH_REV" <<< "$WORKTREE_REVS"
then
# This branch is currently checked out by another. Leave it alone.
echo "$BRANCH skipped, because it is checked out in another worktree. Use 'git worktree list' to diagnose."
else
# This branch is not checked out. Just update it!
git update-ref refs/heads/$BRANCH $BRANCH@{u}
echo "$BRANCH forwarded"
fi
done