How do I fast-forward other tracking branches in git?
Asked Answered
F

5

37

We are working with the model of a single remote repository that all of us use. We branch for new features and reintegrate into a trunk branch. Our workflow is that we should integrate from trunk into our working branches when other features are integrated into the trunk.

As such, it's not uncommon for us to do:

(branch) $ git commit -a -m"blah blah blah"
(branch) $ git fetch  # origin/trunk is updated
(branch) $ git checkout trunk
(trunk) $ git pull  # trunk is fast-forwarded to current version of origin/trunk.
(trunk) $ git checkout branch
(branch) $ git merge trunk
(branch) $ git push

I don't like the "git checkout trunk/git pull/git checkout branch" cycle. It's usually combined with Visual Studio complaining that all my files and projects have changed on disk, and should it reload them. For both checkouts. And the pull. And the merge. The merge is unavoidable, but because of how git works, it should be able to do the fast-forward on trunk without actually needing to check it out.

But I don't know the command, and my google-foo has failed me on this. Anyone know how?

Footing answered 28/2, 2011 at 21:1 Comment(2)
Does this answer your question? Merge, update, and pull Git branches without using checkoutsDiscussant
that's "google-fu"Middlings
E
27

Do you really need to update a local trunk branch?

Just fetch origin/trunk and merge it directly in the branch you are working on.
And that is Mark Longair's advice: git: fetch and merge, don’t pull.


Oliver mentions in his answer (upvoted):

git fetch upstream trunk:trunk

As he comments:

you can skip the merge and simply fast-forward, using a one-liner.

It does fast-forward the local branch trunk to the remote branch's HEAD.

See more at "git: update a local branch without checking it out?"

Elflock answered 28/2, 2011 at 21:7 Comment(5)
:) I have to say I'm slightly freaked out that you happened to have referred to that post (thanks!) in reply to a user whose namesake is mentioned in its first line...Sputter
So your recommendation would be to do "git merge origin/trunk" instead of the checkout/pull/checkout/merge dance? I'll try that the next time this crops up.Footing
Using git fetch upstream trunk:trunk you can skip the merge and simply fast-forward, using a one-liner. See my answer.Ruggiero
@Ruggiero good point, I didn't see your answer at the time (+1). I have included it in my answer for more visibility.Elflock
Merging doesn't suit rebasing work in progress scenario, while Oliver's answer does.Menzies
R
58

I think the easiest way to avoid the git checkout trunk, git pull, git checkout branch cycle is to use this answer:

git fetch upstream trunk:trunk

This does exactly what you want - fast-forward your local branch trunk to the remote branch's HEAD.

Ruggiero answered 6/2, 2014 at 11:14 Comment(1)
git fetch origin trunk:trunk for the beginners who are not fluent with the generic "upstream" term.Reluctance
E
27

Do you really need to update a local trunk branch?

Just fetch origin/trunk and merge it directly in the branch you are working on.
And that is Mark Longair's advice: git: fetch and merge, don’t pull.


Oliver mentions in his answer (upvoted):

git fetch upstream trunk:trunk

As he comments:

you can skip the merge and simply fast-forward, using a one-liner.

It does fast-forward the local branch trunk to the remote branch's HEAD.

See more at "git: update a local branch without checking it out?"

Elflock answered 28/2, 2011 at 21:7 Comment(5)
:) I have to say I'm slightly freaked out that you happened to have referred to that post (thanks!) in reply to a user whose namesake is mentioned in its first line...Sputter
So your recommendation would be to do "git merge origin/trunk" instead of the checkout/pull/checkout/merge dance? I'll try that the next time this crops up.Footing
Using git fetch upstream trunk:trunk you can skip the merge and simply fast-forward, using a one-liner. See my answer.Ruggiero
@Ruggiero good point, I didn't see your answer at the time (+1). I have included it in my answer for more visibility.Elflock
Merging doesn't suit rebasing work in progress scenario, while Oliver's answer does.Menzies
S
8

I agree with VonC's answer, but thought it might be fun to answer the question "How do you fast-forward master if you're on another branch?" anyway. I don't think there's a way to do this just using porcelain commands, but this script does the job (obviously you'd want to change master to trunk in your case):

#!/bin/sh

BRANCH=master
NEWER=origin/master

if [ x"$(git symbolic-ref HEAD)" = x"refs/heads/$BRANCH" ]
then
    echo "This doesn't make sense if you're already on the branch '$BRANCH'"
    echo "Just run: git merge $NEWER"
    exit 1
fi

BRANCH_HASH=$(git rev-parse $BRANCH)
NEWER_HASH=$(git rev-parse $NEWER)
MERGE_BASE=$(git merge-base $BRANCH_HASH $NEWER_HASH)

if [ "$MERGE_BASE" = "$BRANCH_HASH" ]
then
    git update-ref "refs/heads/$BRANCH" "$NEWER_HASH" "$BRANCH_HASH"
else
    echo "$BRANCH can't be fast-forwarded to $NEWER"
    exit 1
fi

Update 2012-10-20: this script was just a quick example; for a script that does the same but for merging any arbitrary commit-ish into a local branch (so long as the merge would be a fast-forward), see Jefromi's answer to a similar question.

Sputter answered 28/2, 2011 at 22:12 Comment(6)
I thought git used to do something very similar to this but when I just checked git-pull.sh in the source I didn't see any indication it still does.Symphony
I just used this script - thanks for the tip! I'm surprised this isn't built into git-merge though. You'd have thought it's quite a common use case.Delaware
You can do this with git branch -f master origin/master, but you don't want to: If it's not a fast-forward merge you'll lose commits and conflicts.Bottleneck
Over on https://mcmap.net/q/53589/-merge-update-and-pull-git-branches-without-using-checkouts someone pointed me here; I think my script there does the same thing, but is more fleshed out, so you can safely use it as git merge-ff <branch> <to-merge>.Irritated
@Jefromi: thanks for pointing that out - I've updated my answer with a link to your answer.Sputter
You can fast-forward master if you're on another branch with git fetch to fetch the remote branch followed by git fetch . origin/master:master to fast-forward the tracking branch. (Perhaps that wasn't possible 6 years ago ;-) )Cygnet
C
0

If you don't need the local copy of trunk, you can just merge the upstream one: git merge origin/trunk, replacing it into your sugested code it ends up as:

(branch) $ git commit -a -m"blah blah blah"
(branch) $ git fetch  # origin/trunk is updated
(branch) $ git merge origin/trunk
(branch) $ git push
Cobaltite answered 28/6, 2022 at 16:32 Comment(0)
E
-5

Try the following:

$ git pull trunk branch
Emeric answered 28/2, 2011 at 21:11 Comment(3)
first checkout branch then do git pull git://foo.com/someone/bar.git trunkEmeric
sll I meant was you should be able to do t his all in one step with pull, but as mentioned above some think this isn't the best idea.Emeric
Sorry, it does not really answer the question since it merge the current branch with the remote "trunk" branch, We want to merge (fast forward) the local branch "trunk" with the remote branch "trunk" while beeing on any another branch and without modifing it.Reluctance

© 2022 - 2024 — McMap. All rights reserved.