我通常至少有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 pull origin master staging production

如果我想推送多个分支,我会调用

git push origin master staging production

但只有当所有提到的分支都不需要任何形式的合并时,两者才有效。

其他回答

自动化并不难:

#!/bin/sh
# Usage: fetchall.sh branch ...

set -x
git fetch --all
for branch in "$@"; do
    git checkout "$branch"      || exit 1
    git rebase "origin/$branch" || exit 1
done

一个略有不同的脚本,它只快进与上游分支名称匹配的分支。如果可以快进,它还会更新当前分支。

通过运行git branch -vv,确保所有分支的上游分支都被正确设置。使用git branch -u origin/yourbanchname设置上游分支

复制粘贴到一个文件并chmod 755:

#!/bin/sh

curbranch=$(git rev-parse --abbrev-ref HEAD)

for branch in $(git for-each-ref refs/heads --format="%(refname:short)"); do
        upbranch=$(git config --get branch.$branch.merge | sed 's:refs/heads/::');
        if [ "$branch" = "$upbranch" ]; then
                if [ "$branch" = "$curbranch" ]; then
                        echo Fast forwarding current branch $curbranch
                        git merge --ff-only origin/$upbranch
                else
                        echo Fast forwarding $branch with origin/$upbranch
                        git fetch . origin/$upbranch:$branch
                fi
        fi
done;

如果refs/heads/master可以快进到refs/remotes/foo/master,则

git merge-base refs/heads/master refs/remotes/foo/master

应该返回refs/heads/master指向的SHA1 id。这样,您就可以将一个脚本组合在一起,自动更新没有应用转移提交的所有本地分支。

这个小shell脚本(我称之为git-can-ff)说明了如何做到这一点。

#!/bin/sh

set -x

usage() {
    echo "usage: $(basename $0) <from-ref> <to-ref>" >&2
    exit 2
}

[ $# -ne 2 ] && usage

FROM_REF=$1
TO_REF=$2

FROM_HASH=$(git show-ref --hash $FROM_REF)
TO_HASH=$(git show-ref --hash $TO_REF)
BASE_HASH=$(git merge-base $FROM_REF $TO_REF)

if [ "$BASE_HASH" = "$FROM_HASH" -o \
     "$BASE_HASH" = "$FROM_REF" ]; then
    exit 0
else
    exit 1
fi

它可以使用下面的脚本…它将首先获取所有分支,逐个签出并自行更新。

#!/bin/bash
git branch -r | grep -v '\->' | while read remote; do git branch --track 
"${remote#origin/}" "$remote"; done

set -x
CURRENT=`git rev-parse --abbrev-ref HEAD`
git fetch --all
branch_name=$(git branch | awk '{print $1" "}' | grep -v '*' | xargs)
for branch in $branch_name; do
   git checkout "$branch" || exit 1
   git rebase "origin/$branch" || exit 1
   git pull origin $branch|| exit 1
done
git checkout "$CURRENT" || exit 1
git pull || exit 1

这个问题(目前)还没有解决,至少在没有脚本的情况下不容易解决:参见Junio C Hamano在git邮件列表上发布的这篇文章,解释了这种情况并提供了一个简单的解决方案。

主要的理由是你不需要这个:

With git that is not ancient (i.e. v1.5.0 or newer), there is no reason to have local "dev" that purely track the remote anymore. If you only want to go-look-and-see, you can check out the remote tracking branch directly on a detached HEAD with "git checkout origin/dev". Which means that the only cases we need to make it convenient for users are to handle these local branches that "track" remote ones when you do have local changes, or when you plan to have some. If you do have local changes on "dev" that is marked to track the remove "dev", and if you are on a branch different from "dev", then we should not do anything after "git fetch" updates the remote tracking "dev". It won't fast forward anyway

解决方案需要一个选项或外部脚本,以修剪当前远程跟踪分支的本地分支,而不是像最初的海报所要求的那样,通过快进来保持它们的最新状态。

那么,“git branch -prune -remote=<upstream>”如何呢 本地分支,如果 (1)不是目前的分支机构;而且 (2)标记为从<上游>取的某个分支;而且 (三)自身无过错; 然后把那根树枝去掉?“git remote——prune-local-forks <upstream>”是 还好;我不关心哪个命令实现了这个特性 多。

注意:从git 2.10开始就没有这样的解决方案了。注意,git remote prune子命令和git fetch——prune是关于删除不再存在于远程上的分支的远程跟踪分支,而不是关于删除跟踪远程跟踪分支的本地分支(其中远程跟踪分支是上游分支)。