Can “git pull --all” update all my local branches?

前端 未结 25 2126
失恋的感觉
失恋的感觉 2020-11-22 16:33

I often have at least 3 remote branches: master, staging and production. I have 3 local branches that track those remote branches.

Updating all my local branches is

相关标签:
25条回答
  • 2020-11-22 17:21

    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
    
    0 讨论(0)
  • 2020-11-22 17:21

    The script from @larsmans, a bit improved:

    #!/bin/sh
    
    set -x
    CURRENT=`git rev-parse --abbrev-ref HEAD`
    git fetch --all
    for branch in "$@"; do
      if ["$branch" -ne "$CURRENT"]; then
        git checkout "$branch" || exit 1
        git rebase "origin/$branch" || exit 1
      fi
    done
    git checkout "$CURRENT" || exit 1
    git rebase "origin/$CURRENT" || exit 1
    

    This, after it finishes, leaves working copy checked out from the same branch as it was before the script was called.

    The git pull version:

    #!/bin/sh
    
    set -x
    CURRENT=`git rev-parse --abbrev-ref HEAD`
    git fetch --all
    for branch in "$@"; do
      if ["$branch" -ne "$CURRENT"]; then
        git checkout "$branch" || exit 1
        git pull || exit 1
      fi
    done
    git checkout "$CURRENT" || exit 1
    git pull || exit 1
    
    0 讨论(0)
  • 2020-11-22 17:22

    It looks like many others have contributed similar solutions, but I thought I'd share what I came up with and invite others to contribute. This solution has a nice colorful output, gracefully handles your current working directory, and is fast because it doesn't do any checkouts, and leaves your working directory in tact. Also, it is just a shell script with no dependencies other than git. (only tested on OSX so far)

    #!/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

    Sorry I also seem to have come up with the same name as the other tool above.

    0 讨论(0)
  • 2020-11-22 17:27

    I came across the same issue of this question...

    Wondering myself about it, I did a small alias function inside my .bashrc file:

    gitPullAll() {
        for branch in `git branch | sed -E 's/^\*/ /' | awk '{print $1}'`; do
            git checkout $branch
            git pull -p
            printf "\n"
        done
        echo "Done"
    }
    

    Worked for me (:

    0 讨论(0)
  • 2020-11-22 17:28

    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!

    0 讨论(0)
  • 2020-11-22 17:28

    The following one-liner fast-forwards all branches that have an upstream branch if possible, and prints an error otherwise:

    git branch \
      --format "%(if)%(upstream:short)%(then)git push . %(upstream:short):%(refname:short)%(end)" |
      sh
    

    How does it work?

    It uses a custom format with the git branch command. For each branch that has an upstream branch, it prints a line with the following pattern:

    git push . <remote-ref>:<branch>
    

    This can be piped directly into sh (assuming that the branch names are well-formed). Omit the | sh to see what it's doing.

    Caveats

    The one-liner will not contact your remotes. Issue a git fetch or git fetch --all before running it.

    The currently checked-out branch will not be updated with a message like

    ! [remote rejected] origin/master -> master (branch is currently checked out)
    

    For this, you can resort to regular git pull --ff-only .

    Alias

    Add the following to your .gitconfig so that git fft performs this command:

    [alias]
            fft = !sh -c 'git branch --format \"%(if)%(upstream:short)%(then)git push . %(upstream:short):%(refname:short)%(end)\" | sh' -
    

    See also my .gitconfig. The alias is a shorthand to "fast-forward tracking (branches)".

    0 讨论(0)
提交回复
热议问题