[{"data":1,"prerenderedAt":1759},["ShallowReactive",2],{"/blog/whats-new-in-git-2-45-0":3,"navigation-en-us":974,"banner-en-us":1401,"footer-en-us":1411,"blog-post-authors-en-us-Patrick Steinhardt":1656,"blog-related-posts-en-us-whats-new-in-git-2-45-0":1671,"blog-promotions-en-us":1695,"next-steps-en-us":1749},{"id":4,"title":5,"authors":6,"body":8,"category":954,"date":955,"description":956,"extension":957,"externalUrl":958,"faq":958,"featured":959,"heroImage":960,"meta":961,"navigation":102,"path":962,"seo":963,"slug":967,"stem":968,"tags":969,"template":972,"updatedDate":958,"__hash__":973},"blogPosts/en-us/blog/whats-new-in-git-2-45-0.md","What’s new in Git 2.45.0?",[7],"Patrick Steinhardt",{"type":9,"value":10,"toc":944},"minimark",[11,22,27,30,45,48,284,287,374,377,394,427,430,445,563,582,585,593,597,600,603,608,611,631,634,637,671,678,681,692,737,740,747,751,754,761,789,792,803,830,835,839,846,853,861,864,875,889,894,898,906,910,940],[12,13,14,15,21],"p",{},"The Git project recently released ",[16,17,20],"a",{"href":18,"rel":19},"https://lore.kernel.org/git/xmqq8r0ww0sj.fsf@gitster.g/",[],"Git Version 2.45.0",". Let's look at the highlights of this release, which includes contributions from GitLab's Git team and the wider Git community.",[23,24,26],"h2",{"id":25},"reftables-a-new-backend-for-storing-references","Reftables: A new backend for storing references",[12,28,29],{},"Every Git repository needs to track two basic data structures:",[31,32,33,37],"ul",{},[34,35,36],"li",{},"The object graph that stores the data of your files, the directory structure, commit messages, and tags.",[34,38,39,40,44],{},"References that are pointers into that object graph to associate specific objects with a more accessible name. For example, a branch is a reference whose name starts with a ",[41,42,43],"code",{},"refs/heads/"," prefix.",[12,46,47],{},"The on-disk format of how references are stored in a repository has remained largely unchanged since Git’s inception and is referred to as  the \"files\" format. Whenever you create a reference, Git creates a so-called \"loose reference\" that is a plain file in your Git repository whose path matches the ref name. For example:",[49,50,55],"pre",{"className":51,"code":52,"language":53,"meta":54,"style":54},"language-shell shiki shiki-themes github-light","$ git init .\nInitialized empty Git repository in /tmp/repo/.git/\n\n# Updating a reference will cause Git to create a \"loose ref\". This loose ref is\n# a simple file which contains the object ID of the commit.\n$ git commit --allow-empty --message \"Initial commit\"\n[main (root-commit) c70f266] Initial commit\n$ cat .git/refs/heads/main\nc70f26689975782739ef9666af079535b12b5946\n\n# Creating a second reference will end up with a second loose ref.\n$ git branch feature\n$ cat .git/refs/heads/feature\nc70f26689975782739ef9666af079535b12b5946\n$ tree .git/refs\n.git/refs/\n├── heads\n│   ├── feature\n│   └── main\n└── tags\n\n3 directories, 2 files\n","shell","",[41,56,57,76,97,104,111,117,137,151,162,168,173,179,192,202,207,218,224,233,244,255,264,269],{"__ignoreMap":54},[58,59,62,66,70,73],"span",{"class":60,"line":61},"line",1,[58,63,65],{"class":64},"s7eDp","$",[58,67,69],{"class":68},"sYBdl"," git",[58,71,72],{"class":68}," init",[58,74,75],{"class":68}," .\n",[58,77,79,82,85,88,91,94],{"class":60,"line":78},2,[58,80,81],{"class":64},"Initialized",[58,83,84],{"class":68}," empty",[58,86,87],{"class":68}," Git",[58,89,90],{"class":68}," repository",[58,92,93],{"class":68}," in",[58,95,96],{"class":68}," /tmp/repo/.git/\n",[58,98,100],{"class":60,"line":99},3,[58,101,103],{"emptyLinePlaceholder":102},true,"\n",[58,105,107],{"class":60,"line":106},4,[58,108,110],{"class":109},"sAwPA","# Updating a reference will cause Git to create a \"loose ref\". This loose ref is\n",[58,112,114],{"class":60,"line":113},5,[58,115,116],{"class":109},"# a simple file which contains the object ID of the commit.\n",[58,118,120,122,124,127,131,134],{"class":60,"line":119},6,[58,121,65],{"class":64},[58,123,69],{"class":68},[58,125,126],{"class":68}," commit",[58,128,130],{"class":129},"sYu0t"," --allow-empty",[58,132,133],{"class":129}," --message",[58,135,136],{"class":68}," \"Initial commit\"\n",[58,138,140,144,148],{"class":60,"line":139},7,[58,141,143],{"class":142},"sgsFI","[main (root",[58,145,147],{"class":146},"sD7c4","-",[58,149,150],{"class":142},"commit) c70f266] Initial commit\n",[58,152,154,156,159],{"class":60,"line":153},8,[58,155,65],{"class":64},[58,157,158],{"class":68}," cat",[58,160,161],{"class":68}," .git/refs/heads/main\n",[58,163,165],{"class":60,"line":164},9,[58,166,167],{"class":64},"c70f26689975782739ef9666af079535b12b5946\n",[58,169,171],{"class":60,"line":170},10,[58,172,103],{"emptyLinePlaceholder":102},[58,174,176],{"class":60,"line":175},11,[58,177,178],{"class":109},"# Creating a second reference will end up with a second loose ref.\n",[58,180,182,184,186,189],{"class":60,"line":181},12,[58,183,65],{"class":64},[58,185,69],{"class":68},[58,187,188],{"class":68}," branch",[58,190,191],{"class":68}," feature\n",[58,193,195,197,199],{"class":60,"line":194},13,[58,196,65],{"class":64},[58,198,158],{"class":68},[58,200,201],{"class":68}," .git/refs/heads/feature\n",[58,203,205],{"class":60,"line":204},14,[58,206,167],{"class":64},[58,208,210,212,215],{"class":60,"line":209},15,[58,211,65],{"class":64},[58,213,214],{"class":68}," tree",[58,216,217],{"class":68}," .git/refs\n",[58,219,221],{"class":60,"line":220},16,[58,222,223],{"class":64},".git/refs/\n",[58,225,227,230],{"class":60,"line":226},17,[58,228,229],{"class":64},"├──",[58,231,232],{"class":68}," heads\n",[58,234,236,239,242],{"class":60,"line":235},18,[58,237,238],{"class":64},"│",[58,240,241],{"class":68},"   ├──",[58,243,191],{"class":68},[58,245,247,249,252],{"class":60,"line":246},19,[58,248,238],{"class":64},[58,250,251],{"class":68},"   └──",[58,253,254],{"class":68}," main\n",[58,256,258,261],{"class":60,"line":257},20,[58,259,260],{"class":64},"└──",[58,262,263],{"class":68}," tags\n",[58,265,267],{"class":60,"line":266},21,[58,268,103],{"emptyLinePlaceholder":102},[58,270,272,275,278,281],{"class":60,"line":271},22,[58,273,274],{"class":64},"3",[58,276,277],{"class":68}," directories,",[58,279,280],{"class":129}," 2",[58,282,283],{"class":68}," files\n",[12,285,286],{},"Every once in a while, Git packs those references into a \"packed\"\nfile format so that it becomes more efficient to look up references. For example:",[49,288,290],{"className":51,"code":289,"language":53,"meta":54,"style":54},"# Packing references will create \"packed\" references, which are a sorted list of\n# references. The loose reference does not exist anymore.\n$ git pack-refs --all\n$ cat .git/refs/heads/main\ncat: .git/refs/heads/main: No such file or directory\n$ cat .git/packed-refs\n# pack-refs with: peeled fully-peeled sorted\nc70f26689975782739ef9666af079535b12b5946 refs/heads/feature\nc70f26689975782739ef9666af079535b12b5946 refs/heads/main\n",[41,291,292,297,302,314,322,345,354,359,367],{"__ignoreMap":54},[58,293,294],{"class":60,"line":61},[58,295,296],{"class":109},"# Packing references will create \"packed\" references, which are a sorted list of\n",[58,298,299],{"class":60,"line":78},[58,300,301],{"class":109},"# references. The loose reference does not exist anymore.\n",[58,303,304,306,308,311],{"class":60,"line":99},[58,305,65],{"class":64},[58,307,69],{"class":68},[58,309,310],{"class":68}," pack-refs",[58,312,313],{"class":129}," --all\n",[58,315,316,318,320],{"class":60,"line":106},[58,317,65],{"class":64},[58,319,158],{"class":68},[58,321,161],{"class":68},[58,323,324,327,330,333,336,339,342],{"class":60,"line":113},[58,325,326],{"class":64},"cat:",[58,328,329],{"class":68}," .git/refs/heads/main:",[58,331,332],{"class":68}," No",[58,334,335],{"class":68}," such",[58,337,338],{"class":68}," file",[58,340,341],{"class":68}," or",[58,343,344],{"class":68}," directory\n",[58,346,347,349,351],{"class":60,"line":119},[58,348,65],{"class":64},[58,350,158],{"class":68},[58,352,353],{"class":68}," .git/packed-refs\n",[58,355,356],{"class":60,"line":139},[58,357,358],{"class":109},"# pack-refs with: peeled fully-peeled sorted\n",[58,360,361,364],{"class":60,"line":153},[58,362,363],{"class":64},"c70f26689975782739ef9666af079535b12b5946",[58,365,366],{"class":68}," refs/heads/feature\n",[58,368,369,371],{"class":60,"line":164},[58,370,363],{"class":64},[58,372,373],{"class":68}," refs/heads/main\n",[12,375,376],{},"While this format is rather simple, it has limitations:",[31,378,379,382,385,388,391],{},[34,380,381],{},"In large mono repos with many references, we started to hit scalability issues. Deleting references is especially inefficient because the entire “packed-refs” file must be rewritten to drop the deleted reference. In our largest repositories, this can lead to rewriting multiple gigabytes of data on every reference deletion.",[34,383,384],{},"It is impossible to perform an atomic read of references without blocking concurrent writers because you have to read multiple files to figure out all references.",[34,386,387],{},"It is impossible to perform an atomic write because it requires you to create or update multiple files, which cannot be done in a single step.",[34,389,390],{},"Housekeeping of references does not scale well because you have to rewrite the full \"packed-refs\" file.",[34,392,393],{},"Because loose references use the filesystem path as their name, they are subject to filesystem-specific behavior. For example, case-insensitive file systems cannot store references for which only the case differs.",[12,395,396,397,402,403,408,409,414,415,420,421,426],{},"To address these issues, Git v2.45.0 introduces a new \"reftable\" backend, which uses a new binary format to store references. This new backend has been in development for a very long time. It was initially proposed by ",[16,398,401],{"href":399,"rel":400},"https://sfconservancy.org/blog/2018/jan/30/shawn-pearce/",[],"Shawn Pearce"," in July 2017 and was initially implemented in ",[16,404,407],{"href":405,"rel":406},"https://www.eclipse.org/jgit/",[],"JGit",". It is used extensively by the ",[16,410,413],{"href":411,"rel":412},"https://www.gerritcodereview.com/",[],"Gerrit project",". In 2021, ",[16,416,419],{"href":417,"rel":418},"https://hanwen.home.xs4all.nl/",[],"Han-Wen Nienhuys"," upstreamed the library into Git that allows it to read and write the ",[16,422,425],{"href":423,"rel":424},"https://git-scm.com/docs/reftable",[],"reftable format",".",[12,428,429],{},"The new \"reftable\" backend that we upstreamed in Git v2.45.0 now finally brings together the reftable library and Git such that it is possible to use the new format as storage backend in your Git repositories.",[12,431,432,433,436,437,440,441,444],{},"Assuming that you run at least Git v2.45.0, you can create new repositories with the \"reftable\" format by passing the ",[41,434,435],{},"--ref-format=reftable"," switch to either ",[41,438,439],{},"git-init(1)"," or ",[41,442,443],{},"git-clone(1)",". For example:",[49,446,448],{"className":51,"code":447,"language":53,"meta":54,"style":54},"$ git init --ref-format=reftable .\nInitialized empty Git repository in /tmp/repo/.git/\n$ git rev-parse --show-ref-format\nreftable\n$ find -type f .git/reftable/\n.git/reftable/0x000000000001-0x000000000001-01b5e47d.ref\n.git/reftable/tables.list\n\n$ git commit --allow-empty --message \"Initial commit\"\n$ find -type f .git/reftable/\n.git/reftable/0x000000000001-0x000000000001-01b5e47d.ref\n.git/reftable/0x000000000002-0x000000000002-87006b81.ref\n.git/reftable/tables.list\n",[41,449,450,463,477,489,494,510,515,520,524,538,550,554,559],{"__ignoreMap":54},[58,451,452,454,456,458,461],{"class":60,"line":61},[58,453,65],{"class":64},[58,455,69],{"class":68},[58,457,72],{"class":68},[58,459,460],{"class":129}," --ref-format=reftable",[58,462,75],{"class":68},[58,464,465,467,469,471,473,475],{"class":60,"line":78},[58,466,81],{"class":64},[58,468,84],{"class":68},[58,470,87],{"class":68},[58,472,90],{"class":68},[58,474,93],{"class":68},[58,476,96],{"class":68},[58,478,479,481,483,486],{"class":60,"line":99},[58,480,65],{"class":64},[58,482,69],{"class":68},[58,484,485],{"class":68}," rev-parse",[58,487,488],{"class":129}," --show-ref-format\n",[58,490,491],{"class":60,"line":106},[58,492,493],{"class":64},"reftable\n",[58,495,496,498,501,504,507],{"class":60,"line":113},[58,497,65],{"class":64},[58,499,500],{"class":68}," find",[58,502,503],{"class":129}," -type",[58,505,506],{"class":68}," f",[58,508,509],{"class":68}," .git/reftable/\n",[58,511,512],{"class":60,"line":119},[58,513,514],{"class":64},".git/reftable/0x000000000001-0x000000000001-01b5e47d.ref\n",[58,516,517],{"class":60,"line":139},[58,518,519],{"class":64},".git/reftable/tables.list\n",[58,521,522],{"class":60,"line":153},[58,523,103],{"emptyLinePlaceholder":102},[58,525,526,528,530,532,534,536],{"class":60,"line":164},[58,527,65],{"class":64},[58,529,69],{"class":68},[58,531,126],{"class":68},[58,533,130],{"class":129},[58,535,133],{"class":129},[58,537,136],{"class":68},[58,539,540,542,544,546,548],{"class":60,"line":170},[58,541,65],{"class":64},[58,543,500],{"class":68},[58,545,503],{"class":129},[58,547,506],{"class":68},[58,549,509],{"class":68},[58,551,552],{"class":60,"line":175},[58,553,514],{"class":64},[58,555,556],{"class":60,"line":181},[58,557,558],{"class":64},".git/reftable/0x000000000002-0x000000000002-87006b81.ref\n",[58,560,561],{"class":60,"line":194},[58,562,519],{"class":64},[12,564,565,566,569,570,573,574,577,578,581],{},"As you can see, the references are now stored in ",[41,567,568],{},".git/reftable"," instead of in the ",[41,571,572],{},".git/refs"," directory. The references and the reference logs are stored in “tables,” which are the files ending with ",[41,575,576],{},".ref",", whereas the ",[41,579,580],{},"tables.list"," file contains the list of all tables that are currently active. The technical details of how this work will be explained in a separate blog post. Stay tuned!",[12,583,584],{},"The “reftable” backend is supposed to be a  drop-in replacement for the “files” backend. Hence, from a user’s perspective, everything should just work the same.",[12,586,587,588,592],{},"This project was led by ",[16,589,7],{"href":590,"rel":591},"https://gitlab.com/pks-gitlab",[],". Credit also goes to Shawn Pearce as original inventor of the format and Han-Wen Nienhuys as the author of the reftable library.",[23,594,596],{"id":595},"better-tooling-for-references","Better tooling for references",[12,598,599],{},"While the \"reftable\" format solves many of the issues we have, it also\nintroduces some new issues. One of the most important issues is accessibility of the data it contains.",[12,601,602],{},"With the \"files\" backend, you can, in the worst case, use your regular Unix tools to inspect the state of references. Both the \"packed\" and the \"loose\" references contain human-readable data that one can easily make sense of. This is different with the \"reftable\" format, which is a binary format. Therefore, Git needs to provide all the necessary tooling to extract data from the new \"reftable\" format.",[604,605,607],"h3",{"id":606},"listing-all-references","Listing all references",[12,609,610],{},"The first problem we had is that it is basically impossible to learn about all the references that a repository knows about. This is somewhat puzzling at first: you can create and modify references via Git, but it cannot exhaustively list all references that it knows about?",[12,612,613,614,617,618,623,624,627,628,426],{},"Indeed, the \"files\" backend can't. While it can trivially list all \"normal\"\nreferences that start with the ",[41,615,616],{},"refs/"," prefix, Git also uses so-called\n",[16,619,622],{"href":620,"rel":621},"https://git-scm.com/docs/gitglossary#Documentation/gitglossary.txt-aiddefpseudorefapseudoref",[],"pseudo refs",". These files live directly in the root of the Git directory and would be files like, for example, ",[41,625,626],{},".git/MERGE_HEAD",". The problem here is that those pseudo refs live next to other files that Git stores like, for example, ",[41,629,630],{},".git/config",[12,632,633],{},"While some pseudo refs are well-known and thus easy to identify, there is\nin theory no limit to what references Git can write. Nothing stops you from\ncreating a reference called \"foobar\".",[12,635,636],{},"For example:",[49,638,640],{"className":51,"code":639,"language":53,"meta":54,"style":54},"$ git update-ref foobar HEAD\n$ cat .git/foobar\nf32633d4d7da32ccc3827e90ecdc10570927c77d\n",[41,641,642,657,666],{"__ignoreMap":54},[58,643,644,646,648,651,654],{"class":60,"line":61},[58,645,65],{"class":64},[58,647,69],{"class":68},[58,649,650],{"class":68}," update-ref",[58,652,653],{"class":68}," foobar",[58,655,656],{"class":68}," HEAD\n",[58,658,659,661,663],{"class":60,"line":78},[58,660,65],{"class":64},[58,662,158],{"class":68},[58,664,665],{"class":68}," .git/foobar\n",[58,667,668],{"class":60,"line":99},[58,669,670],{"class":64},"f32633d4d7da32ccc3827e90ecdc10570927c77d\n",[12,672,673,674,677],{},"Now the problem that the \"files\" backend has is that it can only enumerate\nreferences by scanning through directories. So to figure out that\n",[41,675,676],{},".git/foobar"," is in fact a reference, Git would have to open the file and check whether it is formatted like a reference or not.",[12,679,680],{},"On the other hand, the \"reftable\" backend trivially knows about all references that it contains: They are encoded in its data structures, so all it needs to do is to decode those references and return them. But because of the restrictions of the \"files\" backend, there is no tooling that would allow you to learn about all references that exist.",[12,682,683,684,687,688,691],{},"To address the issue, we upstreamed a new flag to ",[41,685,686],{},"git-for-each-ref(1)"," called ",[41,689,690],{},"--include-root-refs",", which will cause it to also list all references that exist in the root of the reference naming hierarchy. For example:",[49,693,695],{"className":51,"code":694,"language":53,"meta":54,"style":54},"$ git for-each-ref --include-root-refs\nf32633d4d7da32ccc3827e90ecdc10570927c77d commit    HEAD\nf32633d4d7da32ccc3827e90ecdc10570927c77d commit    MERGE_HEAD\nf32633d4d7da32ccc3827e90ecdc10570927c77d commit    refs/heads/main\n",[41,696,697,709,719,728],{"__ignoreMap":54},[58,698,699,701,703,706],{"class":60,"line":61},[58,700,65],{"class":64},[58,702,69],{"class":68},[58,704,705],{"class":68}," for-each-ref",[58,707,708],{"class":129}," --include-root-refs\n",[58,710,711,714,716],{"class":60,"line":78},[58,712,713],{"class":64},"f32633d4d7da32ccc3827e90ecdc10570927c77d",[58,715,126],{"class":68},[58,717,718],{"class":68},"    HEAD\n",[58,720,721,723,725],{"class":60,"line":99},[58,722,713],{"class":64},[58,724,126],{"class":68},[58,726,727],{"class":68},"    MERGE_HEAD\n",[58,729,730,732,734],{"class":60,"line":106},[58,731,713],{"class":64},[58,733,126],{"class":68},[58,735,736],{"class":68},"    refs/heads/main\n",[12,738,739],{},"For the \"files\" backend, this new flag is handled on a best-effort basis where we include all references that match a known pseudo ref name. For the \"reftable\" backend, we can simply list all references known to it.",[12,741,587,742,426],{},[16,743,746],{"href":744,"rel":745},"https://gitlab.com/knayakgl",[],"Karthik Nayak",[604,748,750],{"id":749},"listing-all-reflogs","Listing all reflogs",[12,752,753],{},"Whenever you update branches, Git, by default, tracks those branch updates in a so-called reflog. This reflog allows you to roll back changes to that branch in case you performed an unintended change and can thus be a very helpful tool.",[12,755,756,757,760],{},"With the \"files\" backend, those logs are stored in your ",[41,758,759],{},".git/logs"," directory:",[49,762,764],{"className":51,"code":763,"language":53,"meta":54,"style":54},"$ find -type f .git/logs/\n.git/logs/HEAD\n.git/logs/refs/heads/main\n",[41,765,766,779,784],{"__ignoreMap":54},[58,767,768,770,772,774,776],{"class":60,"line":61},[58,769,65],{"class":64},[58,771,500],{"class":68},[58,773,503],{"class":129},[58,775,506],{"class":68},[58,777,778],{"class":68}," .git/logs/\n",[58,780,781],{"class":60,"line":78},[58,782,783],{"class":64},".git/logs/HEAD\n",[58,785,786],{"class":60,"line":99},[58,787,788],{"class":64},".git/logs/refs/heads/main\n",[12,790,791],{},"In fact, listing files in this directory is the only way for you to learn what references actually have a reflog in the first place. This is a problem for the \"reftable\" backend, which stores those logs together with the references. Consequently, there doesn't exist any way for you to learn about which reflogs exist in the repository at all anymore when you use the \"reftable\" format.",[12,793,794,795,798,799,802],{},"This is not really the fault of the \"reftable\" format though, but an omission in the tooling that Git provides. To address the omission, we introduced a new ",[41,796,797],{},"list"," subcommand for ",[41,800,801],{},"git-reflog(1)"," that allows you to list all existing reflogs:",[49,804,806],{"className":51,"code":805,"language":53,"meta":54,"style":54},"$ git reflog list\nHEAD\nrefs/heads/main\n",[41,807,808,820,825],{"__ignoreMap":54},[58,809,810,812,814,817],{"class":60,"line":61},[58,811,65],{"class":64},[58,813,69],{"class":68},[58,815,816],{"class":68}," reflog",[58,818,819],{"class":68}," list\n",[58,821,822],{"class":60,"line":78},[58,823,824],{"class":64},"HEAD\n",[58,826,827],{"class":60,"line":99},[58,828,829],{"class":64},"refs/heads/main\n",[12,831,587,832,426],{},[16,833,7],{"href":590,"rel":834},[],[604,836,838],{"id":837},"more-efficient-packing-of-references","More efficient packing of references",[12,840,841,842,845],{},"To stay efficient, Git repositories need regular maintenance. Usually,\nthis maintenance is triggered by various Git commands that write data into the Git repositories by executing ",[41,843,844],{},"git maintenance run --auto",". This command\nonly optimizes data structures that actually need to be optimized so that Git doesn’t waste compute resources.",[12,847,848,849,852],{},"One data structure that gets optimized by Git's maintenance is the reference\ndatabase, which is done by executing ",[41,850,851],{},"git pack-refs --all",". For the \"files\"\nbackend, this means that all references get repacked into the \"packed-refs\" file and the loose references get deleted, whereas for the \"reftable\" backend all the tables will get merged into a single table.",[12,854,855,856,860],{},"For the \"files\" backend, we cannot reasonably do much better. Given that we have to rewrite the whole \"packed-refs\" file anyway, it makes sense that we would want to pack ",[857,858,859],"em",{},"all"," loose references.",[12,862,863],{},"But for the \"reftable\" backend this is suboptimal as the \"reftable\" backend is self-optimizing. Whenever Git appends a new table to the \"reftable\" backend, it will perform auto-compaction and merge tables together as needed. Consequently, the reference database should always be in a well-optimized state and thus merging all tables together is a wasted effort.",[12,865,866,867,870,871,874],{},"In Git v2.45.0, we thus introduced a new ",[41,868,869],{},"git pack-refs --auto"," mode, which asks the reference backend to optimize on an as-needed basis. While the \"files\" backend continues to work the same even with the ",[41,872,873],{},"--auto"," flag set, the \"reftable\" backend will use the same heuristics as it already uses for its auto-compaction. In practice, this should be a no-op in most cases.",[12,876,877,878,880,881,884,885,888],{},"Furthermore, ",[41,879,844],{}," has been adapted to pass the ",[41,882,883],{},"-tauto"," flag to ",[41,886,887],{},"git-pack-refs(1)"," to make use of this new mode by default.",[12,890,587,891,426],{},[16,892,7],{"href":590,"rel":893},[],[23,895,897],{"id":896},"read-more","Read more",[12,899,900,901,905],{},"This blog post put a heavy focus on the new \"reftable\" backend, which allows us to scale better in large repositories with many references, as well as related tooling that we have introduced alongside it to make it work well. There, of course, have been various performance improvements, bug fixes and smaller features introduced with this Git release by the wider Git community, as well. You can learn about these from the ",[16,902,904],{"href":18,"rel":903},[],"official release announcement"," of the Git project.",[23,907,909],{"id":908},"gitlabs-previous-git-release-contributions","GitLab's previous Git release contributions",[31,911,912,919,926,933],{},[34,913,914],{},[16,915,918],{"href":916,"rel":917},"https://about.gitlab.com/blog/gitlabs-contributions-to-git-2-44-0/",[],"GitLab's contributions to Git 2.44.0",[34,920,921],{},[16,922,925],{"href":923,"rel":924},"https://about.gitlab.com/blog/the-contributions-we-made-to-the-git-2-43-release/",[],"GitLab's contributions to Git 2.43.0",[34,927,928],{},[16,929,932],{"href":930,"rel":931},"https://about.gitlab.com/blog/contributions-to-git-2-42-release/",[],"GitLab's contributions to Git 2.42.0",[34,934,935],{},[16,936,939],{"href":937,"rel":938},"https://about.gitlab.com/blog/contributions-to-latest-git-release/",[],"GitLab's contributions to Git 2.41.0",[941,942,943],"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 .sAwPA, html code.shiki .sAwPA{--shiki-default:#6A737D}html pre.shiki code .sYu0t, html code.shiki .sYu0t{--shiki-default:#005CC5}html pre.shiki code .sgsFI, html code.shiki .sgsFI{--shiki-default:#24292E}html pre.shiki code .sD7c4, html code.shiki .sD7c4{--shiki-default:#D73A49}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":54,"searchDepth":78,"depth":78,"links":945},[946,947,952,953],{"id":25,"depth":78,"text":26},{"id":595,"depth":78,"text":596,"children":948},[949,950,951],{"id":606,"depth":99,"text":607},{"id":749,"depth":99,"text":750},{"id":837,"depth":99,"text":838},{"id":896,"depth":78,"text":897},{"id":908,"depth":78,"text":909},"open-source","2024-04-30","Here are some highlights of contributions from GitLab's Git team and the wider Git community to the latest Git release, including reftables and better tooling for references.\n","md",null,false,"https://res.cloudinary.com/about-gitlab-com/image/upload/v1749659507/Blog/Hero%20Images/AdobeStock_623844718.jpg",{},"/en-us/blog/whats-new-in-git-2-45-0",{"title":5,"description":956,"ogTitle":5,"ogDescription":956,"noIndex":959,"ogImage":960,"ogUrl":964,"ogSiteName":965,"ogType":966,"canonicalUrls":964},"https://about.gitlab.com/blog/whats-new-in-git-2-45-0","https://about.gitlab.com","article","whats-new-in-git-2-45-0","en-us/blog/whats-new-in-git-2-45-0",[970,971],"git","community","BlogPost","pTzPCZyHp3YDGkAxTagoFiv5grjlyl4StOFDQut1jy4",{"logo":975,"freeTrial":980,"sales":985,"login":990,"items":995,"search":1321,"minimal":1352,"duo":1371,"switchNav":1380,"pricingDeployment":1391},{"config":976},{"href":977,"dataGaName":978,"dataGaLocation":979},"/","gitlab logo","header",{"text":981,"config":982},"Get free trial",{"href":983,"dataGaName":984,"dataGaLocation":979},"https://gitlab.com/-/trial_registrations/new?glm_source=about.gitlab.com&glm_content=default-saas-trial/","free trial",{"text":986,"config":987},"Request a demo",{"href":988,"dataGaName":989,"dataGaLocation":979},"/sales/?contact-topic=request-demo","sales",{"text":991,"config":992},"Sign in",{"href":993,"dataGaName":994,"dataGaLocation":979},"https://gitlab.com/users/sign_in/","sign in",[996,1025,1125,1130,1243,1299],{"text":997,"config":998,"menu":1000},"Platform",{"dataNavLevelOne":999},"platform",{"type":1001,"columns":1002},"cards",[1003,1009,1017],{"title":997,"description":1004,"link":1005},"The intelligent orchestration platform for DevSecOps",{"text":1006,"config":1007},"Explore our Platform",{"href":1008,"dataGaName":999,"dataGaLocation":979},"/platform/",{"title":1010,"description":1011,"link":1012},"GitLab Duo Agent Platform","Agentic AI for the entire software lifecycle",{"text":1013,"config":1014},"Meet GitLab Duo",{"href":1015,"dataGaName":1016,"dataGaLocation":979},"/gitlab-duo-agent-platform/","gitlab duo agent platform",{"title":1018,"description":1019,"link":1020},"Why GitLab","See the top reasons enterprises choose GitLab",{"text":1021,"config":1022},"Learn more",{"href":1023,"dataGaName":1024,"dataGaLocation":979},"/why-gitlab/","why gitlab",{"text":1026,"left":102,"config":1027,"menu":1029},"Product",{"dataNavLevelOne":1028},"solutions",{"type":1030,"link":1031,"columns":1035,"feature":1104},"lists",{"text":1032,"config":1033},"View all Solutions",{"href":1034,"dataGaName":1028,"dataGaLocation":979},"/solutions/",[1036,1060,1083],{"title":1037,"description":1038,"link":1039,"items":1044},"Automation","CI/CD and automation to accelerate deployment",{"config":1040},{"icon":1041,"href":1042,"dataGaName":1043,"dataGaLocation":979},"AutomatedCodeAlt","/solutions/delivery-automation/","automated software delivery",[1045,1049,1052,1056],{"text":1046,"config":1047},"CI/CD",{"href":1048,"dataGaLocation":979,"dataGaName":1046},"/solutions/continuous-integration/",{"text":1010,"config":1050},{"href":1015,"dataGaLocation":979,"dataGaName":1051},"gitlab duo agent platform - product menu",{"text":1053,"config":1054},"Source Code Management",{"href":1055,"dataGaLocation":979,"dataGaName":1053},"/solutions/source-code-management/",{"text":1057,"config":1058},"Automated Software Delivery",{"href":1042,"dataGaLocation":979,"dataGaName":1059},"Automated software delivery",{"title":1061,"description":1062,"link":1063,"items":1068},"Security","Deliver code faster without compromising security",{"config":1064},{"href":1065,"dataGaName":1066,"dataGaLocation":979,"icon":1067},"/solutions/application-security-testing/","security and compliance","ShieldCheckLight",[1069,1073,1078],{"text":1070,"config":1071},"Application Security Testing",{"href":1065,"dataGaName":1072,"dataGaLocation":979},"Application security testing",{"text":1074,"config":1075},"Software Supply Chain Security",{"href":1076,"dataGaLocation":979,"dataGaName":1077},"/solutions/supply-chain/","Software supply chain security",{"text":1079,"config":1080},"Software Compliance",{"href":1081,"dataGaName":1082,"dataGaLocation":979},"/solutions/software-compliance/","software compliance",{"title":1084,"link":1085,"items":1090},"Measurement",{"config":1086},{"icon":1087,"href":1088,"dataGaName":1089,"dataGaLocation":979},"DigitalTransformation","/solutions/visibility-measurement/","visibility and measurement",[1091,1095,1099],{"text":1092,"config":1093},"Visibility & Measurement",{"href":1088,"dataGaLocation":979,"dataGaName":1094},"Visibility and Measurement",{"text":1096,"config":1097},"Value Stream Management",{"href":1098,"dataGaLocation":979,"dataGaName":1096},"/solutions/value-stream-management/",{"text":1100,"config":1101},"Analytics & Insights",{"href":1102,"dataGaLocation":979,"dataGaName":1103},"/solutions/analytics-and-insights/","Analytics and insights",{"title":1105,"type":1030,"items":1106},"GitLab for",[1107,1113,1119],{"text":1108,"config":1109},"Enterprise",{"icon":1110,"href":1111,"dataGaLocation":979,"dataGaName":1112},"Building","/enterprise/","enterprise",{"text":1114,"config":1115},"Small Business",{"icon":1116,"href":1117,"dataGaLocation":979,"dataGaName":1118},"Work","/small-business/","small business",{"text":1120,"config":1121},"Public Sector",{"icon":1122,"href":1123,"dataGaLocation":979,"dataGaName":1124},"Organization","/solutions/public-sector/","public sector",{"text":1126,"config":1127},"Pricing",{"href":1128,"dataGaName":1129,"dataGaLocation":979,"dataNavLevelOne":1129},"/pricing/","pricing",{"text":1131,"config":1132,"menu":1134},"Resources",{"dataNavLevelOne":1133},"resources",{"type":1030,"link":1135,"columns":1139,"feature":1232},{"text":1136,"config":1137},"View all resources",{"href":1138,"dataGaName":1133,"dataGaLocation":979},"/resources/",[1140,1173,1200],{"title":1141,"items":1142},"Getting started",[1143,1148,1153,1158,1163,1168],{"text":1144,"config":1145},"Install",{"href":1146,"dataGaName":1147,"dataGaLocation":979},"/install/","install",{"text":1149,"config":1150},"Quick start guides",{"href":1151,"dataGaName":1152,"dataGaLocation":979},"/get-started/","quick setup checklists",{"text":1154,"config":1155},"Learn",{"href":1156,"dataGaLocation":979,"dataGaName":1157},"https://university.gitlab.com/","learn",{"text":1159,"config":1160},"Product documentation",{"href":1161,"dataGaName":1162,"dataGaLocation":979},"https://docs.gitlab.com/","product documentation",{"text":1164,"config":1165},"Best practice videos",{"href":1166,"dataGaName":1167,"dataGaLocation":979},"/getting-started-videos/","best practice videos",{"text":1169,"config":1170},"Integrations",{"href":1171,"dataGaName":1172,"dataGaLocation":979},"/integrations/","integrations",{"title":1174,"items":1175},"Discover",[1176,1181,1186,1191,1195],{"text":1177,"config":1178},"Customer success stories",{"href":1179,"dataGaName":1180,"dataGaLocation":979},"/customers/","customer success stories",{"text":1182,"config":1183},"Blog",{"href":1184,"dataGaName":1185,"dataGaLocation":979},"/blog/","blog",{"text":1187,"config":1188},"Demo Hub",{"href":1189,"dataGaName":1190,"dataGaLocation":979},"/demo-hub/","demo hub",{"text":1192,"config":1193},"The Source",{"href":1194,"dataGaName":1185,"dataGaLocation":979},"/the-source/",{"text":1196,"config":1197},"Remote",{"href":1198,"dataGaName":1199,"dataGaLocation":979},"https://handbook.gitlab.com/handbook/company/culture/all-remote/","remote",{"title":1201,"items":1202},"Connect",[1203,1208,1213,1217,1222,1227],{"text":1204,"config":1205},"GitLab Services",{"href":1206,"dataGaName":1207,"dataGaLocation":979},"/services/","services",{"text":1209,"config":1210},"Contribute",{"href":1211,"dataGaName":1212,"dataGaLocation":979},"https://contributors.gitlab.com","contribute",{"text":1214,"config":1215},"Community",{"href":1216,"dataGaName":971,"dataGaLocation":979},"/community/",{"text":1218,"config":1219},"Forum",{"href":1220,"dataGaName":1221,"dataGaLocation":979},"https://forum.gitlab.com/","forum",{"text":1223,"config":1224},"Events",{"href":1225,"dataGaName":1226,"dataGaLocation":979},"/events/","events",{"text":1228,"config":1229},"Partners",{"href":1230,"dataGaName":1231,"dataGaLocation":979},"/partners/","partners",{"config":1233,"title":1236,"text":1237,"link":1238},{"background":1234,"textColor":1235},"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":1239,"config":1240},"Read the latest",{"href":1241,"dataGaName":1242,"dataGaLocation":979},"/whats-new/","whats new",{"text":1244,"config":1245,"menu":1247},"Company",{"dataNavLevelOne":1246},"company",{"type":1030,"columns":1248},[1249],{"items":1250},[1251,1256,1262,1264,1269,1274,1279,1284,1289,1294],{"text":1252,"config":1253},"About",{"href":1254,"dataGaName":1255,"dataGaLocation":979},"/company/","about",{"text":1257,"config":1258,"footerGa":1261},"Jobs",{"href":1259,"dataGaName":1260,"dataGaLocation":979},"/jobs/","jobs",{"dataGaName":1260},{"text":1223,"config":1263},{"href":1225,"dataGaName":1226,"dataGaLocation":979},{"text":1265,"config":1266},"Leadership",{"href":1267,"dataGaName":1268,"dataGaLocation":979},"/company/team/e-group/","leadership",{"text":1270,"config":1271},"Handbook",{"href":1272,"dataGaName":1273,"dataGaLocation":979},"https://handbook.gitlab.com/","handbook",{"text":1275,"config":1276},"Investor relations",{"href":1277,"dataGaName":1278,"dataGaLocation":979},"https://ir.gitlab.com/overview/default.aspx","investor relations",{"text":1280,"config":1281},"Trust Center",{"href":1282,"dataGaName":1283,"dataGaLocation":979},"/security/","trust center",{"text":1285,"config":1286},"AI Transparency Center",{"href":1287,"dataGaName":1288,"dataGaLocation":979},"/ai-transparency-center/","ai transparency center",{"text":1290,"config":1291},"Newsletter",{"href":1292,"dataGaName":1293,"dataGaLocation":979},"/company/contact/#contact-forms","newsletter",{"text":1295,"config":1296},"Press",{"href":1297,"dataGaName":1298,"dataGaLocation":979},"/press/","press",{"text":1300,"config":1301,"menu":1302},"Contact us",{"dataNavLevelOne":1246},{"type":1030,"columns":1303},[1304],{"items":1305},[1306,1311,1316],{"text":1307,"config":1308},"Talk to sales",{"href":1309,"dataGaName":1310,"dataGaLocation":979},"/sales/","talk to sales",{"text":1312,"config":1313},"Support portal",{"href":1314,"dataGaName":1315,"dataGaLocation":979},"https://support.gitlab.com/hc/en-us","support portal",{"text":1317,"config":1318},"Customer portal",{"href":1319,"dataGaName":1320,"dataGaLocation":979},"https://customers.gitlab.com/customers/sign_in/","customer portal",{"close":1322,"login":1323,"suggestions":1330},"Close",{"text":1324,"link":1325},"To search repositories and projects, login to",{"text":1326,"config":1327},"gitlab.com",{"href":993,"dataGaName":1328,"dataGaLocation":1329},"search login","search",{"text":1331,"default":1332},"Suggestions",[1333,1335,1339,1341,1345,1349],{"text":1010,"config":1334},{"href":1015,"dataGaName":1010,"dataGaLocation":1329},{"text":1336,"config":1337},"Code Suggestions (AI)",{"href":1338,"dataGaName":1336,"dataGaLocation":1329},"/solutions/code-suggestions/",{"text":1046,"config":1340},{"href":1048,"dataGaName":1046,"dataGaLocation":1329},{"text":1342,"config":1343},"GitLab on AWS",{"href":1344,"dataGaName":1342,"dataGaLocation":1329},"/partners/technology-partners/aws/",{"text":1346,"config":1347},"GitLab on Google Cloud",{"href":1348,"dataGaName":1346,"dataGaLocation":1329},"/partners/technology-partners/google-cloud-platform/",{"text":1350,"config":1351},"Why GitLab?",{"href":1023,"dataGaName":1350,"dataGaLocation":1329},{"freeTrial":1353,"mobileIcon":1358,"desktopIcon":1363,"secondaryButton":1366},{"text":1354,"config":1355},"Start free trial",{"href":1356,"dataGaName":984,"dataGaLocation":1357},"https://gitlab.com/-/trials/new/","nav",{"altText":1359,"config":1360},"Gitlab Icon",{"src":1361,"dataGaName":1362,"dataGaLocation":1357},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1758203874/jypbw1jx72aexsoohd7x.svg","gitlab icon",{"altText":1359,"config":1364},{"src":1365,"dataGaName":1362,"dataGaLocation":1357},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1758203875/gs4c8p8opsgvflgkswz9.svg",{"text":1367,"config":1368},"Get Started",{"href":1369,"dataGaName":1370,"dataGaLocation":1357},"https://gitlab.com/-/trial_registrations/new?glm_source=about.gitlab.com/get-started/","get started",{"freeTrial":1372,"mobileIcon":1376,"desktopIcon":1378},{"text":1373,"config":1374},"Learn more about GitLab Duo",{"href":1015,"dataGaName":1375,"dataGaLocation":1357},"gitlab duo",{"altText":1359,"config":1377},{"src":1361,"dataGaName":1362,"dataGaLocation":1357},{"altText":1359,"config":1379},{"src":1365,"dataGaName":1362,"dataGaLocation":1357},{"button":1381,"mobileIcon":1386,"desktopIcon":1388},{"text":1382,"config":1383},"/switch",{"href":1384,"dataGaName":1385,"dataGaLocation":1357},"#contact","switch",{"altText":1359,"config":1387},{"src":1361,"dataGaName":1362,"dataGaLocation":1357},{"altText":1359,"config":1389},{"src":1390,"dataGaName":1362,"dataGaLocation":1357},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1773335277/ohhpiuoxoldryzrnhfrh.png",{"freeTrial":1392,"mobileIcon":1397,"desktopIcon":1399},{"text":1393,"config":1394},"Back to pricing",{"href":1128,"dataGaName":1395,"dataGaLocation":1357,"icon":1396},"back to pricing","GoBack",{"altText":1359,"config":1398},{"src":1361,"dataGaName":1362,"dataGaLocation":1357},{"altText":1359,"config":1400},{"src":1365,"dataGaName":1362,"dataGaLocation":1357},{"title":1402,"titleMobile":1403,"button":1404,"config":1409},"Duo Agent Platform delivers 400% ROI, per new Forrester Consulting study.","400% ROI: Forrester TEI for GitLab Duo",{"text":1021,"config":1405},{"href":1406,"dataGaName":1407,"dataGaLocation":1408},"https://about.gitlab.com/blog/gitlab-duo-agent-platform-delivers-400-percent-roi/","forrester-tei-dap-banner","global-banner",{"layout":1410,"disabled":959},"release",{"data":1412},{"text":1413,"source":1414,"edit":1420,"contribute":1425,"config":1430,"items":1435,"minimal":1645},"Git is a trademark of Software Freedom Conservancy and our use of 'GitLab' is under license",{"text":1415,"config":1416},"View page source",{"href":1417,"dataGaName":1418,"dataGaLocation":1419},"https://gitlab.com/gitlab-com/marketing/digital-experience/about-gitlab-com/","page source","footer",{"text":1421,"config":1422},"Edit this page",{"href":1423,"dataGaName":1424,"dataGaLocation":1419},"https://gitlab.com/gitlab-com/marketing/digital-experience/about-gitlab-com/-/blob/main/content/","web ide",{"text":1426,"config":1427},"Please contribute",{"href":1428,"dataGaName":1429,"dataGaLocation":1419},"https://gitlab.com/gitlab-com/marketing/digital-experience/about-gitlab-com/-/blob/main/CONTRIBUTING.md/","please contribute",{"twitter":1431,"facebook":1432,"youtube":1433,"linkedin":1434},"https://twitter.com/gitlab","https://www.facebook.com/gitlab","https://www.youtube.com/channel/UCnMGQ8QHMAnVIsI3xJrihhg","https://www.linkedin.com/company/gitlab-com",[1436,1483,1537,1581,1613],{"title":1126,"links":1437,"subMenu":1452},[1438,1442,1447],{"text":1439,"config":1440},"View plans",{"href":1128,"dataGaName":1441,"dataGaLocation":1419},"view plans",{"text":1443,"config":1444},"Why Premium?",{"href":1445,"dataGaName":1446,"dataGaLocation":1419},"/pricing/premium/","why premium",{"text":1448,"config":1449},"Why Ultimate?",{"href":1450,"dataGaName":1451,"dataGaLocation":1419},"/pricing/ultimate/","why ultimate",[1453],{"title":1454,"links":1455},"Contact Us",[1456,1459,1461,1463,1468,1473,1478],{"text":1457,"config":1458},"Contact sales",{"href":1309,"dataGaName":989,"dataGaLocation":1419},{"text":1312,"config":1460},{"href":1314,"dataGaName":1315,"dataGaLocation":1419},{"text":1317,"config":1462},{"href":1319,"dataGaName":1320,"dataGaLocation":1419},{"text":1464,"config":1465},"Status",{"href":1466,"dataGaName":1467,"dataGaLocation":1419},"https://status.gitlab.com/","status",{"text":1469,"config":1470},"Terms of use",{"href":1471,"dataGaName":1472,"dataGaLocation":1419},"/terms/","terms of use",{"text":1474,"config":1475},"Privacy statement",{"href":1476,"dataGaName":1477,"dataGaLocation":1419},"/privacy/","privacy statement",{"text":1479,"config":1480},"Cookie preferences",{"dataGaName":1481,"dataGaLocation":1419,"id":1482,"isOneTrustButton":102},"cookie preferences","ot-sdk-btn",{"title":1026,"links":1484,"subMenu":1493},[1485,1489],{"text":1486,"config":1487},"DevSecOps platform",{"href":1008,"dataGaName":1488,"dataGaLocation":1419},"devsecops platform",{"text":1490,"config":1491},"AI-Assisted Development",{"href":1015,"dataGaName":1492,"dataGaLocation":1419},"ai-assisted development",[1494],{"title":1495,"links":1496},"Topics",[1497,1502,1507,1512,1517,1522,1527,1532],{"text":1498,"config":1499},"CICD",{"href":1500,"dataGaName":1501,"dataGaLocation":1419},"/topics/ci-cd/","cicd",{"text":1503,"config":1504},"GitOps",{"href":1505,"dataGaName":1506,"dataGaLocation":1419},"/topics/gitops/","gitops",{"text":1508,"config":1509},"DevOps",{"href":1510,"dataGaName":1511,"dataGaLocation":1419},"/topics/devops/","devops",{"text":1513,"config":1514},"Version Control",{"href":1515,"dataGaName":1516,"dataGaLocation":1419},"/topics/version-control/","version control",{"text":1518,"config":1519},"DevSecOps",{"href":1520,"dataGaName":1521,"dataGaLocation":1419},"/topics/devsecops/","devsecops",{"text":1523,"config":1524},"Cloud Native",{"href":1525,"dataGaName":1526,"dataGaLocation":1419},"/topics/cloud-native/","cloud native",{"text":1528,"config":1529},"AI for Coding",{"href":1530,"dataGaName":1531,"dataGaLocation":1419},"/topics/devops/ai-for-coding/","ai for coding",{"text":1533,"config":1534},"Agentic AI",{"href":1535,"dataGaName":1536,"dataGaLocation":1419},"/topics/agentic-ai/","agentic ai",{"title":1538,"links":1539},"Solutions",[1540,1542,1544,1549,1553,1556,1560,1563,1565,1568,1571,1576],{"text":1070,"config":1541},{"href":1065,"dataGaName":1070,"dataGaLocation":1419},{"text":1059,"config":1543},{"href":1042,"dataGaName":1043,"dataGaLocation":1419},{"text":1545,"config":1546},"Agile development",{"href":1547,"dataGaName":1548,"dataGaLocation":1419},"/solutions/agile-delivery/","agile delivery",{"text":1550,"config":1551},"SCM",{"href":1055,"dataGaName":1552,"dataGaLocation":1419},"source code management",{"text":1498,"config":1554},{"href":1048,"dataGaName":1555,"dataGaLocation":1419},"continuous integration & delivery",{"text":1557,"config":1558},"Value stream management",{"href":1098,"dataGaName":1559,"dataGaLocation":1419},"value stream management",{"text":1503,"config":1561},{"href":1562,"dataGaName":1506,"dataGaLocation":1419},"/solutions/gitops/",{"text":1108,"config":1564},{"href":1111,"dataGaName":1112,"dataGaLocation":1419},{"text":1566,"config":1567},"Small business",{"href":1117,"dataGaName":1118,"dataGaLocation":1419},{"text":1569,"config":1570},"Public sector",{"href":1123,"dataGaName":1124,"dataGaLocation":1419},{"text":1572,"config":1573},"Education",{"href":1574,"dataGaName":1575,"dataGaLocation":1419},"/solutions/education/","education",{"text":1577,"config":1578},"Financial services",{"href":1579,"dataGaName":1580,"dataGaLocation":1419},"/solutions/finance/","financial services",{"title":1131,"links":1582},[1583,1585,1587,1589,1592,1594,1597,1599,1601,1603,1605,1607,1609,1611],{"text":1144,"config":1584},{"href":1146,"dataGaName":1147,"dataGaLocation":1419},{"text":1149,"config":1586},{"href":1151,"dataGaName":1152,"dataGaLocation":1419},{"text":1154,"config":1588},{"href":1156,"dataGaName":1157,"dataGaLocation":1419},{"text":1159,"config":1590},{"href":1161,"dataGaName":1591,"dataGaLocation":1419},"docs",{"text":1182,"config":1593},{"href":1184,"dataGaName":1185,"dataGaLocation":1419},{"text":1595,"config":1596},"What's new",{"href":1241,"dataGaName":1242,"dataGaLocation":1419},{"text":1177,"config":1598},{"href":1179,"dataGaName":1180,"dataGaLocation":1419},{"text":1196,"config":1600},{"href":1198,"dataGaName":1199,"dataGaLocation":1419},{"text":1204,"config":1602},{"href":1206,"dataGaName":1207,"dataGaLocation":1419},{"text":1209,"config":1604},{"href":1211,"dataGaName":1212,"dataGaLocation":1419},{"text":1214,"config":1606},{"href":1216,"dataGaName":971,"dataGaLocation":1419},{"text":1218,"config":1608},{"href":1220,"dataGaName":1221,"dataGaLocation":1419},{"text":1223,"config":1610},{"href":1225,"dataGaName":1226,"dataGaLocation":1419},{"text":1228,"config":1612},{"href":1230,"dataGaName":1231,"dataGaLocation":1419},{"title":1244,"links":1614},[1615,1617,1619,1621,1623,1625,1629,1634,1636,1638,1640],{"text":1252,"config":1616},{"href":1254,"dataGaName":1246,"dataGaLocation":1419},{"text":1257,"config":1618},{"href":1259,"dataGaName":1260,"dataGaLocation":1419},{"text":1265,"config":1620},{"href":1267,"dataGaName":1268,"dataGaLocation":1419},{"text":1270,"config":1622},{"href":1272,"dataGaName":1273,"dataGaLocation":1419},{"text":1275,"config":1624},{"href":1277,"dataGaName":1278,"dataGaLocation":1419},{"text":1626,"config":1627},"Sustainability",{"href":1628,"dataGaName":1626,"dataGaLocation":1419},"/sustainability/",{"text":1630,"config":1631},"Diversity, inclusion and belonging (DIB)",{"href":1632,"dataGaName":1633,"dataGaLocation":1419},"/diversity-inclusion-belonging/","Diversity, inclusion and belonging",{"text":1280,"config":1635},{"href":1282,"dataGaName":1283,"dataGaLocation":1419},{"text":1290,"config":1637},{"href":1292,"dataGaName":1293,"dataGaLocation":1419},{"text":1295,"config":1639},{"href":1297,"dataGaName":1298,"dataGaLocation":1419},{"text":1641,"config":1642},"Modern Slavery Transparency Statement",{"href":1643,"dataGaName":1644,"dataGaLocation":1419},"https://handbook.gitlab.com/handbook/legal/modern-slavery-act-transparency-statement/","modern slavery transparency statement",{"items":1646},[1647,1650,1653],{"text":1648,"config":1649},"Terms",{"href":1471,"dataGaName":1472,"dataGaLocation":1419},{"text":1651,"config":1652},"Cookies",{"dataGaName":1481,"dataGaLocation":1419,"id":1482,"isOneTrustButton":102},{"text":1654,"config":1655},"Privacy",{"href":1476,"dataGaName":1477,"dataGaLocation":1419},[1657],{"id":1658,"title":7,"body":958,"config":1659,"content":1661,"description":958,"extension":1665,"meta":1666,"navigation":102,"path":1667,"seo":1668,"stem":1669,"__hash__":1670},"blogAuthors/en-us/blog/authors/patrick-steinhardt.yml",{"template":1660},"BlogAuthor",{"name":7,"config":1662},{"headshot":1663,"ctfId":1664},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1749661952/Blog/Author%20Headshots/pks-gitlab-headshot.png","pksgitlab","yml",{},"/en-us/blog/authors/patrick-steinhardt",{},"en-us/blog/authors/patrick-steinhardt","SV9Yd_vW69UbvntDP-SEOV9NKT_VwUAj5nfftf2ElSw",[1672,1680,1688],{"title":1673,"description":1674,"heroImage":1675,"category":954,"date":1676,"authors":1677,"slug":1679,"externalUrl":958},"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",[1678],"Toon Claes","whats-new-in-git-2-55-0",{"title":1681,"description":1682,"heroImage":1683,"category":954,"date":1684,"authors":1685,"slug":1687,"externalUrl":958},"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",[1686],"Nick Veenhof","gitlab-ai-hackathon-2026-meet-the-winners",{"title":1689,"description":1690,"heroImage":1691,"category":954,"date":1692,"authors":1693,"slug":1694,"externalUrl":958},"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",[7],"whats-new-in-git-2-54-0",{"promotions":1696},[1697,1711,1723,1735],{"id":1698,"categories":1699,"header":1701,"text":1702,"button":1703,"image":1708},"ai-modernization",[1700],"ai","Is AI achieving its promise at scale?","Quiz will take 5 minutes or less",{"text":1704,"config":1705},"Get your AI maturity score",{"href":1706,"dataGaName":1707,"dataGaLocation":1185},"/assessments/ai-modernization-assessment/","modernization assessment",{"config":1709},{"src":1710},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1772138786/qix0m7kwnd8x2fh1zq49.png",{"id":1712,"categories":1713,"header":1715,"text":1702,"button":1716,"image":1720},"devops-modernization",[1714,1521],"product","Are you just managing tools or shipping innovation?",{"text":1717,"config":1718},"Get your DevOps maturity score",{"href":1719,"dataGaName":1707,"dataGaLocation":1185},"/assessments/devops-modernization-assessment/",{"config":1721},{"src":1722},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1772138785/eg818fmakweyuznttgid.png",{"id":1724,"categories":1725,"header":1727,"text":1702,"button":1728,"image":1732},"security-modernization",[1726],"security","Are you trading speed for security?",{"text":1729,"config":1730},"Get your security maturity score",{"href":1731,"dataGaName":1707,"dataGaLocation":1185},"/assessments/security-modernization-assessment/",{"config":1733},{"src":1734},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1772138786/p4pbqd9nnjejg5ds6mdk.png",{"id":1736,"paths":1737,"header":1740,"text":1741,"button":1742,"image":1747},"github-azure-migration",[1738,1739],"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":1743,"config":1744},"See how GitLab compares to GitHub",{"href":1745,"dataGaName":1746,"dataGaLocation":1185},"/compare/gitlab-vs-github/github-azure-migration/","github azure migration",{"config":1748},{"src":1722},{"header":1750,"blurb":1751,"button":1752,"secondaryButton":1757},"Start building faster today","See what your team can do with the intelligent orchestration platform for DevSecOps.\n",{"text":1753,"config":1754},"Get your free trial",{"href":1755,"dataGaName":984,"dataGaLocation":1756},"https://gitlab.com/-/trial_registrations/new?glm_content=default-saas-trial&glm_source=about.gitlab.com/","feature",{"text":1457,"config":1758},{"href":1309,"dataGaName":989,"dataGaLocation":1756},1786803776737]