Merge, update, and pull Git branches without using checkouts
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>
.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.
See Also
Git checkout and merge without touching working tree
Merging without changing the working directory
Implementing Pull with Pygit2
First Solution (Not Recommended):
You should not do this. It is possible to lose work this way. However, it works as a hacky solution.
master_ref = repo.lookup_reference('refs/heads/master')
master_ref.set_target(remote_master_id)
# Terrible hack to fix set_target() screwing with the index
repo.reset(master_ref.target, pygit2.GIT_RESET_HARD)
Full source
Second Solution:
This one seems to be promising. After much trial and error, I may have found the solution. If you checkout the tree object you want to target before you update the reference it works. The index is clean like what you would expect when running a git pull
or git merge
repo.checkout_tree(repo.get(remote_master_id))
master_ref = repo.lookup_reference('refs/heads/master')
master_ref.set_target(remote_master_id)
repo.head.set_target(remote_master_id)
Full source
One-to-many using ffbase in R
merge.ffdf(D,C,by = 'col1', all.x=T)
As per the docs, merge.ffdf only allows inner joins (all matching keys) or left joins (all "left" keys).
I suppose it treats each entire row as a key, and discards duplicates.
git log Graph seems differences in GitHub and Console
That's a common practice: do not fast-forward and always create a commit when merging (and is also default behavior for pull-requests on github, I suppose).
As this post says,
The --no-ff flag causes the merge to always create a new commit object, even if the merge could be performed with a fast-forward. This avoids losing information about the historical existence of a feature branch and groups together all commits that together added the feature.
Related Topics
Grit's Clone Method Is Undefined
Git Bash Chcp Windows7 Encoding Issue
How to Stop Savon from Adding Prefixes to Soap.Body
Ruby/Rails Array of Strings to Postgresql Insert
Minitest, Test::Unit, and Rails
Flash Message with HTML_Safe from the Controller in Rails 4 (Safe Version)
When to Use Association Extensions VS Named Scopes
Floating Point Precision in Ruby on Rails Model Validations
Importing CSV Data into Rails App, Using Something Other Then the Association "Id"
How to Change Ruby to Version 1.9.3 (Again) with Rvm
Is There a Groovy Equivalent of the Ruby Timeout Module
How to Figure Out Which Step I'Ve Just Executed in Cucumber's Afterstep Hook
How to Access a Symbol Hash Key Using a Variable in Ruby