[{"data":1,"prerenderedAt":2239},["ShallowReactive",2],{"/blog/whats-new-in-git-2-52-0":3,"navigation-en-us":1431,"banner-en-us":1858,"footer-en-us":1868,"blog-post-authors-en-us-Christian Couder|Toon Claes|Patrick Steinhardt":2113,"blog-related-posts-en-us-whats-new-in-git-2-52-0":2152,"blog-promotions-en-us":2175,"next-steps-en-us":2229},{"id":4,"title":5,"authors":6,"body":10,"category":1412,"date":1413,"description":1414,"extension":1415,"externalUrl":1416,"faq":1416,"featured":268,"heroImage":1417,"meta":1418,"navigation":268,"path":1419,"seo":1420,"slug":1423,"stem":1424,"tags":1425,"template":1429,"updatedDate":1416,"__hash__":1430},"blogPosts/en-us/blog/whats-new-in-git-2-52-0.md","What’s new in Git 2.52.0?",[7,8,9],"Christian Couder","Toon Claes","Patrick Steinhardt",{"type":11,"value":12,"toc":1400},"minimark",[13,30,35,38,242,249,252,308,311,354,357,367,370,377,551,554,574,584,606,610,626,641,662,665,668,676,693,696,728,731,741,748,757,761,764,771,791,797,806,812,818,845,848,851,859,863,872,875,1145,1148,1157,1161,1164,1169,1181,1194,1198,1205,1222,1294,1306,1310,1338,1358,1370,1374,1380,1383,1396],[14,15,16,17,23,24,29],"p",{},"The Git project recently released ",[18,19,22],"a",{"href":20,"rel":21},"https://lore.kernel.org/git/xmqqh5usmvsd.fsf@gitster.g/",[],"Git 2.52",". After a relatively short 8-week ",[18,25,28],{"href":26,"rel":27},"https://about.gitlab.com/blog/what-s-new-in-git-2-51-0/",[],"release cycle for 2.51",", due to summer in the Northern Hemisphere, this release is back to the usual 12-week cycle. Let’s look at some notable changes, including contributions from the GitLab Git team and the wider Git community.",[31,32,34],"h2",{"id":33},"new-git-last-modified1-command","New git-last-modified(1) command",[14,36,37],{},"Many Git forges like GitLab display files in a tree view like this:",[39,40,41,57],"table",{},[42,43,44],"thead",{},[45,46,47,51,54],"tr",{},[48,49,50],"th",{},"Name",[48,52,53],{},"Last commit",[48,55,56],{},"Last update",[58,59,60,72,83,94,105,114,125,140,150,159,169,180,191,202,213,224],"tbody",{},[45,61,62,66,69],{},[63,64,65],"td",{},"README.md",[63,67,68],{},"README: *.txt -> *.adoc fixes",[63,70,71],{},"4 months ago",[45,73,74,77,80],{},[63,75,76],{},"RelNotes",[63,78,79],{},"Start 2.51 cycle, the first batch",[63,81,82],{},"4 weeks ago",[45,84,85,88,91],{},[63,86,87],{},"SECURITY.md",[63,89,90],{},"SECURITY: describe how to report vulnerabilities",[63,92,93],{},"4 years",[45,95,96,99,102],{},[63,97,98],{},"abspath.c",[63,100,101],{},"abspath: move related functions to abspath",[63,103,104],{},"2 years",[45,106,107,110,112],{},[63,108,109],{},"abspath.h",[63,111,101],{},[63,113,104],{},[45,115,116,119,122],{},[63,117,118],{},"aclocal.m4",[63,120,121],{},"configure: use AC_LANG_PROGRAM consistently",[63,123,124],{},"15 years ago",[45,126,127,130,137],{},[63,128,129],{},"add-patch.c",[63,131,132,133],{},"pager: stop using ",[134,135,136],"code",{},"the_repository",[63,138,139],{},"7 months ago",[45,141,142,145,148],{},[63,143,144],{},"advice.c",[63,146,147],{},"advice: allow disabling default branch name advice",[63,149,71],{},[45,151,152,155,157],{},[63,153,154],{},"advice.h",[63,156,147],{},[63,158,71],{},[45,160,161,164,167],{},[63,162,163],{},"alias.h",[63,165,166],{},"rebase -m: fix serialization of strategy options",[63,168,104],{},[45,170,171,174,177],{},[63,172,173],{},"alloc.h",[63,175,176],{},"git-compat-util: move alloc macros to git-compat-util.h",[63,178,179],{},"2 years ago",[45,181,182,185,188],{},[63,183,184],{},"apply.c",[63,186,187],{},"apply: only write intents to add for new files",[63,189,190],{},"8 days ago",[45,192,193,196,199],{},[63,194,195],{},"archive.c",[63,197,198],{},"Merge branch 'ps/parse-options-integers'",[63,200,201],{},"3 months ago",[45,203,204,207,210],{},[63,205,206],{},"archive.h",[63,208,209],{},"archive.h: remove unnecessary include",[63,211,212],{},"1 year",[45,214,215,218,221],{},[63,216,217],{},"attr.h",[63,219,220],{},"fuzz: port fuzz-parse-attr-line from OSS-Fuzz",[63,222,223],{},"9 months ago",[45,225,226,229,240],{},[63,227,228],{},"banned.h",[63,230,231,232,235,236,239],{},"banned.h: mark ",[134,233,234],{},"strtok()"," and ",[134,237,238],{},"strtok_r()"," as banned",[63,241,104],{},[14,243,244,247],{},[245,246],"br",{},[245,248],{},[14,250,251],{},"Next to the files themselves, we also display which commit last modified each respective file. This information is easy to extract from Git by executing the following command:",[253,254,259],"pre",{"className":255,"code":256,"language":257,"meta":258,"style":258},"language-shell shiki shiki-themes github-light","\n$ git log --max-count=1 HEAD -- \u003Cfilename>\n\n","shell","",[134,260,261,270],{"__ignoreMap":258},[262,263,266],"span",{"class":264,"line":265},"line",1,[262,267,269],{"emptyLinePlaceholder":268},true,"\n",[262,271,273,277,281,284,288,291,294,298,301,305],{"class":264,"line":272},2,[262,274,276],{"class":275},"s7eDp","$",[262,278,280],{"class":279},"sYBdl"," git",[262,282,283],{"class":279}," log",[262,285,287],{"class":286},"sYu0t"," --max-count=1",[262,289,290],{"class":279}," HEAD",[262,292,293],{"class":286}," --",[262,295,297],{"class":296},"sD7c4"," \u003C",[262,299,300],{"class":279},"filenam",[262,302,304],{"class":303},"sgsFI","e",[262,306,307],{"class":296},">\n",[14,309,310],{},"While nice and simple, this has a significant catch: Git does not have a way to extract this information for each of these files in a single command. So to get the last commit for all the files in the tree, we'd need to run this command for each file separately. This results in a command pipeline similar to the following:",[253,312,314],{"className":255,"code":313,"language":257,"meta":258,"style":258},"\n$ git ls-tree HEAD --name-only | xargs --max-args=1 git log --max-count=1 HEAD --\n\n",[134,315,316,320],{"__ignoreMap":258},[262,317,318],{"class":264,"line":265},[262,319,269],{"emptyLinePlaceholder":268},[262,321,322,324,326,329,331,334,337,340,343,345,347,349,351],{"class":264,"line":272},[262,323,276],{"class":275},[262,325,280],{"class":279},[262,327,328],{"class":279}," ls-tree",[262,330,290],{"class":279},[262,332,333],{"class":286}," --name-only",[262,335,336],{"class":296}," |",[262,338,339],{"class":275}," xargs",[262,341,342],{"class":286}," --max-args=1",[262,344,280],{"class":279},[262,346,283],{"class":279},[262,348,287],{"class":286},[262,350,290],{"class":279},[262,352,353],{"class":286}," --\n",[14,355,356],{},"Naturally, this isn't very efficient:",[358,359,360,364],"ul",{},[361,362,363],"li",{},"We need to spin up a fresh Git command for each file.",[361,365,366],{},"Git has to step through history for each file separately.",[14,368,369],{},"As a consequence, this whole operation is quite costly and generates significant load for GitLab.",[14,371,372,373,376],{},"To overcome these issues, a new Git subcommand ",[134,374,375],{},"git-last-modified(1)"," has been introduced. This command returns the commit for each file of a given commit:",[253,378,380],{"className":255,"code":379,"language":257,"meta":258,"style":258},"\n$ git last-modified HEAD\n\n\ne56f6dcd7b4c90192018e848d0810f091d092913        add-patch.c\n373ad8917beb99dc643b6e7f5c117a294384a57e        advice.h\ne9330ae4b820147c98e723399e9438c8bee60a80        advice.c\n5e2feb5ca692c5c4d39b11e1ffa056911dd7dfd3        alloc.h\n954d33a9757fcfab723a824116902f1eb16e05f7        RelNotes\n4ce0caa7cc27d50ee1bedf1dff03f13be4c54c1f        apply.c\n5d215a7b3eb0a9a69c0cb9aa43dcae956a0aa03e        archive.c\nc50fbb2dd225e7e82abba4380423ae105089f4d7        README.md\n72686d4e5e9a7236b9716368d86fae5bf1ae6156        attr.h\nc2c4138c07ca4d5ffc41ace0bfda0f189d3e262e        archive.h\n5d1344b4973c8ea4904005f3bb51a47334ebb370        abspath.c\n5d1344b4973c8ea4904005f3bb51a47334ebb370        abspath.h\n60ff56f50372c1498718938ef504e744fe011ffb        banned.h\n4960e5c7bdd399e791353bc6c551f09298746f61        alias.h\n2e99b1e383d2da56c81d7ab7dd849e9dab5b7bf0        SECURITY.md\n1e58dba142c673c59fbb9d10aeecf62217d4fc9c        aclocal.m4\n",[134,381,382,386,398,403,408,417,426,435,444,453,462,471,480,489,498,507,515,524,533,542],{"__ignoreMap":258},[262,383,384],{"class":264,"line":265},[262,385,269],{"emptyLinePlaceholder":268},[262,387,388,390,392,395],{"class":264,"line":272},[262,389,276],{"class":275},[262,391,280],{"class":279},[262,393,394],{"class":279}," last-modified",[262,396,397],{"class":279}," HEAD\n",[262,399,401],{"class":264,"line":400},3,[262,402,269],{"emptyLinePlaceholder":268},[262,404,406],{"class":264,"line":405},4,[262,407,269],{"emptyLinePlaceholder":268},[262,409,411,414],{"class":264,"line":410},5,[262,412,413],{"class":275},"e56f6dcd7b4c90192018e848d0810f091d092913",[262,415,416],{"class":279},"        add-patch.c\n",[262,418,420,423],{"class":264,"line":419},6,[262,421,422],{"class":275},"373ad8917beb99dc643b6e7f5c117a294384a57e",[262,424,425],{"class":279},"        advice.h\n",[262,427,429,432],{"class":264,"line":428},7,[262,430,431],{"class":275},"e9330ae4b820147c98e723399e9438c8bee60a80",[262,433,434],{"class":279},"        advice.c\n",[262,436,438,441],{"class":264,"line":437},8,[262,439,440],{"class":275},"5e2feb5ca692c5c4d39b11e1ffa056911dd7dfd3",[262,442,443],{"class":279},"        alloc.h\n",[262,445,447,450],{"class":264,"line":446},9,[262,448,449],{"class":275},"954d33a9757fcfab723a824116902f1eb16e05f7",[262,451,452],{"class":279},"        RelNotes\n",[262,454,456,459],{"class":264,"line":455},10,[262,457,458],{"class":275},"4ce0caa7cc27d50ee1bedf1dff03f13be4c54c1f",[262,460,461],{"class":279},"        apply.c\n",[262,463,465,468],{"class":264,"line":464},11,[262,466,467],{"class":275},"5d215a7b3eb0a9a69c0cb9aa43dcae956a0aa03e",[262,469,470],{"class":279},"        archive.c\n",[262,472,474,477],{"class":264,"line":473},12,[262,475,476],{"class":275},"c50fbb2dd225e7e82abba4380423ae105089f4d7",[262,478,479],{"class":279},"        README.md\n",[262,481,483,486],{"class":264,"line":482},13,[262,484,485],{"class":275},"72686d4e5e9a7236b9716368d86fae5bf1ae6156",[262,487,488],{"class":279},"        attr.h\n",[262,490,492,495],{"class":264,"line":491},14,[262,493,494],{"class":275},"c2c4138c07ca4d5ffc41ace0bfda0f189d3e262e",[262,496,497],{"class":279},"        archive.h\n",[262,499,501,504],{"class":264,"line":500},15,[262,502,503],{"class":275},"5d1344b4973c8ea4904005f3bb51a47334ebb370",[262,505,506],{"class":279},"        abspath.c\n",[262,508,510,512],{"class":264,"line":509},16,[262,511,503],{"class":275},[262,513,514],{"class":279},"        abspath.h\n",[262,516,518,521],{"class":264,"line":517},17,[262,519,520],{"class":275},"60ff56f50372c1498718938ef504e744fe011ffb",[262,522,523],{"class":279},"        banned.h\n",[262,525,527,530],{"class":264,"line":526},18,[262,528,529],{"class":275},"4960e5c7bdd399e791353bc6c551f09298746f61",[262,531,532],{"class":279},"        alias.h\n",[262,534,536,539],{"class":264,"line":535},19,[262,537,538],{"class":275},"2e99b1e383d2da56c81d7ab7dd849e9dab5b7bf0",[262,540,541],{"class":279},"        SECURITY.md\n",[262,543,545,548],{"class":264,"line":544},20,[262,546,547],{"class":275},"1e58dba142c673c59fbb9d10aeecf62217d4fc9c",[262,549,550],{"class":279},"        aclocal.m4\n",[14,552,553],{},"The benefit of this is obviously that we only have to execute a single Git process now to derive all of that information. But even more importantly, it only requires us to walk the history once for all files together instead of having to walk it multiple times. This is achieved by:",[555,556,557,560,571],"ol",{},[361,558,559],{},"Start walking the history from the specified commit.",[361,561,562,563],{},"For each commit:",[555,564,565,568],{},[361,566,567],{},"If it doesn't modify any of the paths we're interested in we continue to the next commit.",[361,569,570],{},"If it does, we print the commit ID together with the path. Furthermore, we remove the path from the set of interesting paths.",[361,572,573],{},"When the list of interesting paths becomes empty we stop.",[14,575,576,577,579,580,583],{},"Gitaly has already been adjusted to use the new command, but the logic is still guarded by a feature flag. Preliminary testing has shown that ",[134,578,375],{}," is in most situations at least twice as fast compared to using ",[134,581,582],{},"git log --max-count=1",".",[14,585,586],{},[587,588,589,590,595,596,601,602,583],"em",{},"These changes were ",[18,591,594],{"href":592,"rel":593},"https://github.com/ttaylorr/git/tree/tb/blame-tree",[],"originally written"," by multiple developers from GitHub and were ",[18,597,600],{"href":598,"rel":599},"https://lore.kernel.org/git/20250805093358.1791633-1-toon@iotcl.com/",[],"upstreamed"," into Git by ",[18,603,8],{"href":604,"rel":605},"https://gitlab.com/toon",[],[31,607,609],{"id":608},"git-fast-export1-and-git-fast-import1-signature-related-improvements","git-fast-export(1) and git-fast-import(1) signature-related improvements",[14,611,612,613,235,616,619,620,625],{},"The ",[134,614,615],{},"git-fast-export(1)",[134,617,618],{},"git-fast-import(1)"," commands are designed to be mostly used by interoperability or history rewriting tools. The goal of interoperability tools is to make Git interact nicely with other software, usually a different version control system, that stores data in a different format than Git. For example ",[18,621,624],{"href":622,"rel":623},"https://github.com/frej/fast-export",[],"hg-fast-export.sh"," is a “Mercurial to Git converter using git-fast-import.\"",[14,627,628,629,634,635,640],{},"Alternately, history-rewriting tools let users — usually admins — make changes to the history of their repositories that are not possible or not allowed by the version control system. For example, ",[18,630,633],{"href":631,"rel":632},"http://www.catb.org/esr/reposurgeon/",[],"reposurgeon"," says in its ",[18,636,639],{"href":637,"rel":638},"https://gitlab.com/esr/reposurgeon/-/blob/master/repository-editing.adoc?ref_type=heads#introduction",[],"introduction"," that its purpose is “to enable risky operations that version-control systems don't want to let you do, such as (a) editing past comments and metadata, (b) excising commits, (c) coalescing and splitting commits, (d) removing files and subtrees from repo history, (e) merging or grafting two or more repos, and (f) cutting a repo in two by cutting a parent-child link, preserving the branch structure of both child repos.\"",[14,642,643,644,649,650,235,652,654,655,657,658,661],{},"Within GitLab, we use ",[18,645,648],{"href":646,"rel":647},"https://github.com/newren/git-filter-repo",[],"git-filter-repo"," to let admins perform some risky operations on their Git repositories. Unfortunately, until Git 2.50 (released last June), both ",[134,651,615],{},[134,653,618],{}," didn't handle cryptographic commit signatures at all. So, although ",[134,656,615],{}," had a ",[134,659,660],{},"--signed-tags=\u003Cmode>"," option that allows users to change how cryptographic tag signatures are handled, commit signatures were simply ignored.",[14,663,664],{},"Cryptographic signatures are very fragile because they are based on the exact commit or tag data that was signed. When the signed data or any of its preceding history changes, the cryptographic signature becomes invalid. This is a fragile but necessary requirement to make these signatures useful.",[14,666,667],{},"But in the context of rewriting history this is a problem:",[358,669,670,673],{},[361,671,672],{},"We may want to keep cryptographic signatures for both commits and tags that are still valid after the rewrite (e.g. because the history leading up to them did not change).",[361,674,675],{},"We may want to create new cryptographic signatures for commits and tags where the previous signature has become invalid.",[14,677,678,679,681,682,684,685,688,689,692],{},"Neither ",[134,680,618],{}," nor ",[134,683,615],{}," allow for these use cases though, which limits what tools like ",[18,686,648],{"href":646,"rel":687},[]," or ",[18,690,633],{"href":631,"rel":691},[]," can achieve.",[14,694,695],{},"We have made some significant progress:",[358,697,698,711,717],{},[361,699,700,701,704,705,707,708,710],{},"In Git 2.50 we added a ",[134,702,703],{},"--signed-commits=\u003Cmode>"," option to ",[134,706,615],{}," for exporting commit signatures, and support in ",[134,709,618],{}," for importing them.",[361,712,713,714,716],{},"In Git 2.51 we improved the format used for exporting and importing commit signatures, and we made it possible for ",[134,715,618],{}," to import both a signature made on the SHA-1 object ID of the commit and one made on its SHA-256 object ID.",[361,718,719,720,235,722,724,725,727],{},"In Git 2.52 we added the ",[134,721,703],{},[134,723,660],{}," options to ",[134,726,618],{},", so the user has control over how to handle signed data at import time.",[14,729,730],{},"There is still more to be done. We need to add the ability to:",[358,732,733,738],{},[361,734,735,736,583],{},"Retain only those commit signatures that are still valid to ",[134,737,618],{},[361,739,740],{},"Re-sign data where the signature became invalid.",[14,742,743,744,747],{},"We have already started to work on these next steps and expect this to land in Git 2.53. Once done, tools like ",[134,745,746],{},"git-filter-repo(1)"," will finally start to handle cryptographic signatures more gracefully. We will keep you posted in our next Git release blog post.",[14,749,750],{},[587,751,752,753,583],{},"This project was led by ",[18,754,7],{"href":755,"rel":756},"https://gitlab.com/chriscool",[],[31,758,760],{"id":759},"new-and-improved-git-maintenance1-strategies","New and improved git-maintenance(1) strategies",[14,762,763],{},"Git repositories require regular maintenance to ensure that they perform well. This maintenance performs a bunch of different tasks: references get optimized, objects get compressed, and stale data gets pruned.",[14,765,766,767,770],{},"Until Git 2.28, these maintenance tasks were performed by ",[134,768,769],{},"git-gc(1)",". The problem with this command is that it wasn't built with customizability in mind: While certain parameters can be configured, it is not possible to control which parts of a repository should be optimized. This means that it may not be a good fit for all use cases. Even more importantly, it made it very hard to iterate on how exactly Git performs repository maintenance.",[14,772,773,774,779,780,783,784,787,788,790],{},"To fix this issue and allow us to iterate again, ",[18,775,778],{"href":776,"rel":777},"https://github.com/derrickstolee",[],"Derrick Stolee"," introduced ",[134,781,782],{},"git-maintenance(1)",". In contrast to ",[134,785,786],{},"git-gc(1),"," it is built with customizability in mind and allows the user to configure which tasks specifically should be running in a certain repository. This new tool was made the default for Git’s automated maintenance in Git 2.29, but, by default, it still uses ",[134,789,769],{}," to perform the maintenance.",[14,792,793,794,796],{},"While this default maintenance strategy works well in small or even medium-sized repositories, it is problematic in the context of large monorepos. The biggest limiting factor is how ",[134,795,769],{}," repacks objects: Whenever there are more than 50 packfiles, the tool will merge all of them together into a single packfile. This operation is quite CPU-intensive and causes a lot of I/O operations, so for large monorepos this operation can easily take many minutes or even hours to complete.",[14,798,799,800,805],{},"Git already knows how to minimize these repacks via “geometric repacking.” The idea is simple: The packfiles that exist in the repository must follow a geometric progression where every packfile must contain at least twice as many objects as the next smaller one. This allows Git to amortize the number of repacks required while still ensuring that there is only a relatively small number of packfiles overall. This mode was introduced by ",[18,801,804],{"href":802,"rel":803},"https://github.com/ttaylorr",[],"Taylor Blau"," in Git 2.32, but it was not wired up as part of the automated maintenance.",[14,807,808,809,811],{},"All the parts exist to make repository maintenance way more scalable for large monorepos: We have the flexible ",[134,810,782],{}," tool that can be extended to have a new maintenance strategy, and we have a better way to repack objects. All that needs to be done is to combine these two.",[14,813,814,815,817],{},"And that's exactly what we did with Git 2.52! We have introduced a new “geometric” maintenance strategy that you can configure in your Git repositories. This strategy is intended as a full replacement for the old strategy based on ",[134,816,769],{},". Here is the config code you need:",[253,819,821],{"className":255,"code":820,"language":257,"meta":258,"style":258},"\n$ git config set maintenance.strategy geometric\n\n",[134,822,823,827],{"__ignoreMap":258},[262,824,825],{"class":264,"line":265},[262,826,269],{"emptyLinePlaceholder":268},[262,828,829,831,833,836,839,842],{"class":264,"line":272},[262,830,276],{"class":275},[262,832,280],{"class":279},[262,834,835],{"class":279}," config",[262,837,838],{"class":279}," set",[262,840,841],{"class":279}," maintenance.strategy",[262,843,844],{"class":279}," geometric\n",[14,846,847],{},"From hereon, Git will use geometric repacking to optimize your objects. This should lead to less churn while ensuring that your objects are in a better-optimized state, especially in large monorepos.",[14,849,850],{},"In Git 2.53, we aim to make this the default strategy. So stay tuned!",[14,852,853],{},[587,854,752,855,583],{},[18,856,9],{"href":857,"rel":858},"https://gitlab.com/pks-gitlab",[],[31,860,862],{"id":861},"new-subcommand-for-git-repo1-to-display-repository-metrics","New subcommand for git-repo(1) to display repository metrics",[14,864,865,866,871],{},"Performance of Git operations in a repository are often dependent on certain characteristics of its underlying structure. At GitLab, we host some extremely large repositories and having insight into the general structure of a repository is critical to understand performance. While it is possible to compose various Git commands and other tools together to surface certain repository metrics, Git lacks a means to surface info about a repository's shape/structure via a single command. This has led to the development of other external tools, such as ",[18,867,870],{"href":868,"rel":869},"https://github.com/github/git-sizer",[],"git-sizer(1)",", to fill this gap.",[14,873,874],{},"With the release of Git 2.52, a new “structure” subcommand has been added to git-repo(1) with the aim to surface information about a repository's structure. Currently, it displays info about the number of references and objects in the repository in the following form:",[253,876,878],{"className":255,"code":877,"language":257,"meta":258,"style":258},"\n$ git repo structure\n\n\n| Repository structure | Value  |\n| -------------------- | ------ |\n| * References         |        |\n|   * Count            |   1772 |\n|     * Branches       |      3 |\n|     * Tags           |   1025 |\n|     * Remotes        |    744 |\n|     * Others         |      0 |\n|                      |        |\n| * Reachable objects  |        |\n|   * Count            | 418958 |\n|     * Commits        |  87468 |\n|     * Trees          | 168866 |\n|     * Blobs          | 161632 |\n|     * Tags           |    992 |\n\n",[134,879,880,884,896,900,904,923,938,954,972,990,1007,1024,1040,1049,1066,1081,1097,1114,1130],{"__ignoreMap":258},[262,881,882],{"class":264,"line":265},[262,883,269],{"emptyLinePlaceholder":268},[262,885,886,888,890,893],{"class":264,"line":272},[262,887,276],{"class":275},[262,889,280],{"class":279},[262,891,892],{"class":279}," repo",[262,894,895],{"class":279}," structure\n",[262,897,898],{"class":264,"line":400},[262,899,269],{"emptyLinePlaceholder":268},[262,901,902],{"class":264,"line":405},[262,903,269],{"emptyLinePlaceholder":268},[262,905,906,909,912,915,917,920],{"class":264,"line":410},[262,907,908],{"class":296},"|",[262,910,911],{"class":275}," Repository",[262,913,914],{"class":279}," structure",[262,916,336],{"class":296},[262,918,919],{"class":275}," Value",[262,921,922],{"class":296},"  |\n",[262,924,925,927,930,932,935],{"class":264,"line":419},[262,926,908],{"class":296},[262,928,929],{"class":275}," --------------------",[262,931,336],{"class":296},[262,933,934],{"class":275}," ------",[262,936,937],{"class":296}," |\n",[262,939,940,942,945,948,951],{"class":264,"line":428},[262,941,908],{"class":296},[262,943,944],{"class":275}," *",[262,946,947],{"class":279}," References",[262,949,950],{"class":296},"         |",[262,952,953],{"class":296},"        |\n",[262,955,956,958,961,964,967,970],{"class":264,"line":437},[262,957,908],{"class":296},[262,959,960],{"class":275},"   *",[262,962,963],{"class":279}," Count",[262,965,966],{"class":296},"            |",[262,968,969],{"class":275},"   1772",[262,971,937],{"class":296},[262,973,974,976,979,982,985,988],{"class":264,"line":446},[262,975,908],{"class":296},[262,977,978],{"class":275},"     *",[262,980,981],{"class":279}," Branches",[262,983,984],{"class":296},"       |",[262,986,987],{"class":275},"      3",[262,989,937],{"class":296},[262,991,992,994,996,999,1002,1005],{"class":264,"line":455},[262,993,908],{"class":296},[262,995,978],{"class":275},[262,997,998],{"class":279}," Tags",[262,1000,1001],{"class":296},"           |",[262,1003,1004],{"class":275},"   1025",[262,1006,937],{"class":296},[262,1008,1009,1011,1013,1016,1019,1022],{"class":264,"line":464},[262,1010,908],{"class":296},[262,1012,978],{"class":275},[262,1014,1015],{"class":279}," Remotes",[262,1017,1018],{"class":296},"        |",[262,1020,1021],{"class":275},"    744",[262,1023,937],{"class":296},[262,1025,1026,1028,1030,1033,1035,1038],{"class":264,"line":473},[262,1027,908],{"class":296},[262,1029,978],{"class":275},[262,1031,1032],{"class":279}," Others",[262,1034,950],{"class":296},[262,1036,1037],{"class":275},"      0",[262,1039,937],{"class":296},[262,1041,1042,1044,1047],{"class":264,"line":482},[262,1043,908],{"class":296},[262,1045,1046],{"class":296},"                      |",[262,1048,953],{"class":296},[262,1050,1051,1053,1055,1058,1061,1064],{"class":264,"line":491},[262,1052,908],{"class":296},[262,1054,944],{"class":275},[262,1056,1057],{"class":279}," Reachable",[262,1059,1060],{"class":279}," objects",[262,1062,1063],{"class":296},"  |",[262,1065,953],{"class":296},[262,1067,1068,1070,1072,1074,1076,1079],{"class":264,"line":500},[262,1069,908],{"class":296},[262,1071,960],{"class":275},[262,1073,963],{"class":279},[262,1075,966],{"class":296},[262,1077,1078],{"class":275}," 418958",[262,1080,937],{"class":296},[262,1082,1083,1085,1087,1090,1092,1095],{"class":264,"line":509},[262,1084,908],{"class":296},[262,1086,978],{"class":275},[262,1088,1089],{"class":279}," Commits",[262,1091,1018],{"class":296},[262,1093,1094],{"class":275},"  87468",[262,1096,937],{"class":296},[262,1098,1099,1101,1103,1106,1109,1112],{"class":264,"line":517},[262,1100,908],{"class":296},[262,1102,978],{"class":275},[262,1104,1105],{"class":279}," Trees",[262,1107,1108],{"class":296},"          |",[262,1110,1111],{"class":275}," 168866",[262,1113,937],{"class":296},[262,1115,1116,1118,1120,1123,1125,1128],{"class":264,"line":526},[262,1117,908],{"class":296},[262,1119,978],{"class":275},[262,1121,1122],{"class":279}," Blobs",[262,1124,1108],{"class":296},[262,1126,1127],{"class":275}," 161632",[262,1129,937],{"class":296},[262,1131,1132,1134,1136,1138,1140,1143],{"class":264,"line":535},[262,1133,908],{"class":296},[262,1135,978],{"class":275},[262,1137,998],{"class":279},[262,1139,1001],{"class":296},[262,1141,1142],{"class":275},"    992",[262,1144,937],{"class":296},[14,1146,1147],{},"In subsequent releases we hope to expand on this and provide other interesting data points like the largest objects in the repository.",[14,1149,1150],{},[587,1151,752,1152,583],{},[18,1153,1156],{"href":1154,"rel":1155},"https://gitlab.com/justintobler",[],"Justin Tobler",[31,1158,1160],{"id":1159},"improvements-related-to-the-google-summer-of-code-2025","Improvements related to the Google Summer of Code 2025",[14,1162,1163],{},"We had three successful projects with the Google Summer of Code.",[1165,1166,1168],"h3",{"id":1167},"refactoring-in-order-to-reduce-gits-global-state","Refactoring in order to reduce Git's global state",[14,1170,1171,1172,1177,1178,1180],{},"Git contains several global variables used throughout the codebase. This increases the complexity of the code and reduces the maintainability. As part of this project, ",[18,1173,1176],{"href":1174,"rel":1175},"https://ayu-ch.github.io/",[],"Ayush Chandekar"," worked on reducing the usage of the ",[134,1179,136],{}," global variable via a series of patches.",[14,1182,1183],{},[587,1184,1185,1186,235,1189,583],{},"The project was mentored by ",[18,1187,7],{"href":755,"rel":1188},[],[18,1190,1193],{"href":1191,"rel":1192},"https://in.linkedin.com/in/ghanshyam-thakkar",[],"Ghanshyam Thakkar",[1165,1195,1197],{"id":1196},"machine-readable-repository-information-query-tool","Machine-readable Repository Information Query Tool",[14,1199,1200,1201,1204],{},"Git lacks a centralized way to retrieve repository information, requiring users to piece it together from various commands. While ",[134,1202,1203],{},"git-rev-parse(1)"," has become the de-facto tool for accessing much of this information, doing so falls outside its primary purpose.",[14,1206,1207,1208,1213,1214,1217,1218,1221],{},"As part of this project, ",[18,1209,1212],{"href":1210,"rel":1211},"https://lucasoshiro.github.io/en/",[],"Lucas Oshiro"," introduced a new command, ",[134,1215,1216],{},"git-repo(1),"," which will house all repository-level information. Users can now use ",[134,1219,1220],{},"git repo info"," to obtain repository information:",[253,1223,1225],{"className":255,"code":1224,"language":257,"meta":258,"style":258},"\n$ git repo info layout.bare layout.shallow object.format references.format\n\nlayout.bare=false\nlayout.shallow=false\nobject.format=sha1\nreferences.format=reftable\n\n",[134,1226,1227,1231,1254,1258,1269,1278,1286],{"__ignoreMap":258},[262,1228,1229],{"class":264,"line":265},[262,1230,269],{"emptyLinePlaceholder":268},[262,1232,1233,1235,1237,1239,1242,1245,1248,1251],{"class":264,"line":272},[262,1234,276],{"class":275},[262,1236,280],{"class":279},[262,1238,892],{"class":279},[262,1240,1241],{"class":279}," info",[262,1243,1244],{"class":279}," layout.bare",[262,1246,1247],{"class":279}," layout.shallow",[262,1249,1250],{"class":279}," object.format",[262,1252,1253],{"class":279}," references.format\n",[262,1255,1256],{"class":264,"line":400},[262,1257,269],{"emptyLinePlaceholder":268},[262,1259,1260,1263,1266],{"class":264,"line":405},[262,1261,1262],{"class":275},"layout.bare",[262,1264,1265],{"class":279},"=",[262,1267,1268],{"class":286},"false\n",[262,1270,1271,1274,1276],{"class":264,"line":410},[262,1272,1273],{"class":275},"layout.shallow",[262,1275,1265],{"class":279},[262,1277,1268],{"class":286},[262,1279,1280,1283],{"class":264,"line":419},[262,1281,1282],{"class":275},"object.format",[262,1284,1285],{"class":279},"=sha1\n",[262,1287,1288,1291],{"class":264,"line":428},[262,1289,1290],{"class":275},"references.format",[262,1292,1293],{"class":279},"=reftable\n",[14,1295,1296],{},[587,1297,1185,1298,235,1301,583],{},[18,1299,9],{"href":857,"rel":1300},[],[18,1302,1305],{"href":1303,"rel":1304},"https://gitlab.com/knayakgl",[],"Karthik Nayak",[1165,1307,1309],{"id":1308},"consolidate-ref-related-functionality-into-git-refs","Consolidate ref-related functionality into git-refs",[14,1311,1312,1313,1316,1317,1316,1320,1323,1324,1327,1328,1331,1332,1337],{},"Git offers multiple commands for managing references, namely ",[134,1314,1315],{},"git-for-each-ref(1)",", ",[134,1318,1319],{},"git show-ref(1)",[134,1321,1322],{},"git-update-ref(1)",", and ",[134,1325,1326],{},"git-pack-refs(1)",". This makes them harder to discover and creates overlapping functionality. To address this, we introduced the ",[134,1329,1330],{},"git-refs(1)"," command to consolidate these operations under a single interface. As part of this this project, ",[18,1333,1336],{"href":1334,"rel":1335},"https://inosmeet.github.io/",[],"Meet Soni"," extended the command by adding the following subcommands:",[358,1339,1340,1346,1352],{},[361,1341,1342,1345],{},[134,1343,1344],{},"git refs optimize"," to optimize the reference backend",[361,1347,1348,1351],{},[134,1349,1350],{},"git refs list"," to list all references",[361,1353,1354,1357],{},[134,1355,1356],{},"git refs exists"," to verify the existence of a reference",[14,1359,1360],{},[587,1361,1185,1362,235,1365,583],{},[18,1363,9],{"href":857,"rel":1364},[],[18,1366,1369],{"href":1367,"rel":1368},"https://luolibrary.com/",[],"shejialuo",[31,1371,1373],{"id":1372},"whats-next","What's next?",[14,1375,1376,1377,583],{},"Ready to experience these improvements? Update to Git 2.52.0 and start using ",[134,1378,1379],{},"git last-modified",[14,1381,1382],{},"At GitLab, we will of course ensure that all of these improvements will eventually land in a GitLab instance near you!",[14,1384,1385,1386,1390,1391,583],{},"Learn more in the ",[18,1387,1389],{"href":20,"rel":1388},[],"official Git 2.52.0 release notes"," and explore our ",[18,1392,1395],{"href":1393,"rel":1394},"https://about.gitlab.com/blog/tags/git/",[],"complete archive of Git development coverage",[1397,1398,1399],"style",{},"html pre.shiki code .s7eDp, html code.shiki .s7eDp{--shiki-default:#6F42C1}html pre.shiki code .sYBdl, html code.shiki .sYBdl{--shiki-default:#032F62}html pre.shiki code .sYu0t, html code.shiki .sYu0t{--shiki-default:#005CC5}html pre.shiki code .sD7c4, html code.shiki .sD7c4{--shiki-default:#D73A49}html pre.shiki code .sgsFI, html code.shiki .sgsFI{--shiki-default:#24292E}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}",{"title":258,"searchDepth":272,"depth":272,"links":1401},[1402,1403,1404,1405,1406,1411],{"id":33,"depth":272,"text":34},{"id":608,"depth":272,"text":609},{"id":759,"depth":272,"text":760},{"id":861,"depth":272,"text":862},{"id":1159,"depth":272,"text":1160,"children":1407},[1408,1409,1410],{"id":1167,"depth":400,"text":1168},{"id":1196,"depth":400,"text":1197},{"id":1308,"depth":400,"text":1309},{"id":1372,"depth":272,"text":1373},"open-source","2025-11-17","Learn about release contributions, including the new git-last-modified(1) command, improvements to history-rewriting tools, and a new maintenance strategy.","md",null,"https://res.cloudinary.com/about-gitlab-com/image/upload/v1749663087/Blog/Hero%20Images/git3-cover.png",{},"/en-us/blog/whats-new-in-git-2-52-0",{"config":1421,"title":5,"description":1414},{"noIndex":1422},false,"whats-new-in-git-2-52-0","en-us/blog/whats-new-in-git-2-52-0",[1426,1427,1428],"open source","git","community","BlogPost","nz1IA_qbfzRddHl4Ufyexzy9PSFpwjv-TGuI8UCoOV0",{"logo":1432,"freeTrial":1437,"sales":1442,"login":1447,"items":1452,"search":1778,"minimal":1809,"duo":1828,"switchNav":1837,"pricingDeployment":1848},{"config":1433},{"href":1434,"dataGaName":1435,"dataGaLocation":1436},"/","gitlab logo","header",{"text":1438,"config":1439},"Get free trial",{"href":1440,"dataGaName":1441,"dataGaLocation":1436},"https://gitlab.com/-/trial_registrations/new?glm_source=about.gitlab.com&glm_content=default-saas-trial/","free trial",{"text":1443,"config":1444},"Request a demo",{"href":1445,"dataGaName":1446,"dataGaLocation":1436},"/sales/?contact-topic=request-demo","sales",{"text":1448,"config":1449},"Sign in",{"href":1450,"dataGaName":1451,"dataGaLocation":1436},"https://gitlab.com/users/sign_in/","sign in",[1453,1482,1582,1587,1700,1756],{"text":1454,"config":1455,"menu":1457},"Platform",{"dataNavLevelOne":1456},"platform",{"type":1458,"columns":1459},"cards",[1460,1466,1474],{"title":1454,"description":1461,"link":1462},"The intelligent orchestration platform for DevSecOps",{"text":1463,"config":1464},"Explore our Platform",{"href":1465,"dataGaName":1456,"dataGaLocation":1436},"/platform/",{"title":1467,"description":1468,"link":1469},"GitLab Duo Agent Platform","Agentic AI for the entire software lifecycle",{"text":1470,"config":1471},"Meet GitLab Duo",{"href":1472,"dataGaName":1473,"dataGaLocation":1436},"/gitlab-duo-agent-platform/","gitlab duo agent platform",{"title":1475,"description":1476,"link":1477},"Why GitLab","See the top reasons enterprises choose GitLab",{"text":1478,"config":1479},"Learn more",{"href":1480,"dataGaName":1481,"dataGaLocation":1436},"/why-gitlab/","why gitlab",{"text":1483,"left":268,"config":1484,"menu":1486},"Product",{"dataNavLevelOne":1485},"solutions",{"type":1487,"link":1488,"columns":1492,"feature":1561},"lists",{"text":1489,"config":1490},"View all Solutions",{"href":1491,"dataGaName":1485,"dataGaLocation":1436},"/solutions/",[1493,1517,1540],{"title":1494,"description":1495,"link":1496,"items":1501},"Automation","CI/CD and automation to accelerate deployment",{"config":1497},{"icon":1498,"href":1499,"dataGaName":1500,"dataGaLocation":1436},"AutomatedCodeAlt","/solutions/delivery-automation/","automated software delivery",[1502,1506,1509,1513],{"text":1503,"config":1504},"CI/CD",{"href":1505,"dataGaLocation":1436,"dataGaName":1503},"/solutions/continuous-integration/",{"text":1467,"config":1507},{"href":1472,"dataGaLocation":1436,"dataGaName":1508},"gitlab duo agent platform - product menu",{"text":1510,"config":1511},"Source Code Management",{"href":1512,"dataGaLocation":1436,"dataGaName":1510},"/solutions/source-code-management/",{"text":1514,"config":1515},"Automated Software Delivery",{"href":1499,"dataGaLocation":1436,"dataGaName":1516},"Automated software delivery",{"title":1518,"description":1519,"link":1520,"items":1525},"Security","Deliver code faster without compromising security",{"config":1521},{"href":1522,"dataGaName":1523,"dataGaLocation":1436,"icon":1524},"/solutions/application-security-testing/","security and compliance","ShieldCheckLight",[1526,1530,1535],{"text":1527,"config":1528},"Application Security Testing",{"href":1522,"dataGaName":1529,"dataGaLocation":1436},"Application security testing",{"text":1531,"config":1532},"Software Supply Chain Security",{"href":1533,"dataGaLocation":1436,"dataGaName":1534},"/solutions/supply-chain/","Software supply chain security",{"text":1536,"config":1537},"Software Compliance",{"href":1538,"dataGaName":1539,"dataGaLocation":1436},"/solutions/software-compliance/","software compliance",{"title":1541,"link":1542,"items":1547},"Measurement",{"config":1543},{"icon":1544,"href":1545,"dataGaName":1546,"dataGaLocation":1436},"DigitalTransformation","/solutions/visibility-measurement/","visibility and measurement",[1548,1552,1556],{"text":1549,"config":1550},"Visibility & Measurement",{"href":1545,"dataGaLocation":1436,"dataGaName":1551},"Visibility and Measurement",{"text":1553,"config":1554},"Value Stream Management",{"href":1555,"dataGaLocation":1436,"dataGaName":1553},"/solutions/value-stream-management/",{"text":1557,"config":1558},"Analytics & Insights",{"href":1559,"dataGaLocation":1436,"dataGaName":1560},"/solutions/analytics-and-insights/","Analytics and insights",{"title":1562,"type":1487,"items":1563},"GitLab for",[1564,1570,1576],{"text":1565,"config":1566},"Enterprise",{"icon":1567,"href":1568,"dataGaLocation":1436,"dataGaName":1569},"Building","/enterprise/","enterprise",{"text":1571,"config":1572},"Small Business",{"icon":1573,"href":1574,"dataGaLocation":1436,"dataGaName":1575},"Work","/small-business/","small business",{"text":1577,"config":1578},"Public Sector",{"icon":1579,"href":1580,"dataGaLocation":1436,"dataGaName":1581},"Organization","/solutions/public-sector/","public sector",{"text":1583,"config":1584},"Pricing",{"href":1585,"dataGaName":1586,"dataGaLocation":1436,"dataNavLevelOne":1586},"/pricing/","pricing",{"text":1588,"config":1589,"menu":1591},"Resources",{"dataNavLevelOne":1590},"resources",{"type":1487,"link":1592,"columns":1596,"feature":1689},{"text":1593,"config":1594},"View all resources",{"href":1595,"dataGaName":1590,"dataGaLocation":1436},"/resources/",[1597,1630,1657],{"title":1598,"items":1599},"Getting started",[1600,1605,1610,1615,1620,1625],{"text":1601,"config":1602},"Install",{"href":1603,"dataGaName":1604,"dataGaLocation":1436},"/install/","install",{"text":1606,"config":1607},"Quick start guides",{"href":1608,"dataGaName":1609,"dataGaLocation":1436},"/get-started/","quick setup checklists",{"text":1611,"config":1612},"Learn",{"href":1613,"dataGaLocation":1436,"dataGaName":1614},"https://university.gitlab.com/","learn",{"text":1616,"config":1617},"Product documentation",{"href":1618,"dataGaName":1619,"dataGaLocation":1436},"https://docs.gitlab.com/","product documentation",{"text":1621,"config":1622},"Best practice videos",{"href":1623,"dataGaName":1624,"dataGaLocation":1436},"/getting-started-videos/","best practice videos",{"text":1626,"config":1627},"Integrations",{"href":1628,"dataGaName":1629,"dataGaLocation":1436},"/integrations/","integrations",{"title":1631,"items":1632},"Discover",[1633,1638,1643,1648,1652],{"text":1634,"config":1635},"Customer success stories",{"href":1636,"dataGaName":1637,"dataGaLocation":1436},"/customers/","customer success stories",{"text":1639,"config":1640},"Blog",{"href":1641,"dataGaName":1642,"dataGaLocation":1436},"/blog/","blog",{"text":1644,"config":1645},"Demo Hub",{"href":1646,"dataGaName":1647,"dataGaLocation":1436},"/demo-hub/","demo hub",{"text":1649,"config":1650},"The Source",{"href":1651,"dataGaName":1642,"dataGaLocation":1436},"/the-source/",{"text":1653,"config":1654},"Remote",{"href":1655,"dataGaName":1656,"dataGaLocation":1436},"https://handbook.gitlab.com/handbook/company/culture/all-remote/","remote",{"title":1658,"items":1659},"Connect",[1660,1665,1670,1674,1679,1684],{"text":1661,"config":1662},"GitLab Services",{"href":1663,"dataGaName":1664,"dataGaLocation":1436},"/services/","services",{"text":1666,"config":1667},"Contribute",{"href":1668,"dataGaName":1669,"dataGaLocation":1436},"https://contributors.gitlab.com","contribute",{"text":1671,"config":1672},"Community",{"href":1673,"dataGaName":1428,"dataGaLocation":1436},"/community/",{"text":1675,"config":1676},"Forum",{"href":1677,"dataGaName":1678,"dataGaLocation":1436},"https://forum.gitlab.com/","forum",{"text":1680,"config":1681},"Events",{"href":1682,"dataGaName":1683,"dataGaLocation":1436},"/events/","events",{"text":1685,"config":1686},"Partners",{"href":1687,"dataGaName":1688,"dataGaLocation":1436},"/partners/","partners",{"config":1690,"title":1693,"text":1694,"link":1695},{"background":1691,"textColor":1692},"url('https://res.cloudinary.com/about-gitlab-com/image/upload/v1777322348/qpq8yrgn8knii57omj0c.png')","#000","What’s new in GitLab","Stay updated with our latest features and improvements.",{"text":1696,"config":1697},"Read the latest",{"href":1698,"dataGaName":1699,"dataGaLocation":1436},"/whats-new/","whats new",{"text":1701,"config":1702,"menu":1704},"Company",{"dataNavLevelOne":1703},"company",{"type":1487,"columns":1705},[1706],{"items":1707},[1708,1713,1719,1721,1726,1731,1736,1741,1746,1751],{"text":1709,"config":1710},"About",{"href":1711,"dataGaName":1712,"dataGaLocation":1436},"/company/","about",{"text":1714,"config":1715,"footerGa":1718},"Jobs",{"href":1716,"dataGaName":1717,"dataGaLocation":1436},"/jobs/","jobs",{"dataGaName":1717},{"text":1680,"config":1720},{"href":1682,"dataGaName":1683,"dataGaLocation":1436},{"text":1722,"config":1723},"Leadership",{"href":1724,"dataGaName":1725,"dataGaLocation":1436},"/company/team/e-group/","leadership",{"text":1727,"config":1728},"Handbook",{"href":1729,"dataGaName":1730,"dataGaLocation":1436},"https://handbook.gitlab.com/","handbook",{"text":1732,"config":1733},"Investor relations",{"href":1734,"dataGaName":1735,"dataGaLocation":1436},"https://ir.gitlab.com/overview/default.aspx","investor relations",{"text":1737,"config":1738},"Trust Center",{"href":1739,"dataGaName":1740,"dataGaLocation":1436},"/security/","trust center",{"text":1742,"config":1743},"AI Transparency Center",{"href":1744,"dataGaName":1745,"dataGaLocation":1436},"/ai-transparency-center/","ai transparency center",{"text":1747,"config":1748},"Newsletter",{"href":1749,"dataGaName":1750,"dataGaLocation":1436},"/company/contact/#contact-forms","newsletter",{"text":1752,"config":1753},"Press",{"href":1754,"dataGaName":1755,"dataGaLocation":1436},"/press/","press",{"text":1757,"config":1758,"menu":1759},"Contact us",{"dataNavLevelOne":1703},{"type":1487,"columns":1760},[1761],{"items":1762},[1763,1768,1773],{"text":1764,"config":1765},"Talk to sales",{"href":1766,"dataGaName":1767,"dataGaLocation":1436},"/sales/","talk to sales",{"text":1769,"config":1770},"Support portal",{"href":1771,"dataGaName":1772,"dataGaLocation":1436},"https://support.gitlab.com/hc/en-us","support portal",{"text":1774,"config":1775},"Customer portal",{"href":1776,"dataGaName":1777,"dataGaLocation":1436},"https://customers.gitlab.com/customers/sign_in/","customer portal",{"close":1779,"login":1780,"suggestions":1787},"Close",{"text":1781,"link":1782},"To search repositories and projects, login to",{"text":1783,"config":1784},"gitlab.com",{"href":1450,"dataGaName":1785,"dataGaLocation":1786},"search login","search",{"text":1788,"default":1789},"Suggestions",[1790,1792,1796,1798,1802,1806],{"text":1467,"config":1791},{"href":1472,"dataGaName":1467,"dataGaLocation":1786},{"text":1793,"config":1794},"Code Suggestions (AI)",{"href":1795,"dataGaName":1793,"dataGaLocation":1786},"/solutions/code-suggestions/",{"text":1503,"config":1797},{"href":1505,"dataGaName":1503,"dataGaLocation":1786},{"text":1799,"config":1800},"GitLab on AWS",{"href":1801,"dataGaName":1799,"dataGaLocation":1786},"/partners/technology-partners/aws/",{"text":1803,"config":1804},"GitLab on Google Cloud",{"href":1805,"dataGaName":1803,"dataGaLocation":1786},"/partners/technology-partners/google-cloud-platform/",{"text":1807,"config":1808},"Why GitLab?",{"href":1480,"dataGaName":1807,"dataGaLocation":1786},{"freeTrial":1810,"mobileIcon":1815,"desktopIcon":1820,"secondaryButton":1823},{"text":1811,"config":1812},"Start free trial",{"href":1813,"dataGaName":1441,"dataGaLocation":1814},"https://gitlab.com/-/trials/new/","nav",{"altText":1816,"config":1817},"Gitlab Icon",{"src":1818,"dataGaName":1819,"dataGaLocation":1814},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1758203874/jypbw1jx72aexsoohd7x.svg","gitlab icon",{"altText":1816,"config":1821},{"src":1822,"dataGaName":1819,"dataGaLocation":1814},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1758203875/gs4c8p8opsgvflgkswz9.svg",{"text":1824,"config":1825},"Get Started",{"href":1826,"dataGaName":1827,"dataGaLocation":1814},"https://gitlab.com/-/trial_registrations/new?glm_source=about.gitlab.com/get-started/","get started",{"freeTrial":1829,"mobileIcon":1833,"desktopIcon":1835},{"text":1830,"config":1831},"Learn more about GitLab Duo",{"href":1472,"dataGaName":1832,"dataGaLocation":1814},"gitlab duo",{"altText":1816,"config":1834},{"src":1818,"dataGaName":1819,"dataGaLocation":1814},{"altText":1816,"config":1836},{"src":1822,"dataGaName":1819,"dataGaLocation":1814},{"button":1838,"mobileIcon":1843,"desktopIcon":1845},{"text":1839,"config":1840},"/switch",{"href":1841,"dataGaName":1842,"dataGaLocation":1814},"#contact","switch",{"altText":1816,"config":1844},{"src":1818,"dataGaName":1819,"dataGaLocation":1814},{"altText":1816,"config":1846},{"src":1847,"dataGaName":1819,"dataGaLocation":1814},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1773335277/ohhpiuoxoldryzrnhfrh.png",{"freeTrial":1849,"mobileIcon":1854,"desktopIcon":1856},{"text":1850,"config":1851},"Back to pricing",{"href":1585,"dataGaName":1852,"dataGaLocation":1814,"icon":1853},"back to pricing","GoBack",{"altText":1816,"config":1855},{"src":1818,"dataGaName":1819,"dataGaLocation":1814},{"altText":1816,"config":1857},{"src":1822,"dataGaName":1819,"dataGaLocation":1814},{"title":1859,"titleMobile":1860,"button":1861,"config":1866},"Duo Agent Platform delivers 400% ROI, per new Forrester Consulting study.","400% ROI: Forrester TEI for GitLab Duo",{"text":1478,"config":1862},{"href":1863,"dataGaName":1864,"dataGaLocation":1865},"https://about.gitlab.com/blog/gitlab-duo-agent-platform-delivers-400-percent-roi/","forrester-tei-dap-banner","global-banner",{"layout":1867,"disabled":1422},"release",{"data":1869},{"text":1870,"source":1871,"edit":1877,"contribute":1882,"config":1887,"items":1892,"minimal":2102},"Git is a trademark of Software Freedom Conservancy and our use of 'GitLab' is under license",{"text":1872,"config":1873},"View page source",{"href":1874,"dataGaName":1875,"dataGaLocation":1876},"https://gitlab.com/gitlab-com/marketing/digital-experience/about-gitlab-com/","page source","footer",{"text":1878,"config":1879},"Edit this page",{"href":1880,"dataGaName":1881,"dataGaLocation":1876},"https://gitlab.com/gitlab-com/marketing/digital-experience/about-gitlab-com/-/blob/main/content/","web ide",{"text":1883,"config":1884},"Please contribute",{"href":1885,"dataGaName":1886,"dataGaLocation":1876},"https://gitlab.com/gitlab-com/marketing/digital-experience/about-gitlab-com/-/blob/main/CONTRIBUTING.md/","please contribute",{"twitter":1888,"facebook":1889,"youtube":1890,"linkedin":1891},"https://twitter.com/gitlab","https://www.facebook.com/gitlab","https://www.youtube.com/channel/UCnMGQ8QHMAnVIsI3xJrihhg","https://www.linkedin.com/company/gitlab-com",[1893,1940,1994,2038,2070],{"title":1583,"links":1894,"subMenu":1909},[1895,1899,1904],{"text":1896,"config":1897},"View plans",{"href":1585,"dataGaName":1898,"dataGaLocation":1876},"view plans",{"text":1900,"config":1901},"Why Premium?",{"href":1902,"dataGaName":1903,"dataGaLocation":1876},"/pricing/premium/","why premium",{"text":1905,"config":1906},"Why Ultimate?",{"href":1907,"dataGaName":1908,"dataGaLocation":1876},"/pricing/ultimate/","why ultimate",[1910],{"title":1911,"links":1912},"Contact Us",[1913,1916,1918,1920,1925,1930,1935],{"text":1914,"config":1915},"Contact sales",{"href":1766,"dataGaName":1446,"dataGaLocation":1876},{"text":1769,"config":1917},{"href":1771,"dataGaName":1772,"dataGaLocation":1876},{"text":1774,"config":1919},{"href":1776,"dataGaName":1777,"dataGaLocation":1876},{"text":1921,"config":1922},"Status",{"href":1923,"dataGaName":1924,"dataGaLocation":1876},"https://status.gitlab.com/","status",{"text":1926,"config":1927},"Terms of use",{"href":1928,"dataGaName":1929,"dataGaLocation":1876},"/terms/","terms of use",{"text":1931,"config":1932},"Privacy statement",{"href":1933,"dataGaName":1934,"dataGaLocation":1876},"/privacy/","privacy statement",{"text":1936,"config":1937},"Cookie preferences",{"dataGaName":1938,"dataGaLocation":1876,"id":1939,"isOneTrustButton":268},"cookie preferences","ot-sdk-btn",{"title":1483,"links":1941,"subMenu":1950},[1942,1946],{"text":1943,"config":1944},"DevSecOps platform",{"href":1465,"dataGaName":1945,"dataGaLocation":1876},"devsecops platform",{"text":1947,"config":1948},"AI-Assisted Development",{"href":1472,"dataGaName":1949,"dataGaLocation":1876},"ai-assisted development",[1951],{"title":1952,"links":1953},"Topics",[1954,1959,1964,1969,1974,1979,1984,1989],{"text":1955,"config":1956},"CICD",{"href":1957,"dataGaName":1958,"dataGaLocation":1876},"/topics/ci-cd/","cicd",{"text":1960,"config":1961},"GitOps",{"href":1962,"dataGaName":1963,"dataGaLocation":1876},"/topics/gitops/","gitops",{"text":1965,"config":1966},"DevOps",{"href":1967,"dataGaName":1968,"dataGaLocation":1876},"/topics/devops/","devops",{"text":1970,"config":1971},"Version Control",{"href":1972,"dataGaName":1973,"dataGaLocation":1876},"/topics/version-control/","version control",{"text":1975,"config":1976},"DevSecOps",{"href":1977,"dataGaName":1978,"dataGaLocation":1876},"/topics/devsecops/","devsecops",{"text":1980,"config":1981},"Cloud Native",{"href":1982,"dataGaName":1983,"dataGaLocation":1876},"/topics/cloud-native/","cloud native",{"text":1985,"config":1986},"AI for Coding",{"href":1987,"dataGaName":1988,"dataGaLocation":1876},"/topics/devops/ai-for-coding/","ai for coding",{"text":1990,"config":1991},"Agentic AI",{"href":1992,"dataGaName":1993,"dataGaLocation":1876},"/topics/agentic-ai/","agentic ai",{"title":1995,"links":1996},"Solutions",[1997,1999,2001,2006,2010,2013,2017,2020,2022,2025,2028,2033],{"text":1527,"config":1998},{"href":1522,"dataGaName":1527,"dataGaLocation":1876},{"text":1516,"config":2000},{"href":1499,"dataGaName":1500,"dataGaLocation":1876},{"text":2002,"config":2003},"Agile development",{"href":2004,"dataGaName":2005,"dataGaLocation":1876},"/solutions/agile-delivery/","agile delivery",{"text":2007,"config":2008},"SCM",{"href":1512,"dataGaName":2009,"dataGaLocation":1876},"source code management",{"text":1955,"config":2011},{"href":1505,"dataGaName":2012,"dataGaLocation":1876},"continuous integration & delivery",{"text":2014,"config":2015},"Value stream management",{"href":1555,"dataGaName":2016,"dataGaLocation":1876},"value stream management",{"text":1960,"config":2018},{"href":2019,"dataGaName":1963,"dataGaLocation":1876},"/solutions/gitops/",{"text":1565,"config":2021},{"href":1568,"dataGaName":1569,"dataGaLocation":1876},{"text":2023,"config":2024},"Small business",{"href":1574,"dataGaName":1575,"dataGaLocation":1876},{"text":2026,"config":2027},"Public sector",{"href":1580,"dataGaName":1581,"dataGaLocation":1876},{"text":2029,"config":2030},"Education",{"href":2031,"dataGaName":2032,"dataGaLocation":1876},"/solutions/education/","education",{"text":2034,"config":2035},"Financial services",{"href":2036,"dataGaName":2037,"dataGaLocation":1876},"/solutions/finance/","financial services",{"title":1588,"links":2039},[2040,2042,2044,2046,2049,2051,2054,2056,2058,2060,2062,2064,2066,2068],{"text":1601,"config":2041},{"href":1603,"dataGaName":1604,"dataGaLocation":1876},{"text":1606,"config":2043},{"href":1608,"dataGaName":1609,"dataGaLocation":1876},{"text":1611,"config":2045},{"href":1613,"dataGaName":1614,"dataGaLocation":1876},{"text":1616,"config":2047},{"href":1618,"dataGaName":2048,"dataGaLocation":1876},"docs",{"text":1639,"config":2050},{"href":1641,"dataGaName":1642,"dataGaLocation":1876},{"text":2052,"config":2053},"What's new",{"href":1698,"dataGaName":1699,"dataGaLocation":1876},{"text":1634,"config":2055},{"href":1636,"dataGaName":1637,"dataGaLocation":1876},{"text":1653,"config":2057},{"href":1655,"dataGaName":1656,"dataGaLocation":1876},{"text":1661,"config":2059},{"href":1663,"dataGaName":1664,"dataGaLocation":1876},{"text":1666,"config":2061},{"href":1668,"dataGaName":1669,"dataGaLocation":1876},{"text":1671,"config":2063},{"href":1673,"dataGaName":1428,"dataGaLocation":1876},{"text":1675,"config":2065},{"href":1677,"dataGaName":1678,"dataGaLocation":1876},{"text":1680,"config":2067},{"href":1682,"dataGaName":1683,"dataGaLocation":1876},{"text":1685,"config":2069},{"href":1687,"dataGaName":1688,"dataGaLocation":1876},{"title":1701,"links":2071},[2072,2074,2076,2078,2080,2082,2086,2091,2093,2095,2097],{"text":1709,"config":2073},{"href":1711,"dataGaName":1703,"dataGaLocation":1876},{"text":1714,"config":2075},{"href":1716,"dataGaName":1717,"dataGaLocation":1876},{"text":1722,"config":2077},{"href":1724,"dataGaName":1725,"dataGaLocation":1876},{"text":1727,"config":2079},{"href":1729,"dataGaName":1730,"dataGaLocation":1876},{"text":1732,"config":2081},{"href":1734,"dataGaName":1735,"dataGaLocation":1876},{"text":2083,"config":2084},"Sustainability",{"href":2085,"dataGaName":2083,"dataGaLocation":1876},"/sustainability/",{"text":2087,"config":2088},"Diversity, inclusion and belonging (DIB)",{"href":2089,"dataGaName":2090,"dataGaLocation":1876},"/diversity-inclusion-belonging/","Diversity, inclusion and belonging",{"text":1737,"config":2092},{"href":1739,"dataGaName":1740,"dataGaLocation":1876},{"text":1747,"config":2094},{"href":1749,"dataGaName":1750,"dataGaLocation":1876},{"text":1752,"config":2096},{"href":1754,"dataGaName":1755,"dataGaLocation":1876},{"text":2098,"config":2099},"Modern Slavery Transparency Statement",{"href":2100,"dataGaName":2101,"dataGaLocation":1876},"https://handbook.gitlab.com/handbook/legal/modern-slavery-act-transparency-statement/","modern slavery transparency statement",{"items":2103},[2104,2107,2110],{"text":2105,"config":2106},"Terms",{"href":1928,"dataGaName":1929,"dataGaLocation":1876},{"text":2108,"config":2109},"Cookies",{"dataGaName":1938,"dataGaLocation":1876,"id":1939,"isOneTrustButton":268},{"text":2111,"config":2112},"Privacy",{"href":1933,"dataGaName":1934,"dataGaLocation":1876},[2114,2128,2140],{"id":2115,"title":7,"body":1416,"config":2116,"content":2118,"description":1416,"extension":2122,"meta":2123,"navigation":268,"path":2124,"seo":2125,"stem":2126,"__hash__":2127},"blogAuthors/en-us/blog/authors/christian-couder.yml",{"template":2117},"BlogAuthor",{"name":7,"config":2119},{"headshot":2120,"ctfId":2121},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1749663687/Blog/Author%20Headshots/chriscool-headshot.jpg","chriscool","yml",{},"/en-us/blog/authors/christian-couder",{},"en-us/blog/authors/christian-couder","6VsKjKNdm1XKAmFMZHj53ROyylDlxaSJhcARRkw6EQQ",{"id":2129,"title":8,"body":1416,"config":2130,"content":2131,"description":1416,"extension":2122,"meta":2135,"navigation":268,"path":2136,"seo":2137,"stem":2138,"__hash__":2139},"blogAuthors/en-us/blog/authors/toon-claes.yml",{"template":2117},{"name":8,"config":2132},{"headshot":2133,"ctfId":2134},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1749663082/Blog/Author%20Headshots/toon_claes_headshot.png","toon",{},"/en-us/blog/authors/toon-claes",{},"en-us/blog/authors/toon-claes","guXJXoqO1anz4H932Namk7kqyZsO1xyVQr6stBL4o18",{"id":2141,"title":9,"body":1416,"config":2142,"content":2143,"description":1416,"extension":2122,"meta":2147,"navigation":268,"path":2148,"seo":2149,"stem":2150,"__hash__":2151},"blogAuthors/en-us/blog/authors/patrick-steinhardt.yml",{"template":2117},{"name":9,"config":2144},{"headshot":2145,"ctfId":2146},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1749661952/Blog/Author%20Headshots/pks-gitlab-headshot.png","pksgitlab",{},"/en-us/blog/authors/patrick-steinhardt",{},"en-us/blog/authors/patrick-steinhardt","SV9Yd_vW69UbvntDP-SEOV9NKT_VwUAj5nfftf2ElSw",[2153,2160,2168],{"title":2154,"description":2155,"heroImage":2156,"category":1412,"date":2157,"authors":2158,"slug":2159,"externalUrl":1416},"What's new in Git 2.55.0?","Learn about the new features and changes in Git 2.55, including a new git-history(1) fixup command, an fsmonitor daemon for Linux, pushing to remote groups, and more.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1782732487/ztwgrvlolpifo01vj8qc.png","2026-06-29",[8],"whats-new-in-git-2-55-0",{"title":2161,"description":2162,"heroImage":2163,"category":1412,"date":2164,"authors":2165,"slug":2167,"externalUrl":1416},"GitLab AI Hackathon 2026: Meet the winners","Nearly 7,000 developers built 600+ AI agents and flows on GitLab Duo Agent Platform. Find out who won and what they created.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1776457632/llddiylsgwuze0u1rjks.png","2026-04-22",[2166],"Nick Veenhof","gitlab-ai-hackathon-2026-meet-the-winners",{"title":2169,"description":2170,"heroImage":2171,"category":1412,"date":2172,"authors":2173,"slug":2174,"externalUrl":1416},"What’s new in Git 2.54.0?","Learn about release contributions, including new repository maintenance, a new command to edit commit history, a replacement for git-sizer(1), and more.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1782734716/ztwgrvlolpifo01vj8qc.png","2026-04-20",[9],"whats-new-in-git-2-54-0",{"promotions":2176},[2177,2191,2203,2215],{"id":2178,"categories":2179,"header":2181,"text":2182,"button":2183,"image":2188},"ai-modernization",[2180],"ai","Is AI achieving its promise at scale?","Quiz will take 5 minutes or less",{"text":2184,"config":2185},"Get your AI maturity score",{"href":2186,"dataGaName":2187,"dataGaLocation":1642},"/assessments/ai-modernization-assessment/","modernization assessment",{"config":2189},{"src":2190},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1772138786/qix0m7kwnd8x2fh1zq49.png",{"id":2192,"categories":2193,"header":2195,"text":2182,"button":2196,"image":2200},"devops-modernization",[2194,1978],"product","Are you just managing tools or shipping innovation?",{"text":2197,"config":2198},"Get your DevOps maturity score",{"href":2199,"dataGaName":2187,"dataGaLocation":1642},"/assessments/devops-modernization-assessment/",{"config":2201},{"src":2202},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1772138785/eg818fmakweyuznttgid.png",{"id":2204,"categories":2205,"header":2207,"text":2182,"button":2208,"image":2212},"security-modernization",[2206],"security","Are you trading speed for security?",{"text":2209,"config":2210},"Get your security maturity score",{"href":2211,"dataGaName":2187,"dataGaLocation":1642},"/assessments/security-modernization-assessment/",{"config":2213},{"src":2214},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1772138786/p4pbqd9nnjejg5ds6mdk.png",{"id":2216,"paths":2217,"header":2220,"text":2221,"button":2222,"image":2227},"github-azure-migration",[2218,2219],"migration-from-azure-devops-to-gitlab","integrating-azure-devops-scm-and-gitlab","Is your team ready for GitHub's Azure move?","GitHub is already rebuilding around Azure. Find out what it means for you.",{"text":2223,"config":2224},"See how GitLab compares to GitHub",{"href":2225,"dataGaName":2226,"dataGaLocation":1642},"/compare/gitlab-vs-github/github-azure-migration/","github azure migration",{"config":2228},{"src":2202},{"header":2230,"blurb":2231,"button":2232,"secondaryButton":2237},"Start building faster today","See what your team can do with the intelligent orchestration platform for DevSecOps.\n",{"text":2233,"config":2234},"Get your free trial",{"href":2235,"dataGaName":1441,"dataGaLocation":2236},"https://gitlab.com/-/trial_registrations/new?glm_content=default-saas-trial&glm_source=about.gitlab.com/","feature",{"text":1914,"config":2238},{"href":1766,"dataGaName":1446,"dataGaLocation":2236},1786803756464]