Skip to content

Commit ee07226

Browse files
author
Junio C Hamano
committed
Merge branch 'jc/nostat'
* jc/nostat: cache_name_compare() compares name and stage, nothing else. "assume unchanged" git: documentation. ls-files: split "show-valid-bit" into a different option. "Assume unchanged" git: --really-refresh fix. ls-files: debugging aid for CE_VALID changes. "Assume unchanged" git: do not set CE_VALID with --refresh "Assume unchanged" git
2 parents 712b1dd + 7b80be1 commit ee07226

File tree

16 files changed

+222
-27
lines changed

16 files changed

+222
-27
lines changed

Documentation/git-ls-files.txt

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@ git-ls-files - Information about files in the index/working directory
88

99
SYNOPSIS
1010
--------
11-
'git-ls-files' [-z] [-t]
11+
[verse]
12+
'git-ls-files' [-z] [-t] [-v]
1213
(--[cached|deleted|others|ignored|stage|unmerged|killed|modified])\*
1314
(-[c|d|o|i|s|u|k|m])\*
1415
[-x <pattern>|--exclude=<pattern>]
@@ -87,6 +88,10 @@ OPTIONS
8788
K:: to be killed
8889
?:: other
8990

91+
-v::
92+
Similar to `-t`, but use lowercase letters for files
93+
that are marked as 'always matching index'.
94+
9095
--full-name::
9196
When run from a subdirectory, the command usually
9297
outputs paths relative to the current directory. This

Documentation/git-update-index.txt

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,14 @@ git-update-index - Modifies the index or directory cache
88

99
SYNOPSIS
1010
--------
11+
[verse]
1112
'git-update-index'
1213
[--add] [--remove | --force-remove] [--replace]
1314
[--refresh [-q] [--unmerged] [--ignore-missing]]
1415
[--cacheinfo <mode> <object> <file>]\*
1516
[--chmod=(+|-)x]
17+
[--assume-unchanged | --no-assume-unchanged]
18+
[--really-refresh]
1619
[--info-only] [--index-info]
1720
[-z] [--stdin]
1821
[--verbose]
@@ -65,6 +68,18 @@ OPTIONS
6568
--chmod=(+|-)x::
6669
Set the execute permissions on the updated files.
6770

71+
--assume-unchanged, --no-assume-unchanged::
72+
When these flags are specified, the object name recorded
73+
for the paths are not updated. Instead, these options
74+
sets and unsets the "assume unchanged" bit for the
75+
paths. When the "assume unchanged" bit is on, git stops
76+
checking the working tree files for possible
77+
modifications, so you need to manually unset the bit to
78+
tell git when you change the working tree file. This is
79+
sometimes helpful when working with a big project on a
80+
filesystem that has very slow lstat(2) system call
81+
(e.g. cifs).
82+
6883
--info-only::
6984
Do not create objects in the object database for all
7085
<file> arguments that follow this flag; just insert
@@ -193,6 +208,37 @@ $ git ls-files -s
193208
------------
194209

195210

211+
Using "assume unchanged" bit
212+
----------------------------
213+
214+
Many operations in git depend on your filesystem to have an
215+
efficient `lstat(2)` implementation, so that `st_mtime`
216+
information for working tree files can be cheaply checked to see
217+
if the file contents have changed from the version recorded in
218+
the index file. Unfortunately, some filesystems have
219+
inefficient `lstat(2)`. If your filesystem is one of them, you
220+
can set "assume unchanged" bit to paths you have not changed to
221+
cause git not to do this check. Note that setting this bit on a
222+
path does not mean git will check the contents of the file to
223+
see if it has changed -- it makes git to omit any checking and
224+
assume it has *not* changed. When you make changes to working
225+
tree files, you have to explicitly tell git about it by dropping
226+
"assume unchanged" bit, either before or after you modify them.
227+
228+
In order to set "assume unchanged" bit, use `--assume-unchanged`
229+
option. To unset, use `--no-assume-unchanged`.
230+
231+
The command looks at `core.ignorestat` configuration variable. When
232+
this is true, paths updated with `git-update-index paths...` and
233+
paths updated with other git commands that update both index and
234+
working tree (e.g. `git-apply --index`, `git-checkout-index -u`,
235+
and `git-read-tree -u`) are automatically marked as "assume
236+
unchanged". Note that "assume unchanged" bit is *not* set if
237+
`git-update-index --refresh` finds the working tree file matches
238+
the index (use `git-update-index --really-refresh` if you want
239+
to mark them as "assume unchanged").
240+
241+
196242
Examples
197243
--------
198244
To update and refresh only the files already checked out:
@@ -201,6 +247,35 @@ To update and refresh only the files already checked out:
201247
$ git-checkout-index -n -f -a && git-update-index --ignore-missing --refresh
202248
----------------
203249

250+
On an inefficient filesystem with `core.ignorestat` set:
251+
252+
------------
253+
$ git update-index --really-refresh <1>
254+
$ git update-index --no-assume-unchanged foo.c <2>
255+
$ git diff --name-only <3>
256+
$ edit foo.c
257+
$ git diff --name-only <4>
258+
M foo.c
259+
$ git update-index foo.c <5>
260+
$ git diff --name-only <6>
261+
$ edit foo.c
262+
$ git diff --name-only <7>
263+
$ git update-index --no-assume-unchanged foo.c <8>
264+
$ git diff --name-only <9>
265+
M foo.c
266+
267+
<1> forces lstat(2) to set "assume unchanged" bits for paths
268+
that match index.
269+
<2> mark the path to be edited.
270+
<3> this does lstat(2) and finds index matches the path.
271+
<4> this does lstat(2) and finds index does not match the path.
272+
<5> registering the new version to index sets "assume unchanged" bit.
273+
<6> and it is assumed unchanged.
274+
<7> even after you edit it.
275+
<8> you can tell about the change after the fact.
276+
<9> now it checks with lstat(2) and finds it has been changed.
277+
------------
278+
204279

