“git pull --all”可以更新我所有的本地分支吗?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/4318161/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Can "git pull --all" update all my local branches?
提问by mpoisot
I often have at least 3 remote branches: master, staging and production. I have 3 local branches that track those remote branches.
我经常有至少 3 个远程分支:master、staging 和 production。我有 3 个本地分支来跟踪这些远程分支。
Updating all my local branches is tedious:
更新我所有的本地分支很乏味:
git fetch --all
git rebase origin/master
git checkout staging
git rebase origin/staging
git checkout production
git rebase origin/production
I'd love to be able to just do a "git pull -all", but I haven't been able to get it to work. It seems to do a "fetch --all", then updates (fast forward or merges) the current working branch, but not the other local branches.
我很想能够只做一个“git pull -all”,但我一直无法让它工作。它似乎执行“fetch --all”,然后更新(快进或合并)当前工作分支,而不是其他本地分支。
I'm still stuck manually switching to each local branch and updating.
我仍然无法手动切换到每个本地分支并进行更新。
采纳答案by Cascabel
The behavior you describe for pull --all
is exactly as expected, though not necessarily useful. The option is passed along to git fetch, which then fetches all refs from all remotes, instead of just the needed one; pull
then merges (or in your case, rebases) the appropriate single branch.
您描述的行为pull --all
完全符合预期,但不一定有用。该选项传递给 git fetch,然后它从所有遥控器中获取所有引用,而不仅仅是需要的引用;pull
然后合并(或在您的情况下,重新设置)适当的单个分支。
If you want to check out other branches, you're going to have to check them out. And yes, merging (and rebasing) absolutelyrequire a work tree, so they cannot be done without checking out the other branches. You could wrap up your described steps into a script/alias if you like, though I'd suggest joining the commands with &&
so that should one of them fail, it won't try to plow on.
如果你想检查其他分支,你将不得不检查它们。是的,合并(和变基)绝对需要一个工作树,因此如果不检查其他分支就无法完成。如果您愿意,您可以将您描述的步骤包装到脚本/别名中,尽管我建议将这些命令加入,&&
以便其中一个失败,它不会尝试继续前进。
回答by John
I use the sync
subcommandof hubto automate this. I have alias git=hub
in my .bash_profile
, so the command I type is:
我用的sync
子命令的中枢自动执行此。我有alias git=hub
我的.bash_profile
,所以我输入的命令是:
git sync
This updates all local branches that have a matching upstream branch. From the man page:
这会更新所有具有匹配上游分支的本地分支。从手册页:
- If the local branch is outdated, fast-forward it;
- If the local branch contains unpushed work, warn about it;
- If the branch seems merged and its upstream branch was deleted, delete it.
- 如果本地分支过时,则快进;
- 如果本地分支包含未推送的工作,则发出警告;
- 如果分支似乎已合并并且其上游分支已被删除,请将其删除。
It also handles stashing/unstashing uncommitted changes on the current branch.
它还处理当前分支上的隐藏/取消未提交的更改。
I used to use a similar tool called git-up, but it's no longer maintained, and git sync
does almost exactly the same thing.
我曾经使用过一个名为git-up的类似工具,但它不再维护,并且git sync
几乎完全相同。
回答by muhqu
I know this question is almost 3 years old, but I asked myself the very same question and did not found any ready made solution. So, I created a custom git command shell script my self.
我知道这个问题已经快 3 岁了,但我问自己同样的问题,并没有找到任何现成的解决方案。所以,我自己创建了一个自定义的 git 命令 shell 脚本。
Here it goes, the git-ffwd-update
script does the following...
在这里,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 withgit 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 NOTbe 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>
- 它发出 a
git remote update
来获取最新的转速 - 然后用于
git remote show
获取跟踪远程分支的本地分支列表(例如,可以与 一起使用的分支git pull
) - 然后它检查
git rev-list --count <REMOTE_BRANCH>..<LOCAL_BRANCH>
本地分支在远程分支后面有多少提交(反之亦然) - 如果本地分支提前 1 次或多次提交,则不能快进,需要手动合并或重新定位
- 如果本地分支提前 0 次提交,后面有 1 次或更多次提交,则可以通过以下方式进行快进
git branch -f <LOCAL_BRANCH> -t <REMOTE_BRANCH>
the script can be called like:
脚本可以这样调用:
$ 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
The full script, should be saved as git-ffwd-update
and needs to be on the PATH
.
完整的脚本应另存为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 " "}' \
| 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 $@
回答by Fred Foo
It's not so hard to automate:
自动化并不难:
#!/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
回答by Matt Connolly
This still isn't automatic, as I wish there was an option for - and there should be some checking to make sure that this can only happen for fast-forward updates (which is why manually doing a pull is far safer!!), but caveats aside you can:
这仍然不是自动的,因为我希望有一个选项 - 并且应该进行一些检查以确保这只能发生在快进更新中(这就是为什么手动执行拉取更安全!),但除了注意事项之外,您可以:
git fetch origin
git update-ref refs/heads/other-branch origin/other-branch
to update the position of your local branch without having to check it out.
无需检查即可更新本地分支的位置。
Note: you will be losing your current branch position and moving it to where the origin's branch is, which means that if you need to merge you will lose data!
注意:您将丢失当前分支位置并将其移动到原点分支所在的位置,这意味着如果您需要合并,您将丢失数据!
回答by quornian
There are a lot of answers here but none that use git-fetch
to update the local ref directly, which is a lot simpler than checking out branches, and safer than git-update-ref
.
这里有很多答案,但没有一个用于git-fetch
直接更新本地引用,这比检查分支简单得多,也比git-update-ref
.
Here we use git-fetch
to update non-current branches and git pull --ff-only
for the current branch. It:
这里我们git-fetch
用来更新非当前分支和git pull --ff-only
当前分支。它:
- Doesn't require checking out branches
- Updates branches only if they can be fast-forwarded
- Will report when it can't fast-forward
- 不需要检查分支
- 仅当分支可以快进时才更新分支
- 不能快进时会报告
and here it is:
这是:
#!/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
From the manpage for git-fetch
:
从联机帮助页git-fetch
:
<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.
By specifying git fetch <remote> <ref>:<ref>
(without any +
) we get a fetch that updates the local ref only when it can be fast-forwarded.
通过指定git fetch <remote> <ref>:<ref>
(不带任何+
),我们得到一个 fetch,它只有在可以快进时才更新本地 ref。
Note: this assumes the local and remote branches are named the same (and that you want to track all branches), it should really use information about which local branches you have and what they are set up to track.
注意:这假设本地和远程分支的名称相同(并且您要跟踪所有分支),它应该真正使用有关您拥有哪些本地分支以及它们设置为跟踪什么的信息。
回答by Jakub Nar?bski
This issue is not solved (yet), at least not easily / without scripting: see this poston git mailing list by Junio C Hamano explaining situation and providing call for a simple solution.
这个问题还没有解决(还),至少不容易/没有脚本:请参阅Junio C Hamano 在 git 邮件列表上的这篇文章,解释情况并提供一个简单的解决方案。
The major reasoning is that you shouldn't need this:
主要原因是你不应该需要这个:
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(即 v1.5.0 或更新版本),没有理由让本地“开发”不再纯粹跟踪远程。如果你只想去看看,你可以直接在带有“
git checkout origin/dev
”的分离的 HEAD 上查看远程跟踪分支。这意味着我们需要为用户提供方便的唯一情况是在您确实有本地更改或计划进行一些更改时处理这些“跟踪”远程分支的本地分支。
如果您确实对标记为跟踪删除“dev”的“dev”进行了本地更改,并且如果您在与“dev”不同的分支上,那么在“
git fetch
”更新远程跟踪“dev”之后我们不应该做任何事情. 反正不会快进
The call for a solution was for an option or external script to prunelocal branches that follow now remote-tracking branches, rather than to keep them up-to-date by fast-forwarding, like original poster requested.
对解决方案的要求是一个选项或外部脚本来修剪现在跟随远程跟踪分支的本地分支,而不是像原始海报要求的那样通过快进使它们保持最新状态。
So how about "
git branch --prune --remote=<upstream>
" that iterates over local branches, and if(1) it is not the current branch; and
(2) it is marked to track some branch taken from the <upstream>; and
(3) it does not have any commits on its own;then remove that branch? "
git remote --prune-local-forks <upstream>
" is also fine; I do not care about which command implements the feature that much.
那么
git branch --prune --remote=<upstream>
遍历本地分支的" "怎么样,如果(1) 不是当前分支;和
(2)它被标记来跟踪从采取了一些分支的<上游>; 和
(3)它不会对自己的任何承诺;然后删除那个分支?“
git remote --prune-local-forks <upstream>
”也可以;我不太关心哪个命令实现了该功能。
Note:as of git 2.10 no such solution exists. Note that the git remote prune
subcommand, and git fetch --prune
are about removing remote-tracking branch for branch that no longer exists on remote, not about removing local branch that tracks remote-tracking branch (for which remote-tracking branch is upstream branch).
注意:从 git 2.10 开始,不存在这样的解决方案。请注意,git remote prune
子命令, andgit fetch --prune
是关于删除远程不再存在的分支的远程跟踪分支,而不是删除跟踪远程跟踪分支的本地分支(远程跟踪分支是上游分支)。
回答by michael
There are plenty of acceptable answers here, but some of the plumbing may be be a little opaque to the uninitiated. Here's a much simpler example that can easily be customized:
这里有很多可以接受的答案,但有些管道对于外行来说可能有点不透明。这是一个更简单的示例,可以轻松自定义:
$ 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)
[ "" = "-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 "$@"
If you add ~/bin/git
to your PATH
(assuming the file is ~/bin/git/git-update-all
), you can just run:
如果你添加~/bin/git
到你的PATH
(假设文件是~/bin/git/git-update-all
),你可以运行:
$ git update-all
回答by Mike
Add this scriptto .profile
on Mac OS X:
将此脚本添加到.profile
Mac OS X 上:
# Usage:
# `git-pull-all` to pull all your local branches from origin
# `git-pull-all remote` to pull all your local branches from a named remote
function git-pull-all() {
START=$(git symbolic-ref --short -q HEAD);
for branch in $(git branch | sed 's/^.//'); do
git checkout $branch;
git pull ${1:-origin} $branch || break;
done;
git checkout $START;
};
function git-push-all() {
git push --all ${1:-origin};
};
回答by milkovsky
Here is a good answer: How to fetch all git branches
这是一个很好的答案:如何获取所有 git 分支
for remote in `git branch -r`; do git branch --track $remote; done
git pull --all