Skip to content

Commit bcd1ecd

Browse files
committed
Merge branch 'jc/merge'
"git merge FETCH_HEAD" learned that the previous "git fetch" could be to create an Octopus merge, i.e. recording multiple branches that are not marked as "not-for-merge"; this allows us to lose an old style invocation "git merge <msg> HEAD $commits..." in the implementation of "git pull" script; the old style syntax can now be deprecated. * jc/merge: merge: deprecate 'git merge <message> HEAD <commit>' syntax merge: handle FETCH_HEAD internally merge: decide if we auto-generate the message early in collect_parents() merge: make collect_parents() auto-generate the merge message merge: extract prepare_merge_message() logic out merge: narrow scope of merge_names merge: split reduce_parents() out of collect_parents() merge: clarify collect_parents() logic merge: small leakfix and code simplification merge: do not check argc to determine number of remote heads merge: clarify "pulling into void" special case t5520: test pulling an octopus into an unborn branch t5520: style fixes merge: simplify code flow merge: test the top-level merge driver
2 parents eae0216 + d45366e commit bcd1ecd

10 files changed

+324
-112
lines changed

Documentation/git-merge.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,10 @@ commit or stash your changes before running 'git merge'.
104104
If no commit is given from the command line, merge the remote-tracking
105105
branches that the current branch is configured to use as its upstream.
106106
See also the configuration section of this manual page.
107+
+
108+
When `FETCH_HEAD` (and no other commit) is specified, the branches
109+
recorded in the `.git/FETCH_HEAD` file by the previous invocation
110+
of `git fetch` for merging are merged to the current branch.
107111

108112

109113
PRE-MERGE CHECKS

builtin/merge.c

Lines changed: 161 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -492,8 +492,7 @@ static void merge_name(const char *remote, struct strbuf *msg)
492492
}
493493
if (len) {
494494
struct strbuf truname = STRBUF_INIT;
495-
strbuf_addstr(&truname, "refs/heads/");
496-
strbuf_addstr(&truname, remote);
495+
strbuf_addf(&truname, "refs/heads/%s", remote);
497496
strbuf_setlen(&truname, truname.len - len);
498497
if (ref_exists(truname.buf)) {
499498
strbuf_addf(msg,
@@ -504,28 +503,7 @@ static void merge_name(const char *remote, struct strbuf *msg)
504503
strbuf_release(&truname);
505504
goto cleanup;
506505
}
507-
}
508-
509-
if (!strcmp(remote, "FETCH_HEAD") &&
510-
!access(git_path("FETCH_HEAD"), R_OK)) {
511-
const char *filename;
512-
FILE *fp;
513-
struct strbuf line = STRBUF_INIT;
514-
char *ptr;
515-
516-
filename = git_path("FETCH_HEAD");
517-
fp = fopen(filename, "r");
518-
if (!fp)
519-
die_errno(_("could not open '%s' for reading"),
520-
filename);
521-
strbuf_getline(&line, fp, '\n');
522-
fclose(fp);
523-
ptr = strstr(line.buf, "\tnot-for-merge\t");
524-
if (ptr)
525-
strbuf_remove(&line, ptr-line.buf+1, 13);
526-
strbuf_addbuf(msg, &line);
527-
strbuf_release(&line);
528-
goto cleanup;
506+
strbuf_release(&truname);
529507
}
530508

531509
if (remote_head->util) {
@@ -1037,28 +1015,24 @@ static int default_edit_option(void)
10371015
st_stdin.st_mode == st_stdout.st_mode);
10381016
}
10391017

