Skip to content

Commit 674ea47

Browse files
committed
Merge branch 'en/sparse-cone-becomes-default' into seen
source: <pull.1148.v2.git.1647054681.gitgitgadget@gmail.com> * en/sparse-cone-becomes-default: Documentation: some sparsity wording clarifications git-sparse-checkout.txt: mark non-cone mode as deprecated git-sparse-checkout.txt: flesh out non-cone mode pattern discussion a bit git-sparse-checkout.txt: add a new EXAMPLES section git-sparse-checkout.txt: shuffle some sections and mark as internal git-sparse-checkout.txt: update docs for deprecation of 'init' git-sparse-checkout.txt: wording updates for the cone mode default sparse-checkout: make --cone the default tests: stop assuming --no-cone is the default mode for sparse-checkout
2 parents cf78dc5 + 76fc118 commit 674ea47

9 files changed

+207
-86
lines changed

Documentation/git-read-tree.txt

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -375,10 +375,11 @@ have finished your work-in-progress), attempt the merge again.
375375
SPARSE CHECKOUT
376376
---------------
377377

378-
Note: The `update-index` and `read-tree` primitives for supporting the
379-
skip-worktree bit predated the introduction of
380-
linkgit:git-sparse-checkout[1]. Users are encouraged to use
381-
`sparse-checkout` in preference to these low-level primitives.
378+
Note: The skip-worktree capabilities in linkgit:git-update-index[1]
379+
and `read-tree` predated the introduction of
380+
linkgit:git-sparse-checkout[1]. Users are encouraged to use the
381+
`sparse-checkout` command in preference to these plumbing commands for
382+
sparse-checkout/skip-worktree related needs.
382383

383384
"Sparse checkout" allows populating the working directory sparsely.
384385
It uses the skip-worktree bit (see linkgit:git-update-index[1]) to

Documentation/git-sparse-checkout.txt

Lines changed: 184 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -15,15 +15,15 @@ SYNOPSIS
1515
DESCRIPTION
1616
-----------
1717

18-
This command is used to create sparse checkouts, which means that it
19-
changes the working tree from having all tracked files present, to only
20-
have a subset of them. It can also switch which subset of files are
21-
present, or undo and go back to having all tracked files present in the
22-
working copy.
18+
This command is used to create sparse checkouts, which change the
19+
working tree from having all tracked files present to only having a
20+
subset of those files. It can also switch which subset of files are
21+
present, or undo and go back to having all tracked files present in
22+
the working copy.
2323

2424
The subset of files is chosen by providing a list of directories in
25-
cone mode (which is recommended), or by providing a list of patterns
26-
in non-cone mode.
25+
cone mode (the default), or by providing a list of patterns in
26+
non-cone mode.
2727

