我通常至少有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-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。
注意,这假设本地分支和远程分支的名称相同(并且您希望跟踪所有分支),它实际上应该使用关于您拥有哪些本地分支以及它们被设置为跟踪的内容的信息。
似乎很多人都提供了类似的解决方案,但我想分享一下我的想法,并邀请其他人来贡献。这个解决方案有一个漂亮的彩色输出,优雅地处理您当前的工作目录,并且速度很快,因为它不做任何检出,并巧妙地保留您的工作目录。此外,它只是一个shell脚本,除了git之外没有其他依赖项。(目前只在OSX上测试过)
#!/usr/bin/env bash
gitup(){
RED='\033[33;31m'
YELLO='\033[33;33m'
GREEN='\033[33;32m'
NC='\033[0m' # No Color
HEAD=$(git rev-parse HEAD)
CHANGED=$(git status --porcelain | wc -l)
echo "Fetching..."
git fetch --all --prune &>/dev/null
for branch in `git for-each-ref --format='%(refname:short)' refs/heads`; do
LOCAL=$(git rev-parse --quiet --verify $branch)
if [ "$HEAD" = "$LOCAL" ] && [ $CHANGED -gt 0 ]; then
echo -e "${YELLO}WORKING${NC}\t\t$branch"
elif git rev-parse --verify --quiet $branch@{u}&>/dev/null; then
REMOTE=$(git rev-parse --quiet --verify $branch@{u})
BASE=$(git merge-base $branch $branch@{u})
if [ "$LOCAL" = "$REMOTE" ]; then
echo -e "${GREEN}OK${NC}\t\t$branch"
elif [ "$LOCAL" = "$BASE" ]; then
if [ "$HEAD" = "$LOCAL" ]; then
git merge $REMOTE&>/dev/null
else
git branch -f $branch $REMOTE
fi
echo -e "${GREEN}UPDATED${NC}\t\t$branch"
elif [ "$REMOTE" = "$BASE" ]; then
echo -e "${RED}AHEAD${NC}\t\t$branch"
else
echo -e "${RED}DIVERGED${NC}\t\t$branch"
fi
else
echo -e "${RED}NO REMOTE${NC}\t$branch"
fi
done
}
https://github.com/davestimpert/gitup
对不起,我似乎也想出了与上面其他工具相同的名字。
如果可能,以下一行代码将快速前进所有具有上游分支的分支,否则打印错误:
git branch \
--format "%(if)%(upstream:short)%(then)git push . %(upstream:short):%(refname:short)%(end)" |
sh
它是如何工作的?
它使用git分支命令的自定义格式。对于每个具有上游分支的分支,它打印一行具有以下模式的代码:
git push . <remote-ref>:<branch>
这可以直接通过管道传输到sh(假设分支名称是格式良好的)。忽略| sh,看看它在做什么。
警告
单行程序不会联系你的遥控器。在运行它之前,发出git fetch或git fetch。
当前签出的分支将不会用类似于
! [remote rejected] origin/master -> master (branch is currently checked out)
为此,您可以求助于常规的git pull -ff-only。
别名
将以下内容添加到你的.gitconfig中,以便git fft执行此命令:
[alias]
fft = !sh -c 'git branch --format \"%(if)%(upstream:short)%(then)git push . %(upstream:short):%(refname:short)%(end)\" | sh' -
参见my .gitconfig。别名是“快进跟踪(分支)”的缩写。