Skip to content

Rebase to Git for Windows v2.54.0#892

Open
dscho wants to merge 319 commits intovfs-2.54.0from
tentative/vfs-2.54.0
Open

Rebase to Git for Windows v2.54.0#892
dscho wants to merge 319 commits intovfs-2.54.0from
tentative/vfs-2.54.0

Conversation

@dscho
Copy link
Copy Markdown
Member

@dscho dscho commented Apr 20, 2026

Range-diff relative to v2.54.0-rc2.vfs.0.1
  • 6: 752da3b = 1: a8452ef survey: calculate more stats on refs

  • 7: fe3f5f7 = 2: 2321fd6 survey: show some commits/trees/blobs histograms

  • 8: d41b7d0 = 3: 6fdf945 survey: add vector of largest objects for various scaling dimensions

  • 9: 653687a = 4: 0ca3873 survey: add pathname of blob or tree to large_item_vec

  • 10: 564482d = 5: db1cdd0 survey: add commit-oid to large_item detail

  • 12: 98cc0b6 = 6: e6ba70a survey: add commit name-rev lookup to each large_item

  • 13: 72c4a50 = 7: 8534ebc survey: add --no-name-rev option

  • 14: f75127c = 8: cacaeb0 survey: started TODO list at bottom of source file

  • 15: 6cd5fac = 9: 84c21fb survey: expanded TODO list at the bottom of the source file

  • 2: fa5e46d = 10: 891f70c sparse-index.c: fix use of index hashes in expand_index

  • 1: a8b5670 = 11: 4cdb47d t: remove advice from some tests

  • 3: 5e2953f = 12: 71a54dc t5300: confirm failure of git index-pack when non-idx suffix requested

  • 16: 58f2dfe = 13: 4a3622e survey: expanded TODO with more notes

  • 4: f3a148c = 14: 411229f t1092: add test for untracked files and directories

  • 5: 227c0c3 = 15: d48ea40 index-pack: disable rev-index if index file has non .idx suffix

  • 11: 145cc6b = 16: 7a375bf trace2: prefetch value of GIT_TRACE2_DST_DEBUG at startup

  • 17: 4bd146d = 17: bfe187a reset --stdin: trim carriage return from the paths

  • 18: 840b607 ! 18: b8ce767 Identify microsoft/git via a distinct version suffix

    @@ Commit message
      ## GIT-VERSION-GEN ##
     @@
      
    - DEF_VER=v2.54.0-rc2
    + DEF_VER=v2.54.0
      
     +# Identify microsoft/git via a distinct version suffix
     +DEF_VER=$DEF_VER.vfs.0.0
  • 19: ee35ee1 = 19: 74aaaed gvfs: ensure that the version is based on a GVFS tag

  • 20: 54f83ba = 20: 9037a12 gvfs: add a GVFS-specific header file

  • 21: 4f9c015 = 21: 3bb5350 gvfs: add the core.gvfs config setting

  • 22: 031d1e9 = 22: 2e5589d gvfs: add the feature to skip writing the index' SHA-1

  • 23: aa839b7 = 23: 8d12904 gvfs: add the feature that blobs may be missing

  • 24: ac713d2 = 24: 1210bf1 gvfs: prevent files to be deleted outside the sparse checkout

  • 51: 6c5c7d9 = 25: 2a26b3e gvfs: optionally skip reachability checks/upload pack during fetch

  • 52: 8f8e4a9 = 26: 6c77873 gvfs: ensure all filters and EOL conversions are blocked

  • 53: 3b3c29f = 27: 25b9de3 gvfs: allow "virtualizing" objects

  • 54: db094aa = 28: 397b60d Hydrate missing loose objects in check_and_freshen()

  • 55: 0ecac98 = 29: e611a66 sha1_file: when writing objects, skip the read_object_hook

  • 56: 6096a76 = 30: ce00e56 gvfs: add global command pre and post hook procs

  • 57: 6af73d5 = 31: ee0ef83 t0400: verify that the hook is called correctly from a subdirectory

  • 58: bf3a5ff = 32: e774e3b t0400: verify core.hooksPath is respected by pre-command

  • 59: 8a38f28 = 33: 9b93fc1 Pass PID of git process to hooks.

  • 60: cb18230 = 34: 60b3b1a sparse-checkout: make sure to update files with a modify/delete conflict

  • 61: e459ab2 = 35: 5486f75 worktree: allow in Scalar repositories

  • 62: 0682d47 = 36: 0142ed0 sparse-checkout: avoid writing entries with the skip-worktree bit

  • 63: 1cad0d4 = 37: 4d5da32 Do not remove files outside the sparse-checkout

  • 64: 694a097 = 38: da90ad3 send-pack: do not check for sha1 file when GVFS_MISSING_OK set

  • 65: 5ba0910 = 39: 8581441 gvfs: allow corrupt objects to be re-downloaded

  • 66: 6602ef5 = 40: 83160f2 cache-tree: remove use of strbuf_addf in update_one

  • 67: 6bfef91 = 41: 2dd58ca gvfs: block unsupported commands when running in a GVFS repo

  • 68: 4577d0b = 42: e0a2d36 gvfs: allow overriding core.gvfs

  • 69: 80db01c = 43: 3378e7d BRANCHES.md: Add explanation of branches and using forks

  • 70: 588b661 = 44: 0e19dd5 git.c: add VFS enabled cmd blocking

  • 71: 5556af7 = 45: 4685c72 git.c: permit repack cmd in Scalar repos

  • 72: 000c192 = 46: 6df5778 git.c: permit fsck cmd in Scalar repos

  • 73: 6cd4041 = 47: fc28ad1 git.c: permit prune cmd in Scalar repos

  • 77: 78255c5 = 48: 467879d worktree: remove special case GVFS cmd blocking

  • 79: 2bc2bf0 = 49: ee1a38f builtin/repack.c: emit warning when shared cache is present

  • 74: 8642204 = 50: 8c94b78 Add virtual file system settings and hook proc

  • 75: 8d21b0a = 51: a9491f2 virtualfilesystem: don't run the virtual file system hook if the index has been redirected

  • 76: c302d0d = 52: 969b601 virtualfilesystem: check if directory is included

  • 78: 4301484 = 53: 8299cb9 backwards-compatibility: support the post-indexchanged hook

  • 80: 2fe9f7e = 54: 919620b gvfs: verify that the built-in FSMonitor is disabled

  • 81: 061c21a = 55: 710d5a7 wt-status: add trace2 data for sparse-checkout percentage

  • 82: f1e5fdf = 56: 5079d37 status: add status serialization mechanism

  • 83: 42dda07 = 57: 85d7f19 Teach ahead-behind and serialized status to play nicely together

  • 84: e2476d7 = 58: be5fefb status: serialize to path

  • 85: 336c021 = 59: 008f2c5 status: reject deserialize in V2 and conflicts

  • 86: 51b28b1 = 60: 185e4e7 serialize-status: serialize global and repo-local exclude file metadata

  • 87: f2e8e52 = 61: 1ae7a94 status: deserialization wait

  • 88: 1f45fda = 62: bfa7736 status: deserialize with -uno does not print correct hint

  • 89: 17b1fe2 = 63: e059869 fsmonitor: check CE_FSMONITOR_VALID in ce_uptodate

  • 90: 12b3942 = 64: 9e9d115 fsmonitor: add script for debugging and update script for tests

  • 91: 01a4a16 = 65: eda895f status: disable deserialize when verbose output requested.

  • 92: 2a97d15 = 66: 0ae8e59 t7524: add test for verbose status deserialzation

  • 93: e66373a = 67: ddea586 deserialize-status: silently fallback if we cannot read cache file

  • 94: 0aee816 = 68: 90e5e1e gvfs:trace2:data: add trace2 tracing around read_object_process

  • 95: ee278a1 = 69: e7cc49b gvfs:trace2:data: status deserialization information

  • 96: bdd02dd = 70: b8030ad gvfs:trace2:data: status serialization

  • 97: 693e7f0 = 71: 2e5f21e gvfs:trace2:data: add vfs stats

  • 98: f206888 = 72: ab6aaac trace2: refactor setting process starting time

  • 99: 984bacb = 73: 7cac489 trace2:gvfs:experiment: clear_ce_flags_1

  • 100: ca649da = 74: db7a92d trace2:gvfs:experiment: report_tracking

  • 101: 354d2e7 = 75: 4b307ec trace2:gvfs:experiment: read_cache: annotate thread usage in read-cache

  • 102: 3e21ca0 = 76: f9a0cc7 trace2:gvfs:experiment: read-cache: time read/write of cache-tree extension

  • 103: 18fa0c1 = 77: 5ccc665 trace2:gvfs:experiment: add region to apply_virtualfilesystem()

  • 104: a77f91f = 78: a1c4e16 trace2:gvfs:experiment: add region around unpack_trees()

  • 105: f72701a = 79: 3844304 trace2:gvfs:experiment: add region to cache_tree_fully_valid()

  • 106: ded032c = 80: d2883d8 trace2:gvfs:experiment: add unpack_entry() counter to unpack_trees() and report_tracking()

  • 107: c13e45c = 81: c3f8841 trace2:gvfs:experiment: increase default event depth for unpack-tree data

  • 108: 053fa03 = 82: 654a504 trace2:gvfs:experiment: add data for check_updates() in unpack_trees()

  • 109: 9aa2717 = 83: 733d0f5 Trace2:gvfs:experiment: capture more 'tracking' details

  • 110: 1141617 = 84: c047e0a credential: set trace2_child_class for credential manager children

  • 111: 37ef52b = 85: 68b5bf2 sub-process: do not borrow cmd pointer from caller

  • 112: 16e6fb6 = 86: a36b94d sub-process: add subprocess_start_argv()

  • 113: a8fea04 = 87: f1d57cc sha1-file: add function to update existing loose object cache

  • 114: ca951d0 = 88: f431105 index-pack: avoid immediate object fetch while parsing packfile

  • 115: 7930a81 = 89: 2467774 gvfs-helper: create tool to fetch objects using the GVFS Protocol

  • 116: c22235a = 90: 5834c1e sha1-file: create shared-cache directory if it doesn't exist

  • 117: a1d7ed5 = 91: 0d8ca0d gvfs-helper: better handling of network errors

  • 118: 4869384 = 92: 5a42fd6 gvfs-helper-client: properly update loose cache with fetched OID

  • 119: 659aa92 = 93: a4fa869 gvfs-helper: V2 robust retry and throttling

  • 120: 7d0b0aa = 94: 30cc86b gvfs-helper: expose gvfs/objects GET and POST semantics

  • 121: e95e585 = 95: 8f5bfd7 gvfs-helper: dramatically reduce progress noise

  • 122: 3eb677d = 96: 4c4dd7f gvfs-helper: handle pack-file after single POST request

  • 123: bee254b = 97: 01b2f6c test-gvfs-prococol, t5799: tests for gvfs-helper

  • 124: 75e734c = 98: aa254e6 gvfs-helper: move result-list construction into install functions

  • 125: 18d2344 = 99: 22de5b3 t5799: add support for POST to return either a loose object or packfile

  • 126: 5004665 = 100: 693dcc9 t5799: cleanup wc-l and grep-c lines

  • 127: d6fc107 = 101: 38dc180 gvfs-helper: verify loose objects after write

  • 128: 6b7d23b = 102: 9ebc0f3 t7599: create corrupt blob test

  • 129: 0331552 = 103: 577aabd gvfs-helper: add prefetch support

  • 130: 5e2a48f = 104: 3ff796a gvfs-helper: add prefetch .keep file for last packfile

  • 131: a0ae34a = 105: 7c13748 gvfs-helper: do one read in my_copy_fd_len_tail()

  • 132: ed044ca = 106: 3fb8569 gvfs-helper: move content-type warning for prefetch packs

  • 133: debafa8 = 107: 9e95b97 fetch: use gvfs-helper prefetch under config

  • 134: 0e612e8 = 108: c44a206 gvfs-helper: better support for concurrent packfile fetches

  • 135: 379563f = 109: 01a538f remote-curl: do not call fetch-pack when using gvfs-helper

  • 136: 533015f = 110: 056bb72 fetch: reprepare packs before checking connectivity

  • 137: 3193c2b = 111: af57ac7 gvfs-helper: retry when creating temp files

  • 138: 8ff6c73 = 112: 4742bc4 sparse: avoid warnings about known cURL issues in gvfs-helper.c

  • 139: f8e06d3 = 113: 9bf8e27 gvfs-helper: add --max-retries to prefetch verb

  • 145: 613e283 = 114: 135eb5d maintenance: care about gvfs.sharedCache config

  • 147: 024adf4 = 115: ed9fd0d unpack-trees:virtualfilesystem: Improve efficiency of clear_ce_flags

  • 148: 366a304 = 116: 4dde591 homebrew: add GitHub workflow to release Cask

  • 157: ed351c1 = 117: b911fc3 Adding winget workflows

  • 158: 5152ac6 = 118: b16eb3e Disable the monitor-components workflow in msft-git

  • 159: 4d58a4d = 119: dcf7a55 .github: enable windows builds on microsoft fork

  • 140: 70438b1 = 120: cf9dee3 t5799: add tests to detect corrupt pack/idx files in prefetch

  • 160: 8d51fcd = 121: 29c7f02 .github/actions/akv-secret: add action to get secrets

  • 141: d87df12 = 122: 6c82f84 gvfs-helper: ignore .idx files in prefetch multi-part responses

  • 161: 171a02c = 123: 39fdcb5 release: create initial Windows installer build workflow

  • 142: 8bcc637 = 124: 8626621 t5799: explicitly test gvfs-helper --fallback and --no-fallback

  • 162: 1174363 = 125: 453f8c5 release: create initial Windows installer build workflow

  • 143: a5c0dfb = 126: 91fbb99 gvfs-helper: don't fallback with new config

  • 163: c6fc80e = 127: 66ce629 help: special-case HOST_CPU universal

  • 144: 13639f5 = 128: 51ffffe test-gvfs-protocol: add cache_http_503 to mayhem

  • 164: 0f5de19 = 129: 3ba4ddb release: add Mac OSX installer build

  • 146: 655bc3c = 130: ffed10f t5799: add unit tests for new gvfs.fallback config setting

  • 165: 3e4bc26 = 131: 2c1973d release: build unsigned Ubuntu .deb package

  • 166: 7d266cd = 132: a63e353 release: add signing step for .deb package

  • 168: cc81645 = 133: bad6926 release: create draft GitHub release with packages & installers

  • 170: cc2fcdf = 134: 6b1d000 build-git-installers: publish gpg public key

  • 167: 4888e78 = 135: 4f9ca28 update-microsoft-git: create barebones builtin

  • 172: 9c795c7 = 136: 9314704 release: continue pestering until user upgrades

  • 169: eb94661 = 137: 0656543 update-microsoft-git: Windows implementation

  • 174: 9627b29 = 138: fb2ee4c dist: archive HEAD instead of HEAD^{tree}

  • 171: 037386f = 139: 6fffe5a update-microsoft-git: use brew on macOS

  • 176: c04df22 = 140: e107a79 release: include GIT_BUILT_FROM_COMMIT in MacOS build

  • 173: de593a9 = 141: d49fbb9 .github: reinstate ISSUE_TEMPLATE.md for microsoft/git

  • 178: c0c84fe = 142: 8eba308 release: add installer validation

  • 175: f6c5ed3 = 143: 3fafd11 .github: update PULL_REQUEST_TEMPLATE.md

  • 25: 3bb56f4 = 144: 7cbeb9c git_config_set_multivar_in_file_gently(): add a lock timeout

  • 177: 45c0dc8 = 145: 268e680 Adjust README.md for microsoft/git

  • 26: a46f3b2 = 146: ef23cac scalar: set the config write-lock timeout to 150ms

  • 27: c685d99 = 147: 3356b30 scalar: add docs from microsoft/scalar

  • 28: 504e90d = 148: 0cedb2b scalar (Windows): use forward slashes as directory separators

  • 29: f41388d = 149: 4d5f852 scalar: add retry logic to run_git()

  • 30: 8f54a61 = 150: 3804a81 scalar: support the config command for backwards compatibility

  • 179: b794304 = 151: c23a0f1 scalar: implement a minimal JSON parser

  • 180: 7c3e81b = 152: 657cebb scalar clone: support GVFS-enabled remote repositories

  • 181: d1ead25 = 153: 58da6b9 test-gvfs-protocol: also serve smart protocol

  • 182: e018c88 = 154: cd9da9c gvfs-helper: add the endpoint command

  • 183: a160b34 = 155: d7c9693 dir_inside_of(): handle directory separators correctly

  • 184: 0be568d = 156: 7937a58 scalar: disable authentication in unattended mode

  • 185: ed27cb5 = 157: 4b26b6f abspath: make strip_last_path_component() global

  • 186: 1d64a4e = 158: 35d09df scalar: do initialize gvfs.sharedCache

  • 187: 1f769f9 = 159: 290228b scalar diagnose: include shared cache info

  • 188: 5f46742 = 160: 62f99c5 scalar: only try GVFS protocol on https:// URLs

  • 189: 0fc72fc = 161: 4b56f3f scalar: verify that we can use a GVFS-enabled repository

  • 190: 1050c7a = 162: baf31be scalar: add the cache-server command

  • 191: c51cff9 = 163: 6e44511 scalar: add a test toggle to skip accessing the vsts/info endpoint

  • 192: b0bbdf8 = 164: 8b485bf scalar: adjust documentation to the microsoft/git fork

  • 193: 8890e02 = 165: 975b79e scalar: enable untracked cache unconditionally

  • 194: 3b2b2a3 = 166: 82508f4 scalar: parse clone --no-fetch-commits-and-trees for backwards compatibility

  • 195: 700f570 = 167: e56b327 scalar: make GVFS Protocol a forced choice

  • 196: 6196de4 = 168: 9878e92 scalar: work around GVFS Protocol HTTP/2 failures

  • 197: dc58725 = 169: 94a86dc gvfs-helper-client: clean up server process(es)

  • 198: 1e30fb8 = 170: 3fabf95 scalar diagnose: accommodate Scalar's Functional Tests

  • 199: ce98f4b = 171: 166ed4d ci: run Scalar's Functional Tests

  • 200: 92155a9 = 172: 3a0f593 scalar: upgrade to newest FSMonitor config setting

  • 201: 2d28de5 = 173: e70ed15 add/rm: allow adding sparse entries when virtual

  • 202: 5ca037c = 174: 0176b10 sparse-checkout: add config to disable deleting dirs

  • 203: 4b57833 = 175: 16d9542 diff: ignore sparse paths in diffstat

  • 204: 3b6b9fe = 176: 34b71f5 repo-settings: enable sparse index by default

  • 31: 31d6630 = 177: b56ca58 TO-UPSTREAM: sequencer: avoid progress when stderr is redirected

  • 205: 380a871 = 178: 87b4a62 TO-CHECK: t1092: use quiet mode for rebase tests

  • 206: 7147676 = 179: 51a3f58 reset: fix mixed reset when using virtual filesystem

  • 207: 618c65c = 180: 0d4c9a9 diff(sparse-index): verify with partially-sparse

  • 208: 9793f56 = 181: 1e1c953 stash: expand testing for git stash -u

  • 209: 873ac96 = 182: ba15888 sparse-index: add ensure_full_index_with_reason()

  • 210: 4d155b7 = 183: 28b8b1f treewide: add reasons for expanding index

  • 211: f307cca = 184: 0cba1c3 treewide: custom reasons for expanding index

  • 212: 1b28bcf = 185: 095f791 sparse-index: add macro for unaudited expansions

  • 213: a68caff = 186: f234ddc Docs: update sparse index plan with logging

  • 214: 349cbed = 187: 3df78f8 sparse-index: log failure to clear skip-worktree

  • 215: ac24719 = 188: a310bcc stash: use -f in checkout-index child process

  • 216: 714d7ca = 189: ed49c0e sparse-index: do not copy hashtables during expansion

  • 217: 183b74b = 190: 3169ba3 TO-UPSTREAM: sub-process: avoid leaking cmd

  • 218: 870c7e4 = 191: 2a0d73e remote-curl: release filter options before re-setting them

  • 219: fc2895b = 192: 20aaf05 transport: release object filter options

  • 220: 8933d14 = 193: e129f43 push: don't reuse deltas with path walk

  • 221: 32a33fa = 194: a22c0b6 t7900-maintenance.sh: reset config between tests

  • 222: bf66109 = 195: a3d92a3 maintenance: add cache-local-objects maintenance task

  • 223: bac532f = 196: 27b19a5 scalar.c: add cache-local-objects task

  • 224: 1f27629 = 197: e2d5332 hooks: add custom post-command hook config

  • 225: 397268e = 198: 67995b0 TO-UPSTREAM: Docs: fix asciidoc failures from short delimiters

  • 226: f7f55ad = 199: 1ef68d0 hooks: make hook logic memory-leak free

  • 32: cd4bde0 = 200: c18f47b cat_one_file(): make it easy to see that the size variable is initialized

  • 227: 0e08e58 = 201: f6bf764 t0401: test post-command for alias, version, typo

  • 33: 869b7d8 = 202: b7b0458 fsck: avoid using an uninitialized variable

  • 228: 76817ee = 203: 885c9c6 hooks: better handle config without gitdir

  • 34: 5981b91 = 204: 09c8246 revision: defensive programming

  • 36: 2fa7ac8 = 205: 18eaf1a get_parent(): defensive programming

  • 38: 7b01628 = 206: 2e3161b fetch-pack: defensive programming

  • 39: 0d029f7 = 207: b7cd525 unparse_commit(): defensive programming

  • 40: c6653c7 = 208: 5b2b925 verify_commit_graph(): defensive programming

  • 50: 96fbdbe = 209: 6ec7dc4 codeql: run static analysis as part of CI builds

  • 41: a591a45 = 210: c559617 stash: defensive programming

  • 149: f060662 = 211: e149087 codeql: publish the sarif file as build artifact

  • 42: 52e0dd6 = 212: c43326c stash: defensive programming

  • 44: e09e3c9 = 213: 3d1585f fetch: silence a CodeQL alert about a local variable's address' use after release

  • 150: 42be491 = 214: e277e03 codeql: disable a couple of non-critical queries for now

  • 43: 1d13d0d = 215: 4634cc6 push: defensive programming

  • 45: 57085a3 = 216: 8eac178 test-tool repository: check return value of lookup_commit()

  • 151: af4148d = 217: ef097fa date: help CodeQL understand that there are no leap-year issues here

  • 35: 7b34fd4 = 218: f38cce3 load_revindex_from_disk(): avoid accessing uninitialized data

  • 46: d86846e = 219: d0b514e fetch: defensive programming

  • 47: 8a1802e = 220: 61484c8 shallow: handle missing shallow commits gracefully

  • 152: da6be0c = 221: c32c244 help: help CodeQL understand that consuming envvars is okay here

  • 37: 55cdf49 = 222: 6184a4d load_pack_mtimes_file(): avoid accessing uninitialized data

  • 48: 0524783 = 223: e98e25b inherit_tracking(): defensive programming

  • 49: bb22be6 = 224: 02dd28f commit-graph: suppress warning about using a stale stack addresses

  • 153: 6934954 = 225: 29e8ee6 ctype: help CodeQL understand that sane_istest() does not access array past end

  • 154: 698d121 = 226: ade505c ctype: accommodate for CodeQL misinterpreting the z in mallocz()

  • 155: 3baf95a = 227: ced0669 strbuf_read: help with CodeQL misunderstanding that strbuf_read() does NUL-terminate correctly

  • 156: 163af1d = 228: 6ea08af codeql: also check JavaScript code

  • 229: 91e18f8 = 229: 079a4fd scalar: add run_git_argv

  • 230: 0084143 = 230: 0be8fee scalar: add --ref-format option to scalar clone

  • 231: a4eda7d = 231: 9efd894 gvfs-helper: skip collision check for loose objects

  • 232: 20daea7 = 232: 4fd0406 gvfs-helper: emit advice on transient errors

  • 233: 5337222 = 233: b73eb04 gvfs-helper: avoid collision check for packfiles

  • 234: 3a57c69 = 234: 1fae09d t5799: update cache-server methods for multiple instances

  • 235: e61005b = 235: 99f5a12 gvfs-helper: override cache server for prefetch

  • 236: 7c4abd9 = 236: 56827ed gvfs-helper: override cache server for get

  • 237: 818c001 = 237: c55b37c gvfs-helper: override cache server for post

  • 238: 37cef2f = 238: 6f88546 t5799: add test for all verb-specific cache-servers together

  • 239: d830c55 = 239: 366d8b7 lib-gvfs-helper: create helper script for protocol tests

  • 240: 3f130f3 = 240: f959aa2 t579*: split t5799 into several parts

  • 241: 5e2443b = 241: cc2c471 scalar: add ---cache-server-url options

  • 242: 757834d = 242: 81888ba Restore previous errno after post command hook

  • 243: 4916d76 = 243: df551f8 t9210: differentiate origin and cache servers

  • 246: 36733f2 = 244: 79c62b2 gvfs-helper: send X-Session-Id headers

  • 244: ceb0b30 = 245: 4866686 unpack-trees: skip lstats for deleted VFS entries in checkout

  • 245: 86a24da = 246: f4a85c5 worktree: conditionally allow worktree on VFS-enabled repos

  • 247: b52d71e = 247: 7db55f9 gvfs-helper: create shared object cache if missing

  • 248: 150ae94 = 248: caf4f51 gvfs: add gvfs.sessionKey config

  • 249: 91ea950 = 249: 2a24af5 gvfs: clear DIE_IF_CORRUPT in streaming incore fallback

  • 250: c2c454f = 250: 1f90f17 workflow: add release-vfsforgit to automate VFS for Git updates

  • 251: b06aa95 = 251: a485bab worktree remove: use GVFS_SUPPORTS_WORKTREES for skip-clean-check gate

  • 252: 24f326b = 252: b124df1 ci: add new VFS for Git functional tests workflow

  • 253: 5262c84 = 253: 3282678 azure-pipelines: add stub release pipeline for Azure

  • 254: bcb77db = 254: ed5c15a diff: add renameThreshold configuration option