2828
When in a sparse-checkout, other Git commands behave a bit differently.
2929
For example, switching branches will not update paths outside the
@@ -44,9 +44,9 @@ COMMANDS
4444
Enable the necessary sparse-checkout config settings
4545
(`core.sparseCheckout`, `core.sparseCheckoutCone`, and
4646
`index.sparse`) if they are not already set to the desired values,
47-
and write a set of patterns to the sparse-checkout file from the
48-
list of arguments following the 'set' subcommand. Update the
49-
working directory to match the new patterns.
47+
populate the sparse-checkout file from the list of arguments
48+
following the 'set' subcommand, and update the working directory to
49+
match.
5050
+
5151
To ensure that adjusting the sparse-checkout settings within a worktree
5252
does not alter the sparse-checkout settings in other worktrees, the 'set'
@@ -60,22 +60,24 @@ When the `--stdin` option is provided, the directories or patterns are
6060
read from standard in as a newline-delimited list instead of from the
6161
arguments.
6262
+
63-
When `--cone` is passed or `core.sparseCheckoutCone` is enabled, the
64-
input list is considered a list of directories. This allows for
65-
better performance with a limited set of patterns (see 'CONE PATTERN
66-
SET' below). The input format matches the output of `git ls-tree
67-
--name-only`. This includes interpreting pathnames that begin with a
68-
double quote (") as C-style quoted strings. Note that the set command
69-
will write patterns to the sparse-checkout file to include all files
70-
contained in those directories (recursively) as well as files that are
71-
siblings of ancestor directories. This may become the default in the
72-
future; --no-cone can be passed to request non-cone mode.
63+
By default, the input list is considered a list of directories, matching
64+
the output of `git ls-tree -d --name-only`. This includes interpreting
65+
pathnames that begin with a double quote (") as C-style quoted strings.
66+
Note that all files under the specified directories (at any depth) will
67+
be included in the sparse checkout, as well as files that are siblings
68+
of either the given directory or any of its ancestors (see 'CONE PATTERN
69+
SET' below for more details). In the past, this was not the default,
70+
and `--cone` needed to be specified or `core.sparseCheckoutCone` needed
71+
to be enabled.
7372
+
74-
When `--no-cone` is passed or `core.sparseCheckoutCone` is not enabled,
75-
the input list is considered a list of patterns. This mode is harder
76-
to use and less performant, and is thus not recommended. See the
77-
"Sparse Checkout" section of linkgit:git-read-tree[1] and the "Pattern
78-
Set" sections below for more details.
73+
When `--no-cone` is passed, the input list is considered a list of
74+
patterns. This mode is harder to use, and unless you can keep the
75+
number of patterns small, its design also scales poorly. It used to be
76+
the default mode, but we do not recommend using it. It does not work
77+
with the `--sparse-index` option, and will likely be incompatible with
78+
other new features as they are added. See the "Non-cone Problems"
79+
section below and the "Sparse Checkout" section of
80+
linkgit:git-read-tree[1] for more details.
7981
+
8082
Use the `--[no-]sparse-index` option to use a sparse index (the
8183
default is to not use it). A sparse index reduces the size of the
@@ -137,8 +139,45 @@ paths to pass to a subsequent 'set' or 'add' command. However,
137139
the disable command, so the easy restore of calling a plain `init`
138140
decreased in utility.
139141

140-
SPARSE CHECKOUT
141-
---------------
142+
EXAMPLES
143+
--------
144+
`git sparse-checkout set MY/DIR1 SUB/DIR2`::
145+
146+
Change to a sparse checkout with all files (at any depth) under
147+
MY/DIR1/ and SUB/DIR2/ present in the working copy (plus all
148+
files immediately under MY/ and SUB/ and the toplevel
149+
directory). If already in a sparse checkout, change which files
150+
are present in the working copy to this new selection. Note
151+
that this command will also delete all ignored files in any
152+
directory that no longer has either tracked or
153+
non-ignored-untracked files present.
154+
155+
`git sparse-checkout disable`::
156+
157+
Repopulate the working directory with all files, disabling sparse
158+
checkouts.
159+
160+
`git sparse-checkout add SOME/DIR/ECTORY`::
161+
162+
Add all files under SOME/DIR/ECTORY/ (at any depth) to the
163+
sparse checkout, as well as all files immediately under
164+
SOME/DIR/ and immediately under SOME/. Must already be in a
165+
sparse checkout before using this command.
166+
167+
`git sparse-checkout reapply`::
168+
169+
It is possible for commands to update the working tree in a
170+
way that does not respect the selected sparsity directories.
171+
This can come from tools external to Git writing files, or
172+
even affect Git commands because of either special cases (such
173+
as hitting conflicts when merging/rebasing), or because some
174+
commands didn't fully support sparse checkouts (e.g. the old
175+
`recursive` merge backend had only limited support). This
176+
command reapplies the existing sparse directory specifications
177+
to make the working directory match.
178+
179+
INTERNALS -- SPARSE CHECKOUT
180+
----------------------------
142181

143182
"Sparse checkout" allows populating the working directory sparsely. It
144183
uses the skip-worktree bit (see linkgit:git-update-index[1]) to tell Git
@@ -155,31 +194,84 @@ directory, it updates the skip-worktree bits in the index based
155194
on this file. The files matching the patterns in the file will
156195
appear in the working directory, and the rest will not.
157196

158-
To enable the sparse-checkout feature, run `git sparse-checkout set` to
159-
set the patterns you want to use.
160-
161-
To repopulate the working directory with all files, use the
162-
`git sparse-checkout disable` command.
163-
164-
165-
FULL PATTERN SET
166-
----------------
167-
168-
By default, the sparse-checkout file uses the same syntax as `.gitignore`
169-
files.
170-
171-
While `$GIT_DIR/info/sparse-checkout` is usually used to specify what
172-
files are included, you can also specify what files are _not_ included,
173-
using negative patterns. For example, to remove the file `unwanted`:
174-
175-
----------------
176-
/*
177-
!unwanted
178-
----------------
179-
180-
181-
CONE PATTERN SET
182-
----------------
197+
INTERNALS -- NON-CONE PROBLEMS
198+
------------------------------
199+
200+
The `$GIT_DIR/info/sparse-checkout` file populated by the `set` and
201+
`add` subcommands is defined to be a bunch of patterns (one per line)
202+
using the same syntax as `.gitignore` files. In cone mode, these
203+
patterns are restricted to matching directories (and users only ever
204+
need supply or see directory names), while in non-cone mode any
205+
gitignore-style pattern is permitted. Using the full gitignore-style
206+
patterns in non-cone mode has a number of shortcomings:
207+
208+
* Fundamentally, it makes various worktree-updating processes (pull,
209+
merge, rebase, switch, reset, checkout, etc.) require O(N*M) pattern
210+
matches, where N is the number of patterns and M is the number of
211+
paths in the index. This scales poorly.
212+
213+
* Avoiding the scaling issue has to be done via limiting the number
214+
of patterns via specifying leading directory name or glob.
215+
216+
* Passing globs on the command line is error-prone as users may
217+
forget to quote the glob, causing the shell to expand it into all
218+
matching files and pass them all individually along to
219+
sparse-checkout set/add. This both exacerbates the scaling
220+
problem, and hardcodes the list of selected files to those which
221+
were present at the time the initial set/add subcommand was run
222+
(and thus ignoring other files matching the same glob which come
223+
into the working tree after switching branches or pulling down
224+
updates).
225+
226+
* It uses "ignore"/"exclude" syntax for selecting what to "include",
227+
which periodically causes confusion.
228+
229+
* It introduces inconsistencies in the Git command line, since other
230+
commands use pathspecs, but sparse-checkout (in non-cone mode) uses
231+
gitignore patterns.
232+
233+
* It has edge cases where the "right" behavior is unclear. Two examples:
234+
235+
First, two users are in a subdirectory, and the first runs
236+
git sparse-checkout set '/toplevel-dir/*.c'
237+
while the second runs
238+
git sparse-checkout set relative-dir
239+
Should those arguments be transliterated into
240+
current/subdirectory/toplevel-dir/*.c
241+
and
242+
current/subdirectory/relative-dir
243+
before inserting into the sparse-checkout file? The user who typed
244+
the first command is probably aware that arguments to set/add are
245+
supposed to be patterns in non-cone mode, and probably would not be
246+
happy with such a transliteration. However, many gitignore-style
247+
patterns are just paths, which might be what the user who typed the
248+
second command was thinking, and they'd be upset if their argument
249+
wasn't transliterated.
250+
251+
Second, what should bash-completion complete on for set/add commands
252+
for non-cone users? If it suggests paths, is it exacerbating the
253+
problem above? Also, if it suggests paths, what if the user has a
254+
file or directory that begins with either a '!' or '#' or has a '*',
255+
'\', '?', '[', or ']' in its name? And if it suggests paths, will
256+
it complete "/pro" to "/proc" (in the root filesytem) rather than to
257+
"/progress.txt" in the current directory? (Note that users are
258+
likely to want to start paths with a leading '/' in non-cone mode,
259+
for the same reason that .gitignore files often have one.)
260+
Completing on files or directories might give nasty surprises in
261+
all these cases.
262+
263+
* The excessive flexibility made other extensions essentially
264+
impractical. `--sparse-index` may not have been feasible in
265+
non-cone mode, but even if it was, it would have been far more work
266+
to implement and may have been too slow in practice. Some ideas for
267+
adding coupling between partial clones and sparse checkouts are only
268+
practical with a more restricted set of paths.
269+
270+
For all these reasons, non-cone mode is deprecated. Please switch to
271+
using cone mode.
272+
273+
INTERNALS -- CONE PATTERN SET
274+
-----------------------------
183275

184276
The full pattern set allows for arbitrary pattern matches and complicated
185277
inclusion/exclusion rules. These can result in O(N*M) pattern matches when
@@ -197,9 +289,9 @@ In addition to the above two patterns, we also expect that all files in the
197289
root directory are included. If a recursive pattern is added, then all
198290
leading directories are added as parent patterns.
199291

200-
By default, when running `git sparse-checkout init`, the root directory is
201-
added as a parent pattern. At this point, the sparse-checkout file contains
202-
the following patterns:
292+
By default, when running `git sparse-checkout set` with no directories
293+
specified, the root directory is added as a parent pattern. At this
294+
point, the sparse-checkout file contains the following patterns:
203295

204296
----------------
205297
/*
@@ -209,10 +301,9 @@ the following patterns:
209301
This says "include everything in root, but nothing two levels below root."
210302

211303
When in cone mode, the `git sparse-checkout set` subcommand takes a list of
212-
directories instead of a list of sparse-checkout patterns. In this mode,
213-
the command `git sparse-checkout set A/B/C` sets the directory `A/B/C` as
214-
a recursive pattern, the directories `A` and `A/B` are added as parent
215-
patterns. The resulting sparse-checkout file is now
304+
directories. In this mode, the command `git sparse-checkout set A/B/C` sets
305+
the directory `A/B/C` as a recursive pattern, the directories `A` and `A/B`
306+
are added as parent patterns. The resulting sparse-checkout file is now
216307

217308
----------------
218309
/*
@@ -227,10 +318,11 @@ patterns. The resulting sparse-checkout file is now
227318
Here, order matters, so the negative patterns are overridden by the positive
228319
patterns that appear lower in the file.
229320

230-
If `core.sparseCheckoutCone=true`, then Git will parse the sparse-checkout file
231-
expecting patterns of these types. Git will warn if the patterns do not match.
232-
If the patterns do match the expected format, then Git will use faster hash-
233-
based algorithms to compute inclusion in the sparse-checkout.
321+
If `core.sparseCheckoutCone=true` (set by default or with an explicit
322+
`--cone`), then Git will parse the sparse-checkout file expecting
323+
patterns of these types. Git will warn if the patterns do not match. If
324+
the patterns do match the expected format, then Git will use faster
325+
hash-based algorithms to compute inclusion in the sparse-checkout.
234326

235327
In the cone mode case, the `git sparse-checkout list` subcommand will list the
236328
directories that define the recursive patterns. For the example sparse-checkout
@@ -257,8 +349,35 @@ use `git add` and `git commit` to store them, then remove any remaining files
257349
manually to ensure Git can behave optimally.
258350

259351

260-
SUBMODULES
261-
----------
352+
INTERNALS -- FULL PATTERN SET
353+
-----------------------------
354+
355+
As noted above, the sparse-checkout file uses the same syntax as
356+
`.gitignore` files; see linkgit:gitignore[5] for details. Here,
357+
though, the patterns are usually being used to select which files to
358+
include rather than which files to exclude. (However, it can get a
359+
bit confusing since gitignore-style patterns have negations defined by
360+
patterns which begin with a '!', so you can also select files to _not_
361+
include.)
362+
363+
For example, to select everything, and then to remove the file
364+
`unwanted` (so that every file will appear in your working tree except
365+
the file named `unwanted`):
366+
367+
git sparse-checkout set --no-cone '/*' '!unwanted'
368+
369+
These patterns are just placed into the
370+
`$GIT_DIR/info/sparse-checkout` as-is, so the contents of that file
371+
at this point would be
372+
373+
----------------
374+
/*
375+
!unwanted
376+
----------------
377+
378+
379+
INTERNALS -- SUBMODULES
380+
-----------------------
262381

263382
If your repository contains one or more submodules, then submodules
264383
are populated based on interactions with the `git submodule` command.

builtin/sparse-checkout.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -395,7 +395,7 @@ static int update_modes(int *cone_mode, int *sparse_index)
395395

396396
/* Set cone/non-cone mode appropriately */
397397
core_apply_sparse_checkout = 1;
398-
if (*cone_mode == 1) {
398+
if (*cone_mode) { /* also handles "not specified" (value of -1) */
399399
mode = MODE_CONE_PATTERNS;
400400
core_sparse_checkout_cone = 1;
401401
} else {

0 commit comments

Comments
 (0)