Take the 2-minute tour ×
Super User is a question and answer site for computer enthusiasts and power users. It's 100% free, no registration required.

In a repo I have multiple branches, among them "master" and "develop", which are set up to track remote branches "origin/master" and "origin/develop".

Is it possible to specify that I want both master and develop to be merged(fast-forwarded) at once?

When I do git pull now I get something like this:

remote: Counting objects: 92, done.
remote: Compressing objects: 100% (56/56), done.
remote: Total 70 (delta 29), reused 28 (delta 8)
Unpacking objects: 100% (70/70), done.
From scm.my-site.com:my-repo
   5386563..902fb45  develop    -> origin/develop
   d637d67..ba81fb2  master     -> origin/master
Updating 5386563..902fb45
Fast-forward

all the remote branches are fetched, but only the branch I'm currently on is merged with its corresponding remote branch.

So I have to do git checkout master ...

Switched to branch 'master'
Your branch is behind 'origin/master' by 106 commits, and can be fast-forwarded.

...and then git pull again, and then switch back to develop, to get the desired result.

I know I can make aliases/scripts that does these steps. But I want to avoid that if possible, as it is error prone and not very efficient.
Edit: ok let me rephrase that. My goal was not to discourage or frown upon script/alias customizing of git. I would just prefer a builtin solution if it exists :)

share|improve this question
    
I tried git pull origin refs/heads/develop:refs/remotes/origin/develop refs/heads/master:refs/remotes/origin/master but that caused the remote master to be merged into develop.. –  Superole Jul 23 '13 at 15:44
1  
Why would it be error-prone or inefficient? Git is intended to be customized like this. BTW, to avoid having to check out each branch, you may want to split your pull into a fetch followed by a merge into each branch. –  jjlin Jul 23 '13 at 19:53
    
@jjlin well if I can do it without checking out each branch that may help on the efficiency. It is error prone because the matrix of things that can go wrong and the effects it can have on the rest of the script is somewhat complex. I'm not saying it's infeasible to make it safe, but it would be a trade-off. So I'd prefer a builtin solution if it exists :) –  Superole Jul 24 '13 at 7:39

2 Answers 2

You can set up an alias that uses git fetch with refspecs to fast-forward merge your branches with just one command. Set this up as an alias in your user .gitconfig file:

[alias]
    sync = !sh -c 'git checkout --quiet HEAD&& \
                   git fetch origin master:master develop:develop && \
                   git checkout --quiet - || git checkout --quiet -'

Usage: git sync.

Here is why it works:

  1. git checkout --quiet HEAD directly checks out your current commit, putting you into detached head state. This way, if you're on master or develop, you detach your working copy from those branch pointers, allowing them to be moved (Git won't allow you to move the branch references while your working copy has them checked out).

  2. git fetch origin master:master develop:develop uses refspecs with fetch to fast-forward the master and develop branches in your local repo. The syntax basically tells Git "here is a refspec of the form <source>:<destination>, take <destination> and fast-forward it to the same point as <source>". So the sources in the alias are the branches from origin, while the destinations are the local repo versions of those branches.

  3. Finally, git checkout --quiet - || git checkout --quiet - checks out the branch you were last on, regardless of whether or not there was a failure in the previous commands. So if you were on master when you ran git sync, and everything succeeds, you'll leave detached head state and check out the newly updated master.

See also my answer to git: update a local branch without checking it out?.

share|improve this answer
    
I don't quite understand the detached-magic here, why can't the pointer to master be moved when develop is checked out? ...anyway I tried this, and it seems to work except now I get "Your branch is ahead of 'origin/develop' by 1 commit." –  Superole Aug 6 '13 at 8:06
    
...which is solved the next time I pull –  Superole Aug 6 '13 at 8:08
    
@Superole which branch is ahead of origin/develop when you use the alias? It wouldn't make sense if it was your local develop branch. Also, the pointer for master can be moved if it's develop that is checked out, the point is that if it's master that is checked out, then you can't fast-forward master because that would affect your working copy, so that's why you detach the working copy from it first by using git checkout head. I saw another answer that described it as "standing on a rock", you have to get off the rock before you can move it. –  Cupcake Aug 6 '13 at 8:24
    
it was indeed my local develop. And the reason must be that this fetch does not update the tracking branches. As I understand it; a pull will fetch into origin/develop, and then merge that into develop. –  Superole Aug 8 '13 at 9:31

It seems that there is no builtin option for git to pull into multiple branches. At least not in version 1.8.0. although @Cupcake's answer is close to it.

However @jjlin's comment made me realize that at least I don't need to pull twice.

So a slightly more efficient sequence would be:

git pull
git checkout master
git merge origin/master
git checkout -

Inevitably I ended up creating an alias, but decided to leave the pull out of it, and focused on just fast-forwarding a different branch.

[alias]
ffwd = "!_() { git checkout $1 && git merge --ff-only origin/$1 && git checkout -; }; _"

Of course, with no testing this alias assumes that I supply a valid name of a ff'able branch as 1st argument, and has undefined behaviour otherwise. It is also not optimal for use-cases with more than two branches, but it will get me what I need for now.

git pull
git ffwd master
share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.