jeffhostetler and others added 30 commits April 20, 2026 20:22
Changes to the global or repo-local excludes files can change the
results returned by "git status" for untracked files.  Therefore,
it is important that the exclude-file values used during serialization
are still current at the time of deserialization.

Teach "git status --serialize" to report metadata on the user's global
exclude file (which defaults to "$XDG_HOME/git/ignore") and for the
repo-local excludes file (which is in ".git/info/excludes").  Serialize
will record the pathnames and mtimes for these files in the serialization
header (next to the mtime data for the .git/index file).

Teach "git status --deserialize" to validate this new metadata.  If either
exclude file has changed since the serialization-cache-file was written,
then deserialize will reject the cache file and force a full/normal status
run.

Signed-off-by: Jeff Hostetler <jeffhost@microsoft.com>
Create trace2_initialize_clock() and call from main() to capture
process start time in isolation and before other sub-systems are
ready.

Signed-off-by: Jeff Hostetler <jeffhost@microsoft.com>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
Teach `git status --deserialize` to either wait indefintely
or immediately fail if the status serialization cache file
is stale.

Signed-off-by: Jeff Hostetler <jeffhost@microsoft.com>
Signed-off-by: Jeff Hostetler <jeffhost@microsoft.com>
With the "--untracked-files=complete" option status computes a
superset of the untracked files.  We use this when writing the
status cache.  If subsequent deserialize commands ask for either
the complete set or one of the "no", "normal", or "all" subsets,
it can still use the cache file because of filtering in the
deserialize parser.

