diff --git a/Documentation/git-merge.txt b/Documentation/git-merge.txt
index fb4c05b83f..e2e6aba17e 100644
--- a/Documentation/git-merge.txt
+++ b/Documentation/git-merge.txt
@@ -11,7 +11,7 @@ SYNOPSIS
 [verse]
 'git merge' [-n] [--stat] [--no-commit] [--squash]
 	[-s <strategy>] [-X <strategy-option>]
-	[--[no-]rerere-autoupdate] [-m <msg>] <commit>...
+	[--[no-]rerere-autoupdate] [-m <msg>] [<commit>...]
 'git merge' <msg> HEAD <commit>...
 'git merge' --abort
 
@@ -95,8 +95,13 @@ commit or stash your changes before running 'git merge'.
 
 <commit>...::
 	Commits, usually other branch heads, to merge into our branch.
-	You need at least one <commit>.  Specifying more than one
-	<commit> obviously means you are trying an Octopus.
+	Specifying more than one commit will create a merge with
+	more than two parents (affectionately called an Octopus merge).
++
+If no commit is given from the command line, and if `merge.defaultToUpstream`
+configuration variable is set, merge the remote tracking branches
+that the current branch is configured to use as its upstream.
+See also the configuration section of this manual page.
 
 
 PRE-MERGE CHECKS
diff --git a/Documentation/merge-config.txt b/Documentation/merge-config.txt
index 33bf74c334..8920258baa 100644
--- a/Documentation/merge-config.txt
+++ b/Documentation/merge-config.txt
@@ -6,6 +6,16 @@ merge.conflictstyle::
 	a `>>>>>>>` marker.  An alternate style, "diff3", adds a `|||||||`
 	marker and the original text before the `=======` marker.
 
+merge.defaultToUpstream::
+	If merge is called without any commit argument, merge the upstream
+	branches configured for the current branch by using their last
+	observed values stored in their remote tracking branches.
+	The values of the `branch.<current branch>.merge` that name the
+	branches at the remote named by `branch.<current branch>.remote`
+	are consulted, and then they are mapped via `remote.<remote>.fetch`
+	to their corresponding remote tracking branches, and the tips of
+	these tracking branches are merged.
+
 merge.log::
 	In addition to branch names, populate the log message with at
 	most the specified number of one-line descriptions from the
diff --git a/builtin/merge.c b/builtin/merge.c
index 1e0bcfd792..d54e7ddbb1 100644
--- a/builtin/merge.c
+++ b/builtin/merge.c
@@ -25,6 +25,7 @@
 #include "help.h"
 #include "merge-recursive.h"
 #include "resolve-undo.h"
+#include "remote.h"
 
 #define DEFAULT_TWOHEAD (1<<0)
 #define DEFAULT_OCTOPUS (1<<1)
@@ -37,8 +38,9 @@ struct strategy {
 };
 
 static const char * const builtin_merge_usage[] = {
-	"git merge [options] <remote>...",
-	"git merge [options] <msg> HEAD <remote>",
+	"git merge [options] [<commit>...]",
+	"git merge [options] <msg> HEAD <commit>",
+	"git merge --abort",
 	NULL
 };
 
@@ -59,6 +61,7 @@ static int verbosity;
 static int allow_rerere_auto;
 static int abort_current_merge;
 static int show_progress = -1;
+static int default_to_upstream;
 
 static struct strategy all_strategy[] = {
 	{ "recursive",  DEFAULT_TWOHEAD | NO_TRIVIAL },
@@ -538,6 +541,9 @@ static int git_merge_config(const char *k, const char *v, void *cb)
 		if (is_bool && shortlog_len)
 			shortlog_len = DEFAULT_MERGE_LOG_LEN;
 		return 0;
+	} else if (!strcmp(k, "merge.defaulttoupstream")) {
+		default_to_upstream = git_config_bool(k, v);
+		return 0;
 	}
 	return git_diff_ui_config(k, v, cb);
 }
@@ -945,6 +951,35 @@ static int evaluate_result(void)
 	return cnt;
 }
 
+/*
+ * Pretend as if the user told us to merge with the tracking
+ * branch we have for the upstream of the current branch
+ */
+static int setup_with_upstream(const char ***argv)
+{
+	struct branch *branch = branch_get(NULL);
+	int i;
+	const char **args;
+
+	if (!branch)
+		die("No current branch.");
+	if (!branch->remote)
+		die("No remote for the current branch.");
+	if (!branch->merge_nr)
+		die("No default upstream defined for the current branch.");
+
+	args = xcalloc(branch->merge_nr + 1, sizeof(char *));
+	for (i = 0; i < branch->merge_nr; i++) {
+		if (!branch->merge[i]->dst)
+			die("No remote tracking branch for %s from %s",
+			    branch->merge[i]->src, branch->remote_name);
+		args[i] = branch->merge[i]->dst;
+	}
+	args[i] = NULL;
+	*argv = args;
+	return i;
+}
+
 int cmd_merge(int argc, const char **argv, const char *prefix)
 {
 	unsigned char result_tree[20];
@@ -1027,6 +1062,9 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
 	if (!allow_fast_forward && fast_forward_only)
 		die(_("You cannot combine --no-ff with --ff-only."));
 
+	if (!argc && !abort_current_merge && default_to_upstream)
+		argc = setup_with_upstream(&argv);
+
 	if (!argc)
 		usage_with_options(builtin_merge_usage,
 			builtin_merge_options);