1040-
static struct commit_list *collect_parents(struct commit *head_commit,
1041-
int *head_subsumed,
1042-
int argc, const char **argv)
1018+
static struct commit_list *reduce_parents(struct commit *head_commit,
1019+
int *head_subsumed,
1020+
struct commit_list *remoteheads)
10431021
{
1044-
int i;
1045-
struct commit_list *remoteheads = NULL, *parents, *next;
1046-
struct commit_list **remotes = &remoteheads;
1022+
struct commit_list *parents, *next, **remotes = &remoteheads;
10471023

1048-
if (head_commit)
1049-
remotes = &commit_list_insert(head_commit, remotes)->next;
1050-
for (i = 0; i < argc; i++) {
1051-
struct commit *commit = get_merge_parent(argv[i]);
1052-
if (!commit)
1053-
help_unknown_ref(argv[i], "merge",
1054-
"not something we can merge");
1055-
remotes = &commit_list_insert(commit, remotes)->next;
1056-
}
1057-
*remotes = NULL;
1024+
/*
1025+
* Is the current HEAD reachable from another commit being
1026+
* merged? If so we do not want to record it as a parent of
1027+
* the resulting merge, unless --no-ff is given. We will flip
1028+
* this variable to 0 when we find HEAD among the independent
1029+
* tips being merged.
1030+
*/
1031+
*head_subsumed = 1;
10581032

1033+
/* Find what parents to record by checking independent ones. */
10591034
parents = reduce_heads(remoteheads);
10601035

1061-
*head_subsumed = 1; /* we will flip this to 0 when we find it */
10621036
for (remoteheads = NULL, remotes = &remoteheads;
10631037
parents;
10641038
parents = next) {
@@ -1068,7 +1042,119 @@ static struct commit_list *collect_parents(struct commit *head_commit,
10681042
*head_subsumed = 0;
10691043
else
10701044
remotes = &commit_list_insert(commit, remotes)->next;
1045+
free(parents);
1046+
}
1047+
return remoteheads;
1048+
}
1049+
1050+
static void prepare_merge_message(struct strbuf *merge_names, struct strbuf *merge_msg)
1051+
{
1052+
struct fmt_merge_msg_opts opts;
1053+
1054+
memset(&opts, 0, sizeof(opts));
1055+
opts.add_title = !have_message;
1056+
opts.shortlog_len = shortlog_len;
1057+
opts.credit_people = (0 < option_edit);
1058+
1059+
fmt_merge_msg(merge_names, merge_msg, &opts);
1060+
if (merge_msg->len)
1061+
strbuf_setlen(merge_msg, merge_msg->len - 1);
1062+
}
1063+
1064+
static void handle_fetch_head(struct commit_list **remotes, struct strbuf *merge_names)
1065+
{
1066+
const char *filename;
1067+
int fd, pos, npos;
1068+
struct strbuf fetch_head_file = STRBUF_INIT;
1069+
1070+
if (!merge_names)
1071+
merge_names = &fetch_head_file;
1072+
1073+
filename = git_path("FETCH_HEAD");
1074+
fd = open(filename, O_RDONLY);
1075+
if (fd < 0)
1076+
die_errno(_("could not open '%s' for reading"), filename);
1077+
1078+
if (strbuf_read(merge_names, fd, 0) < 0)
1079+
die_errno(_("could not read '%s'"), filename);
1080+
if (close(fd) < 0)
1081+
die_errno(_("could not close '%s'"), filename);
1082+
1083+
for (pos = 0; pos < merge_names->len; pos = npos) {
1084+
unsigned char sha1[20];
1085+
char *ptr;
1086+
struct commit *commit;
1087+
1088+
ptr = strchr(merge_names->buf + pos, '\n');
1089+
if (ptr)
1090+
npos = ptr - merge_names->buf + 1;
1091+
else
1092+
npos = merge_names->len;
1093+
1094+
if (npos - pos < 40 + 2 ||
1095+
get_sha1_hex(merge_names->buf + pos, sha1))
1096+
commit = NULL; /* bad */
1097+
else if (memcmp(merge_names->buf + pos + 40, "\t\t", 2))
1098+
continue; /* not-for-merge */
1099+
else {
1100+
char saved = merge_names->buf[pos + 40];
1101+
merge_names->buf[pos + 40] = '\0';
1102+
commit = get_merge_parent(merge_names->buf + pos);
1103+
merge_names->buf[pos + 40] = saved;
1104+
}
1105+
if (!commit) {
1106+
if (ptr)
1107+
*ptr = '\0';
1108+
die("not something we can merge in %s: %s",
1109+
filename, merge_names->buf + pos);
1110+
}
1111+
remotes = &commit_list_insert(commit, remotes)->next;
1112+
}
1113+
1114+
if (merge_names == &fetch_head_file)
1115+
strbuf_release(&fetch_head_file);
1116+
}
1117+
1118+
static struct commit_list *collect_parents(struct commit *head_commit,
1119+
int *head_subsumed,
1120+
int argc, const char **argv,
1121+
struct strbuf *merge_msg)
1122+
{
1123+
int i;
1124+
struct commit_list *remoteheads = NULL;
1125+
struct commit_list **remotes = &remoteheads;
1126+
struct strbuf merge_names = STRBUF_INIT, *autogen = NULL;
1127+
1128+
if (merge_msg && (!have_message || shortlog_len))
1129+
autogen = &merge_names;
1130+
1131+
if (head_commit)
1132+
remotes = &commit_list_insert(head_commit, remotes)->next;
1133+
1134+
if (argc == 1 && !strcmp(argv[0], "FETCH_HEAD")) {
1135+
handle_fetch_head(remotes, autogen);
1136+
remoteheads = reduce_parents(head_commit, head_subsumed, remoteheads);
1137+
} else {
1138+
for (i = 0; i < argc; i++) {
1139+
struct commit *commit = get_merge_parent(argv[i]);
1140+
if (!commit)
1141+
help_unknown_ref(argv[i], "merge",
1142+
"not something we can merge");
1143+
remotes = &commit_list_insert(commit, remotes)->next;
1144+
}
1145+
remoteheads = reduce_parents(head_commit, head_subsumed, remoteheads);
1146+
if (autogen) {
1147+
struct commit_list *p;
1148+
for (p = remoteheads; p; p = p->next)
1149+
merge_name(merge_remote_util(p->item)->name, autogen);
1150+
}
10711151
}
1152+
1153+
if (autogen) {
1154+
prepare_merge_message(autogen, merge_msg);
1155+
strbuf_release(autogen);
1156+
}
1157+
10721158
return remoteheads;
10731159
}
10741160

@@ -1158,61 +1244,62 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
11581244
option_commit = 0;
11591245
}
11601246