When running status with the "-uno" option, the long format
status would print a "(use -u to show untracked files)" hint.

When deserializing with the "-uno" option and using a cache computed
with "-ucomplete", the "nothing to commit, working tree clean" message
would be printed instead of the hint.

It was easy to miss because the correct hint message was printed
if the cache was rejected for any reason (and status did the full
fallback).

The "struct wt_status des" structure was initialized with the
content of the status cache (and thus defaulted to "complete").
This change sets "des.show_untracked_files" to the requested
subset from the command-line or config.  This allows the long
format to print the hint.

Signed-off-by: Jeff Hostetler <jeffhost@microsoft.com>
Signed-off-by: Jeff Hostetler <jeffhost@microsoft.com>
When using fsmonitor the CE_FSMONITOR_VALID flag should be checked when
wanting to know if the entry has been updated. If the flag is set the
entry should be considered up to date and the same as if the CE_UPTODATE
is set.

In order to trust the CE_FSMONITOR_VALID flag, the fsmonitor data needs to
be refreshed when the fsmonitor bitmap is applied to the index in
tweak_fsmonitor. Since the fsmonitor data is kept up to date for every
command, some tests needed to be updated to take that into account.

istate->untracked->use_fsmonitor was set in tweak_fsmonitor when the
fsmonitor bitmap data was loaded and is now in refresh_fsmonitor since
that is being called in tweak_fsmonitor. refresh_fsmonitor will only be
called once and any other callers should be setting it when refreshing
the fsmonitor data so that code can use the fsmonitor data when checking
untracked files.

