I work on a project that has 2 branches, A and B. I typically work on branch A, and merge stuff from branch B. For the merging, I would typically do:
git merge origin/branchB
However, I would also like to keep a local copy of branch B, as I may occasionally check out the branch without first merging with my branch A. For this, I would do:
git checkout branchB
git pull
git checkout branchA
Is there a way to do the above in one command, and without having to switch branch back and forth? Should I be using git update-ref
for that? How?
ベストアンサー1
The Short Answer
As long as you're doing a fast-forward merge, then you can simply use
git fetch <remote> <sourceBranch>:<destinationBranch>
Examples:
# Merge local branch foo into local branch master,
# without having to checkout master first.
# Here `.` means to use the local repository as the "remote":
git fetch . foo:master
# Merge remote branch origin/foo into local branch foo,
# without having to checkout foo first:
git fetch origin foo:foo
While Amber's answer will also work in fast-forward cases, using git fetch
in this way instead is a little safer than just force-moving the branch reference, since git fetch
will automatically prevent accidental non-fast-forwards as long as you don't use +
in the refspec.
The Long Answer
You cannot merge a branch B into branch A without checking out A first if it would result in a non-fast-forward merge. This is because a working copy is needed to resolve any potential conflicts.
However, in the case of fast-forward merges, this is possible, because such merges can never result in conflicts, by definition. To do this without checking out a branch first, you can use git fetch
with a refspec.
Here's an example of updating master
(disallowing non-fast-forward changes) if you have another branch feature
checked out:
git fetch upstream master:master
This use-case is so common, that you'll probably want to make an alias for it in your git configuration file, like this one:
[alias]
sync = !sh -c 'git checkout --quiet HEAD; git fetch upstream master:master; git checkout --quiet -'
What this alias does is the following:
git checkout HEAD
: this puts your working copy into a detached-head state. This is useful if you want to updatemaster
while you happen to have it checked-out. I think it was necessary to do with because otherwise the branch reference formaster
won't move, but I don't remember if that's really right off-the-top of my head.git fetch upstream master:master
: this fast-forwards your localmaster
to the same place asupstream/master
.git checkout -
checks out your previously checked-out branch (that's what the-
does in this case).
The syntax of git fetch
for (non-)fast-forward merges
If you want the fetch
command to fail if the update is non-fast-forward, then you simply use a refspec of the form
git fetch <remote> <remoteBranch>:<localBranch>
If you want to allow non-fast-forward updates, then you add a +
to the front of the refspec:
git fetch <remote> +<remoteBranch>:<localBranch>
Note that you can pass your local repo as the "remote" parameter using .
:
git fetch . <sourceBranch>:<destinationBranch>
The Documentation
From the git fetch
documentation that explains this syntax (emphasis mine):
<refspec>
The format of a
<refspec>
parameter is an optional plus+
, followed by the source ref<src>
, followed by a colon:
, followed by the destination ref<dst>
.一致するリモート参照が
<src>
取得され、 が<dst>
空の文字列でない場合は、それに一致するローカル参照が を使用して早送りされます<src>
。オプションのプラス+
を使用すると、早送り更新が行われない場合でも、ローカル参照が更新されます。