Can "git pull --all" update all my local branches?
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
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.
If you want to check out other branches, you're going to have to check them out. And yes, merging (and rebasing) absolutely require 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.
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.
Here it goes, the git-ffwd-update
script does the following...
- 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 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>
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
.
#!/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 $@
I use the sync
subcommand of hub to automate this. I have alias git=hub
in my .bash_profile
, so the command I type is:
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.