When writing the index, fsmonitor_last_update is used to determine if
the fsmonitor bitmap should be created and the extension data written to
the index. When running through unpack-trees this is not copied to the
result index. This makes the next time a git command is ran do all the
work of lstating all files to determine what is clean since all entries
in the index are marked as dirty since there wasn't any fsmonitor data
saved in the index extension.

Copying the fsmonitor_last_update to the result index will cause the
extension data for fsmonitor to be in the index for the next git command
to use.

Signed-off-by: Kevin Willford <Kevin.Willford@microsoft.com>
Add trace2_thread_start() and trace2_thread_exit() events to the worker
threads used to read the index.  This gives per-thread perf data.

These workers were introduced in:
abb4bb8 read-cache: load cache extensions on a worker thread
77ff112 read-cache: load cache entries on worker threads

Signed-off-by: Jeff Hostetler <jeffhost@microsoft.com>
The fsmonitor script that can be used for running all the git tests
using watchman was causing some of the tests to fail because it wrote
to stderr and created some files for debugging purposes.

Add a new debug script to use with debugging and modify the other script
to remove the code that would cause tests to fail.

Signed-off-by: Kevin Willford <Kevin.Willford@microsoft.com>
…ension

Add regions around code to read and write the cache-tree extension
when the index is read or written.

