merge: handle FETCH_HEAD internally

The collect_parents() function now is responsible for 1. parsing the commits given on the command line into a list of commits to be merged; 2. filtering these parents into independent ones; and 3. optionally calling fmt_merge_msg() via prepare_merge_message() to prepare an auto-generated merge log message, using fake contents that FETCH_HEAD would have had if these commits were fetched from the current repository with "git pull . $args..." Make "git merge FETCH_HEAD" to be the same as the traditional git merge "$(git fmt-merge-msg <.git/FETCH_HEAD)" $commits invocation of the command in "git pull", where $commits are the ones that appear in FETCH_HEAD that are not marked as not-for-merge, by making it do a bit more, specifically: - noticing "FETCH_HEAD" is the only "commit" on the command line and picking the commits that are not marked as not-for-merge as the list of commits to be merged (substitute for step #1 above); - letting the resulting list fed to step #2 above; - doing the step #3 above, using the contents of the FETCH_HEAD instead of fake contents crafted from the list of commits parsed in the step #1 above. Note that this changes the semantics. "git merge FETCH_HEAD" has always behaved as if the first commit in the FETCH_HEAD file were directly specified on the command line, creating a two-way merge whose auto-generated merge log said "merge commit xyz". With this change, if the previous fetch was to grab multiple branches (e.g. "git fetch $there topic-a topic-b"), the new world order is to create an octopus, behaving as if "git pull $there topic-a topic-b" were run. This is a deliberate change to make that happen, and can be seen in the changes to t3033 tests. Signed-off-by: Junio C Hamano <gitster@pobox.com>

Junio C Hamano committed Apr 25, 2015 at 18:47 UTC 74e8bc59cb324d2d7a55c90195db004219770eec
3 files changed +81 -39
Documentation/git-merge.txt
+4
@@ -104,6 +104,10 @@ commit or stash your changes before running 'git merge'.
104 If no commit is given from the command line, merge the remote-tracking
105 branches that the current branch is configured to use as its upstream.
106 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.
111
112
113 PRE-MERGE CHECKS
builtin/merge.c
+72 -34
@@ -505,28 +505,6 @@ static void merge_name(const char *remote, struct strbuf *msg)
505 strbuf_release(&truname);
506 }
507
508 - if (!strcmp(remote, "FETCH_HEAD") &&
509 - !access(git_path("FETCH_HEAD"), R_OK)) {
510 - const char *filename;
511 - FILE *fp;
512 - struct strbuf line = STRBUF_INIT;
513 - char *ptr;
514 -
515 - filename = git_path("FETCH_HEAD");
516 - fp = fopen(filename, "r");
517 - if (!fp)
518 - die_errno(_("could not open '%s' for reading"),
519 - filename);
520 - strbuf_getline(&line, fp, '\n');
521 - fclose(fp);
522 - ptr = strstr(line.buf, "\tnot-for-merge\t");
523 - if (ptr)
524 - strbuf_remove(&line, ptr-line.buf+1, 13);
525 - strbuf_addbuf(msg, &line);
526 - strbuf_release(&line);
527 - goto cleanup;
528 - }
529 -
508 if (remote_head->util) {
509 struct merge_remote_desc *desc;
510 desc = merge_remote_util(remote_head);
@@ -1090,6 +1068,60 @@ static void prepare_merge_message(struct strbuf *merge_names, struct strbuf *mer
1068 strbuf_setlen(merge_msg, merge_msg->len - 1);
1069 }
1070
1071 +static void handle_fetch_head(struct commit_list **remotes, struct strbuf *merge_names)
1072 +{
1073 + const char *filename;
1074 + int fd, pos, npos;
1075 + struct strbuf fetch_head_file = STRBUF_INIT;
1076 +
1077 + if (!merge_names)
1078 + merge_names = &fetch_head_file;
1079 +
1080 + filename = git_path("FETCH_HEAD");
1081 + fd = open(filename, O_RDONLY);
1082 + if (fd < 0)
1083 + die_errno(_("could not open '%s' for reading"), filename);
1084 +
1085 + if (strbuf_read(merge_names, fd, 0) < 0)
1086 + die_errno(_("could not read '%s'"), filename);
1087 + if (close(fd) < 0)
1088 + die_errno(_("could not close '%s'"), filename);
1089 +
1090 + for (pos = 0; pos < merge_names->len; pos = npos) {
1091 + unsigned char sha1[20];
1092 + char *ptr;
1093 + struct commit *commit;
1094 +
1095 + ptr = strchr(merge_names->buf + pos, '\n');
1096 + if (ptr)
1097 + npos = ptr - merge_names->buf + 1;
1098 + else
1099 + npos = merge_names->len;
1100 +
1101 + if (npos - pos < 40 + 2 ||
1102 + get_sha1_hex(merge_names->buf + pos, sha1))
1103 + commit = NULL; /* bad */
1104 + else if (memcmp(merge_names->buf + pos + 40, "\t\t", 2))
1105 + continue; /* not-for-merge */
1106 + else {
1107 + char saved = merge_names->buf[pos + 40];
1108 + merge_names->buf[pos + 40] = '\0';
1109 + commit = get_merge_parent(merge_names->buf + pos);
1110 + merge_names->buf[pos + 40] = saved;
1111 + }
1112 + if (!commit) {
1113 + if (ptr)
1114 + *ptr = '\0';
1115 + die("not something we can merge in %s: %s",
1116 + filename, merge_names->buf + pos);
1117 + }
1118 + remotes = &commit_list_insert(commit, remotes)->next;
1119 + }
1120 +
1121 + if (merge_names == &fetch_head_file)
1122 + strbuf_release(&fetch_head_file);
1123 +}
1124 +
1125 static struct commit_list *collect_parents(struct commit *head_commit,
1126 int *head_subsumed,
1127 int argc, const char **argv,
@@ -1105,21 +1137,27 @@ static struct commit_list *collect_parents(struct commit *head_commit,
1137
1138 if (head_commit)
1139 remotes = &commit_list_insert(head_commit, remotes)->next;
1108 - for (i = 0; i < argc; i++) {
1109 - struct commit *commit = get_merge_parent(argv[i]);
1110 - if (!commit)
1111 - help_unknown_ref(argv[i], "merge",
1112 - "not something we can merge");
1113 - remotes = &commit_list_insert(commit, remotes)->next;
1114 - }
1140
1116 - remoteheads = reduce_parents(head_commit, head_subsumed, remoteheads);
1141 + if (argc == 1 && !strcmp(argv[0], "FETCH_HEAD")) {
1142 + handle_fetch_head(remotes, autogen);
1143 + remoteheads = reduce_parents(head_commit, head_subsumed, remoteheads);
1144 + } else {
1145 + for (i = 0; i < argc; i++) {
1146 + struct commit *commit = get_merge_parent(argv[i]);
1147 + if (!commit)
1148 + help_unknown_ref(argv[i], "merge",
1149 + "not something we can merge");
1150 + remotes = &commit_list_insert(commit, remotes)->next;
1151 + }
1152 + remoteheads = reduce_parents(head_commit, head_subsumed, remoteheads);
1153 + if (autogen) {
1154 + struct commit_list *p;
1155 + for (p = remoteheads; p; p = p->next)
1156 + merge_name(merge_remote_util(p->item)->name, autogen);
1157 + }
1158 + }
1159
1160 if (autogen) {
1119 - struct commit_list *p;
1120 - for (p = remoteheads; p; p = p->next)
1121 - merge_name(merge_remote_util(p->item)->name, autogen);
1122 -
1161 prepare_merge_message(autogen, merge_msg);
1162 strbuf_release(autogen);
1163 }
t/t3033-merge-toplevel.sh
+5 -5
@@ -77,7 +77,7 @@ test_expect_success 'merge octopus, non-fast-forward' '
77
78 # The same set with FETCH_HEAD
79
80 -test_expect_failure 'merge FETCH_HEAD octopus into void' '
80 +test_expect_success 'merge FETCH_HEAD octopus into void' '
81 t3033_reset &&
82 git checkout --orphan test &&
83 git rm -fr . &&
@@ -88,7 +88,7 @@ test_expect_failure 'merge FETCH_HEAD octopus into void' '
88 test_must_fail git rev-parse HEAD
89 '
90
91 -test_expect_failure 'merge FETCH_HEAD octopus fast-forward (ff)' '
91 +test_expect_success 'merge FETCH_HEAD octopus fast-forward (ff)' '
92 t3033_reset &&
93 git reset --hard one &&
94 git fetch . left right &&
@@ -100,7 +100,7 @@ test_expect_failure 'merge FETCH_HEAD octopus fast-forward (ff)' '
100 test_cmp expect actual
101 '
102
103 -test_expect_failure 'merge FETCH_HEAD octopus non-fast-forward (ff)' '
103 +test_expect_success 'merge FETCH_HEAD octopus non-fast-forward (ff)' '
104 t3033_reset &&
105 git reset --hard one &&
106 git fetch . left right &&
@@ -112,7 +112,7 @@ test_expect_failure 'merge FETCH_HEAD octopus non-fast-forward (ff)' '
112 test_cmp expect actual
113 '
114
115 -test_expect_failure 'merge FETCH_HEAD octopus fast-forward (does not ff)' '
115 +test_expect_success 'merge FETCH_HEAD octopus fast-forward (does not ff)' '
116 t3033_reset &&
117 git fetch . left right &&
118 git merge FETCH_HEAD &&
@@ -123,7 +123,7 @@ test_expect_failure 'merge FETCH_HEAD octopus fast-forward (does not ff)' '
123 test_cmp expect actual
124 '
125
126 -test_expect_failure 'merge FETCH_HEAD octopus non-fast-forward' '
126 +test_expect_success 'merge FETCH_HEAD octopus non-fast-forward' '
127 t3033_reset &&
128 git fetch . left right &&
129 git merge --no-ff FETCH_HEAD &&