Skip to content

Commit 96890f4

Browse files
joeyhgitster
authored andcommitted
write first for-merge ref to FETCH_HEAD first
The FETCH_HEAD refname is supposed to refer to the ref that was fetched and should be merged. However all fetched refs are written to .git/FETCH_HEAD in an arbitrary order, and resolve_ref_unsafe simply takes the first ref as the FETCH_HEAD, which is often the wrong one, when other branches were also fetched. The solution is to write the for-merge ref(s) to FETCH_HEAD first. Then, unless --append is used, the FETCH_HEAD refname behaves as intended. If the user uses --append, they presumably are doing so in order to preserve the old FETCH_HEAD. While we are at it, update an old example in the read-tree documentation that implied that each entry in FETCH_HEAD only has the object name, which is not true for quite a while. [jc: adjusted tests] Signed-off-by: Joey Hess <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent ec33015 commit 96890f4

25 files changed

+114
-102
lines changed

Documentation/git-read-tree.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -342,7 +342,7 @@ since you pulled from him:
342342

343343
----------------
344344
$ git fetch git://.... linus
345-
$ LT=`cat .git/FETCH_HEAD`
345+
$ LT=`git rev-parse FETCH_HEAD`
346346
----------------
347347

348348
Your work tree is still based on your HEAD ($JC), but you have

builtin/fetch.c