This is an experiment and may be dropped in future releases if
we don't need it anymore.

This experiment demonstrates that it takes more time to parse and
deserialize the cache-tree extension than it does to read the
cache-entries.

Commits [1] and [2] spreads cache-entry reading across N-1 cores
and dedicates a single core to simultaneously read the index extensions.

Local testing (on my machine) shows that reading the cache-tree extension
takes ~0.28 seconds.  The 11 cache-entry threads take ~0.08 seconds.
The main thread is blocked for 0.15 to 0.20 seconds waiting for the
extension thread to finish.

Let's use this commit to gather some telemetry and confirm this.

My point is that improvements, such as index V5 which makes the
cache entries smaller, may improve performance, but the gains may
be limited because of this extension.  And that we may need to
look inside the cache-tree extension to truly improve do_read_index()
performance.

[1] abb4bb8 read-cache: load cache extensions on a worker thread
[2] 77ff112 read-cache: load cache entries on worker threads

Signed-off-by: Jeff Hostetler <jeffhost@microsoft.com>
Disable deserialization when verbose output requested.

Verbose mode causes Git to print diffs for modified files.
This requires the index to be loaded to have the currently
staged OID values.  Without loading the index, verbose output
make it look like everything was deleted.

Signed-off-by: Jeff Hostetler <jeffhost@microsoft.com>
Signed-off-by: Jeff Hostetler <jeffhost@microsoft.com>
Verify that `git status --deserialize=x -v` does not crash and
generates the same output as a normal (scanning) status command.

These issues are described in the previous 2 commits.

Signed-off-by: Jeff Hostetler <jeffhost@microsoft.com>
Signed-off-by: Jeff Hostetler <jeffhost@microsoft.com>
Teach Git to not throw a fatal error when an explicitly-specified
status-cache file (`git status --deserialize=<foo>`) could not be
found or opened for reading and silently fallback to a traditional
scan.

This matches the behavior when the status-cache file is implicitly
given via a config setting.

Note: the current version causes a test to start failing. Mark this as
an expected result for now.

Signed-off-by: Jeff Hostetler <jeffhost@microsoft.com>
Signed-off-by: Derrick Stolee <dstolee@microsoft.com>
Signed-off-by: Jeff Hostetler <jeffhost@microsoft.com>
Teach subprocess_start() to use a copy of the passed `cmd` string
rather than borrowing the buffer from the caller.

Some callers of subprocess_start() pass the value returned from
find_hook() which points to a static buffer and therefore is only
good until the next call to find_hook().  This could cause problems
for the long-running background processes managed by sub-process.c
where later calls to subprocess_find_entry() to get an existing
process will fail.  This could cause more than 1 long-running
process to be created.

TODO Need to confirm, but if only read_object_hook() uses
TODO subprocess_start() in this manner, we could drop this
TODO commit when we drop support for read_object_hook().

Signed-off-by: Jeff Hostetler <jeffhost@microsoft.com>
Add function to start a subprocess with an argv.

Signed-off-by: Jeff Hostetler <jeffhost@microsoft.com>
Create a function to add a new object to the loose object cache
after the existing odb/xx/ directory was scanned.

This will be used in a later commit to keep the loose object
cache fresh after dynamically fetching an individual object
and without requiring the odb/xx/ directory to be rescanned.

Signed-off-by: Jeff Hostetler <jeffhost@microsoft.com>
Prevent packfile parsing from accidentally dynamically fetching
each individual object found in the packfile.

When index-pack parses the input packfile, it does a lookup in the
ODB to test for conflicts/collisions.  This can accidentally cause
the object to be individually fetched when gvfs-helper (or
read-object-hook or partial-clone) is enabled.

The call site was migrated to odb_has_object() as part of the upstream
refactoring, but odb_has_object(odb, oid, HAS_OBJECT_FETCH_PROMISOR)
sets only OBJECT_INFO_QUICK without OBJECT_INFO_SKIP_FETCH_OBJECT, which
means it WILL trigger remote fetches via gvfs-helper. But we want to
prevent index-pack from individually fetching every object it encounters
during the collision check.

Passing 0 instead gives us both OBJECT_INFO_QUICK and
OBJECT_INFO_SKIP_FETCH_OBJECT, which is the correct equivalent of the
original OBJECT_INFO_FOR_PREFETCH behavior.

Signed-off-by: Jeff Hostetler <jeffhost@microsoft.com>
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Create gvfs-helper.  This is a helper tool to use the GVFS Protocol
REST API to fetch objects and configuration data from a GVFS cache-server
or Git server.  This tool uses libcurl to send object requests to either
server.  This tool creates loose objects and/or packfiles.

Create gvfs-helper-client.  This code resides within git proper and
uses the sub-process API to manage gvfs-helper as a long-running background
process.

