@@ -71,10 +71,9 @@ and `--cone` needed to be specified or `core.sparseCheckoutCone` needed
71
71
to be enabled.
72
72
+
73
73
When `--no-cone` is passed, the input list is considered a list of
74
- patterns. This mode is harder to use and less performant, and is thus
75
- not recommended. See the "Sparse Checkout" section of
76
- linkgit:git-read-tree[1] and the "Internals...Pattern Set" sections
77
- below for more details.
74
+ patterns. This mode has a number of drawbacks, including not working
75
+ with some options like `--sparse-index`. As explained in the
76
+ "Non-cone Problems" section below, we do not recommend using it.
78
77
+
79
78
Use the `--[no-]sparse-index` option to use a sparse index (the
80
79
default is to not use it). A sparse index reduces the size of the
@@ -191,6 +190,97 @@ directory, it updates the skip-worktree bits in the index based
191
190
on this file. The files matching the patterns in the file will
192
191
appear in the working directory, and the rest will not.
193
192
193
+ INTERNALS -- NON-CONE PROBLEMS
194
+ ------------------------------
195
+
196
+ The `$GIT_DIR/info/sparse-checkout` file populated by the `set` and
197
+ `add` subcommands is defined to be a bunch of patterns (one per line)
198
+ using the same syntax as `.gitignore` files. In cone mode, these
199
+ patterns are restricted to matching directories (and users only ever
200
+ need supply or see directory names), while in non-cone mode any
201
+ gitignore-style pattern is permitted. Using the full gitignore-style
202
+ patterns in non-cone mode has a number of shortcomings:
203
+
204
+ * Fundamentally, it makes various worktree-updating processes (pull,
205
+ merge, rebase, switch, reset, checkout, etc.) require O(N*M) pattern
206
+ matches, where N is the number of patterns and M is the number of
207
+ paths in the index. This scales poorly.
208
+
209
+ * Avoiding the scaling issue has to be done via limiting the number
210
+ of patterns via specifying leading directory name or glob.
211
+
212
+ * Passing globs on the command line is error-prone as users may
213
+ forget to quote the glob, causing the shell to expand it into all
214
+ matching files and pass them all individually along to
215
+ sparse-checkout set/add. While this could also be a problem with
216
+ e.g. "git grep -- *.c", mistakes with grep/log/status appear in
217
+ the immediate output. With sparse-checkout, the mistake gets
218
+ recorded at the time the sparse-checkout command is run and might
219
+ not be problematic until the user later switches branches or rebases
220
+ or merges, thus putting a delay between the user's error and when
221
+ they have a chance to catch/notice it.
222
+
223
+ * Related to the previous item, sparse-checkout has an 'add'
224
+ subcommand but no 'remove' subcommand. Even if a 'remove'
225
+ subcommand were added, undoing an accidental unquoted glob runs
226
+ the risk of "removing too much", as it may remove entries that had
227
+ been included before the accidental add.
228
+
229
+ * Non-cone mode uses gitignore-style patterns to select what to
230
+ *include* (with the exception of negated patterns), while
231
+ .gitignore files use gitignore-style patterns to select what to
232
+ *exclude* (with the exception of negated patterns). The
233
+ documentation on gitignore-style patterns usually does not talk in
234
+ terms of matching or non-matching, but on what the user wants to
235
+ "exclude". This can cause confusion for users trying to learn how
236
+ to specify sparse-checkout patterns to get their desired behavior.
237
+
238
+ * Every other git subcommand that wants to provide "special path
239
+ pattern matching" of some sort uses pathspecs, but non-cone mode
240
+ for sparse-checkout uses gitignore patterns, which feels
241
+ inconsistent.
242
+
243
+ * It has edge cases where the "right" behavior is unclear. Two examples:
244
+
245
+ First, two users are in a subdirectory, and the first runs
246
+ git sparse-checkout set '/toplevel-dir/*.c'
247
+ while the second runs
248
+ git sparse-checkout set relative-dir
249
+ Should those arguments be transliterated into
250
+ current/subdirectory/toplevel-dir/*.c
251
+ and
252
+ current/subdirectory/relative-dir
253
+ before inserting into the sparse-checkout file? The user who typed
254
+ the first command is probably aware that arguments to set/add are
255
+ supposed to be patterns in non-cone mode, and probably would not be
256
+ happy with such a transliteration. However, many gitignore-style
257
+ patterns are just paths, which might be what the user who typed the
258
+ second command was thinking, and they'd be upset if their argument
259
+ wasn't transliterated.
260
+
261
+ Second, what should bash-completion complete on for set/add commands
262
+ for non-cone users? If it suggests paths, is it exacerbating the
263
+ problem above? Also, if it suggests paths, what if the user has a
264
+ file or directory that begins with either a '!' or '#' or has a '*',
265
+ '\', '?', '[', or ']' in its name? And if it suggests paths, will
266
+ it complete "/pro" to "/proc" (in the root filesytem) rather than to
267
+ "/progress.txt" in the current directory? (Note that users are
268
+ likely to want to start paths with a leading '/' in non-cone mode,
269
+ for the same reason that .gitignore files often have one.)
270
+ Completing on files or directories might give nasty surprises in
271
+ all these cases.
272
+
273
+ * The excessive flexibility made other extensions essentially
274
+ impractical. `--sparse-index` is likely impossible in non-cone
275
+ mode; even if it is somehow feasible, it would have been far more
276
+ work to implement and may have been too slow in practice. Some
277
+ ideas for adding coupling between partial clones and sparse
278
+ checkouts are only practical with a more restricted set of paths
279
+ as well.
280
+
281
+ For all these reasons, non-cone mode is deprecated. Please switch to
282
+ using cone mode.
283
+
194
284
195
285
INTERNALS -- CONE MODE HANDLING
196
286
-------------------------------
0 commit comments