Skip to content

Commit f096e6e

Browse files
mhaggergitster
authored andcommitted
fetch: improve the error messages emitted for conflicting refspecs
If we find two refspecs that want to update the same local reference, emit an error message that is more informative based on whether one of the conflicting refspecs is an opportunistic update during a fetch with explicit command-line refspecs. And especially, do not die if an opportunistic reference update conflicts with an express wish of the user; rather, just emit a warning and skip the opportunistic reference update. Signed-off-by: Michael Haggerty <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent 76ea671 commit f096e6e

File tree

2 files changed

+31
-8
lines changed

2 files changed

+31
-8
lines changed

remote.c

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -747,9 +747,28 @@ int for_each_remote(each_remote_fn fn, void *priv)
747747

748748
static void handle_duplicate(struct ref *ref1, struct ref *ref2)
749749
{
750-
if (strcmp(ref1->name, ref2->name))
751-
die(_("%s tracks both %s and %s"),
752-
ref2->peer_ref->name, ref1->name, ref2->name);
750+
if (strcmp(ref1->name, ref2->name)) {
751+
if (ref1->fetch_head_status != FETCH_HEAD_IGNORE &&
752+
ref2->fetch_head_status != FETCH_HEAD_IGNORE) {
753+
die(_("Cannot fetch both %s and %s to %s"),
754+
ref1->name, ref2->name, ref2->peer_ref->name);
755+
} else if (ref1->fetch_head_status != FETCH_HEAD_IGNORE &&
756+
ref2->fetch_head_status == FETCH_HEAD_IGNORE) {
757+
warning(_("%s usually tracks %s, not %s"),
758+
ref2->peer_ref->name, ref2->name, ref1->name);
759+
} else if (ref1->fetch_head_status == FETCH_HEAD_IGNORE &&
760+
ref2->fetch_head_status == FETCH_HEAD_IGNORE) {
761+
die(_("%s tracks both %s and %s"),
762+
ref2->peer_ref->name, ref1->name, ref2->name);
763+
} else {
764+
/*
765+
* This last possibility doesn't occur because
766+
* FETCH_HEAD_IGNORE entries always appear at
767+
* the end of the list.
768+
*/
769+
die(_("Internal error"));
770+
}
771+
}
753772
free(ref2->peer_ref);
754773
free(ref2);
755774
}

t/t5536-fetch-conflicts.sh

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ verify_stderr () {
2222
cat >expected &&
2323
# We're not interested in the error
2424
# "fatal: The remote end hung up unexpectedly":
25-
grep -v "hung up" <error >actual &&
25+
grep -E '^(fatal|warning):' <error | grep -v 'hung up' >actual | sort &&
2626
test_cmp expected actual
2727
}
2828

@@ -49,7 +49,7 @@ test_expect_success 'fetch conflict: config vs. config' '
4949
cd ccc &&
5050
test_must_fail git fetch origin 2>error &&
5151
verify_stderr <<-\EOF
52-
fatal: refs/remotes/origin/branch1 tracks both refs/heads/branch1 and refs/heads/branch2
52+
fatal: Cannot fetch both refs/heads/branch1 and refs/heads/branch2 to refs/remotes/origin/branch1
5353
EOF
5454
)
5555
'
@@ -78,18 +78,22 @@ test_expect_success 'fetch conflict: arg vs. arg' '
7878
refs/heads/*:refs/remotes/origin/* \
7979
refs/heads/branch2:refs/remotes/origin/branch1 2>error &&
8080
verify_stderr <<-\EOF
81-
fatal: refs/remotes/origin/branch1 tracks both refs/heads/branch1 and refs/heads/branch2
81+
fatal: Cannot fetch both refs/heads/branch1 and refs/heads/branch2 to refs/remotes/origin/branch1
8282
EOF
8383
)
8484
'
8585

86-
test_expect_failure 'fetch conflict: criss-cross args' '
86+
test_expect_success 'fetch conflict: criss-cross args' '
8787
setup_repository xaa \
8888
"+refs/heads/*:refs/remotes/origin/*" && (
8989
cd xaa &&
9090
git fetch origin \
9191
refs/heads/branch1:refs/remotes/origin/branch2 \
92-
refs/heads/branch2:refs/remotes/origin/branch1
92+
refs/heads/branch2:refs/remotes/origin/branch1 2>error &&
93+
verify_stderr <<-\EOF
94+
warning: refs/remotes/origin/branch1 usually tracks refs/heads/branch1, not refs/heads/branch2
95+
warning: refs/remotes/origin/branch2 usually tracks refs/heads/branch2, not refs/heads/branch1
96+
EOF
9397
)
9498
'
9599

0 commit comments

Comments
 (0)