path: root/builtin/merge.c
diff options
authorJunio C Hamano <>2016-04-08 21:29:11 (GMT)
committerJunio C Hamano <>2016-04-08 21:29:11 (GMT)
commitd04aa7ec4738f90220b9e205326f17938b8f89d4 (patch)
tree7be435da616d58dec183f8c6c8f1517819a2a626 /builtin/merge.c
parent72d917a7f9a5123ef7c0d6db306bbc0d385227e2 (diff)
parente379fdf34fee96cd205be83ff4e71699bdc32b18 (diff)
Merge branch 'jc/merge-refuse-new-root'
"git merge" used to allow merging two branches that have no common base by default, which led to a brand new history of an existing project created and then get pulled by an unsuspecting maintainer, which allowed an unnecessary parallel history merged into the existing project. The command has been taught not to allow this by default, with an escape hatch "--allow-unrelated-histories" option to be used in a rare event that merges histories of two projects that started their lives independently. * jc/merge-refuse-new-root: merge: refuse to create too cool a merge by default
Diffstat (limited to 'builtin/merge.c')
1 files changed, 9 insertions, 3 deletions
diff --git a/builtin/merge.c b/builtin/merge.c
index 30b7bd5..41467e4 100644
--- a/builtin/merge.c
+++ b/builtin/merge.c
@@ -64,6 +64,7 @@ static int option_renormalize;
static int verbosity;
static int allow_rerere_auto;
static int abort_current_merge;
+static int allow_unrelated_histories;
static int show_progress = -1;
static int default_to_upstream = 1;
static const char *sign_commit;
@@ -221,6 +222,8 @@ static struct option builtin_merge_options[] = {
OPT_BOOL(0, "abort", &abort_current_merge,
N_("abort the current in-progress merge")),
+ OPT_BOOL(0, "allow-unrelated-histories", &allow_unrelated_histories,
+ N_("allow merging unrelated histories")),
OPT_SET_INT(0, "progress", &show_progress, N_("force progress reporting"), 1),
{ OPTION_STRING, 'S', "gpg-sign", &sign_commit, N_("key-id"),
N_("GPG sign commit"), PARSE_OPT_OPTARG, NULL, (intptr_t) "" },
@@ -1398,9 +1401,12 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
update_ref("updating ORIG_HEAD", "ORIG_HEAD", head_commit->object.oid.hash,
- if (remoteheads && !common)
- ; /* No common ancestors found. We need a real merge. */
- else if (!remoteheads ||
+ if (remoteheads && !common) {
+ /* No common ancestors found. */
+ if (!allow_unrelated_histories)
+ die(_("refusing to merge unrelated histories"));
+ /* otherwise, we need a real merge. */
+ } else if (!remoteheads ||
(!remoteheads->next && !common->next &&
common->item == remoteheads->item)) {