我通常至少有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”,然后更新(快进或合并)当前工作的分支,但不包括其他本地分支。
我仍然需要手动切换到每个本地分支并进行更新。
如果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-fetch直接更新本地ref,这比检查分支简单得多,也比git-update-ref更安全。
这里我们使用git-fetch来更新非当前分支,而git pull——ff-only用于当前分支。它:
不需要检查分支机构
仅在可以快进的情况下更新分支
当它不能快进时会报告吗
就是这样:
#!/bin/bash
currentbranchref="$(git symbolic-ref HEAD 2>&-)"
git branch -r | grep -v ' -> ' | while read remotebranch
do
# Split <remote>/<branch> into remote and branchref parts
remote="${remotebranch%%/*}"
branchref="refs/heads/${remotebranch#*/}"
if [ "$branchref" == "$currentbranchref" ]
then
echo "Updating current branch $branchref from $remote..."
git pull --ff-only
else
echo "Updating non-current ref $branchref from $remote..."
git fetch "$remote" "$branchref:$branchref"
fi
done
从git-fetch的manpage:
<refspec>
The format of a <refspec> parameter is an optional plus +, followed by the source ref <src>,
followed by a colon :, followed by the destination ref <dst>.
The remote ref that matches <src> is fetched, and if <dst> is not empty string, the local ref
that matches it is fast-forwarded using <src>. If the optional plus + is used, the local ref is
updated even if it does not result in a fast-forward update.
通过指定git fetch <remote> <ref>:<ref>(没有任何+),我们得到一个只在本地ref可以快进时更新它的fetch。
注意,这假设本地分支和远程分支的名称相同(并且您希望跟踪所有分支),它实际上应该使用关于您拥有哪些本地分支以及它们被设置为跟踪的内容的信息。
事实上,在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(我使用的),它可以工作。