Signed-off-by: Jeff Hostetler <jeffhost@microsoft.com>
Signed-off-by: Derrick Stolee <dstolee@microsoft.com>
The config variable `gvfs.sharedCache` contains the pathname to an alternate
<odb> that will be used by `gvfs-helper` to store dynamically-fetched missing
objects.  If this directory does not exist on disk, `prepare_alt_odb()` omits
this directory from the in-memory list of alternates.  This causes `git`
commands (and `gvfs-helper` in particular) to fall-back to `.git/objects` for
storage of these objects.  This disables the shared-cache and leads to poorer
performance.

Teach `alt_obj_usable()` and `prepare_alt_odb()`, match up the directory
named in `gvfs.sharedCache` with an entry in `.git/objects/info/alternates`
and force-create the `<odb>` root directory (and the associated `<odb>/pack`
directory) if necessary.

If the value of `gvfs.sharedCache` refers to a directory that is NOT listed
as an alternate, create an in-memory alternate entry in the odb-list.  (This
is similar to how GIT_ALTERNATE_OBJECT_DIRECTORIES works.)

This work happens the first time that `prepare_alt_odb()` is called.

Furthermore, teach the `--shared-cache=<odb>` command line option in
`gvfs-helper` (which is runs after the first call to `prepare_alt_odb()`)
to override the inherited shared-cache (and again, create the ODB directory
if necessary).

Signed-off-by: Jeff Hostetler <jeffhost@microsoft.com>
Add trace2 message for CURL and HTTP errors.

Fix typo reporting network error code back to gvfs-helper-client.

Signed-off-by: Jeff Hostetler <jeffhost@microsoft.com>
Signed-off-by: Jeff Hostetler <jeffhost@microsoft.com>
Fix parsing of the "loose <odb>" response from `gvfs-helper` and
use the actually parsed OID when updating the loose oid cache.

Previously, an uninitialized "struct oid" was used to update
the cache.  This did not cause any corruption, but could cause
extra fetches for objects visited multiple times.

Signed-off-by: Jeff Hostetler <jeffhost@microsoft.com>
…and report_tracking()

Signed-off-by: Jeff Hostetler <jeffhost@microsoft.com>
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Add robust-retry mechanism to automatically retry a request after network
errors.  This includes retry after:
   [] transient network problems reported by CURL.
   [] http 429 throttling (with associated Retry-After)
   [] http 503 server unavailable (with associated Retry-After)

Add voluntary throttling using Azure X-RateLimit-* hints to avoid being
soft-throttled (tarpitted) or hard-throttled (429) on later requests.

Add global (outside of a single request) azure-throttle data to track the
rate limit hints from the cache-server and main Git server independently.

Add exponential retry backoff.  This is used for transient network problems
when we don't have a Retry-After hint.

Move the call to index-pack earlier in the response/error handling sequence
so that if we receive a 200 but yet the packfile is truncated/corrupted, we
can use the regular retry logic to get it again.

Refactor the way we create tempfiles for packfiles to use
<odb>/pack/tempPacks/ rather than working directly in the <odb>/pack/
directory.

Move the code to create a new tempfile to the start of a single request
attempt (initial and retry attempts), rather than at the overall start
of a request.  This gives us a fresh tempfile for each network request
attempt.  This simplifies the retry mechanism and isolates us from the file
ownership issues hidden within the tempfile class.  And avoids the need to
truncate previous incomplete results.  This was necessary because index-pack
was pulled into the retry loop.

Minor: Add support for logging X-VSS-E2EID to telemetry on network errors.

Minor: rename variable:
    params.b_no_cache_server --> params.b_permit_cache_server_if_defined.
This variable is used to indicate whether we should try to use the
cache-server when it is defined.  Got rid of double-negative logic.

Minor: rename variable:
    params.label --> params.tr2_label
Clarify that this variable is only used with trace2 logging.

Minor: Move the code to automatically map cache-server 400 responses
to normal 401 response earlier in the response/error handling sequence
to simplify later retry logic.

Minor: Decorate trace2 messages with "(cs)" or "(main)" to identify the
server in log messages.  Add params->server_type to simplify this.

Signed-off-by: Jeff Hostetler <jeffhost@microsoft.com>
Expose the differences in the semantics of GET and POST for
the "gvfs/objects" API:

    HTTP GET: fetches a single loose object over the network.
              When a commit object is requested, it just returns
	      the single object.

    HTTP POST: fetches a batch of objects over the network.
               When the oid-set contains a commit object, all
	       referenced trees are also included in the response.

gvfs-helper is updated to take "get" and "post" command line options.
the gvfs-helper "server" mode is updated to take "objects.get" and
"objects.post" verbs.

For convenience, the "get" option and the "objects.get" verb
do allow more than one object to be requested.  gvfs-helper will
automatically issue a series of (single object) HTTP GET requests
and creating a series of loose objects.

The "post" option and the "objects.post" verb will perform bulk
object fetching using the batch-size chunking.  Individual HTTP
POST requests containing more than one object will be created
as a packfile.  A HTTP POST for a single object will create a
loose object.

This commit also contains some refactoring to eliminate the
assumption that POST is always associated with packfiles.

In gvfs-helper-client.c, gh_client__get_immediate() now uses the
"objects.get" verb and ignores any currently queued objects.

In gvfs-helper-client.c, the OIDSET built by gh_client__queue_oid()
is only processed when gh_client__drain_queue() is called.  The queue
is processed using the "object.post" verb.

Signed-off-by: Jeff Hostetler <jeffhost@microsoft.com>
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
Add data for the number of files created/overwritten and deleted during the checkout.

Give proper category name to all events in unpack-trees.c and eliminate "exp".

This is modified slightly from the original version due to interactions with 26f924d
(unpack-trees: exit check_updates() early if updates are not wanted, 2020-01-07).

Signed-off-by: Jeff Hostetler <jeffhost@microsoft.com>
Signed-off-by: Derrick Stolee <dstolee@microsoft.com>
Tyrie Vella and others added 19 commits April 20, 2026 20:22
Add GVFS_SUPPORTS_WORKTREES flag (1<<8) to core.gvfs bitmask. When set,
allow git worktree commands to run on VFS-enabled repos instead of
blocking them with BLOCK_ON_VFS_ENABLED.

Force --no-checkout during worktree add when VFS is active so ProjFS can
be mounted before files are projected.

Support skip-clean-check marker file in worktree gitdir: if
.git/worktrees/<name>/skip-clean-check exists, skip the cleanliness
check during worktree remove. This allows VFSForGit's pre-command hook
to unmount ProjFS after its own status check, then let git proceed
without re-checking (which would fail without the virtual filesystem).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Users should be allowed to delete their shared cache and have it
recreated on 'git fetch'. This change makes that happen by creating any
leading directories and then creating the directory itself with mkdir().

Add a test that exercises --local-cache-path for the first time and
checks this scenario.

Signed-off-by: Derrick Stolee <stolee@gmail.com>
In different engineering systems, there may already be pseudonymous
identifiers stored in the local Git config. For Office and 1JS, this is
present in the 'otel.trace2.id' config value.

We'd like to be able to collect server-side telemetry based on these
pseudonymous identifiers, so prefxing the X-Session-Id header with this
value is helpful.

