{"thread":{"id":"65279","subject":"[GSoC Proposal] Refactoring in order to reduce Git's global state","startedAt":"2026-03-17T17:54:30Z","lastAt":"2026-03-24T19:31:57Z","messageCount":5,"participants":["Francesco Paparatto","Christian Couder","Junio C Hamano"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"539244","messageId":"CAEaT9_9jAoXkxKn+2+q654aKybC1=bk6p7xiVHmcy+YDDe7GXw@mail.gmail.com","threadId":"65279","inReplyTo":null,"subject":"[GSoC Proposal] Refactoring in order to reduce Git's global state","fromName":"Francesco Paparatto","fromEmail":"francescopaparatto@gmail.com","sentAt":"2026-03-17T17:54:18Z","receivedAt":"2026-03-17T17:54:30Z","isPatch":false,"sender":{"key":"francescopaparatto@gmail.com","avatar":null},"body":"Refactoring in order to reduce Git's global state\n\nPersonal Information\n--------------------\nName: Francesco Paparatto\nPronouns: he/him\nLocation: Milan, Italy\nTime Zone: CET (UTC+1)\nEmail: francescopaparatto@gmail.com\nGitHub: https://github.com/frapaparatto\nLinkedIn: https://www.linkedin.com/in/francesco-paparatto/\n\nAbout Me\n--------\nI am Francesco Paparatto, a self-taught programmer who dropped out\nof a degree in Management to dedicate full-time to software\nengineering.\n\nMy goal is to work as a Backend/Infrastructure Engineer,\nand to reach that goal I am balancing CS fundamentals through\ntheoretical courses with challenging projects that help me develop\nstrong engineering skills, not only from a code perspective but also\nfrom a system thinking point of view. I also like building\nfundamental things from scratch in order to understand how they work.\n\nThis is my first time in open source and I am fascinated by this\nworld. I wish to become a cornerstone in one open source community.\n\nGit Experience and Contributions\n---------------------------------\nI started learning Git in depth at the beginning of 2026 when I\nbegan working on my cgit project [1], a small reimplementation of\nGit's core plumbing commands in order to understand how they really\nwork under the hood, but also as a way to start reading and learning\nfrom real codebases and learn how to design and structure code\nproperly.\n\nSo far, I have made the following contributions:\n\n* [GSoC PATCH v2] t3310: replace test -f/-d with\n  test_path_is_file/test_path_is_dir\n  Link: https://lore.kernel.org/git/20260228005939.9012-1-francescopaparatto@gmail.com/\n  Status: Graduated to 'master'.\n\n* [PATCH v4] t3310: avoid hiding failures from rev-parse in\n  command substitutions\n  Link: https://lore.kernel.org/git/20260307103631.89829-1-francescopaparatto@gmail.com/\n  Status: Will merge to 'master'.\n\nOverview\n--------\nGit's internal functions rely heavily on global state stored in\nenvironment.c. Configuration values like trust_executable_bit,\neditor_program, and git_commit_encoding are declared as file-scope\nglobals and populated at startup through git_default_config() and\nits sub-handlers like git_default_core_config().\n\nThis design assumes a single repository per process. When Git is\nused as a library (libification) or needs to handle multiple\nrepositories in the same process, globals from one repository\noverwrite values from another. For example, two threads formatting\ncommits for repositories with different i18n.commitEncoding settings\nwould race on the same git_commit_encoding pointer.\n\nThe goal of this project is to move these global variables into\nper-repository structures within struct repository, following the\npattern established by Olamide Bello's Outreachy work with struct\nrepo_config_values [2].\n\nContext and Prior Work\n-----------------------\nNot all config variables can be treated in the same way. There is\na fundamental distinction between eagerly and lazily parsed\nvariables, and conflating the two causes regressions.\n\nVariables set in git_default_core_config() are eagerly parsed. They\nare read at startup, and if a value is invalid, Git calls die()\nimmediately with a clear error before doing any real work. The user\ngets early feedback and can fix their config.\n\nVariables in struct repo_settings are lazily parsed. They are\npopulated on first access via prepare_repo_settings(). If an eagerly\nparsed variable is naively moved into this struct, invalid config\nthat used to crash at startup now crashes mid-operation — the user\nmay have already started work that is now lost.\n\nDuring GSoC 2025, Ayush Chandekar moved several global configuration\nvariables into repository-scoped structures [3]. Through this work\nand subsequent review discussions, the eager/lazy problem became\nvisible [4].\n\nAyush's work also surfaced the getter/setter debate. When he\nintroduced getter and setter functions for repo_settings fields,\nreviewers pointed out they added no value without calling\nprepare_repo_settings() internally. From this discussion, Junio\nsuggested two approaches for repo_settings variables that must\nnot be mixed [5]:\n\n- Common variables: populated in prepare_repo_settings(), accessed\n  directly via repo->settings.foo. No getter, no setter.\n- Rare variables: prepare_repo_settings() does not touch the field.\n  A lazy getter checks a sentinel value (e.g. -1), reads from\n  config on first access, and caches the result.\n\nThe appropriate pattern for each variable will require reasoning\nand discussion on the mailing list.\n\nPhillip Wood suggested a third approach: passing a\nrepository pointer through git_default_config() via the void *cb\ncallback data parameter, so handlers can populate per-repo structs\nwithout touching globals [6].\n\nBuilding on these lessons, Olamide Bello during the Outreachy\nprogram introduced struct repo_config_values [2], a structure\nlinked to struct repository that stores eagerly parsed configuration\nvalues while preserving their startup-time error detection. An\naccessor function repo_config_values() enforces safety by preventing\naccess from uninitialized repositories and guarding against access\nfrom secondary repository instances that do not yet have their\nconfig populated.\n\nSo we now have two structs living inside struct repository:\nrepo_settings for lazily parsed variables, and repo_config_values\nfor eagerly parsed variables.\n\nApproach\n--------\nI will follow the pattern established in Olamide Bello's approved\npatch series [2], which provides the concrete workflow for each\nvariable:\n\n1. Add a new field to struct repo_config_values in environment.h.\n2. Initialize the field in repo_config_values_init().\n3. Update the config callback: get cfg via\n   repo_config_values(the_repository), write to cfg->field instead\n   of the global.\n4. Update all call sites: replace the global with cfg->field.\n5. Remove the global from environment.c and the extern from\n   environment.h.\n6. Run tests and check fuzz targets.\n\nThis workflow is not purely mechanical. Each variable requires\ncase-by-case analysis:\n\n- Is the variable per-repository? Some variables like\n  editor_program are user preferences. As Phillip Wood asked [7]:\n  \"Why would I want to use different editors for different\n  repositories in the same process?\" Variables where per-repo\n  scoping does not make semantic sense may be better handled by\n  localizing them to their subsystem.\n- How deep is the call chain? As preparation for this proposal, I\n  traced askpass_program end-to-end. It has a single reader in\n  prompt.c, which looks simple. But git_prompt() is called from\n  two paths: the credential system and the bisect system. The\n  difficulty of a variable is not about reader count — it is\n  about call chain depth.\n- Are there initialization ordering constraints? Some variables\n  like is_bare_repository_cfg are set during .git directory\n  discovery, before struct repository is fully initialized.\n  Moving them into the repository struct creates a chicken-and-egg\n  problem that requires design discussion on the mailing list.\n\nThe macro #define USE_THE_REPOSITORY_VARIABLE, introduced by\nPatrick Steinhardt [8], controls access to the_repository\nglobal. The macro serves both as a migration indicator and a\ntechnical gate. When all globals in a file have been migrated\nand all functions receive struct repository * explicitly,\nthe macro can be removed.\n\nFollowing Stolee's two-step migration model [9], I will first\nmove variables into repo_config_values using the_repository\n(Step 1: safe, mechanical, no behavior change). For selected\nvariables with shallow call chains, I will also thread struct\nrepository *repo through callers to begin replacing direct\nthe_repository usage (Step 2).\n\nI propose a dual approach for organizing the work:\n\n- Variable-focused migration: move environment.c globals into\n  repo_config_values following Bello's pattern. This is the\n  primary track. For each variable, I classify it, trace readers,\n  migrate it, and remove the global.\n- File-focused cleanup: for files where only a few the_repository\n  usages remain after variable migration, complete the cleanup\n  and remove USE_THE_REPOSITORY_VARIABLE entirely. This is a\n  natural side effect of the first track.\n\nSome variables may need a hybrid approach: when a variable is\nused across many files but heavily concentrated in one subsystem,\nit may make sense to migrate it alongside other globals in that\nsubsystem rather than in isolation.\n\nThe two tracks reinforce each other: migrating a variable often\nremoves the last reason a file needs the macro.\n\nTimeline\n--------\nProject size: 175 hours.\n\nCommunity Bonding (May 1 - May 25):\n- Discuss project direction and design approaches with mentors.\n- Study Bello Caleb's and Ayush Chandekar's patches in depth.\n  Review remaining repo_config_values work and identify\n  unfinished tasks.\n- Identify and prioritize two main areas of work:\n  + Variables in environment.c to migrate into repo_config_values.\n  + Files where USE_THE_REPOSITORY_VARIABLE can be removed.\n- Submit an RFC patch following Bello's pattern to validate\n  the workflow before the coding period begins.\n\nCoding Period (May 26 - August 16):\n- Start with straightforward variables: those with few readers,\n  clear per-repository semantics, and simple parsing logic\n  (e.g., boolean flags and integer configs).\n- Progressively move to more involved variables with deeper call\n  chains, string-type values, or dependencies on other variables.\n- Apply the dual approach described above:\n  + Variable-focused migration: classify, trace, migrate, and\n    remove globals following Bello's pattern.\n  + File-focused cleanup: where variable migration removes the\n    last global dependency in a file, complete the cleanup and\n    remove USE_THE_REPOSITORY_VARIABLE.\n- Submit small patch series (3-5 patches each) frequently to\n  respect reviewers' time and maintain steady velocity.\n- Maintain two parallel series: one in review and one being\n  written, to account for review cycle delays.\n- Continuously iterate: incorporate mailing list feedback,\n  reroll patches (v2/v3), and refine the approach based on\n  community input.\n- Publish weekly or biweekly blog updates documenting progress\n  and design decisions.\n\nFinal period (August 17 - August 24):\n- Address any remaining tasks or pending patches.\n- Run full test suite with AddressSanitizer to verify no\n  memory issues were introduced.\n- Update internal documentation.\n- Receive final feedback from mentors and reviewers.\n- Prepare and submit the final project report.\n\nA 30% buffer is built into the schedule to account for\nunexpected review delays and design discussions.\n\nBlogging\n--------\nI believe blogging is an important part of growing as a developer\nand an effective way to learn, because writing forces you to\ntruly understand what you are working on.\n\nI plan to publish weekly updates documenting my journey through this\nproject: progress, design decisions, challenges, and lessons\nlearned. I also want these posts to serve as a valuable resource\nfor anyone who, like me today, will look for guidance on\ncontributing to Git or to open source projects in general.\n\nAvailability\n------------\nGit will be my top priority. I have no other commitments\nscheduled during the GSoC period, so I will be able to work on\nthis full-time. In fact, I plan to devote 35–40+ hours per week\nto the Git project. My preferred working window is 9:00-18:00 CET.\n\nPost-GSoC\n---------\nContributing to Git has been an invaluable experience.\nNot only on a personal level—because it pushed me out of my\ncomfort zone and challenged me—but also, and above all, on a\nprofessional level. The feeling of working on code used by millions\nof developers and companies around the world is incredibly rewarding.\n\nThis iterative process of discussions, writing code, and receiving\nfeedback helps you grow tremendously as a developer—and\nespecially quickly.\n\nBeing exposed to a codebase like Git’s forces you to think much more\ndeeply, to understand how everything works and how it connects\nto the rest of the program. For these reasons, I intend to continue\nworking on Git even after GSoC by contributing patches, participating\nin discussions, and reviewing new members’ code.\n\nFurthermore, this refactoring process is a long-term effort,\nand I’d like to keep working on it.\n\nReferences\n----------\n[1] https://github.com/frapaparatto/cgit\n[2] https://lore.kernel.org/git/cover.1768217572.git.belkid98@gmail.com/\n[3] https://lore.kernel.org/git/20250603131806.14915-1-ayu.chandekar@gmail.com/\n[4] https://lore.kernel.org/git/17b7f51c-0c3d-4d63-a501-47ce829f7345@gmail.com/\n[5] https://lore.kernel.org/git/xmqqbjquge0c.fsf@gitster.g/\n[6] https://lore.kernel.org/git/d61c966b-61ae-4ba9-b983-c8dab6e2c292@gmail.com/\n[7] https://lore.kernel.org/git/8e657184-ee0b-453a-9f2d-a98080d3582e@gmail.com/\n[8] https://lore.kernel.org/git/cover.1718347699.git.ps@pks.im/\n[9] https://lore.kernel.org/git/47d09c43-6d27-40ff-8dbc-22cc4a5949ed@gmail.com/\n"},{"id":"539599","messageId":"CAP8UFD1H8ZsxfGSnnvX9xkKLSSpDjA3e3KNZ7eHN3ruq-sC7fw@mail.gmail.com","threadId":"65279","inReplyTo":"CAEaT9_9jAoXkxKn+2+q654aKybC1=bk6p7xiVHmcy+YDDe7GXw@mail.gmail.com","subject":"Re: [GSoC Proposal] Refactoring in order to reduce Git's global state","fromName":"Christian Couder","fromEmail":"christian.couder@gmail.com","sentAt":"2026-03-21T13:36:01Z","receivedAt":"2026-03-21T13:36:13Z","isPatch":false,"sender":{"key":"christian.couder@gmail.com","avatar":null},"body":"Hi,\n\nOn Tue, Mar 17, 2026 at 6:54 PM Francesco Paparatto\n<francescopaparatto@gmail.com> wrote:\n\n[...]\n\n> So far, I have made the following contributions:\n>\n> * [GSoC PATCH v2] t3310: replace test -f/-d with\n>   test_path_is_file/test_path_is_dir\n>   Link: https://lore.kernel.org/git/20260228005939.9012-1-francescopaparatto@gmail.com/\n>   Status: Graduated to 'master'.\n\nFor commits which graduated to master, please give the commit ID of\neither the commits you authored or the merge commit that merged your\ncommit(s) into master.\n\n> * [PATCH v4] t3310: avoid hiding failures from rev-parse in\n>   command substitutions\n>   Link: https://lore.kernel.org/git/20260307103631.89829-1-francescopaparatto@gmail.com/\n>   Status: Will merge to 'master'.\n\n[...]\n\n> Context and Prior Work\n> -----------------------\n> Not all config variables can be treated in the same way. There is\n> a fundamental distinction between eagerly and lazily parsed\n> variables, and conflating the two causes regressions.\n>\n> Variables set in git_default_core_config() are eagerly parsed. They\n> are read at startup, and if a value is invalid, Git calls die()\n> immediately with a clear error before doing any real work. The user\n> gets early feedback and can fix their config.\n>\n> Variables in struct repo_settings are lazily parsed. They are\n> populated on first access via prepare_repo_settings(). If an eagerly\n> parsed variable is naively moved into this struct, invalid config\n> that used to crash at startup now crashes mid-operation — the user\n> may have already started work that is now lost.\n>\n> During GSoC 2025, Ayush Chandekar moved several global configuration\n> variables into repository-scoped structures [3]. Through this work\n> and subsequent review discussions, the eager/lazy problem became\n> visible [4].\n>\n> Ayush's work also surfaced the getter/setter debate. When he\n> introduced getter and setter functions for repo_settings fields,\n> reviewers pointed out they added no value without calling\n> prepare_repo_settings() internally. From this discussion, Junio\n> suggested two approaches for repo_settings variables that must\n> not be mixed [5]:\n>\n> - Common variables: populated in prepare_repo_settings(), accessed\n>   directly via repo->settings.foo. No getter, no setter.\n> - Rare variables: prepare_repo_settings() does not touch the field.\n>   A lazy getter checks a sentinel value (e.g. -1), reads from\n>   config on first access, and caches the result.\n>\n> The appropriate pattern for each variable will require reasoning\n> and discussion on the mailing list.\n>\n> Phillip Wood suggested a third approach: passing a\n> repository pointer through git_default_config() via the void *cb\n> callback data parameter, so handlers can populate per-repo structs\n> without touching globals [6].\n>\n> Building on these lessons, Olamide Bello during the Outreachy\n> program introduced struct repo_config_values [2], a structure\n> linked to struct repository that stores eagerly parsed configuration\n> values while preserving their startup-time error detection. An\n> accessor function repo_config_values() enforces safety by preventing\n> access from uninitialized repositories and guarding against access\n> from secondary repository instances that do not yet have their\n> config populated.\n>\n> So we now have two structs living inside struct repository:\n> repo_settings for lazily parsed variables, and repo_config_values\n> for eagerly parsed variables.\n>\n> Approach\n> --------\n> I will follow the pattern established in Olamide Bello's approved\n> patch series [2], which provides the concrete workflow for each\n> variable:\n>\n> 1. Add a new field to struct repo_config_values in environment.h.\n> 2. Initialize the field in repo_config_values_init().\n> 3. Update the config callback: get cfg via\n>    repo_config_values(the_repository), write to cfg->field instead\n>    of the global.\n> 4. Update all call sites: replace the global with cfg->field.\n> 5. Remove the global from environment.c and the extern from\n>    environment.h.\n> 6. Run tests and check fuzz targets.\n\nBy the way there is also this series from Olamide Bello:\n\nhttps://lore.kernel.org/git/cover.1773127785.git.belkid98@gmail.com/\n\n> Timeline\n> --------\n> Project size: 175 hours.\n>\n> Community Bonding (May 1 - May 25):\n> - Discuss project direction and design approaches with mentors.\n> - Study Bello Caleb's and Ayush Chandekar's patches in depth.\n>   Review remaining repo_config_values work and identify\n>   unfinished tasks.\n\nIt would be nice if your proposal started to look at the remaining\nrepo_config_values work already.\n\nThanks for your interest in Git and this project.\n\nBest,\nChristian.\n"},{"id":"539600","messageId":"CAEaT9__zLj+9YQCn-nWqRL6qF=T4rUnY2r6Un=1cjZEFOP8dmw@mail.gmail.com","threadId":"65279","inReplyTo":"CAP8UFD1H8ZsxfGSnnvX9xkKLSSpDjA3e3KNZ7eHN3ruq-sC7fw@mail.gmail.com","subject":"Re: [GSoC Proposal] Refactoring in order to reduce Git's global state","fromName":"Francesco Paparatto","fromEmail":"francescopaparatto@gmail.com","sentAt":"2026-03-21T13:56:46Z","receivedAt":"2026-03-21T13:56:59Z","isPatch":false,"sender":{"key":"francescopaparatto@gmail.com","avatar":null},"body":"Christian Couder <christian.couder@gmail.com> writes:\n\nHi Christian,\nThanks for the feedback.\n\n>\n> For commits which graduated to master, please give the commit ID of\n> either the commits you authored or the merge commit that merged your\n> commit(s) into master.\n\nI will add the commit IDs in v2.\n\n>\n> By the way there is also this series from Olamide Bello:\n>\n> https://lore.kernel.org/git/cover.1773127785.git.belkid98@gmail.com/\n\nThanks for pointing me to Olamide's latest series, I will\nstudy it and use it to map the remaining repo_config_values\nwork directly in the proposal.\n\nBest,\nFrancesco\n"},{"id":"539604","messageId":"xmqq5x6pb0st.fsf@gitster.g","threadId":"65279","inReplyTo":"CAP8UFD1H8ZsxfGSnnvX9xkKLSSpDjA3e3KNZ7eHN3ruq-sC7fw@mail.gmail.com","subject":"Re: [GSoC Proposal] Refactoring in order to reduce Git's global state","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2026-03-21T16:32:50Z","receivedAt":"2026-03-21T16:32:53Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":null},"body":"Christian Couder <christian.couder@gmail.com> writes:\n\n>> * [GSoC PATCH v2] t3310: replace test -f/-d with\n>>   test_path_is_file/test_path_is_dir\n>>   Link: https://lore.kernel.org/git/20260228005939.9012-1-francescopaparatto@gmail.com/\n>>   Status: Graduated to 'master'.\n>\n> For commits which graduated to master, please give the commit ID of\n> either the commits you authored or the merge commit that merged your\n> commit(s) into master.\n\nThis might be way offtopic, I know, but the success criteria of\nmicroproject being that the candidate has learned to effectively\ncommunicate what they did and interact with others on the list,\nit might be less work for both of you to drop \"Status\".  Whether\nthe resulting commit is in my tree or not is of much lessor\nimportance than what we can see in the exchange in the discussion\nthread.\n\n\n"},{"id":"539875","messageId":"CAEaT9_9vYVWBjYVfdkipTO85NE93XbZqrKGMAd5FAC6BLtnhwg@mail.gmail.com","threadId":"65279","inReplyTo":"CAEaT9_9jAoXkxKn+2+q654aKybC1=bk6p7xiVHmcy+YDDe7GXw@mail.gmail.com","subject":"Re: [GSoC Proposal v2] Refactoring in order to reduce Git's global state","fromName":"Francesco Paparatto","fromEmail":"francescopaparatto@gmail.com","sentAt":"2026-03-24T19:31:44Z","receivedAt":"2026-03-24T19:31:57Z","isPatch":false,"sender":{"key":"francescopaparatto@gmail.com","avatar":null},"body":"This is my second version of GSoC 2026 Proposal for the project\n'Refactoring in order to reduce Git’s global state'.\n\nDoc version: https://docs.google.com/document/d/1xknrv88MnFPidpCbGoK43oAH3rlb_Iiu7Ufx42A3krw/edit?usp=sharing\n\nChanges from v1:\n- Added Doc version of the proposal\n- Added commit IDs for patches merged to master.\n- Added reference to Olamide Bello's latest series [10].\n- Added \"Remaining Work\" section with variable classification\n  based on codebase analysis of the Olamide Bello latest series,\n  as suggested by Christian [11].\n\n---\n\nRefactoring in order to reduce Git's global state\n\nPersonal Information\n--------------------\nName: Francesco Paparatto\nPronouns: he/him\nLocation: Milan, Italy\nTimezone: CET (UTC+1)\n\nEmail: francescopaparatto@gmail.com\nGitHub: https://github.com/frapaparatto\nLinkedIn: https://www.linkedin.com/in/francesco-paparatto/\n\nAbout Me\n--------\nI am Francesco Paparatto, a self-taught programmer who dropped out\nof a degree in Management to dedicate full-time to software\nengineering.\n\nMy goal is to work as a Backend/Infrastructure Engineer,\nand to reach that goal I am balancing CS fundamentals through\ntheoretical courses with challenging projects that help me develop\nstrong engineering skills, not only from a code perspective but also\nfrom a system thinking point of view. I also like building\nfundamental things from scratch in order to understand how they work.\n\nThis is my first time in open source and I am fascinated by this\nworld. I wish to become a cornerstone in one open source community.\n\nGit Experience and Contributions\n---------------------------------\nI started learning Git in depth at the beginning of 2026 when I\nbegan working on my cgit project [1], a small reimplementation of\nGit's core plumbing commands in order to understand how they really\nwork under the hood, but also as a way to start reading and learning\nfrom real codebases and learn how to design and structure code\nproperly.\n\nSo far, I have made the following contributions:\n\n* [GSoC PATCH v2] t3310: replace test -f/-d with\n  test_path_is_file/test_path_is_dir\n  Status: Graduated to 'master'.\n  Link: https://lore.kernel.org/git/20260228005939.9012-1-francescopaparatto@gmail.com/\n  Commit: f31b322008c526693660770e66c12f4bcfd29558\n\n* [PATCH v4] t3310: avoid hiding failures from rev-parse in\n  command substitutions\n  Status: Graduated to 'master'.\n  Link: https://lore.kernel.org/git/20260307103631.89829-1-francescopaparatto@gmail.com/\n  Commit: d3edca979a1e916518bc2376e468609ddae2a217\n\nOverview\n--------\nGit's internal functions rely heavily on global state stored in\nenvironment.c. Configuration values like trust_executable_bit,\neditor_program, and git_commit_encoding are declared as file-scope\nglobals and populated at startup through git_default_config() and\nits sub-handlers like git_default_core_config().\n\nThis design assumes a single repository per process. When Git is\nused as a library (libification) or needs to handle multiple\nrepositories in the same process, globals from one repository\noverwrite values from another. For example, two threads formatting\ncommits for repositories with different i18n.commitEncoding settings\nwould race on the same git_commit_encoding pointer.\n\nThe goal of this project is to move these global variables into\nper-repository structures within struct repository, following the\npattern established by Olamide Bello's Outreachy work with struct\nrepo_config_values [2].\n\nContext and Prior Work\n-----------------------\nNot all config variables can be treated in the same way. There is\na fundamental distinction between eagerly and lazily parsed\nvariables, and conflating the two causes regressions.\n\nVariables set in git_default_core_config() are eagerly parsed. They\nare read at startup, and if a value is invalid, Git calls die()\nimmediately with a clear error before doing any real work. The user\ngets early feedback and can fix their config.\n\nVariables in struct repo_settings are lazily parsed. They are\npopulated on first access via prepare_repo_settings(). If an eagerly\nparsed variable is naively moved into this struct, invalid config\nthat used to crash at startup now crashes mid-operation.\n\nDuring GSoC 2025, Ayush Chandekar moved several global configuration\nvariables into repository-scoped structures [3]. Through this work\nand subsequent review discussions, the eager/lazy problem became\nvisible [4].\n\nAyush's work also surfaced the getter/setter debate. When he\nintroduced getter and setter functions for repo_settings fields,\nreviewers pointed out they added no value without calling\nprepare_repo_settings() internally. From this discussion, Junio\nsuggested two approaches for repo_settings variables that must\nnot be mixed [5]:\n\n- Common variables: populated in prepare_repo_settings(), accessed\n  directly via repo->settings.foo. No getter, no setter.\n- Rare variables: prepare_repo_settings() does not touch the field.\n  A lazy getter checks a sentinel value (e.g. -1), reads from\n  config on first access, and caches the result.\n\nThe appropriate pattern for each variable will require reasoning\nand discussion on the mailing list.\n\nPhillip Wood suggested a third approach: passing a\nrepository pointer through git_default_config() via the void *cb\ncallback data parameter, so handlers can populate per-repo structs\nwithout touching globals [6].\n\nBuilding on these lessons, Olamide Bello during the Outreachy\nprogram introduced struct repo_config_values [2], a structure\nlinked to struct repository that stores eagerly parsed configuration\nvalues while preserving their startup-time error detection. An\naccessor function repo_config_values() enforces safety by preventing\naccess from uninitialized repositories and guarding against access\nfrom secondary repository instances that do not yet have their\nconfig populated.\n\nSo we now have two structs living inside struct repository:\nrepo_settings for lazily parsed variables, and repo_config_values\nfor eagerly parsed variables.\n\nApproach\n--------\nI will follow the pattern established in Olamide Bello's approved\npatch series [2], which provides the concrete workflow for each\nvariable:\n\n1. Add a new field to struct repo_config_values in environment.h.\n2. Initialize the field in repo_config_values_init().\n3. Update the config callback: get cfg via\n   repo_config_values(the_repository), write to cfg->field instead\n   of the global.\n4. Update all call sites: replace the global with cfg->field.\n5. Remove the global from environment.c and the extern from\n   environment.h.\n6. Run tests and check fuzz targets.\n\nAdditionally, when a variable is also written by CLI options (e.g.,\nOPT_INTEGER or OPT_BOOL in builtin/*.c), those option definitions\nmust also be updated to point to cfg->field. If only the config\npath is updated and the CLI path is missed, CLI values silently\nstop working. This was caught during review of Bello's\npack_compression_level patch [10].\n\nThis workflow is not purely mechanical. Each variable requires\ncase-by-case analysis:\n\n- Is the variable per-repository? Some variables like\n  editor_program are user preferences. As Phillip Wood asked [7],\n  variables where per-repo scoping does not make semantic sense\n  may be better handled by localizing them to their subsystem.\n\n- How deep is the call chain? As preparation for this proposal, I\n  traced askpass_program end-to-end. It has a single reader in\n  prompt.c, which looks simple. But git_prompt() is called from\n  two paths: the credential system and the bisect system. The\n  difficulty of a variable is not about reader count, it is\n  about call chain depth.\n\n- Are there initialization ordering constraints? Some variables\n  like is_bare_repository_cfg are set during .git directory\n  discovery, before struct repository is fully initialized.\n  Moving them into the repository struct creates a chicken-and-egg\n  problem that requires design discussion on the mailing list.\n\n- Are there dependent variables? Some variables must be migrated\n  together. For example, comment_line_str_to_free and\n  auto_comment_line_char are set in the same config callback and\n  read together in builtin/commit.c. Migrating one without the\n  other would leave half the state global and half per-repo.\n\n- Does the variable have CLI interaction? Variables written by\n  command-line options via OPT_INTEGER, OPT_BOOL, etc. need both\n  the config path and the CLI path updated.\n\nThe macro #define USE_THE_REPOSITORY_VARIABLE, introduced by\nPatrick Steinhardt [8], controls access to the_repository\nglobal. The macro serves both as a migration indicator and a\ntechnical gate. When all globals in a file have been migrated\nand all functions receive struct repository * explicitly,\nthe macro can be removed.\n\nFollowing Stolee's two-step migration model [9], I will first\nmove variables into repo_config_values using the_repository\n(Step 1: safe, mechanical, no behavior change). For selected\nvariables with shallow call chains, I will also thread struct\nrepository *repo through callers to begin replacing direct\nthe_repository usage (Step 2).\n\nI propose a dual approach for organizing the work:\n\n- Variable-focused migration: move environment.c globals into\n  repo_config_values following Bello's pattern. This is the\n  primary track. For each variable, I classify it, trace readers,\n  migrate it, and remove the global.\n- File-focused cleanup: for files where only a few the_repository\n  usages remain after variable migration, complete the cleanup\n  and remove USE_THE_REPOSITORY_VARIABLE entirely. This is a\n  natural side effect of the first track.\n\nSome variables may need a hybrid approach: when a variable is\nused across many files but heavily concentrated in one subsystem,\nit may make sense to migrate it alongside other globals in that\nsubsystem rather than in isolation.\n\nThe two tracks reinforce each other: migrating a variable often\nremoves the last reason a file needs the macro.\n\nRemaining Work and Variable Classification\n--------------------------------------------\nOlamide Bello's merged series [2] migrated: git_attributes_file,\ncore_apply_sparse_checkout, and git_branch_track.\n\nHis latest series [10] addresses: trust_ctime, check_stat,\nzlib_compression_level, pack_compression_level, precomposed_unicode,\ncore_sparse_checkout_cone, sparse_expect_files_outside_of_patterns,\nand warn_on_object_refname_ambiguity.\n\nAfter those series, approximately 20+ variables remain in\nenvironment.c. I analyzed them and classified a representative\nset below, grouped by difficulty and type of challenge they\npresent.\n\nStraightforward per-repo booleans (few readers, no CLI\ninteraction, clearly filesystem-dependent):\n\n* trust_executable_bit (core.filemode)\n  Eagerly parsed in git_default_core_config() at\n  environment.c:307. Determines whether the filesystem\n  correctly represents executable bits. Per-repo because\n  different repos may live on different filesystems (e.g.,\n  FAT32 does not support executable bits, ext4 does). Git\n  probes this during init/clone.\n\n  Reader files: apply.c, read-cache.c, read-cache.h (3 files).\n  No CLI interaction.\n  Note: used together with has_symlinks in read-cache.c:744,\n  migrating both in the same series would be clean.\n\n* has_symlinks (core.symlinks)\n  Eagerly parsed in git_default_core_config(). Determines\n  whether the filesystem supports symbolic links. Same\n  rationale as trust_executable_bit: filesystem-dependent,\n  clearly per-repo.\n\n  Reader files: apply.c, combine-diff.c, compat/mingw.c,\n  entry.c, read-cache.c, read-cache.h (6 files).\n  No CLI interaction with the global. Note: builtin/difftool.c\n  has its own local has_symlinks field inside struct\n  difftool_options. This is a separate variable with the same\n  name, not the global.\n\nAmbiguous per-repo semantics (require mailing list discussion):\n\n* editor_program (core.editor)\n  Eagerly parsed in git_default_core_config() at\n  environment.c:438. Sets the default editor. Phillip Wood\n  questioned whether per-repo scoping makes sense [7], since\n  it is a user preference rather than a repository property.\n\n  Reader files: editor.c (1 file). Very shallow call chain\n  but the design question must be resolved first.\n  No CLI interaction. No dependencies.\n\nDependent variables (must be migrated together):\n\n* comment_line_str_to_free and auto_comment_line_char\n  (core.commentchar, core.commentstring)\n  Both eagerly parsed in the same config callback in\n  git_default_core_config(). auto_comment_line_char is a\n  boolean flag controlling whether Git auto-selects a comment\n  character that does not conflict with the commit message.\n  comment_line_str_to_free stores the actual string used.\n  They are set together and read together in\n  builtin/commit.c. Migrating one without the other would\n  leave half the state global and half per-repo.\n\n  Reader files: builtin/commit.c (1 file for both).\n  No CLI interaction.\n\nHigh reader count (significant effort):\n\n* ignore_case (core.ignorecase)\n  Eagerly parsed in git_default_core_config(). Enables Git\n  to work on case-insensitive filesystems. Clearly per-repo\n  (filesystem-dependent, probed during init/clone).\n\n  Reader files: apply.c, dir.c, fsmonitor.c, name-hash.c,\n  read-cache.c, refs/files-backend.c, submodule.c, ... (15+ files)\n\n  Note: many builtin/ files (grep.c, branch.c, tag.c,\n  for-each-ref.c) have their own ignore_case fields in local\n  structs. These are separate from the global. Careful\n  analysis is needed to distinguish global usage from local\n  usage.\n\nOther remaining variables that will be classified during the\ncommunity bonding period:\n\n  minimum_abbrev, default_abbrev, assume_unchanged,\n  git_commit_encoding, git_log_output_encoding,\n  apply_default_whitespace, apply_default_ignorewhitespace,\n  fsync_object_files, use_fsync, fsync_method,\n  fsync_components, askpass_program, excludes_file,\n  auto_crlf, core_eol, global_conv_flags_eol,\n  check_roundtrip_encoding, autorebase, push_default,\n  object_creation_mode, grafts_keep_true_parents,\n  pack_size_limit_cfg, protect_hfs, protect_ntfs,\n  git_work_tree_cfg.\n\nTimeline\n--------\nProject size: 175 hours.\n\nCommunity Bonding (May 1 - May 25):\n- Discuss project direction and design approaches with mentors.\n- Study Bello Caleb's and Ayush Chandekar's patches in depth.\n  Review remaining repo_config_values work and identify\n  unfinished tasks.\n- Complete classification of remaining variables listed above.\n- Start discussions for ambiguous cases on the mailing list.\n- Submit an RFC patch following Bello's pattern to validate\n  the workflow before the coding period begins.\n\nCoding Period (May 26 - August 16):\n- Start with straightforward variables: filesystem-dependent\n  booleans like trust_executable_bit and has_symlinks. These\n  have few readers, clear per-repo semantics, and no complex\n  parsing.\n- Progressively move to more involved variables: string-type\n  values like excludes_file, dependent pairs like\n  comment_line_str_to_free and auto_comment_line_char, and\n  high-reader-count variables like ignore_case.\n- Apply the dual approach described above:\n  + Variable-focused migration: classify, trace, migrate, and\n    remove globals following Bello's pattern.\n  + File-focused cleanup: where variable migration removes the\n    last global dependency in a file, complete the cleanup and\n    remove USE_THE_REPOSITORY_VARIABLE.\n- Submit small patch series (3-5 patches each) frequently to\n  respect reviewers' time and maintain steady velocity.\n- Maintain two parallel series: one in review and one being\n  written, to account for review cycle delays.\n- Continuously iterate: incorporate mailing list feedback,\n  reroll patches (v2/v3), and refine the approach based on\n  community input.\n- Publish weekly blog updates documenting progress and design\n  decisions.\n\nFinal period (August 17 - August 24):\n- Address any remaining tasks or pending patches.\n- Update internal documentation.\n- Receive final feedback from mentors and reviewers.\n- Prepare and submit the final project report.\n\nA 30% buffer is built into the schedule to account for\nunexpected review delays and design discussions.\n\nBlogging\n--------\nI believe blogging is an important part of growing as a developer\nand an effective way to learn, because writing forces you to\ntruly understand what you are working on.\n\nI plan to publish weekly updates documenting my journey through this\nproject: progress, design decisions, challenges, and lessons\nlearned. I also want these posts to serve as a valuable resource\nfor anyone who, like me today, will look for guidance on\ncontributing to Git or to open source projects in general.\n\nAvailability\n------------\nGit will be my top priority. I have no other commitments\nscheduled during the GSoC period, so I will be able to work on\nthis full-time. In fact, I plan to devote 35–40+ hours per week\nto the Git project. My preferred working window is 9:00-18:00 CET.\n\nPost-GSoC\n---------\nContributing to Git has been an invaluable experience.\nNot only on a personal level because it pushed me out of my\ncomfort zone and challenged me but also, and above all, on a\nprofessional level. The feeling of working on code used by millions\nof developers and companies around the world is incredibly rewarding.\n\nThis iterative process of discussions, writing code, and receiving\nfeedback helps you grow tremendously as a developer and\nespecially quickly.\n\nBeing exposed to a codebase like Git’s forces you to think much more\ndeeply, to understand how everything works and how it connects\nto the rest of the program. For these reasons, I intend to continue\nworking on Git even after GSoC by contributing patches, participating\nin discussions, and reviewing new members’ code.\n\nFurthermore, this refactoring process is a long-term effort,\nand I’d like to keep working on it.\n\nReferences\n----------\n[1] https://github.com/frapaparatto/cgit\n[2] https://lore.kernel.org/git/cover.1768217572.git.belkid98@gmail.com/\n[3] https://lore.kernel.org/git/20250603131806.14915-1-ayu.chandekar@gmail.com/\n[4] https://lore.kernel.org/git/17b7f51c-0c3d-4d63-a501-47ce829f7345@gmail.com/\n[5] https://lore.kernel.org/git/xmqqbjquge0c.fsf@gitster.g/\n[6] https://lore.kernel.org/git/d61c966b-61ae-4ba9-b983-c8dab6e2c292@gmail.com/\n[7] https://lore.kernel.org/git/8e657184-ee0b-453a-9f2d-a98080d3582e@gmail.com/\n[8] https://lore.kernel.org/git/cover.1718347699.git.ps@pks.im/\n[9] https://lore.kernel.org/git/47d09c43-6d27-40ff-8dbc-22cc4a5949ed@gmail.com/\n[10] https://lore.kernel.org/git/cover.1773127785.git.belkid98@gmail.com/\n[11] https://lore.kernel.org/git/CAP8UFD1H8ZsxfGSnnvX9xkKLSSpDjA3e3KNZ7eHN3ruq-sC7fw@mail.gmail.com/\n"}]}