Skip to content

Commit

Permalink
fetch: improve the error messages emitted for conflicting refspecs
Browse files Browse the repository at this point in the history
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 <mhagger@alum.mit.edu>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
  • Loading branch information
Michael Haggerty authored and Junio C Hamano committed Oct 30, 2013
1 parent 76ea671 commit f096e6e
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 8 deletions.
25 changes: 22 additions & 3 deletions remote.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Expand Down
14 changes: 9 additions & 5 deletions t/t5536-fetch-conflicts.sh
Original file line number Diff line number Diff line change
Expand Up @@ -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" <error >actual &&
grep -E '^(fatal|warning):' <error | grep -v 'hung up' >actual | sort &&
test_cmp expected actual
}

Expand All @@ -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
)
'
Expand Down Expand Up @@ -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
)
'

Expand Down

0 comments on commit f096e6e

Please sign in to comment.