#include "help.h"
#include "merge-recursive.h"
#include "resolve-undo.h"
+#include "remote.h"
#define DEFAULT_TWOHEAD (1<<0)
#define DEFAULT_OCTOPUS (1<<1)
};
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
};
static const char **xopts;
static size_t xopts_nr, xopts_alloc;
static const char *branch;
+static char *branch_mergeoptions;
static int option_renormalize;
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 },
strbuf_release(&bname);
}
+static void parse_branch_merge_options(char *bmo)
+{
+ const char **argv;
+ int argc;
+
+ if (!bmo)
+ return;
+ argc = split_cmdline(bmo, &argv);
+ if (argc < 0)
+ die(_("Bad branch.%s.mergeoptions string: %s"), branch,
+ split_cmdline_strerror(argc));
+ argv = xrealloc(argv, sizeof(*argv) * (argc + 2));
+ memmove(argv + 1, argv, sizeof(*argv) * (argc + 1));
+ argc++;
+ argv[0] = "branch.*.mergeoptions";
+ parse_options(argc, argv, NULL, builtin_merge_options,
+ builtin_merge_usage, 0);
+ free(argv);
+}
+
static int git_merge_config(const char *k, const char *v, void *cb)
{
if (branch && !prefixcmp(k, "branch.") &&
!prefixcmp(k + 7, branch) &&
!strcmp(k + 7 + strlen(branch), ".mergeoptions")) {
- const char **argv;
- int argc;
- char *buf;
-
- buf = xstrdup(v);
- argc = split_cmdline(buf, &argv);
- if (argc < 0)
- die(_("Bad branch.%s.mergeoptions string: %s"), branch,
- split_cmdline_strerror(argc));
- argv = xrealloc(argv, sizeof(*argv) * (argc + 2));
- memmove(argv + 1, argv, sizeof(*argv) * (argc + 1));
- argc++;
- parse_options(argc, argv, NULL, builtin_merge_options,
- builtin_merge_usage, 0);
- free(buf);
+ free(branch_mergeoptions);
+ branch_mergeoptions = xstrdup(v);
+ return 0;
}
if (!strcmp(k, "merge.diffstat") || !strcmp(k, "merge.stat"))
if (is_bool && shortlog_len)
shortlog_len = DEFAULT_MERGE_LOG_LEN;
return 0;
+ } else if (!strcmp(k, "merge.ff")) {
+ int boolval = git_config_maybe_bool(k, v);
+ if (0 <= boolval) {
+ allow_fast_forward = boolval;
+ } else if (v && !strcmp(v, "only")) {
+ allow_fast_forward = 1;
+ fast_forward_only = 1;
+ } /* do not barf on values from future versions of git */
+ 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);
}
{
strbuf_reset(&merge_msg);
if (strbuf_read_file(&merge_msg, git_path("MERGE_MSG"), 0) < 0)
- die_errno("Could not read from '%s'", git_path("MERGE_MSG"));
+ die_errno(_("Could not read from '%s'"), git_path("MERGE_MSG"));
}
static void run_prepare_commit_msg(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];
if (diff_use_color_default == -1)
diff_use_color_default = git_use_color_default;
+ if (branch_mergeoptions)
+ parse_branch_merge_options(branch_mergeoptions);
argc = parse_options(argc, argv, prefix, builtin_merge_options,
builtin_merge_usage, 0);
}
if (file_exists(git_path("CHERRY_PICK_HEAD"))) {
if (advice_resolve_conflict)
- die("You have not concluded your cherry-pick (CHERRY_PICK_HEAD exists).\n"
- "Please, commit your changes before you can merge.");
+ die(_("You have not concluded your cherry-pick (CHERRY_PICK_HEAD exists).\n"
+ "Please, commit your changes before you can merge."));
else
- die("You have not concluded your cherry-pick (CHERRY_PICK_HEAD exists).");
+ die(_("You have not concluded your cherry-pick (CHERRY_PICK_HEAD exists)."));
}
resolve_undo_clear();
if (!allow_fast_forward && fast_forward_only)
die(_("You cannot combine --no-ff with --ff-only."));
+ if (!abort_current_merge) {
+ if (!argc && default_to_upstream)
+ argc = setup_with_upstream(&argv);
+ else if (argc == 1 && !strcmp(argv[0], "-"))
+ argv[0] = "@{-1}";
+ }
if (!argc)
usage_with_options(builtin_merge_usage,
builtin_merge_options);