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

前端 未结 25 2497
失恋的感觉
失恋的感觉 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:13

    You can't do it with only one git command but you can automate it with one bash line.

    To safely update all branches with one line, here is what I do:

    git fetch --all && for branch in $(git branch | sed '/*/{$q;h;d};$G' | tr -d '*') ; do git checkout $branch && git merge --ff-only || break ; done
    
    • If it can't fast-forward one branch or encounter an error, it will stop and leave you in that branch so that you can take back control and merge manually.

    • If all branches can be fast-forwarded, it will end with the branch you were currently in, leaving you where you were before updating.

    Explanations:

    For a better readability, it can be split over several lines:

    git fetch --all && \
    for branch in $(git branch | sed '/*/{$q;h;d};$G' | tr -d '*')
        do git checkout $branch && \
        git merge --ff-only || break
    done
    
    1. git fetch --all && ... => Fetches all refs from all remotes and continue with the next command if there has been no error.

    2. git branch | sed '/*/{$q;h;d};$G' | tr -d '*' => From the output of git branch, sed take the line with a * and move it to the end (so that the current branch will be updated last). Then tr simply remove the *.

    3. for branch in $(...) ; do git checkout $branch && git merge --ff-only || break ; done = > For each branch name obtained from the previous command, checkout this branch and try to merge with a fast-forward. If it fails, break is called and the command stops here.

    Of course, you can replace git merge --ff-only with git rebase if it is what you want.

    Finally, you can put it in your bashrc as an alias:

    alias git-pull-all='git fetch --all && for branch in $(git branch | sed '\''/*/{$q;h;d};$G'\'' | tr -d "*") ; do git checkout $branch && git merge --ff-only || break ; done'
    

    Or if you are afraid of messing up with the ' and ", or you simply prefer to keep syntactic readability in your editor, you can declare it as a function:

    git-pull-all()
    {
        git fetch --all && for branch in $(git branch | sed '/*/{$q;h;d};$G' | tr -d '*') ; do git checkout $branch && git merge --ff-only || break ; done
    }
    

    Bonus:

    For those who'd like the explanation on the sed '/*/{$q;h;d};$G' part:

    • /*/ => Search for the line with a *.

    • {$q => If it is in the last line, quit (we don't need to do anything because the current branch is already the last one in the list).

    • ;h;d} => Otherwise, store the line in the hold buffer and delete it in the current list position.

    • ;$G => When it reaches the last line, append the content of the hold buffer.

提交回复
热议问题