git/list[1] front-page[2] threads[3] people[4] search[5] about
 

[PATCH v6 03/16] builtin/update-ref: skip ambiguity checks when parsing object IDs

From
Patrick Steinhardt <ps@pks.im>
Date
Mar 12, 2025, 15:56 UTC
Message-ID
<20250312-pks-update-ref-optimization-v6-3-f778e0414f55@pks.im>
In-Reply-To
<20250312-pks-update-ref-optimization-v6-0-f778e0414f55@pks.im>

Most of the commands in git-update-ref(1) accept an old and/or new object ID to update a specific reference to. These object IDs get parsed via `repo_get_oid()`, which not only handles plain object IDs, but also those that have a suffix like "~" or "^2". More surprisingly though, it even knows to resolve arbitrary revisions, despite the fact that its manpage does not mention this fact even once.

One consequence of this is that we also check for ambiguous references: when parsing a full object ID where the DWIM mechanism would also cause us to resolve it as a branch, we'd end up printing a warning. While this check makes sense to have in general, it is arguably less useful in the context of git-update-ref(1). This is due to multiple reasons:

  - The manpage is explicitly structured around object IDs. So if we see
    a fully blown object ID, the intent should be quite clear in
    general.
  - The command is part of our plumbing layer and not a tool that users
    would generally use in interactive workflows. As such, the warning
    will likely not be visible to anybody in the first place.
  - Users can and should use the fully-qualified refname in case there
    is any potential for ambiguity. And given that this command is part
    of our plumbing layer, one should always try to be as defensive as
    possible and use fully-qualified refnames.

Furthermore, this check can be quite expensive when updating lots of references via `--stdin`, because we try to read multiple references per object ID that we parse according to the DWIM rules. This effect can be seen both with the "files" and "reftable" backend.

The issue is not unique to git-update-ref(1), but was also an issue in git-cat-file(1), where it was addressed by disabling the ambiguity check in 25fba78d36b (cat-file: disable object/refname ambiguity check for batch mode, 2013-07-12).

Disable the warning in git-update-ref(1), which provides a significant speedup with both backends. The user-visible outcome is unchanged even when ambiguity exists, except that we don't show the warning anymore.

The following benchmark creates 10000 new references with a 100000 preexisting refs with the "files" backend:

    Benchmark 1: update-ref: create many refs (refformat = files, preexisting = 100000, new = 10000, revision = HEAD~)
      Time (mean ± σ):     467.3 ms ±   5.1 ms    [User: 100.0 ms, System: 365.1 ms]
      Range (min … max):   461.9 ms … 479.3 ms    10 runs
    Benchmark 2: update-ref: create many refs (refformat = files, preexisting = 100000, new = 10000, revision = HEAD)
      Time (mean ± σ):     394.1 ms ±   5.8 ms    [User: 63.3 ms, System: 327.6 ms]
      Range (min … max):   384.9 ms … 405.7 ms    10 runs
    Summary
      update-ref: create many refs (refformat = files, preexisting = 100000, new = 10000, revision = HEAD) ran
        1.19 ± 0.02 times faster than update-ref: create many refs (refformat = files, preexisting = 100000, new = 10000, revision = HEAD~)
And with the "reftable" backend:
    Benchmark 1: update-ref: create many refs (refformat = reftable, preexisting = 100000, new = 10000, revision = HEAD~)
      Time (mean ± σ):     146.9 ms ±   2.2 ms    [User: 90.4 ms, System: 56.0 ms]
      Range (min … max):   142.7 ms … 150.8 ms    19 runs
    Benchmark 2: update-ref: create many refs (refformat = reftable, preexisting = 100000, new = 10000, revision = HEAD)
      Time (mean ± σ):      63.2 ms ±   1.1 ms    [User: 41.0 ms, System: 21.8 ms]
      Range (min … max):    61.1 ms …  66.6 ms    41 runs
    Summary
      update-ref: create many refs (refformat = reftable, preexisting = 100000, new = 10000, revision = HEAD) ran
        2.32 ± 0.05 times faster than update-ref: create many refs (refformat = reftable, preexisting = 100000, new = 10000, revision = HEAD~)

