我通常至少有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”,然后更新(快进或合并)当前工作的分支,但不包括其他本地分支。
我仍然需要手动切换到每个本地分支并进行更新。
这个问题(目前)还没有解决,至少在没有脚本的情况下不容易解决:参见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是关于删除不再存在于远程上的分支的远程跟踪分支,而不是关于删除跟踪远程跟踪分支的本地分支(其中远程跟踪分支是上游分支)。
这里有很多可以接受的答案,但对于外行来说,有些管道可能有点不透明。下面是一个可以轻松定制的简单示例:
$ cat ~/bin/git/git-update-all
#!/bin/bash
# Update all local branches, checking out each branch in succession.
# Eventually returns to the original branch. Use "-n" for dry-run.
git_update_all() {
local run br
br=$(git name-rev --name-only HEAD 2>/dev/null)
[ "$1" = "-n" ] && shift && run=echo
for x in $( git branch | cut -c3- ) ; do
$run git checkout $x && $run git pull --ff-only || return 2
done
[ ${#br} -gt 0 ] && $run git checkout "$br"
}
git_update_all "$@"
如果你添加~/bin/git到你的PATH(假设文件是~/bin/git/git-update-all),你可以运行:
$ git update-all
我知道这个问题已经提了将近3年了,但我也问过自己同样的问题,但没有找到任何现成的解决方案。所以,我自己创建了一个自定义的git命令shell脚本。
在这里,git-ffwd-update脚本执行以下操作…
it issues a git remote update to fetch the lates revs
then uses git remote show to get a list of local branches that track a remote branch (e.g. branches that can be used with git pull)
then it checks with git rev-list --count <REMOTE_BRANCH>..<LOCAL_BRANCH> how many commit the local branch is behind the remote (and ahead vice versa)
if the local branch is 1 or more commits ahead, it can NOT be fast-forwarded and needs to be merged or rebased by hand
if the local branch is 0 commits ahead and 1 or more commits behind, it can be fast-forwarded by git branch -f <LOCAL_BRANCH> -t <REMOTE_BRANCH>
脚本可以这样调用:
$ git ffwd-update
Fetching origin
branch bigcouch was 10 commit(s) behind of origin/bigcouch. resetting local branch to remote
branch develop was 3 commit(s) behind of origin/develop. resetting local branch to remote
branch master is 6 commit(s) behind and 1 commit(s) ahead of origin/master. could not be fast-forwarded
完整的脚本应该保存为git-ffwd-update,并且需要在PATH上。
#!/bin/bash
main() {
REMOTES="$@";
if [ -z "$REMOTES" ]; then
REMOTES=$(git remote);
fi
REMOTES=$(echo "$REMOTES" | xargs -n1 echo)
CLB=$(git rev-parse --abbrev-ref HEAD);
echo "$REMOTES" | while read REMOTE; do
git remote update $REMOTE
git remote show $REMOTE -n \
| awk '/merges with remote/{print $5" "$1}' \
| while read RB LB; do
ARB="refs/remotes/$REMOTE/$RB";
ALB="refs/heads/$LB";
NBEHIND=$(( $(git rev-list --count $ALB..$ARB 2>/dev/null) +0));
NAHEAD=$(( $(git rev-list --count $ARB..$ALB 2>/dev/null) +0));
if [ "$NBEHIND" -gt 0 ]; then
if [ "$NAHEAD" -gt 0 ]; then
echo " branch $LB is $NBEHIND commit(s) behind and $NAHEAD commit(s) ahead of $REMOTE/$RB. could not be fast-forwarded";
elif [ "$LB" = "$CLB" ]; then
echo " branch $LB was $NBEHIND commit(s) behind of $REMOTE/$RB. fast-forward merge";
git merge -q $ARB;
else
echo " branch $LB was $NBEHIND commit(s) behind of $REMOTE/$RB. resetting local branch to remote";
git branch -f $LB -t $ARB >/dev/null;
fi
fi
done
done
}
main $@