fetch: utilize rejected ref error details
In 0e358de64a (fetch: use batched reference updates, 2025-05-19), git-fetch(1) switched to using batched reference updates. This also introduced a regression wherein instead of providing detailed error messages for failed referenced updates, the users were provided generic error messages based on the error type. Similar to the previous commit, switch to using detailed error messages if present for failed reference updates to fix this regression. Reported-by: Elijah Newren <newren@gmail.com> Co-authored-by: Jeff King <peff@peff.net> Signed-off-by: Karthik Nayak <karthik.188@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
Karthik Nayak committed
Jan 25, 2026 at 23:52 UTC
274f4355527275515a2c7c5f5a1214cf57b06338
2 files changed
+10
-8
builtin/fetch.c
+6
-4
@@ -1649,7 +1649,7 @@ static void ref_transaction_rejection_handler(const char *refname,
1649
const char *old_target UNUSED,
1650
const char *new_target UNUSED,
1651
enum ref_transaction_error err,
1652
- const char *details UNUSED,
1652
+ const char *details,
1653
void *cb_data)
1654
{
1655
struct ref_rejection_data *data = cb_data;
@@ -1674,9 +1674,11 @@ static void ref_transaction_rejection_handler(const char *refname,
1674
"branches"), data->remote_name);
1675
data->conflict_msg_shown = true;
1676
} else {
1677
- const char *reason = ref_transaction_error_msg(err);
1678
-
1679
- error(_("fetching ref %s failed: %s"), refname, reason);
1677
+ if (details)
1678
+ error("%s", details);
1679
+ else
1680
+ error(_("fetching ref %s failed: %s"),
1681
+ refname, ref_transaction_error_msg(err));
1682
}
1683
1684
*data->retcode = 1;
t/t5510-fetch.sh
+4
-4
@@ -1516,7 +1516,7 @@ test_expect_success REFFILES 'existing reference lock in repo' '
1516
git remote add origin ../base &&
1517
touch refs/heads/foo.lock &&
1518
test_must_fail git fetch -f origin "refs/heads/*:refs/heads/*" 2>err &&
1519
- test_grep "error: fetching ref refs/heads/foo failed: reference already exists" err &&
1519
+ test_grep -e "error: cannot lock ref ${SQ}refs/heads/foo${SQ}: Unable to create" -e "refs/heads/foo.lock${SQ}: File exists." err &&
1520
git rev-parse refs/heads/main >expect &&
1521
git rev-parse refs/heads/branch >actual &&
1522
test_cmp expect actual
@@ -1530,7 +1530,7 @@ test_expect_success CASE_INSENSITIVE_FS,REFFILES 'F/D conflict on case insensiti
1530
cd case_insensitive &&
1531
git remote add origin -- ../case_sensitive_fd &&
1532
test_must_fail git fetch -f origin "refs/heads/*:refs/heads/*" 2>err &&
1533
- test_grep "failed: refname conflict" err &&
1533
+ test_grep "cannot process ${SQ}refs/remotes/origin/foo${SQ} and ${SQ}refs/remotes/origin/foo/bar${SQ} at the same time" err &&
1534
git rev-parse refs/heads/main >expect &&
1535
git rev-parse refs/heads/foo/bar >actual &&
1536
test_cmp expect actual
@@ -1544,7 +1544,7 @@ test_expect_success CASE_INSENSITIVE_FS,REFFILES 'D/F conflict on case insensiti
1544
cd case_insensitive &&
1545
git remote add origin -- ../case_sensitive_df &&
1546
test_must_fail git fetch -f origin "refs/heads/*:refs/heads/*" 2>err &&
1547
- test_grep "failed: refname conflict" err &&
1547
+ test_grep "cannot lock ref ${SQ}refs/remotes/origin/foo${SQ}: there is a non-empty directory ${SQ}./refs/remotes/origin/foo${SQ} blocking reference ${SQ}refs/remotes/origin/foo${SQ}" err &&
1548
git rev-parse refs/heads/main >expect &&
1549
git rev-parse refs/heads/Foo/bar >actual &&
1550
test_cmp expect actual
@@ -1658,7 +1658,7 @@ test_expect_success REFFILES "FETCH_HEAD is updated even if ref updates fail" '
1658
git remote add origin ../base &&
1659
>refs/heads/foo.lock &&
1660
test_must_fail git fetch -f origin "refs/heads/*:refs/heads/*" 2>err &&
1661
- test_grep "error: fetching ref refs/heads/foo failed: reference already exists" err &&
1661
+ test_grep -e "error: cannot lock ref ${SQ}refs/heads/foo${SQ}: Unable to create" -e "refs/heads/foo.lock${SQ}: File exists." err &&
1662
test_grep "branch ${SQ}branch${SQ} of ../base" FETCH_HEAD &&
1663
test_grep "branch ${SQ}foo${SQ} of ../base" FETCH_HEAD
1664
)