diff --git a/Documentation/scalar.adoc b/Documentation/scalar.adoc index f81b2832f8dfeb..f1d776ae0bf951 100644 --- a/Documentation/scalar.adoc +++ b/Documentation/scalar.adoc @@ -197,6 +197,164 @@ delete :: This subcommand lets you delete an existing Scalar enlistment from your local file system, unregistering the repository. +REQUIRED AND RECOMMENDED CONFIG +------------------------------- + +As part of both `scalar clone` and `scalar register`, certain Git config +values are set to optimize for large repositories or cross-platform support. +These options are updated in new Git versions according to the best known +advice for large repositories, and users can get the latest recommendations +by running `scalar reconfigure [--all]`. + +This section lists justifications for the config values that are set in the +latest version. + +am.keepCR=true:: + This setting is important for cross-platform development across Windows + and non-Windows platforms and keeping carriage return (`\r`) characters + in certain workflows. + +commitGraph.changedPaths=true:: + This setting helps the background maintenance steps that compute the + serialized commit-graph to also store changed-path Bloom filters. This + accelerates file history commands and allows users to automatically + benefit without running a foreground command. + +commitGraph.generationVersion=1:: + While the preferred version is 2 for performance reasons, existing users + that had version 1 by default will need special care in upgrading to + version 2. This is likely to change in the future as the upgrade story + solidifies. + +core.autoCRLF=false:: + This removes the transformation of worktree files to add CRLF line + endings when only LF line endings exist. This is removed for performance + reasons. Repositories that use tools that care about CRLF line endings + should commit the necessary files with those line endings instead. + +core.logAllRefUpdates=true:: + This enables the reflog on all branches. While this is a performance + cost for large repositories, it is frequently an important data source + for users to get out of bad situations or to seek support from experts. + +core.safeCRLF=false:: + Similar to `core.autoCRLF=false`, this disables checks around whether + the CRLF conversion is reversible. This is a performance improvement, + but can be dangerous if `core.autoCRLF` is reenabled by the user. + +credential.https://dev.azure.com.useHttpPath=true:: + This setting enables the `credential.useHttpPath` feature only for web + URLs for Azure DevOps. This is important for users interacting with that + service using multiple organizations and thus multiple credential + tokens. + +feature.experimental=false:: + This disables the "experimental" optimizations grouped under this + feature config. The expectation is that all valuable optimizations are + also set explicitly by Scalar config, and any differences are + intentional. Notable differences include several bitmap-related config + options which are disabled for client-focused Scalar repos. + +feature.manyFiles=false:: + This disables the "many files" optimizations grouped under this feature + config. The expectation is that all valuable optimizations are also set + explicitly by Scalar config, and any differences are intentional. + +fetch.showForcedUpdates=false:: + This disables the check at the end of `git fetch` that notifies the user + if the ref update was a forced update (one where the previous position + is not reachable from the latest position). This check can be very + expensive in large repositories, so is disabled and replaced with an + advice message. Set `advice.fetchShowForcedUpdates=false` to disable + this advice message. + +fetch.unpackLimit=1:: + This setting prevents Git from unpacking packfiles into loose objects + as they are downloaded from the server. The default limit of 100 was + intended as a way to prevent performance issues from too many packfiles, + but Scalar uses background maintenance to group packfiles and cover them + with a multi-pack-index, removing this issue. + +fetch.writeCommitGraph=false:: + This config setting was created to help users automatically update their + commit-graph files as they perform fetches. However, this takes time + from foreground fetches and pulls and Scalar uses background maintenance + for this function instead. + +gc.auto=0:: + This disables automatic garbage collection, since Scalar uses background + maintenance to keep the repository data in good shape. + +gui.GCWarning=false:: + Since Scalar disables garbage collection by setting `gc.auto=0`, the + `git-gui` tool may start to warn about this setting. Disable this + warning as Scalar's background maintenance configuration makes the + warning irrelevant. + +index.skipHash=true:: + Disable computing the hash of the index contents as it is being written. + This assists with performance, especially for large index files. + +index.threads=true:: + This tells Git to automatically detect how many threads it should use + when reading the index due to the default value of `core.preloadIndex`, + which enables parallel index reads. + +index.version=4:: + This index version adds compression to the path names, reducing the size + of the index in a significant way for large repos. This is an important + performance boost. + +merge.renames=true:: + When computing merges in large repos, it is particularly important to + detect renames to maximize the potential for a result that will validate + correctly. Users performing merges locally are more likely to be doing + so because a server-side merge (via pull request or similar) resulted in + conflicts. While this is the default setting, it is set specifically to + override a potential change to `diff.renames` which a user may set for + performance reasons. + +merge.stat=false:: + This disables a diff output after computing a merge. This improves + performance of `git merge` for large repos while reducing noisy output. + +pack.useBitmaps=false:: + This disables the use of `.bitmap` files attached to packfiles. Bitmap + files are optimized for server-side use, not client-side use. Scalar + disables this to avoid some performance issues that can occur if a user + accidentally creates `.bitmap` files. + +pack.usePathWalk=true:: + This enables the `--path-walk` option to `git pack-objects` by default. + This can accelerate the computation and compression of packfiles created + by `git push` and other repack operations. + +receive.autoGC=false:: + Similar to `gc.auto`, this setting is disabled in preference of + background maintenance. + +status.aheadBehind=false:: + This disables the ahead/behind calculation that would normally happen + during a `git status` command. This information is frequently ignored by + users but can be expensive to calculate in large repos that receive + thousands of commits per day. The calculation is replaced with an advice + message that can be disabled by disabling the `advice.statusAheadBehind` + config. + +The following settings are different based on which platform is in use: + +core.untrackedCache=(true|false):: + The untracked cache feature is important for performance benefits on + large repositories, but has demonstrated some bugs on Windows + filesystems. Thus, this is set for other platforms but disabled on + Windows. + +http.sslBackend=schannel:: + On Windows, the `openssl` backend has some issues with certain types of + remote providers and certificate types. Override the default setting to + avoid these common problems. + + SEE ALSO -------- linkgit:git-clone[1], linkgit:git-maintenance[1]. diff --git a/scalar.c b/scalar.c index f7543116272b77..1fbd02e03acb45 100644 --- a/scalar.c +++ b/scalar.c @@ -19,6 +19,7 @@ #include "help.h" #include "setup.h" #include "trace2.h" +#include "path.h" static void setup_enlistment_directory(int argc, const char **argv, const char * const *usagestr, @@ -95,6 +96,16 @@ struct scalar_config { int overwrite_on_reconfigure; }; +static int set_config_with_comment(const char *key, const char *value) +{ + char *file = repo_git_path(the_repository, "config"); + int res = repo_config_set_multivar_in_file_gently(the_repository, file, + key, value, NULL, + " # set by scalar", 0); + free(file); + return res; +} + static int set_scalar_config(const struct scalar_config *config, int reconfigure) { char *value = NULL; @@ -103,7 +114,7 @@ static int set_scalar_config(const struct scalar_config *config, int reconfigure if ((reconfigure && config->overwrite_on_reconfigure) || repo_config_get_string(the_repository, config->key, &value)) { trace2_data_string("scalar", the_repository, config->key, "created"); - res = repo_config_set_gently(the_repository, config->key, config->value); + res = set_config_with_comment(config->key, config->value); } else { trace2_data_string("scalar", the_repository, config->key, "exists"); res = 0; @@ -122,13 +133,33 @@ static int have_fsmonitor_support(void) static int set_recommended_config(int reconfigure) { struct scalar_config config[] = { - /* Required */ - { "am.keepCR", "true", 1 }, - { "core.FSCache", "true", 1 }, - { "core.multiPackIndex", "true", 1 }, - { "core.preloadIndex", "true", 1 }, + { "am.keepCR", "true" }, + { "commitGraph.changedPaths", "true" }, + { "commitGraph.generationVersion", "1" }, + { "core.autoCRLF", "false" }, + { "core.logAllRefUpdates", "true" }, + { "core.safeCRLF", "false" }, + { "credential.https://dev.azure.com.useHttpPath", "true" }, + { "feature.experimental", "false" }, + { "feature.manyFiles", "false" }, + { "fetch.showForcedUpdates", "false" }, + { "fetch.unpackLimit", "1" }, + { "fetch.writeCommitGraph", "false" }, + { "gc.auto", "0" }, + { "gui.GCWarning", "false" }, + { "index.skipHash", "true", 1 /* Fix previous setting. */ }, + { "index.threads", "true"}, + { "index.version", "4" }, + { "merge.renames", "true" }, + { "merge.stat", "false" }, + { "pack.useBitmaps", "false" }, + { "pack.usePathWalk", "true" }, + { "receive.autoGC", "false" }, + { "status.aheadBehind", "false" }, + + /* platform-specific */ #ifndef WIN32 - { "core.untrackedCache", "true", 1 }, + { "core.untrackedCache", "true" }, #else /* * Unfortunately, Scalar's Functional Tests demonstrated @@ -142,36 +173,11 @@ static int set_recommended_config(int reconfigure) * Therefore, with a sad heart, we disable this very useful * feature on Windows. */ - { "core.untrackedCache", "false", 1 }, -#endif - { "core.logAllRefUpdates", "true", 1 }, - { "credential.https://dev.azure.com.useHttpPath", "true", 1 }, - { "credential.validate", "false", 1 }, /* GCM4W-only */ - { "gc.auto", "0", 1 }, - { "gui.GCWarning", "false", 1 }, - { "index.skipHash", "false", 1 }, - { "index.threads", "true", 1 }, - { "index.version", "4", 1 }, - { "merge.stat", "false", 1 }, - { "merge.renames", "true", 1 }, - { "pack.useBitmaps", "false", 1 }, - { "pack.useSparse", "true", 1 }, - { "receive.autoGC", "false", 1 }, - { "feature.manyFiles", "false", 1 }, - { "feature.experimental", "false", 1 }, - { "fetch.unpackLimit", "1", 1 }, - { "fetch.writeCommitGraph", "false", 1 }, -#ifdef WIN32 - { "http.sslBackend", "schannel", 1 }, + { "core.untrackedCache", "false" }, + + /* Other Windows-specific required settings: */ + { "http.sslBackend", "schannel" }, #endif - /* Optional */ - { "status.aheadBehind", "false" }, - { "commitGraph.changedPaths", "true" }, - { "commitGraph.generationVersion", "1" }, - { "core.autoCRLF", "false" }, - { "core.safeCRLF", "false" }, - { "fetch.showForcedUpdates", "false" }, - { "pack.usePathWalk", "true" }, { NULL, NULL }, }; int i; @@ -197,9 +203,8 @@ static int set_recommended_config(int reconfigure) if (repo_config_get_string(the_repository, "log.excludeDecoration", &value)) { trace2_data_string("scalar", the_repository, "log.excludeDecoration", "created"); - if (repo_config_set_multivar_gently(the_repository, "log.excludeDecoration", - "refs/prefetch/*", - CONFIG_REGEX_NONE, 0)) + if (set_config_with_comment("log.excludeDecoration", + "refs/prefetch/*")) return error(_("could not configure " "log.excludeDecoration")); } else { diff --git a/t/t9210-scalar.sh b/t/t9210-scalar.sh index bd6f0c40d229b6..009437a5f3168f 100755 --- a/t/t9210-scalar.sh +++ b/t/t9210-scalar.sh @@ -202,14 +202,17 @@ test_expect_success 'scalar clone --no-... opts' ' test_expect_success 'scalar reconfigure' ' git init one/src && scalar register one && - git -C one/src config core.preloadIndex false && + git -C one/src config unset gui.gcwarning && scalar reconfigure one && - test true = "$(git -C one/src config core.preloadIndex)" && - git -C one/src config core.preloadIndex false && + test false = "$(git -C one/src config gui.gcwarning)" && + git -C one/src config unset gui.gcwarning && rm one/src/cron.txt && GIT_TRACE2_EVENT="$(pwd)/reconfigure" scalar reconfigure -a && test_path_is_file one/src/cron.txt && - test true = "$(git -C one/src config core.preloadIndex)" && + test false = "$(git -C one/src config gui.gcwarning)" && + test_grep "GCWarning = false # set by scalar" one/src/.git/config && + test_grep "excludeDecoration = refs/prefetch/\* # set by scalar" one/src/.git/config && + test_subcommand git maintenance start ` errors out when dir is missing' '