Note that the absolute improvement with both backends is roughly in the same ballpark, but the relative improvement for the "reftable" backend is more significant because writing the new table to disk is faster in the first place.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
---
 builtin/update-ref.c | 15 ++++++++++-----
 1 file changed, 10 insertions(+), 5 deletions(-)
diff --git a/builtin/update-ref.c b/builtin/update-ref.c
index 4d35bdc4b4b..1d541e13ade 100644
--- a/builtin/update-ref.c
+++ b/builtin/update-ref.c
@@ -179,7 +179,8 @@ static int parse_next_oid(const char **next, const char *end,
 		(*next)++;
 		*next = parse_arg(*next, &arg);
 		if (arg.len) {
-			if (repo_get_oid(the_repository, arg.buf, oid))
+			if (repo_get_oid_with_flags(the_repository, arg.buf, oid,
+						    GET_OID_SKIP_AMBIGUITY_CHECK))
 				goto invalid;
 		} else {
 			/* Without -z, an empty value means all zeros: */
@@ -197,7 +198,8 @@ static int parse_next_oid(const char **next, const char *end,
 		*next += arg.len;
 
 		if (arg.len) {
-			if (repo_get_oid(the_repository, arg.buf, oid))
+			if (repo_get_oid_with_flags(the_repository, arg.buf, oid,
+						    GET_OID_SKIP_AMBIGUITY_CHECK))
 				goto invalid;
 		} else if (flags & PARSE_SHA1_ALLOW_EMPTY) {
 			/* With -z, treat an empty value as all zeros: */
@@ -299,7 +301,8 @@ static void parse_cmd_symref_update(struct ref_transaction *transaction,
 			die("symref-update %s: expected old value", refname);
 
 		if (!strcmp(old_arg, "oid")) {
-			if (repo_get_oid(the_repository, old_target, &old_oid))
+			if (repo_get_oid_with_flags(the_repository, old_target, &old_oid,
+						    GET_OID_SKIP_AMBIGUITY_CHECK))
 				die("symref-update %s: invalid oid: %s", refname, old_target);
 
 			have_old_oid = 1;
@@ -772,7 +775,8 @@ int cmd_update_ref(int argc,
 		refname = argv[0];
 		value = argv[1];
 		oldval = argv[2];
-		if (repo_get_oid(the_repository, value, &oid))
+		if (repo_get_oid_with_flags(the_repository, value, &oid,
+					    GET_OID_SKIP_AMBIGUITY_CHECK))
 			die("%s: not a valid SHA1", value);
 	}
 
@@ -783,7 +787,8 @@ int cmd_update_ref(int argc,
 			 * must not already exist:
 			 */
 			oidclr(&oldoid, the_repository->hash_algo);
-		else if (repo_get_oid(the_repository, oldval, &oldoid))
+		else if (repo_get_oid_with_flags(the_repository, oldval, &oldoid,
+						 GET_OID_SKIP_AMBIGUITY_CHECK))
 			die("%s: not a valid old SHA1", oldval);
 	}
 
-- 
2.49.0.rc2.394.gf6994c5077.dirty
Previous: Patrick SteinhardtNext: Patrick Steinhardt
Message 149 of 169 in “refs: batch refname availability checks”
  1. 00/14 refs: batch refname availability checksPatrick Steinhardt, Feb 17, 2025
  2. 01/14 object-name: introduce `repo_get_oid_with_flags()`Patrick Steinhardt, Feb 17, 2025
  3. 02/14 object-name: allow skipping ambiguity checks in `get_oid()` familyPatrick Steinhardt, Feb 17, 2025
  4. 03/14 builtin/update-ref: skip ambiguity checks when parsing object IDsPatrick Steinhardt, Feb 17, 2025
  5. Karthik NayakFeb 18, 2025
  6. 04/14 refs: introduce function to batch refname availability checksPatrick Steinhardt, Feb 17, 2025
  7. 05/14 refs/reftable: start using `refs_verify_refnames_available()`Patrick Steinhardt, Feb 17, 2025
  8. 06/14 refs: stop re-verifying common prefixes for availabilityPatrick Steinhardt, Feb 17, 2025
  9. Karthik NayakFeb 18, 2025
  10. Patrick SteinhardtFeb 19, 2025
  11. 07/14 refs/iterator: separate lifecycle from iterationPatrick Steinhardt, Feb 17, 2025
  12. shejialuoFeb 18, 2025
  13. Patrick SteinhardtFeb 19, 2025
  14. shejialuoFeb 19, 2025
  15. Patrick SteinhardtFeb 19, 2025
  16. shejialuoFeb 19, 2025
  17. Patrick SteinhardtFeb 19, 2025
  18. Patrick SteinhardtFeb 19, 2025
  19. shejialuoFeb 19, 2025
  20. Karthik NayakFeb 18, 2025
  21. Patrick SteinhardtFeb 19, 2025
  22. 08/14 refs/iterator: provide infrastructure to re-seek iteratorsPatrick Steinhardt, Feb 17, 2025
  23. 09/14 refs/iterator: implement seeking for merged iteratorsPatrick Steinhardt, Feb 17, 2025
  24. Karthik NayakFeb 19, 2025
  25. 10/14 refs/iterator: implement seeking for reftable iteratorsPatrick Steinhardt, Feb 17, 2025
  26. Karthik NayakFeb 19, 2025
  27. 11/14 refs/iterator: implement seeking for ref-cache iteratorsPatrick Steinhardt, Feb 17, 2025
  28. 12/14 refs/iterator: implement seeking for `packed-ref` iteratorsPatrick Steinhardt, Feb 17, 2025
  29. 13/14 refs/iterator: implement seeking for "files" iteratorsPatrick Steinhardt, Feb 17, 2025
  30. 14/14 refs: reuse iterators when determining refname availabilityPatrick Steinhardt, Feb 17, 2025
  31. brian m. carlsonFeb 18, 2025
  32. 00/16 refs: batch refname availability checksPatrick Steinhardt, Feb 19, 2025
  33. 01/16 object-name: introduce `repo_get_oid_with_flags()`Patrick Steinhardt, Feb 19, 2025
  34. Justin ToblerFeb 19, 2025
  35. 02/16 object-name: allow skipping ambiguity checks in `get_oid()` familyPatrick Steinhardt, Feb 19, 2025
  36. Jeff KingFeb 21, 2025
  37. Patrick SteinhardtFeb 21, 2025
  38. Jeff KingFeb 21, 2025
  39. 03/16 builtin/update-ref: skip ambiguity checks when parsing object IDsPatrick Steinhardt, Feb 19, 2025
  40. Justin ToblerFeb 19, 2025
  41. Patrick SteinhardtFeb 20, 2025
  42. 04/16 refs: introduce function to batch refname availability checksPatrick Steinhardt, Feb 19, 2025
  43. 05/16 refs/reftable: batch refname availability checksPatrick Steinhardt, Feb 19, 2025
  44. 06/16 refs/files: batch refname availability checks for normal transactionsPatrick Steinhardt, Feb 19, 2025
  45. 07/16 refs/files: batch refname availability checks for initial transactionsPatrick Steinhardt, Feb 19, 2025
  46. 08/16 refs: stop re-verifying common prefixes for availabilityPatrick Steinhardt, Feb 19, 2025
  47. 09/16 refs/iterator: separate lifecycle from iterationPatrick Steinhardt, Feb 19, 2025
  48. 11/16 refs/iterator: implement seeking for merged iteratorsPatrick Steinhardt, Feb 19, 2025
  49. shejialuoFeb 24, 2025
  50. Patrick SteinhardtFeb 25, 2025
  51. 10/16 refs/iterator: provide infrastructure to re-seek iteratorsPatrick Steinhardt, Feb 19, 2025
  52. shejialuoFeb 24, 2025
  53. Patrick SteinhardtFeb 25, 2025
  54. 12/16 refs/iterator: implement seeking for reftable iteratorsPatrick Steinhardt, Feb 19, 2025
  55. shejialuoFeb 24, 2025
  56. Patrick SteinhardtFeb 25, 2025
  57. 13/16 refs/iterator: implement seeking for ref-cache iteratorsPatrick Steinhardt, Feb 19, 2025
  58. shejialuoFeb 24, 2025
  59. Patrick SteinhardtFeb 25, 2025
  60. 14/16 refs/iterator: implement seeking for `packed-ref` iteratorsPatrick Steinhardt, Feb 19, 2025
  61. shejialuoFeb 24, 2025
  62. Patrick SteinhardtFeb 25, 2025
  63. shejialuoFeb 25, 2025
  64. 16/16 refs: reuse iterators when determining refname availabilityPatrick Steinhardt, Feb 19, 2025
  65. shejialuoFeb 24, 2025
  66. 15/16 refs/iterator: implement seeking for "files" iteratorsPatrick Steinhardt, Feb 19, 2025
  67. shejialuoFeb 24, 2025
  68. Patrick SteinhardtFeb 25, 2025
  69. 00/16 refs: batch refname availability checksPatrick Steinhardt, Feb 25, 2025
  70. 01/16 object-name: introduce `repo_get_oid_with_flags()`Patrick Steinhardt, Feb 25, 2025
  71. 02/16 object-name: allow skipping ambiguity checks in `get_oid()` familyPatrick Steinhardt, Feb 25, 2025
  72. 03/16 builtin/update-ref: skip ambiguity checks when parsing object IDsPatrick Steinhardt, Feb 25, 2025
  73. Junio C HamanoFeb 26, 2025
  74. Patrick SteinhardtFeb 27, 2025
  75. 04/16 refs: introduce function to batch refname availability checksPatrick Steinhardt, Feb 25, 2025
  76. 05/16 refs/reftable: batch refname availability checksPatrick Steinhardt, Feb 25, 2025
  77. 06/16 refs/files: batch refname availability checks for normal transactionsPatrick Steinhardt, Feb 25, 2025
  78. 07/16 refs/files: batch refname availability checks for initial transactionsPatrick Steinhardt, Feb 25, 2025
  79. 08/16 refs: stop re-verifying common prefixes for availabilityPatrick Steinhardt, Feb 25, 2025
  80. 10/16 refs/iterator: provide infrastructure to re-seek iteratorsPatrick Steinhardt, Feb 25, 2025
  81. 09/16 refs/iterator: separate lifecycle from iterationPatrick Steinhardt, Feb 25, 2025
  82. 11/16 refs/iterator: implement seeking for merged iteratorsPatrick Steinhardt, Feb 25, 2025
  83. 12/16 refs/iterator: implement seeking for reftable iteratorsPatrick Steinhardt, Feb 25, 2025
  84. 13/16 refs/iterator: implement seeking for ref-cache iteratorsPatrick Steinhardt, Feb 25, 2025
  85. 14/16 refs/iterator: implement seeking for packed-ref iteratorsPatrick Steinhardt, Feb 25, 2025
  86. 15/16 refs/iterator: implement seeking for files iteratorsPatrick Steinhardt, Feb 25, 2025
  87. 16/16 refs: reuse iterators when determining refname availabilityPatrick Steinhardt, Feb 25, 2025
  88. 00/16 refs: batch refname availability checksPatrick Steinhardt, Feb 28, 2025
  89. 01/16 object-name: introduce `repo_get_oid_with_flags()`Patrick Steinhardt, Feb 28, 2025
  90. 02/16 object-name: allow skipping ambiguity checks in `get_oid()` familyPatrick Steinhardt, Feb 28, 2025
  91. Karthik NayakMar 6, 2025
  92. 03/16 builtin/update-ref: skip ambiguity checks when parsing object IDsPatrick Steinhardt, Feb 28, 2025
  93. 04/16 refs: introduce function to batch refname availability checksPatrick Steinhardt, Feb 28, 2025
  94. Karthik NayakMar 6, 2025
  95. 05/16 refs/reftable: batch refname availability checksPatrick Steinhardt, Feb 28, 2025
  96. Karthik NayakMar 6, 2025
  97. Karthik NayakMar 6, 2025
  98. Patrick SteinhardtMar 6, 2025
  99. 06/16 refs/files: batch refname availability checks for normal transactionsPatrick Steinhardt, Feb 28, 2025
  100. 07/16 refs/files: batch refname availability checks for initial transactionsPatrick Steinhardt, Feb 28, 2025
  101. Karthik NayakMar 6, 2025
  102. 08/16 refs: stop re-verifying common prefixes for availabilityPatrick Steinhardt, Feb 28, 2025
  103. 09/16 refs/iterator: separate lifecycle from iterationPatrick Steinhardt, Feb 28, 2025
  104. 10/16 refs/iterator: provide infrastructure to re-seek iteratorsPatrick Steinhardt, Feb 28, 2025
  105. 11/16 refs/iterator: implement seeking for merged iteratorsPatrick Steinhardt, Feb 28, 2025
  106. 12/16 refs/iterator: implement seeking for reftable iteratorsPatrick Steinhardt, Feb 28, 2025
  107. Karthik NayakMar 6, 2025
  108. 13/16 refs/iterator: implement seeking for ref-cache iteratorsPatrick Steinhardt, Feb 28, 2025
  109. 14/16 refs/iterator: implement seeking for packed-ref iteratorsPatrick Steinhardt, Feb 28, 2025
  110. 15/16 refs/iterator: implement seeking for files iteratorsPatrick Steinhardt, Feb 28, 2025
  111. 16/16 refs: reuse iterators when determining refname availabilityPatrick Steinhardt, Feb 28, 2025
  112. Karthik NayakMar 6, 2025
  113. 00/16 refs: batch refname availability checksPatrick Steinhardt, Mar 6, 2025
  114. 01/16 object-name: introduce `repo_get_oid_with_flags()`Patrick Steinhardt, Mar 6, 2025
  115. 02/16 object-name: allow skipping ambiguity checks in `get_oid()` familyPatrick Steinhardt, Mar 6, 2025
  116. shejialuoMar 12, 2025
  117. 03/16 builtin/update-ref: skip ambiguity checks when parsing object IDsPatrick Steinhardt, Mar 6, 2025
  118. 04/16 refs: introduce function to batch refname availability checksPatrick Steinhardt, Mar 6, 2025
  119. shejialuoMar 12, 2025
  120. shejialuoMar 12, 2025
  121. Patrick SteinhardtMar 12, 2025
  122. 05/16 refs/reftable: batch refname availability checksPatrick Steinhardt, Mar 6, 2025
  123. shejialuoMar 12, 2025
  124. Patrick SteinhardtMar 12, 2025
  125. 06/16 refs/files: batch refname availability checks for normal transactionsPatrick Steinhardt, Mar 6, 2025
  126. shejialuoMar 12, 2025
  127. Patrick SteinhardtMar 12, 2025
  128. 07/16 refs/files: batch refname availability checks for initial transactionsPatrick Steinhardt, Mar 6, 2025
  129. shejialuoMar 12, 2025
  130. Patrick SteinhardtMar 12, 2025
  131. 08/16 refs: stop re-verifying common prefixes for availabilityPatrick Steinhardt, Mar 6, 2025
  132. shejialuoMar 12, 2025
  133. Patrick SteinhardtMar 12, 2025
  134. 11/16 refs/iterator: implement seeking for merged iteratorsPatrick Steinhardt, Mar 6, 2025
  135. 09/16 refs/iterator: separate lifecycle from iterationPatrick Steinhardt, Mar 6, 2025
  136. shejialuoMar 12, 2025
  137. Patrick SteinhardtMar 12, 2025
  138. 10/16 refs/iterator: provide infrastructure to re-seek iteratorsPatrick Steinhardt, Mar 6, 2025
  139. 12/16 refs/iterator: implement seeking for reftable iteratorsPatrick Steinhardt, Mar 6, 2025
  140. 13/16 refs/iterator: implement seeking for ref-cache iteratorsPatrick Steinhardt, Mar 6, 2025
  141. 14/16 refs/iterator: implement seeking for packed-ref iteratorsPatrick Steinhardt, Mar 6, 2025
  142. 15/16 refs/iterator: implement seeking for files iteratorsPatrick Steinhardt, Mar 6, 2025
  143. 16/16 refs: reuse iterators when determining refname availabilityPatrick Steinhardt, Mar 6, 2025
  144. Karthik NayakMar 6, 2025
  145. shejialuoMar 12, 2025
  146. 00/16 refs: batch refname availability checksPatrick Steinhardt, Mar 12, 2025
  147. 01/16 object-name: introduce `repo_get_oid_with_flags()`Patrick Steinhardt, Mar 12, 2025
  148. 02/16 object-name: allow skipping ambiguity checks in `get_oid()` familyPatrick Steinhardt, Mar 12, 2025
  149. 03/16 builtin/update-ref: skip ambiguity checks when parsing object IDsPatrick Steinhardt, Mar 12, 2025
  150. 04/16 refs: introduce function to batch refname availability checksPatrick Steinhardt, Mar 12, 2025
  151. 05/16 refs/reftable: batch refname availability checksPatrick Steinhardt, Mar 12, 2025
  152. 06/16 refs/files: batch refname availability checks for normal transactionsPatrick Steinhardt, Mar 12, 2025
  153. 07/16 refs/files: batch refname availability checks for initial transactionsPatrick Steinhardt, Mar 12, 2025
  154. 08/16 refs: stop re-verifying common prefixes for availabilityPatrick Steinhardt, Mar 12, 2025
  155. 11/16 refs/iterator: implement seeking for merged iteratorsPatrick Steinhardt, Mar 12, 2025
  156. 10/16 refs/iterator: provide infrastructure to re-seek iteratorsPatrick Steinhardt, Mar 12, 2025
  157. 09/16 refs/iterator: separate lifecycle from iterationPatrick Steinhardt, Mar 12, 2025
  158. 12/16 refs/iterator: implement seeking for reftable iteratorsPatrick Steinhardt, Mar 12, 2025
  159. 14/16 refs/iterator: implement seeking for packed-ref iteratorsPatrick Steinhardt, Mar 12, 2025
  160. Elijah NewrenApr 3, 2025
  161. brian m. carlsonApr 3, 2025
  162. shejialuoApr 4, 2025
  163. Patrick SteinhardtApr 4, 2025
  164. Patrick SteinhardtApr 4, 2025
  165. Patrick SteinhardtApr 4, 2025
  166. 13/16 refs/iterator: implement seeking for ref-cache iteratorsPatrick Steinhardt, Mar 12, 2025
  167. 15/16 refs/iterator: implement seeking for files iteratorsPatrick Steinhardt, Mar 12, 2025
  168. 16/16 refs: reuse iterators when determining refname availabilityPatrick Steinhardt, Mar 12, 2025
  169. shejialuoMar 13, 2025

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.