205280
Configuration
206281
-------------
@@ -213,6 +288,9 @@ in the index and the file mode on the filesystem if they differ only on
213288
executable bit. On such an unfortunate filesystem, you may
214289
need to use `git-update-index --chmod=`.
215290

291+
The command looks at `core.ignorestat` configuration variable. See
292+
'Using "assume unchanged" bit' section above.
293+
216294

217295
See Also
218296
--------

apply.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1317,7 +1317,7 @@ static int check_patch(struct patch *patch)
13171317
return -1;
13181318
}
13191319

1320-
changed = ce_match_stat(active_cache[pos], &st);
1320+
changed = ce_match_stat(active_cache[pos], &st, 1);
13211321
if (changed)
13221322
return error("%s: does not match index",
13231323
old_name);

cache.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@ struct cache_entry {
9191
#define CE_NAMEMASK (0x0fff)
9292
#define CE_STAGEMASK (0x3000)
9393
#define CE_UPDATE (0x4000)
94+
#define CE_VALID (0x8000)
9495
#define CE_STAGESHIFT 12
9596

9697
#define create_ce_flags(len, stage) htons((len) | ((stage) << CE_STAGESHIFT))
@@ -144,8 +145,8 @@ extern int add_cache_entry(struct cache_entry *ce, int option);
144145
extern int remove_cache_entry_at(int pos);
145146
extern int remove_file_from_cache(const char *path);
146147
extern int ce_same_name(struct cache_entry *a, struct cache_entry *b);
147-
extern int ce_match_stat(struct cache_entry *ce, struct stat *st);
148-
extern int ce_modified(struct cache_entry *ce, struct stat *st);
148+
extern int ce_match_stat(struct cache_entry *ce, struct stat *st, int);
149+
extern int ce_modified(struct cache_entry *ce, struct stat *st, int);
149150
extern int ce_path_match(const struct cache_entry *ce, const char **pathspec);
150151
extern int index_fd(unsigned char *sha1, int fd, struct stat *st, int write_object, const char *type);
151152
extern int index_pipe(unsigned char *sha1, int fd, const char *type, int write_object);
@@ -161,6 +162,7 @@ extern int commit_index_file(struct cache_file *);
161162
extern void rollback_index_file(struct cache_file *);
162163

163164
extern int trust_executable_bit;
165+
extern int assume_unchanged;
164166
extern int only_use_symrefs;
165167
extern int diff_rename_limit_default;
166168
extern int shared_repository;

checkout-index.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,7 @@ int main(int argc, char **argv)
116116
int all = 0;
117117

118118
prefix = setup_git_directory();
119+
git_config(git_default_config);
119120
prefix_length = prefix ? strlen(prefix) : 0;
120121

121122
if (read_cache() < 0) {

config.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,11 @@ int git_default_config(const char *var, const char *value)
222222
return 0;
223223
}
224224

225+
if (!strcmp(var, "core.ignorestat")) {
226+
assume_unchanged = git_config_bool(var, value);
227+
return 0;
228+
}
229+
225230
if (!strcmp(var, "core.symrefsonly")) {
226231
only_use_symrefs = git_config_bool(var, value);
227232
return 0;

diff-files.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -193,7 +193,7 @@ int main(int argc, const char **argv)
193193
show_file('-', ce);
194194
continue;
195195
}
196-
changed = ce_match_stat(ce, &st);
196+
changed = ce_match_stat(ce, &st, 0);
197197
if (!changed && !diff_options.find_copies_harder)
198198
continue;
199199
oldmode = ntohl(ce->ce_mode);

diff-index.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ static int get_stat_data(struct cache_entry *ce,
3333
}
3434
return -1;
3535
}
36-
changed = ce_match_stat(ce, &st);
36+
changed = ce_match_stat(ce, &st, 0);
3737
if (changed) {
3838
mode = create_ce_mode(st.st_mode);
3939
if (!trust_executable_bit &&

diff.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -311,7 +311,7 @@ static int work_tree_matches(const char *name, const unsigned char *sha1)
311311
ce = active_cache[pos];
312312
if ((lstat(name, &st) < 0) ||
313313
!S_ISREG(st.st_mode) || /* careful! */
314-
ce_match_stat(ce, &st) ||
314+
ce_match_stat(ce, &st, 0) ||
315315
memcmp(sha1, ce->sha1, 20))
316316
return 0;
317317
/* we return 1 only when we can stat, it is a regular file,

entry.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,7 @@ int checkout_entry(struct cache_entry *ce, struct checkout *state)
123123
strcpy(path + len, ce->name);
124124

125125
if (!lstat(path, &st)) {
126-
unsigned changed = ce_match_stat(ce, &st);
126+
unsigned changed = ce_match_stat(ce, &st, 1);
127127
if (!changed)
128128
return 0;
129129
if (!state->force) {

0 commit comments

Comments
 (0)