Lines changed: 86 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -377,6 +377,7 @@ static int store_updated_refs(const char *raw_url, const char *remote_name,
377377
const char *what, *kind;
378378
struct ref *rm;
379379
char *url, *filename = dry_run ? "/dev/null" : git_path("FETCH_HEAD");
380+
int want_merge;
380381

381382
fp = fopen(filename, "a");
382383
if (!fp)
@@ -393,84 +394,95 @@ static int store_updated_refs(const char *raw_url, const char *remote_name,
393394
goto abort;
394395
}
395396

396-
for (rm = ref_map; rm; rm = rm->next) {
397-
struct ref *ref = NULL;
398-
399-
if (rm->peer_ref) {
400-
ref = xcalloc(1, sizeof(*ref) + strlen(rm->peer_ref->name) + 1);
401-
strcpy(ref->name, rm->peer_ref->name);
402-
hashcpy(ref->old_sha1, rm->peer_ref->old_sha1);
403-
hashcpy(ref->new_sha1, rm->old_sha1);
404-
ref->force = rm->peer_ref->force;
405-
}
397+
/*
398+
* The first pass writes objects to be merged and then the
399+
* second pass writes the rest, in order to allow using
400+
* FETCH_HEAD as a refname to refer to the ref to be merged.
401+
*/
402+
for (want_merge = 1; 0 <= want_merge; want_merge--) {
403+
for (rm = ref_map; rm; rm = rm->next) {
404+
struct ref *ref = NULL;
405+
406+
commit = lookup_commit_reference_gently(rm->old_sha1, 1);
407+
if (!commit)
408+
rm->merge = 0;
409+
410+
if (rm->merge != want_merge)
411+
continue;
412+
413+
if (rm->peer_ref) {
414+
ref = xcalloc(1, sizeof(*ref) + strlen(rm->peer_ref->name) + 1);
415+
strcpy(ref->name, rm->peer_ref->name);
416+
hashcpy(ref->old_sha1, rm->peer_ref->old_sha1);
417+
hashcpy(ref->new_sha1, rm->old_sha1);
418+
ref->force = rm->peer_ref->force;
419+
}
406420

407-
commit = lookup_commit_reference_gently(rm->old_sha1, 1);
408-
if (!commit)
409-
rm->merge = 0;
410421

411-
if (!strcmp(rm->name, "HEAD")) {
412-
kind = "";
413-
what = "";
414-
}
415-
else if (!prefixcmp(rm->name, "refs/heads/")) {
416-
kind = "branch";
417-
what = rm->name + 11;
418-
}
419-
else if (!prefixcmp(rm->name, "refs/tags/")) {
420-
kind = "tag";
421-
what = rm->name + 10;
422-
}
423-
else if (!prefixcmp(rm->name, "refs/remotes/")) {
424-
kind = "remote-tracking branch";
425-
what = rm->name + 13;
426-
}
427-
else {
428-
kind = "";
429-
what = rm->name;
430-
}
422+
if (!strcmp(rm->name, "HEAD")) {
423+
kind = "";
424+
what = "";
425+
}
426+
else if (!prefixcmp(rm->name, "refs/heads/")) {
427+
kind = "branch";
428+
what = rm->name + 11;
429+
}
430+
else if (!prefixcmp(rm->name, "refs/tags/")) {
431+
kind = "tag";
432+
what = rm->name + 10;
433+
}
434+
else if (!prefixcmp(rm->name, "refs/remotes/")) {
435+
kind = "remote-tracking branch";
436+
what = rm->name + 13;
437+
}
438+
else {
439+
kind = "";
440+
what = rm->name;
441+
}
431442

432-
url_len = strlen(url);
433-
for (i = url_len - 1; url[i] == '/' && 0 <= i; i--)
434-
;
435-
url_len = i + 1;
436-
if (4 < i && !strncmp(".git", url + i - 3, 4))
437-
url_len = i - 3;
438-
439-
strbuf_reset(&note);
440-
if (*what) {
441-
if (*kind)
442-
strbuf_addf(&note, "%s ", kind);
443-
strbuf_addf(&note, "'%s' of ", what);
444-
}
445-
fprintf(fp, "%s\t%s\t%s",
446-
sha1_to_hex(rm->old_sha1),
447-
rm->merge ? "" : "not-for-merge",
448-
note.buf);
449-
for (i = 0; i < url_len; ++i)
450-
if ('\n' == url[i])
451-
fputs("\\n", fp);
452-
else
453-
fputc(url[i], fp);
454-
fputc('\n', fp);
455-
456-
strbuf_reset(&note);
457-
if (ref) {
458-
rc |= update_local_ref(ref, what, &note);
459-
free(ref);
460-
} else
461-
strbuf_addf(&note, "* %-*s %-*s -> FETCH_HEAD",
462-
TRANSPORT_SUMMARY_WIDTH,
463-
*kind ? kind : "branch",
464-
REFCOL_WIDTH,
465-
*what ? what : "HEAD");
466-
if (note.len) {
467-
if (verbosity >= 0 && !shown_url) {
468-
fprintf(stderr, _("From %.*s\n"),
469-
url_len, url);
470-
shown_url = 1;
443+
url_len = strlen(url);
444+
for (i = url_len - 1; url[i] == '/' && 0 <= i; i--)
445+
;
446+
url_len = i + 1;
447+
if (4 < i && !strncmp(".git", url + i - 3, 4))
448+
url_len = i - 3;
449+
450+
strbuf_reset(&note);
451+
if (*what) {
452+
if (*kind)
453+
strbuf_addf(&note, "%s ", kind);
454+
strbuf_addf(&note, "'%s' of ", what);
455+
}
456+
fprintf(fp, "%s\t%s\t%s",
457+
sha1_to_hex(rm->old_sha1),
458+
rm->merge ? "" : "not-for-merge",
459+
note.buf);
460+
for (i = 0; i < url_len; ++i)
461+
if ('\n' == url[i])
462+
fputs("\\n", fp);
463+
else
464+
fputc(url[i], fp);
465+
fputc('\n', fp);
466+
467+
strbuf_reset(&note);
468+
if (ref) {
469+
rc |= update_local_ref(ref, what, &note);
470+
free(ref);
471+
} else
472+
strbuf_addf(&note, "* %-*s %-*s -> FETCH_HEAD",
473+
TRANSPORT_SUMMARY_WIDTH,
474+
*kind ? kind : "branch",
475+
REFCOL_WIDTH,
476+
*what ? what : "HEAD");
477+
if (note.len) {
478+
if (verbosity >= 0 && !shown_url) {
479+
fprintf(stderr, _("From %.*s\n"),
480+
url_len, url);
481+
shown_url = 1;
482+
}
483+
if (verbosity >= 0)
484+
fprintf(stderr, " %s\n", note.buf);
471485
}
472-
if (verbosity >= 0)
473-
fprintf(stderr, " %s\n", note.buf);
474486
}
475487
}
476488

t/t5510-fetch.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,8 +70,8 @@ test_expect_success "fetch test for-merge" '
7070
master_in_two=`cd ../two && git rev-parse master` &&
7171
one_in_two=`cd ../two && git rev-parse one` &&
7272
{
73-
echo "$master_in_two not-for-merge"
7473
echo "$one_in_two "
74+
echo "$master_in_two not-for-merge"
7575
} >expected &&
7676
cut -f -2 .git/FETCH_HEAD >actual &&
7777
test_cmp expected actual'

t/t5515/fetch.br-branches-default-merge

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# br-branches-default-merge
2-
754b754407bf032e9a2f9d5a9ad05ca79a6b228f not-for-merge branch 'master' of ../
32
0567da4d5edd2ff4bb292a465ba9e64dcad9536b branch 'three' of ../
3+
754b754407bf032e9a2f9d5a9ad05ca79a6b228f not-for-merge branch 'master' of ../
44
6c9dec2b923228c9ff994c6cfe4ae16c12408dc5 not-for-merge tag 'tag-master' of ../
55
8e32a6d901327a23ef831511badce7bf3bf46689 not-for-merge tag 'tag-one' of ../
66
22feea448b023a2d864ef94b013735af34d238ba not-for-merge tag 'tag-one-tree' of ../

t/t5515/fetch.br-branches-default-merge_branches-default

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# br-branches-default-merge branches-default
2-
754b754407bf032e9a2f9d5a9ad05ca79a6b228f not-for-merge branch 'master' of ../
32
0567da4d5edd2ff4bb292a465ba9e64dcad9536b branch 'three' of ../
3+
754b754407bf032e9a2f9d5a9ad05ca79a6b228f not-for-merge branch 'master' of ../
44
6c9dec2b923228c9ff994c6cfe4ae16c12408dc5 not-for-merge tag 'tag-master' of ../
55
8e32a6d901327a23ef831511badce7bf3bf46689 not-for-merge tag 'tag-one' of ../
66
22feea448b023a2d864ef94b013735af34d238ba not-for-merge tag 'tag-one-tree' of ../

t/t5515/fetch.br-branches-default-octopus

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# br-branches-default-octopus
2-
754b754407bf032e9a2f9d5a9ad05ca79a6b228f not-for-merge branch 'master' of ../
32
8e32a6d901327a23ef831511badce7bf3bf46689 branch 'one' of ../
43
6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 branch 'two' of ../
4+
754b754407bf032e9a2f9d5a9ad05ca79a6b228f not-for-merge branch 'master' of ../
55
6c9dec2b923228c9ff994c6cfe4ae16c12408dc5 not-for-merge tag 'tag-master' of ../
66
8e32a6d901327a23ef831511badce7bf3bf46689 not-for-merge tag 'tag-one' of ../
77
22feea448b023a2d864ef94b013735af34d238ba not-for-merge tag 'tag-one-tree' of ../

t/t5515/fetch.br-branches-default-octopus_branches-default

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# br-branches-default-octopus branches-default
2-
754b754407bf032e9a2f9d5a9ad05ca79a6b228f not-for-merge branch 'master' of ../
32
8e32a6d901327a23ef831511badce7bf3bf46689 branch 'one' of ../
43
6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 branch 'two' of ../
4+
754b754407bf032e9a2f9d5a9ad05ca79a6b228f not-for-merge branch 'master' of ../
55
6c9dec2b923228c9ff994c6cfe4ae16c12408dc5 not-for-merge tag 'tag-master' of ../
66
8e32a6d901327a23ef831511badce7bf3bf46689 not-for-merge tag 'tag-one' of ../
77
22feea448b023a2d864ef94b013735af34d238ba not-for-merge tag 'tag-one-tree' of ../

t/t5515/fetch.br-branches-one-merge

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# br-branches-one-merge
2-
8e32a6d901327a23ef831511badce7bf3bf46689 not-for-merge branch 'one' of ../
32
0567da4d5edd2ff4bb292a465ba9e64dcad9536b branch 'three' of ../
3+
8e32a6d901327a23ef831511badce7bf3bf46689 not-for-merge branch 'one' of ../
44
6c9dec2b923228c9ff994c6cfe4ae16c12408dc5 not-for-merge tag 'tag-master' of ../
55
8e32a6d901327a23ef831511badce7bf3bf46689 not-for-merge tag 'tag-one' of ../
66
22feea448b023a2d864ef94b013735af34d238ba not-for-merge tag 'tag-one-tree' of ../

t/t5515/fetch.br-branches-one-merge_branches-one

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# br-branches-one-merge branches-one
2-
8e32a6d901327a23ef831511badce7bf3bf46689 not-for-merge branch 'one' of ../
32
0567da4d5edd2ff4bb292a465ba9e64dcad9536b branch 'three' of ../
3+
8e32a6d901327a23ef831511badce7bf3bf46689 not-for-merge branch 'one' of ../
44
6c9dec2b923228c9ff994c6cfe4ae16c12408dc5 not-for-merge tag 'tag-master' of ../
55
8e32a6d901327a23ef831511badce7bf3bf46689 not-for-merge tag 'tag-one' of ../
66
22feea448b023a2d864ef94b013735af34d238ba not-for-merge tag 'tag-one-tree' of ../

t/t5515/fetch.br-config-explicit-merge

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
# br-config-explicit-merge
2+
0567da4d5edd2ff4bb292a465ba9e64dcad9536b branch 'three' of ../
23
754b754407bf032e9a2f9d5a9ad05ca79a6b228f not-for-merge branch 'master' of ../
34
8e32a6d901327a23ef831511badce7bf3bf46689 not-for-merge branch 'one' of ../
45
6134ee8f857693b96ff1cc98d3e2fd62b199e5a8 not-for-merge branch 'two' of ../
5-
0567da4d5edd2ff4bb292a465ba9e64dcad9536b branch 'three' of ../
66
6c9dec2b923228c9ff994c6cfe4ae16c12408dc5 not-for-merge tag 'tag-master' of ../
77
8e32a6d901327a23ef831511badce7bf3bf46689 not-for-merge tag 'tag-one' of ../
88
22feea448b023a2d864ef94b013735af34d238ba not-for-merge tag 'tag-one-tree' of ../

0 commit comments

Comments
 (0)