我通常至少有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”,然后更新(快进或合并)当前工作的分支,但不包括其他本地分支。

我仍然需要手动切换到每个本地分支并进行更新。


当前回答

我使用hub的sync子命令来实现自动化。我在我的.bash_profile中有别名git=hub,所以我键入的命令是:

git sync

这将更新具有匹配上游分支的所有本地分支。从手册页:

如果本地分支已经过时,快进; 如果本地分支包含未推送的工作,请对此发出警告; 如果分支显示为已合并,且上游分支已被删除,则删除该分支。

它还处理在当前分支上存储/解存储未提交的更改。

我曾经使用过一个类似的工具,叫做git-up,但它不再被维护,git sync几乎做了完全相同的事情。

其他回答

为了完成Matt Connolly的回答,这是一种更安全的更新本地分支引用的方法,可以快进,而不签出分支。它不会更新不能快进的分支(即已经分离的分支),也不会更新当前签出的分支(因为这样工作副本也应该更新)。

git fetch

head="$(git symbolic-ref HEAD)"
git for-each-ref --format="%(refname) %(upstream)" refs/heads | while read ref up; do
    if [ -n "$up" -a "$ref" != "$head" ]; then
        mine="$(git rev-parse "$ref")"
        theirs="$(git rev-parse "$up")"
        base="$(git merge-base "$ref" "$up")"
        if [ "$mine" != "$theirs" -a "$mine" == "$base" ]; then
            git update-ref "$ref" "$theirs"
        fi
    fi
done

事实上,在git 1.8.3.1版本中,它是这样工作的:

[root@test test]# git br
* master
  release/0.1
  update
[root@test test]# git pull --rebase
remote: Enumerating objects: 9, done.
remote: Counting objects: 100% (9/9), done.
remote: Compressing objects: 100% (9/9), done.
remote: Total 9 (delta 2), reused 0 (delta 0)
Unpacking objects: 100% (9/9), done.
From http://xxx/scm/csdx/test-git
   d32ca6d..2caa393  release/0.1 -> origin/release/0.1
Current branch master is up to date.
[root@test test]# git --version
git version 1.8.3.1

在主分支中,您可以更新所有其他分支。@Cascabel

我不知道哪个版本破坏/修复了它,在2.17(我使用的),它可以工作。

如果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

“git pull -all”可以更新我所有的本地分支吗?

不,它不能。对于快进,我只是编写了一个小工具。https://github.com/changyuheng/git-fast-forward-all

该工具的优点:

在一个存储库中支持多个远程。(集线器同步目前不支持多个遥控器。) 支持在本地分支和相应的远程跟踪分支上使用不同的名称。 比其他获取每个分支的远程脚本快得多。 没有容易出错的正则表达式解析/编辑。

自动化并不难:

#!/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