Git - Automatically fast forward all tracking branches on pull

后端 未结 6 1713
闹比i
闹比i 2020-12-28 12:32

I\'ve set up tracking branches with the --track option, and when I do a git pull on master, it fetches all branches to origin/br

相关标签:
6条回答
  • 2020-12-28 13:11

    I just wrote a small tool to do so. https://github.com/changyuheng/git-fast-forward-all

    Advantages of this tool:

    1. Supports multiple remotes in one repository. (hub sync doesn't support multiple remotes at the moment.)
    2. Supports having different names on the local branch and the corresponding remote tracking branche.
    3. Much faster than other scripts that fetches remote for every single branch.
    4. No error-prone regex parsing/editing.
    0 讨论(0)
  • 2020-12-28 13:23

    But wait:

    • git won't merge (the second step of git pull after the fetch part) files unless the branch is checked out first. See "Can “git pull --all” update all my local branches?"
    • git pull on master will merge files on master, meaning the next push will be a fast-forward one. A non fast-forward can only occur if a push to the remote master from another repo has been done prior to your push.

    Note: I suppose you have tracked all your remote branches as in "Track all remote git branches as local branches."


    Note: Git 2.0 (Q2 2014) will introduce with commit b814da8 a config push.ff:

    pull.ff::
    

    By default, Git does not create an extra merge commit when merging a commit that is a descendant of the current commit. Instead, the tip of the current branch is fast-forwarded.

    • When set to false, this variable tells Git to create an extra merge commit in such a case (equivalent to giving the --no-ff option from the command line).
    • When set to only, only such fast-forward merges are allowed (equivalent to giving the --ff-only option from the command line).
    0 讨论(0)
  • 2020-12-28 13:24

    Shell script that fast-forwards all branches that have their upstream branch set to the matching origin/ branch without doing any checkouts

    • it doesn't change your current branch at any time, no need to deal with working copy changes and time lost checking out

    • it only does fast-forwards, branches that cannot be fast-forwarded will show an error message and will be skipped

    Make sure all your branches' upstream branches are set correctly by running git branch -vv. Set the upstream branch with git branch -u origin/yourbanchname

    Copy-paste into a file and chmod 755:

    #!/bin/sh
    
    curbranch=$(git rev-parse --abbrev-ref HEAD)
    
    for branch in $(git for-each-ref refs/heads --format="%(refname:short)"); do
            upbranch=$(git config --get branch.$branch.merge | sed 's:refs/heads/::');
            if [ "$branch" = "$upbranch" ]; then
                    if [ "$branch" = "$curbranch" ]; then
                            echo Fast forwarding current branch $curbranch
                            git merge --ff-only origin/$upbranch
                    else
                            echo Fast forwarding $branch with origin/$upbranch
                            git fetch . origin/$upbranch:$branch
                    fi
            fi
    done;
    
    0 讨论(0)
  • 2020-12-28 13:26

    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.

    Caveat

    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' -
    

    The alias is a shorthand to "fast-forward tracking (branches)".

    0 讨论(0)
  • 2020-12-28 13:32

    SmartGit, for example, has an option to automatically merge changes from the tracked branch if you switch to a branch. This should do what you want to achieve.

    0 讨论(0)
  • 2020-12-28 13:36

    If you really want to fast forward all local branches that are tracking remote branches you might want to consider adding this as an alias to your ~/.gitconfig:

    [alias]
        pull-all = !"for b in $(git for-each-ref refs/heads --format='%(refname)') ; do git checkout ${b#refs/heads/} ; git pull --ff-only ; done"
    

    You can then run git pull-all, it will iterate through your local branches and run a git pull --ff-only on each.

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