We could create a single 'gvfs.sessionPrefix' config key that stores
this value, but then we'd need to duplicate the identifier and risk
drift in the value. For now, we create this indirection by saying "what
config _key_ should Git use to look up the value to add as a prefix?"

Signed-off-by: Derrick Stolee <stolee@gmail.com>
When core_virtualfilesystem is set and a branch switch deletes entries
(present in old tree, absent in new tree), deleted_entry() calls
verify_absent_if_directory() with 'ce' pointing to a tree entry from
traverse_trees(). This tree entry lacks CE_NEW_SKIP_WORKTREE because
that flag is only set on src_index entries by mark_new_skip_worktree().

The missing flag causes verify_absent_if_directory()'s fast-path to
fail, falling through to verify_absent_1() which lstats every such path.
In a VFS repo each lstat may trigger callbacks, creating placeholders.
On a large repo switching between LTS releases this produces tens of
thousands of placeholders that the VFS must then clean up when they are
deleted as part of the checkout.

Fix this by propagating CE_NEW_SKIP_WORKTREE from the index entry (old)
to the tree entry (ce) when core_virtualfilesystem is set. This allows
the existing fast-path to work, eliminating the unnecessary lstats
entirely.

Measured on a 2.8M file VFS repo (0% hydrated):
  Before: ~135s checkout, ~23k folder placeholders created
  After:  ~25s checkout, 0 folder placeholders created

* [x] This change only applies to the virtualization hook and VFS for
Git.
Add GVFS_SUPPORTS_WORKTREES flag (1<<8) to core.gvfs bitmask. When set,
allow git worktree commands to run on VFS-enabled repos instead of
blocking them with BLOCK_ON_VFS_ENABLED.

Force --no-checkout during worktree add when VFS is active so ProjFS can
be mounted before files are projected.

Support skip-clean-check marker file in worktree gitdir: if
.git/worktrees/<name>/skip-clean-check exists, skip the cleanliness
check during worktree remove. This allows VFSForGit's pre-command hook
to unmount ProjFS after its own status check, then let git proceed
without re-checking (which would fail without the virtual filesystem).

The corresponding change in VFSForGit is
microsoft/VFSForGit#1911

* [x] This change only applies to the virtualization hook and VFS for
Git.
Users should be allowed to delete their shared cache and have it
recreated on 'git fetch'. This change makes that happen by creating any
leading directories and then creating the directory itself with
`mkdir()`.

Users may have had more instances of this due to #840, which advises
deleting the shared cache on a mistaken assumption that it would be
recreated on `git fetch`.

* [X] This change only applies to interactions with Azure DevOps and the
      GVFS Protocol.
The upstream refactoring in 4c89d31 (streaming: rely on object
sources to create object stream, 2025-11-23) changed how
istream_source() discovers objects. Previously, it called
odb_read_object_info_extended() with flags=0 to locate the object, then
tried the source-specific opener (e.g. open_istream_loose). If that
failed (e.g. corrupt loose object), it fell back to open_istream_incore
which re-read the object — by which time the read-object hook had
already re-fetched a clean copy.

After the refactoring, istream_source() iterates over sources directly.
When a corrupt loose object is found, odb_source_loose_read_object_stream
fails and the loop continues to the next source. When no source has the
object, it falls through to open_istream_incore, which calls
odb_read_object_info_extended with OBJECT_INFO_DIE_IF_CORRUPT. This
encounters the same corrupt loose file still on disk and dies before the
read-object hook gets a chance to re-download a clean replacement.

Fix this by clearing OBJECT_INFO_DIE_IF_CORRUPT in open_istream_incore
when GVFS_MISSING_OK is set, matching the existing pattern in
odb_read_object.

This fixes the GitCorruptObjectTests functional test failures
(GitRequestsReplacementForAllNullObject,
GitRequestsReplacementForObjectCorruptedWithBadData,
GitRequestsReplacementForTruncatedObject) that appeared when upgrading
from v2.50.1.vfs.0.1 to v2.53.0.vfs.0.0.

Signed-off-by: Tyler Vella <tyvella@microsoft.com>
A common problem when tracking GVFS Protocol queries is that we don't
have a way to connect client and server interactions. This is especially
true in the typical case where a cache server deployment is hidden
behind a load balancer. We can't even determine which cache server was
used for certain requests!

Add some client-identifying data to the HTTP queries using the
X-Session-Id header. This will by default identify the helper process
using its SID. If configured via the new gvfs.sessionKey config, it will
prefix this SID with another config value.

For example, Office monorepo users have an 'otel.trace2.id' config value
that is a pseudonymous identifier. This allows telemetry readers to
group requests by enlistment without knowing the user's identity at all.
Users could opt-in to provide this identifier for investigations around
their long-term performance or issues. This change makes it possible to
extend this to cache server interactions.

* [X] This change only applies to interactions with Azure DevOps and the
      GVFS Protocol.
When a new microsoft/git release is published, VFS for Git needs to
pick up the new Git version. Today this is a manual process. This
workflow automates it by reacting to GitHub release events.

On a full releases: creates a PR in microsoft/VFSForGit to bump the
default GIT_VERSION in the build workflow, so future CI runs and
manual dispatches use the latest stable Git version.

Authentication uses the existing Azure Key Vault + OIDC pattern
(matching release-homebrew and release-winget) to retrieve a token
with write access to the VFS for Git repository.

In a separate effort we'll add another workflow that triggers on
push to vfs-* branches to trigger a run of VFS for Git Functional Tests
(from the master branch).

Signed-off-by: Matthew John Cheetham <mjcheetham@outlook.com>
The upstream refactoring in 4c89d31 (streaming: rely on object
sources to create object stream, 2025-11-23) changed how
istream_source() discovers objects. Previously, it called
odb_read_object_info_extended() with flags=0 to locate the object, then
tried the source-specific opener (e.g. open_istream_loose). If that
failed (e.g. corrupt loose object), it fell back to open_istream_incore
which re-read the object — by which time the read-object hook had
already re-fetched a clean copy.

After the refactoring, istream_source() iterates over sources directly.
When a corrupt loose object is found,
odb_source_loose_read_object_stream fails and the loop continues to the
next source. When no source has the object, it falls through to
open_istream_incore, which calls odb_read_object_info_extended with
OBJECT_INFO_DIE_IF_CORRUPT. This encounters the same corrupt loose file
still on disk and dies before the read-object hook gets a chance to
re-download a clean replacement.

Fix this by clearing OBJECT_INFO_DIE_IF_CORRUPT in open_istream_incore
when GVFS_MISSING_OK is set, matching the existing pattern in
odb_read_object.

This fixes the GitCorruptObjectTests functional test failures
(GitRequestsReplacementForAllNullObject,
GitRequestsReplacementForObjectCorruptedWithBadData,
GitRequestsReplacementForTruncatedObject) that appeared when upgrading
from v2.50.1.vfs.0.1 to v2.53.0.vfs.0.0.

This is a companion to #782 (which predates
4c89d31,
though, therefore it is not _exactly_ an omission of that PR).
The skip-clean-check guard in remove_worktree() was gated on
core_virtualfilesystem, which is only initialized by
repo_config_get_virtualfilesystem() during index loading. Since the
worktree remove path never loads the index before this check, the
variable was always NULL, causing check_clean_worktree() to run even
when VFSForGit had already unmounted the projection and written the
skip-clean-check marker file. This made 'git worktree remove' fail
with 'fatal: failed to run git status' in GVFS repos.

