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 <mhagger@alum.mit.edu> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Michael Haggerty committed
Oct 30, 2013 at 06:33 UTC
f096e6e826678c29e4bfde4d9d1ae1df79074ce3
2 files changed
+31
-8
remote.c
+22
-3
@@ -747,9 +747,28 @@ int for_each_remote(each_remote_fn fn, void *priv)
747
748
static void handle_duplicate(struct ref *ref1, struct ref *ref2)
749
{
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
+ }
772
free(ref2->peer_ref);
773
free(ref2);
774
}
t/t5536-fetch-conflicts.sh
+9
-5
@@ -22,7 +22,7 @@ verify_stderr () {
22
cat >expected &&
23
# We're not interested in the error
24
# "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 &&
26
test_cmp expected actual
27
}
28
@@ -49,7 +49,7 @@ test_expect_success 'fetch conflict: config vs. config' '
49
cd ccc &&
50
test_must_fail git fetch origin 2>error &&
51
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
53
EOF
54
)
55
'
@@ -78,18 +78,22 @@ test_expect_success 'fetch conflict: arg vs. arg' '
78
refs/heads/*:refs/remotes/origin/* \
79
refs/heads/branch2:refs/remotes/origin/branch1 2>error &&
80
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
82
EOF
83
)
84
'
85
86
-test_expect_failure 'fetch conflict: criss-cross args' '
86
+test_expect_success 'fetch conflict: criss-cross args' '
87
setup_repository xaa \
88
"+refs/heads/*:refs/remotes/origin/*" && (
89
cd xaa &&
90
git fetch origin \
91
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
97
)
98
'
99