diff --git a/remote.c b/remote.c index 0848faffa4..dc56619d23 100644 --- a/remote.c +++ b/remote.c @@ -747,9 +747,28 @@ int for_each_remote(each_remote_fn fn, void *priv) static void handle_duplicate(struct ref *ref1, struct ref *ref2) { - if (strcmp(ref1->name, ref2->name)) - die(_("%s tracks both %s and %s"), - ref2->peer_ref->name, ref1->name, ref2->name); + if (strcmp(ref1->name, ref2->name)) { + if (ref1->fetch_head_status != FETCH_HEAD_IGNORE && + ref2->fetch_head_status != FETCH_HEAD_IGNORE) { + die(_("Cannot fetch both %s and %s to %s"), + ref1->name, ref2->name, ref2->peer_ref->name); + } else if (ref1->fetch_head_status != FETCH_HEAD_IGNORE && + ref2->fetch_head_status == FETCH_HEAD_IGNORE) { + warning(_("%s usually tracks %s, not %s"), + ref2->peer_ref->name, ref2->name, ref1->name); + } else if (ref1->fetch_head_status == FETCH_HEAD_IGNORE && + ref2->fetch_head_status == FETCH_HEAD_IGNORE) { + die(_("%s tracks both %s and %s"), + ref2->peer_ref->name, ref1->name, ref2->name); + } else { + /* + * This last possibility doesn't occur because + * FETCH_HEAD_IGNORE entries always appear at + * the end of the list. + */ + die(_("Internal error")); + } + } free(ref2->peer_ref); free(ref2); } diff --git a/t/t5536-fetch-conflicts.sh b/t/t5536-fetch-conflicts.sh index 679c53e044..6c5d3a4ce0 100755 --- a/t/t5536-fetch-conflicts.sh +++ b/t/t5536-fetch-conflicts.sh @@ -22,7 +22,7 @@ verify_stderr () { cat >expected && # We're not interested in the error # "fatal: The remote end hung up unexpectedly": - grep -v "hung up" actual && + grep -E '^(fatal|warning):' actual | sort && test_cmp expected actual } @@ -49,7 +49,7 @@ test_expect_success 'fetch conflict: config vs. config' ' cd ccc && test_must_fail git fetch origin 2>error && verify_stderr <<-\EOF - fatal: refs/remotes/origin/branch1 tracks both refs/heads/branch1 and refs/heads/branch2 + fatal: Cannot fetch both refs/heads/branch1 and refs/heads/branch2 to refs/remotes/origin/branch1 EOF ) ' @@ -78,18 +78,22 @@ test_expect_success 'fetch conflict: arg vs. arg' ' refs/heads/*:refs/remotes/origin/* \ refs/heads/branch2:refs/remotes/origin/branch1 2>error && verify_stderr <<-\EOF - fatal: refs/remotes/origin/branch1 tracks both refs/heads/branch1 and refs/heads/branch2 + fatal: Cannot fetch both refs/heads/branch1 and refs/heads/branch2 to refs/remotes/origin/branch1 EOF ) ' -test_expect_failure 'fetch conflict: criss-cross args' ' +test_expect_success 'fetch conflict: criss-cross args' ' setup_repository xaa \ "+refs/heads/*:refs/remotes/origin/*" && ( cd xaa && git fetch origin \ refs/heads/branch1:refs/remotes/origin/branch2 \ - refs/heads/branch2:refs/remotes/origin/branch1 + refs/heads/branch2:refs/remotes/origin/branch1 2>error && + verify_stderr <<-\EOF + warning: refs/remotes/origin/branch1 usually tracks refs/heads/branch1, not refs/heads/branch2 + warning: refs/remotes/origin/branch2 usually tracks refs/heads/branch2, not refs/heads/branch1 + EOF ) '