开发者

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

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?


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.


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?"


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.


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


Try the following:

$ git pull trunk branch
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