shortcut for git merging master into current branch

Viewed 1615

So sometimes I'm working on a branch and I want to pull in the changes made on origin/master since branch created. Just doing git merge master is not usually adequate because local master may not have the changes from remote master, so I find myself having to do this:

# save any uncommitted changes (if there are any)
git stash  
# update master first:
git checkout master
git pull
# back to where we were:
git checkout <previous branch>
git stash pop # omit if git stash not done
# and finally the actual merge: 
git merge master

Surely there is a shorter way, just one or two git commands?

3 Answers

One command:

git pull origin master:master

Let's me split it and explain. git pull master:master is equivalent to

git fetch origin master:master
git merge master

git fetch origin master:master means: fetch new commits from remote origin branch master and update local branch master to point to the same commit as remote master. It's what you do with

git checkout master
git pull
git checkout <previous branch>

but much faster (no need to do 2 checkouts).

If you need to stash add --autostash:

git pull --autostash origin master:master

I face your scenario constantly and rapidly got tired of doing it more or less like you described, so I created an alias to fast-forward master without switching to it.

I have created an alias in the [alias] section of my ~/.gitconfig to update master (or any branch) to origin/master without checking it out.

Here is a simple (but unsafe) version of this alias:

    ff = !sh -c 'git update-ref refs/heads/$1 origin/$1' -

You call it by typing git ff some_branch, and it uses update-ref to set that branch to origin/some_branch.

Once this alias is defined, your operation becomes:

git fetch
git ff master
git merge master

However, this is unsafe because it will do the update even if is not equivalent to a fast-forward merge, and therefore it might discard some commits. Here is the second version of this alias, with a safeguard so that it only does fast-forwarding, and refuses to do anything in other situations:

    # Do a fast-forward merge on the branch specified as argument, as long
    # as it's safe: $1 is not checked out, and a fast-forward merge is possible.
    ff = !bash -c '\
           if [[ `git symbolic-ref HEAD` = refs/heads/$1 ]] ";" then \
              echo $1 is checked out, use pull or merge instead. ";" \
           else \
              git update-ref refs/heads/$1 origin/$1 `git merge-base origin/$1 $1` ";" \
           fi' -

I often find the unsafe alias useful too, in particular when I do want to discard some work on my local copy of the branch, so I also kept it as ff-force:

    # Not safe - reset the specified branch to its state on origin, even if it's not a fast-forward merge and potentially throws away some commits
    ff-force = !sh -c 'git update-ref refs/heads/$1 origin/$1' -

Known limitation for both my aliases: the remote has to be called origin.

I do

  1. git fetch origin develop - get latest changes but don't merge them to the local develop -
  2. git merge origin/develop - merge
Related