1161-
if (!abort_current_merge) {
1162-
if (!argc) {
1163-
if (default_to_upstream)
1164-
argc = setup_with_upstream(&argv);
1165-
else
1166-
die(_("No commit specified and merge.defaultToUpstream not set."));
1167-
} else if (argc == 1 && !strcmp(argv[0], "-"))
1168-
argv[0] = "@{-1}";
1247+
if (!argc) {
1248+
if (default_to_upstream)
1249+
argc = setup_with_upstream(&argv);
1250+
else
1251+
die(_("No commit specified and merge.defaultToUpstream not set."));
1252+
} else if (argc == 1 && !strcmp(argv[0], "-")) {
1253+
argv[0] = "@{-1}";
11691254
}
1255+
11701256
if (!argc)
11711257
usage_with_options(builtin_merge_usage,
11721258
builtin_merge_options);
11731259

1174-
/*
1175-
* This could be traditional "merge <msg> HEAD <commit>..." and
1176-
* the way we can tell it is to see if the second token is HEAD,
1177-
* but some people might have misused the interface and used a
1178-
* commit-ish that is the same as HEAD there instead.
1179-
* Traditional format never would have "-m" so it is an
1180-
* additional safety measure to check for it.
1181-
*/
1182-
1183-
if (!have_message && head_commit &&
1184-
is_old_style_invocation(argc, argv, head_commit->object.sha1)) {
1185-
strbuf_addstr(&merge_msg, argv[0]);
1186-
head_arg = argv[1];
1187-
argv += 2;
1188-
argc -= 2;
1189-
remoteheads = collect_parents(head_commit, &head_subsumed, argc, argv);
1190-
} else if (!head_commit) {
1260+
if (!head_commit) {
11911261
struct commit *remote_head;
11921262
/*
11931263
* If the merged head is a valid one there is no reason
11941264
* to forbid "git merge" into a branch yet to be born.
11951265
* We do the same for "git pull".
11961266
*/
1197-
if (argc != 1)
1198-
die(_("Can merge only exactly one commit into "
1199-
"empty head"));
12001267
if (squash)
12011268
die(_("Squash commit into empty head not supported yet"));
12021269
if (fast_forward == FF_NO)
12031270
die(_("Non-fast-forward commit does not make sense into "
12041271
"an empty head"));
1205-
remoteheads = collect_parents(head_commit, &head_subsumed, argc, argv);
1272+
remoteheads = collect_parents(head_commit, &head_subsumed,
1273+
argc, argv, NULL);
12061274
remote_head = remoteheads->item;
12071275
if (!remote_head)
12081276
die(_("%s - not something we can merge"), argv[0]);
1277+
if (remoteheads->next)
1278+
die(_("Can merge only exactly one commit into empty head"));
12091279
read_empty(remote_head->object.sha1, 0);
12101280
update_ref("initial pull", "HEAD", remote_head->object.sha1,
12111281
NULL, 0, UPDATE_REFS_DIE_ON_ERR);
12121282
goto done;
1213-
} else {
1214-
struct strbuf merge_names = STRBUF_INIT;
1283+
}
12151284

1285+
/*
1286+
* This could be traditional "merge <msg> HEAD <commit>..." and
1287+
* the way we can tell it is to see if the second token is HEAD,
1288+
* but some people might have misused the interface and used a
1289+
* commit-ish that is the same as HEAD there instead.
1290+
* Traditional format never would have "-m" so it is an
1291+
* additional safety measure to check for it.
1292+
*/
1293+
if (!have_message &&
1294+
is_old_style_invocation(argc, argv, head_commit->object.sha1)) {
1295+
warning("old-style 'git merge <msg> HEAD <commit>' is deprecated.");
1296+
strbuf_addstr(&merge_msg, argv[0]);
1297+
head_arg = argv[1];
1298+
argv += 2;
1299+
argc -= 2;
1300+
remoteheads = collect_parents(head_commit, &head_subsumed,
1301+
argc, argv, NULL);
1302+
} else {
12161303
/* We are invoked directly as the first-class UI. */
12171304
head_arg = "HEAD";
12181305

@@ -1221,21 +1308,8 @@ int cmd_merge(int argc, const char **argv, const char *prefix)
12211308
* the standard merge summary message to be appended
12221309
* to the given message.
12231310
*/
1224-
remoteheads = collect_parents(head_commit, &head_subsumed, argc, argv);
1225-
for (p = remoteheads; p; p = p->next)
1226-
merge_name(merge_remote_util(p->item)->name, &merge_names);
1227-
1228-
if (!have_message || shortlog_len) {
1229-
struct fmt_merge_msg_opts opts;
1230-
memset(&opts, 0, sizeof(opts));
1231-
opts.add_title = !have_message;
1232-
opts.shortlog_len = shortlog_len;
1233-
opts.credit_people = (0 < option_edit);
1234-
1235-
fmt_merge_msg(&merge_names, &merge_msg, &opts);
1236-
if (merge_msg.len)
1237-
strbuf_setlen(&merge_msg, merge_msg.len - 1);
1238-
}
1311+
remoteheads = collect_parents(head_commit, &head_subsumed,
1312+
argc, argv, &merge_msg);
12391313
}
12401314

12411315
if (!head_commit || !argc)

git-cvsimport.perl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1162,7 +1162,7 @@ sub commit {
11621162
die "Fast-forward update failed: $?\n" if $?;
11631163
}
11641164
else {
1165-
system(qw(git merge cvsimport HEAD), "$remote/$opt_o");
1165+
system(qw(git merge -m cvsimport), "$remote/$opt_o");
11661166
die "Could not merge $opt_o into the current branch.\n" if $?;
11671167
}
11681168
} else {

git-pull.sh

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -323,7 +323,6 @@ then
323323
fi
324324
fi
325325

326-
merge_name=$(git fmt-merge-msg $log_arg <"$GIT_DIR/FETCH_HEAD") || exit
327326
case "$rebase" in
328327
true)
329328
eval="git-rebase $diffstat $strategy_args $merge_args $rebase_args $verbosity"
@@ -334,7 +333,7 @@ true)
334333
eval="git-merge $diffstat $no_commit $verify_signatures $edit $squash $no_ff $ff_only"
335334
eval="$eval $log_arg $strategy_args $merge_args $verbosity $progress"
336335
eval="$eval $gpg_sign_args"
337-
eval="$eval \"\$merge_name\" HEAD $merge_head"
336+
eval="$eval FETCH_HEAD"
338337
;;
339338
esac
340339
eval "exec $eval"

0 commit comments

Comments
 (0)