Skip to content

Commit 74e8bc5

Browse files
committed
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 <[email protected]>
1 parent 7703801 commit 74e8bc5

File tree

3 files changed

+81
-39
lines changed

3 files changed

+81
-39
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: 72 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -505,28 +505,6 @@ static void merge_name(const char *remote, struct strbuf *msg)
505505
strbuf_release(&truname);
506506
}
507507

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-
530508
if (remote_head->util) {
531509
struct merge_remote_desc *desc;
532510
desc = merge_remote_util(remote_head);
@@ -1090,6 +1068,60 @@ static void prepare_merge_message(struct strbuf *merge_names, struct strbuf *mer
10901068
strbuf_setlen(merge_msg, merge_msg->len - 1);
10911069
}
10921070

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+
10931125
static struct commit_list *collect_parents(struct commit *head_commit,
10941126
int *head_subsumed,
10951127
int argc, const char **argv,
@@ -1105,21 +1137,27 @@ static struct commit_list *collect_parents(struct commit *head_commit,
11051137

11061138
if (head_commit)
11071139
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-
}
11151140

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+
}
11171159

11181160
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-
11231161
prepare_merge_message(autogen, merge_msg);
11241162
strbuf_release(autogen);
11251163
}

t/t3033-merge-toplevel.sh

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ test_expect_success 'merge octopus, non-fast-forward' '
7777

7878
# The same set with FETCH_HEAD
7979

80-
test_expect_failure 'merge FETCH_HEAD octopus into void' '
80+
test_expect_success 'merge FETCH_HEAD octopus into void' '
8181
t3033_reset &&
8282
git checkout --orphan test &&
8383
git rm -fr . &&
@@ -88,7 +88,7 @@ test_expect_failure 'merge FETCH_HEAD octopus into void' '
8888
test_must_fail git rev-parse HEAD
8989
'
9090

91-
test_expect_failure 'merge FETCH_HEAD octopus fast-forward (ff)' '
91+
test_expect_success 'merge FETCH_HEAD octopus fast-forward (ff)' '
9292
t3033_reset &&
9393
git reset --hard one &&
9494
git fetch . left right &&
@@ -100,7 +100,7 @@ test_expect_failure 'merge FETCH_HEAD octopus fast-forward (ff)' '
100100
test_cmp expect actual
101101
'
102102

103-
test_expect_failure 'merge FETCH_HEAD octopus non-fast-forward (ff)' '
103+
test_expect_success 'merge FETCH_HEAD octopus non-fast-forward (ff)' '
104104
t3033_reset &&
105105
git reset --hard one &&
106106
git fetch . left right &&
@@ -112,7 +112,7 @@ test_expect_failure 'merge FETCH_HEAD octopus non-fast-forward (ff)' '
112112
test_cmp expect actual
113113
'
114114

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)' '
116116
t3033_reset &&
117117
git fetch . left right &&
118118
git merge FETCH_HEAD &&
@@ -123,7 +123,7 @@ test_expect_failure 'merge FETCH_HEAD octopus fast-forward (does not ff)' '
123123
test_cmp expect actual
124124
'
125125

126-
test_expect_failure 'merge FETCH_HEAD octopus non-fast-forward' '
126+
test_expect_success 'merge FETCH_HEAD octopus non-fast-forward' '
127127
t3033_reset &&
128128
git fetch . left right &&
129129
git merge --no-ff FETCH_HEAD &&

0 commit comments

Comments
 (0)