Replace core_virtualfilesystem with
gvfs_config_is_set(GVFS_SUPPORTS_WORKTREES). This is the correct bit
to check here: remove_worktree() can only be reached when
GVFS_SUPPORTS_WORKTREES is set (cmd_worktree blocks otherwise at line
1501), and it directly expresses that the VFS layer supports worktree
operations and knows how to signal when a clean check can be skipped.
Unlike core_virtualfilesystem, gvfs_config_is_set() is self-loading
from core.gvfs and does not depend on the index having been read.

Assisted-by: Claude Opus 4.6
Signed-off-by: Tyrie Vella <tyrielv@gmail.com>
When a new `microsoft/git` release is published, VFS for Git needs to
pick up the new Git version. Today this is a manual process. This
workflow automates it by reacting to GitHub release events.
    
On a full releases: creates a PR in `microsoft/VFSForGit` to bump the
default `GIT_VERSION` in the build workflow, so future CI runs and
manual dispatches use the latest stable Git version.
    
Authentication uses the existing Azure Key Vault + OIDC pattern
(matching `release-homebrew` and `release-winget`) to retrieve a token
with write access to the VFS for Git repository.
    
In a separate effort we'll add another workflow that triggers on push to
`vfs-*` branches to trigger a run of VFS for Git Functional Tests (from
the `master` branch).
Build Git with VFS support using the Git for Windows SDK and package
it as a MicrosoftGit artifact with an install.bat that uses robocopy
to deploy to 'C:\Program Files\Git'.

Find the latest successful VFSForGit build on master and call its
reusable functional-tests.yaml workflow, which downloads the GVFS
installer and FT executables from that run, and the Git artifact
from this run.

Requires a VFSFORGIT_TOKEN secret with actions:read on
microsoft/VFSForGit for cross-repo artifact downloads.
The skip-clean-check guard in remove_worktree() was gated on
core_virtualfilesystem, which is only initialized by
repo_config_get_virtualfilesystem() during index loading. Since the
worktree remove path never loads the index before this check, the
variable was always NULL, causing check_clean_worktree() to run even
when VFSForGit had already unmounted the projection and written the
skip-clean-check marker file. This made 'git worktree remove' fail with
'fatal: failed to run git status' in GVFS repos.

Replace core_virtualfilesystem with
gvfs_config_is_set(GVFS_USE_VIRTUAL_FILESYSTEM), which is already loaded
from core.gvfs by cmd_worktree() before dispatch to remove_worktree().
Add a stub pipeline for releases using Azure Pipelines.

The pipeline runs on Microsoft internal images/runners across:
 * Windows x64
 * Windows ARM64
 * macOS
 * Ubuntu x64
 * Ubuntu ARM64

At the start of a run there is a prerequisite stage and pre-build
validation. Today this does nothing, and should be updated to:
 * validate the current commit is tagged (annotated), and
 * capture the Git version, tag name and SHA.

Artifacts are uploaded from the build stage, and downloaded into the
release stage later for uploading to a draft GitHub release.

ESRP signing to be added later.

Signed-off-by: Matthew John Cheetham <mjcheetham@outlook.com>
## TL;DR

Add a new `vfs-functional-tests.yml` workflow that builds Git from this
repository and runs the VFS for Git functional tests against it, using
VFSForGit's reusable workflow.

## Why?

VFS for Git functional tests currently only run in the VFSForGit
repository, against a tagged microsoft/git release. This means
VFS-related regressions in Git are only caught *after* a release is
tagged. By running the FTs here on every push and PR to `vfs-*`
branches, we can catch regressions before they ship.

This is the counterpart to
microsoft/VFSForGit#1932, which extracted the
functional tests into a reusable `workflow_call` workflow.

## How it works

1. **Build Git** — checks out this repo, builds with the Git for Windows
SDK, and packages the result into a `MicrosoftGit` artifact with an
`install.bat` that deploys via robocopy to `C:\Program Files\Git`. Both
ARM64 and x64 are built and combined into a single artifact for the FTs
to install and use.

2. **Find VFSForGit build** — locates the latest successful VFSForGit CI
run on `master` to get the GVFS installer and FT executables. If the
build was a 'skipped' build (because an existing run succeeded with that
tree) then follow the annotation to the real run.

3. **Call reusable workflow** — invokes
`microsoft/VFSForGit/.github/workflows/functional-tests.yaml@master`,
which handles the full test matrix (2 configs × 2 architectures × 10
slices)
Add diff.renameThreshold, merge.renameThreshold, and
status.renameThreshold configuration options to control the minimum
similarity threshold for rename detection without requiring
command-line flags.

The cascade follows the existing pattern for renameLimit and renames:
  - merge.renameThreshold overrides diff.renameThreshold for merges
  - status.renameThreshold overrides diff.renameThreshold for status
  - CLI flags (-M, --find-renames) override all config values

The value accepts the same format as -M: a percentage (e.g. 50%) or
a fraction (e.g. 0.5). If unset, the default remains 50%.

This also gives git-blame users control over the rename threshold
for the first time, since blame has no -M threshold flag but inherits
diff.renameThreshold via repo_diff_setup().

Assisted-by: Claude Opus 4.6
Signed-off-by: Tyrie Vella <tyrielv@gmail.com>
Add a stub pipeline for releases using Azure Pipelines.

The pipeline runs on Microsoft internal images/runners across:
 * Windows x64
 * Windows ARM64
 * macOS
 * Ubuntu x64
 * Ubuntu ARM64

At the start of a run there is a prerequisite stage and pre-build
validation. Today this does nothing, and should be updated to:
 * validate the current commit is tagged (annotated), and
 * capture the Git version, tag name and SHA.

Artifacts are uploaded from the build stage, and downloaded into the
release stage later for uploading to a draft GitHub release.

ESRP signing to be added later.
Add diff.renameThreshold, merge.renameThreshold, and
status.renameThreshold configuration options to control the minimum
similarity threshold for rename detection without requiring command-line
flags.

The cascade follows the existing pattern for renameLimit and renames:
  - merge.renameThreshold overrides diff.renameThreshold for merges
  - status.renameThreshold overrides diff.renameThreshold for status
  - CLI flags (-M, --find-renames) override all config values

The value accepts the same format as -M: a percentage (e.g. 50%) or a
fraction (e.g. 0.5). If unset, the default remains 50%.

This also gives git-blame users control over the rename threshold for
the first time, since blame has no -M threshold flag but inherits
diff.renameThreshold via repo_diff_setup().

Assisted-by: Claude Opus 4.6

__________________

Thanks for taking the time to contribute to Git!

This fork contains changes specific to monorepo scenarios. If you are an
external contributor, then please detail your reason for submitting to
this fork:

* [x] This is an early version of work already under review upstream.
* [ ] This change only applies to interactions with Azure DevOps and the
      GVFS Protocol.
* [ ] This change only applies to the virtualization hook and VFS for
Git.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

10 participants