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 mer
just to pull the master without checking out the master I use
git fetch origin master:master
If you want to keep the same tree as one of the branch you want to merge (ie. not a real "merge"), you can do it like this.
# Check if you can fast-forward
if git merge-base --is-ancestor a b; then
git update-ref refs/heads/a refs/heads/b
exit
fi
# Else, create a "merge" commit
commit="$(git commit-tree -p a -p b -m "merge b into a" "$(git show -s --pretty=format:%T b)")"
# And update the branch to point to that commit
git update-ref refs/heads/a "$commit"
Another way to effectively do this is:
git fetch
git branch -d branchB
git branch -t branchB origin/branchB
Because it's a lower case -d
, it will only delete it if the data will still exist somewhere. It's similar to @kkoehne's answer except it doesn't force. Because of the -t
it will set up the remote again.
I had a slightly different need than OP, which was to create a new feature branch off develop
(or master
), after merging a pull request. That can be accomplished in a one-liner without force, but it doesn't update the local develop
branch. It's just a matter of checking out a new branch and having it be based off origin/develop
:
git checkout -b new-feature origin/develop
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.
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 update master
while you happen to have it checked-out. I think it was necessary to do with because otherwise the branch reference for master
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 local master
to the same place as upstream/master
.
git checkout -
checks out your previously checked-out branch (that's what the -
does in this case).
git fetch
for (non-)fast-forward mergesIf 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>
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>
.The remote ref that matches
<src>
is fetched, and if<dst>
is not empty string, the local ref that matches it is fast-forwarded using<src>
. If the optional plus+
is used, the local ref is updated even if it does not result in a fast-forward update.
Git checkout and merge without touching working tree
Merging without changing the working directory
Another, admittedly pretty brute way is to just re-create the branch:
git fetch remote
git branch -f localbranch remote/remotebranch
This throws away the local outdated branch and re-creates one with the same name, so use with care ...
In your case you can use
git fetch origin branchB:branchB
which does what you want (assuming the merge is fast-forward). If the branch can't be updated because it requires a non-fast-forward merge, then this fails safely with a message.
This form of fetch has some more useful options too:
git fetch <remote> <sourceBranch>:<destinationBranch>
Note that <remote>
can be a local repository, and <sourceBranch>
can be a tracking branch. So you can update a local branch, even if it's not checked out, without accessing the network.
Currently, my upstream server access is via a slow VPN, so I periodically connect, git fetch
to update all remotes, and then disconnect. Then if, say, the remote master has changed, I can do
git fetch . remotes/origin/master:master
to safely bring my local master up to date, even if I currently have some other branch checked out. No network access required.