[{"data":1,"prerenderedAt":1836},["ShallowReactive",2],{"/blog/whats-new-in-git-2-46-0":3,"navigation-en-us":1051,"banner-en-us":1478,"footer-en-us":1488,"blog-post-authors-en-us-Justin Tobler":1733,"blog-related-posts-en-us-whats-new-in-git-2-46-0":1748,"blog-promotions-en-us":1772,"next-steps-en-us":1826},{"id":4,"title":5,"authors":6,"body":8,"category":1030,"date":1031,"description":1032,"extension":1033,"externalUrl":1034,"faq":1034,"featured":1035,"heroImage":1036,"meta":1037,"navigation":1035,"path":1038,"seo":1039,"slug":1044,"stem":1045,"tags":1046,"template":1049,"updatedDate":1034,"__hash__":1050},"blogPosts/en-us/blog/whats-new-in-git-2-46-0.md","What’s new in Git 2.46.0?",[7],"Justin Tobler",{"type":9,"value":10,"toc":1021},"minimark",[11,22,27,48,56,364,370,373,376,384,388,401,551,554,572,661,669,676,680,683,801,837,881,886,890,901,914,922,950,954,957,978,982,990,999,1003,1017],[12,13,14,15,21],"p",{},"The Git project recently released ",[16,17,20],"a",{"href":18,"rel":19},"https://lore.kernel.org/git/xmqqzfq0i0qa.fsf@gitster.g/T/#u",[],"Git v2.46.0",". Let's look at a few notable highlights from this release, which includes contributions from GitLab's Git team and the wider Git community.",[23,24,26],"h2",{"id":25},"tooling-to-migrate-reference-backends","Tooling to migrate reference backends",[12,28,29,30,35,36,41,42,47],{},"In the previous ",[16,31,34],{"href":32,"rel":33},"https://gitlab.com/gitlab-org/git/-/raw/master/Documentation/RelNotes/2.45.0.txt?ref_type=heads",[],"Git 2.45.0","\nrelease, the reftables format was introduced as a new backend for storing\nreferences. This new reference format solves some challenges that large\nrepositories face as the number of references scales. If you are not yet\nfamiliar with the reftables backend, check out our previous ",[16,37,40],{"href":38,"rel":39},"https://about.gitlab.com/blog/whats-new-in-git-2-45-0/",[],"Git release blog post"," where the feature was introduced and our beginner’s guide to ",[16,43,46],{"href":44,"rel":45},"https://about.gitlab.com/blog/a-beginners-guide-to-the-git-reftable-format/",[],"learn more about how reftables work",".",[12,49,50,51,55],{},"The reftable backend has a different on-disk format than the pre-existing files backend. Consequently, to use reftables on an existing repository requires a conversion between the different formats. To accomplish this, a new git-refs(1) command has been introduced with the ",[52,53,54],"code",{},"migrate"," subcommand to perform reference backend migrations. Below is an example of how this command can be used.",[57,58,63],"pre",{"className":59,"code":60,"language":61,"meta":62,"style":62},"language-shell shiki shiki-themes github-light","# Initialize a new repository as “bare” so it does not contain reflogs.\n$ git init --bare .\n$ git commit --allow-empty -m \"init\"\n# Populate repository with references in the files backend.\n$ git branch foo\n$ git branch bar\n$ tree .git/refs\n.git/refs\n├── heads\n│   ├── bar\n│   ├── foo\n│   ├── main\n└── tags\n# Perform reference migration to reftables format.\n$ git refs migrate --ref-format=reftable\n# Check that reftables backend is now in use.\n$ tree .git/reftable\n.git/reftable\n├── 0x000000000001-0x000000000001-a3451eed.ref\n└── tables.list\n# Check the repository config to see the updated `refstorage` format.\n$ cat config\n[core]\n        repositoryformatversion = 1\n        filemode = true\n        bare = true\n        ignorecase = true\n        precomposeunicode = true\n[extensions]\n        refstorage = reftable\n\n","shell","",[52,64,65,74,95,114,120,133,145,156,162,171,182,191,201,210,216,232,238,248,254,262,270,276,287,294,306,317,327,337,347,353],{"__ignoreMap":62},[66,67,70],"span",{"class":68,"line":69},"line",1,[66,71,73],{"class":72},"sAwPA","# Initialize a new repository as “bare” so it does not contain reflogs.\n",[66,75,77,81,85,88,92],{"class":68,"line":76},2,[66,78,80],{"class":79},"s7eDp","$",[66,82,84],{"class":83},"sYBdl"," git",[66,86,87],{"class":83}," init",[66,89,91],{"class":90},"sYu0t"," --bare",[66,93,94],{"class":83}," .\n",[66,96,98,100,102,105,108,111],{"class":68,"line":97},3,[66,99,80],{"class":79},[66,101,84],{"class":83},[66,103,104],{"class":83}," commit",[66,106,107],{"class":90}," --allow-empty",[66,109,110],{"class":90}," -m",[66,112,113],{"class":83}," \"init\"\n",[66,115,117],{"class":68,"line":116},4,[66,118,119],{"class":72},"# Populate repository with references in the files backend.\n",[66,121,123,125,127,130],{"class":68,"line":122},5,[66,124,80],{"class":79},[66,126,84],{"class":83},[66,128,129],{"class":83}," branch",[66,131,132],{"class":83}," foo\n",[66,134,136,138,140,142],{"class":68,"line":135},6,[66,137,80],{"class":79},[66,139,84],{"class":83},[66,141,129],{"class":83},[66,143,144],{"class":83}," bar\n",[66,146,148,150,153],{"class":68,"line":147},7,[66,149,80],{"class":79},[66,151,152],{"class":83}," tree",[66,154,155],{"class":83}," .git/refs\n",[66,157,159],{"class":68,"line":158},8,[66,160,161],{"class":79},".git/refs\n",[66,163,165,168],{"class":68,"line":164},9,[66,166,167],{"class":79},"├──",[66,169,170],{"class":83}," heads\n",[66,172,174,177,180],{"class":68,"line":173},10,[66,175,176],{"class":79},"│",[66,178,179],{"class":83},"   ├──",[66,181,144],{"class":83},[66,183,185,187,189],{"class":68,"line":184},11,[66,186,176],{"class":79},[66,188,179],{"class":83},[66,190,132],{"class":83},[66,192,194,196,198],{"class":68,"line":193},12,[66,195,176],{"class":79},[66,197,179],{"class":83},[66,199,200],{"class":83}," main\n",[66,202,204,207],{"class":68,"line":203},13,[66,205,206],{"class":79},"└──",[66,208,209],{"class":83}," tags\n",[66,211,213],{"class":68,"line":212},14,[66,214,215],{"class":72},"# Perform reference migration to reftables format.\n",[66,217,219,221,223,226,229],{"class":68,"line":218},15,[66,220,80],{"class":79},[66,222,84],{"class":83},[66,224,225],{"class":83}," refs",[66,227,228],{"class":83}," migrate",[66,230,231],{"class":90}," --ref-format=reftable\n",[66,233,235],{"class":68,"line":234},16,[66,236,237],{"class":72},"# Check that reftables backend is now in use.\n",[66,239,241,243,245],{"class":68,"line":240},17,[66,242,80],{"class":79},[66,244,152],{"class":83},[66,246,247],{"class":83}," .git/reftable\n",[66,249,251],{"class":68,"line":250},18,[66,252,253],{"class":79},".git/reftable\n",[66,255,257,259],{"class":68,"line":256},19,[66,258,167],{"class":79},[66,260,261],{"class":83}," 0x000000000001-0x000000000001-a3451eed.ref\n",[66,263,265,267],{"class":68,"line":264},20,[66,266,206],{"class":79},[66,268,269],{"class":83}," tables.list\n",[66,271,273],{"class":68,"line":272},21,[66,274,275],{"class":72},"# Check the repository config to see the updated `refstorage` format.\n",[66,277,279,281,284],{"class":68,"line":278},22,[66,280,80],{"class":79},[66,282,283],{"class":83}," cat",[66,285,286],{"class":83}," config\n",[66,288,290],{"class":68,"line":289},23,[66,291,293],{"class":292},"sgsFI","[core]\n",[66,295,297,300,303],{"class":68,"line":296},24,[66,298,299],{"class":79},"        repositoryformatversion",[66,301,302],{"class":83}," =",[66,304,305],{"class":90}," 1\n",[66,307,309,312,314],{"class":68,"line":308},25,[66,310,311],{"class":79},"        filemode",[66,313,302],{"class":83},[66,315,316],{"class":90}," true\n",[66,318,320,323,325],{"class":68,"line":319},26,[66,321,322],{"class":79},"        bare",[66,324,302],{"class":83},[66,326,316],{"class":90},[66,328,330,333,335],{"class":68,"line":329},27,[66,331,332],{"class":79},"        ignorecase",[66,334,302],{"class":83},[66,336,316],{"class":90},[66,338,340,343,345],{"class":68,"line":339},28,[66,341,342],{"class":79},"        precomposeunicode",[66,344,302],{"class":83},[66,346,316],{"class":90},[66,348,350],{"class":68,"line":349},29,[66,351,352],{"class":292},"[extensions]\n",[66,354,356,359,361],{"class":68,"line":355},30,[66,357,358],{"class":79},"        refstorage",[66,360,302],{"class":83},[66,362,363],{"class":83}," reftable\n",[12,365,366,367,47],{},"Once a repository has been migrated, the on-disk format is changed to begin\nusing the reftable backend. Git operations on the repository continue to\nfunction and interact with remotes the same as before. The migration only\naffects how references are stored internally for the repository. If you wish to go back to the files reference backend, you can accomplish this with the same command by instead specifying ",[52,368,369],{},"--ref-format=files",[12,371,372],{},"The migration tooling currently has some notable limitations. The reflogs in a repository are a component of a reference backend and would also require\nmigration between formats. Unfortunately, the tooling is not yet capable of\nconverting reflogs between the files and reftables backends. Also, a repository with worktrees essentially has multiple ref stores and the migration tool is not yet capable of handling this scenario. Therefore, if a repository contains reflogs or worktrees, reference migration is currently unavailable. These limitations may be overcome in future versions.",[12,374,375],{},"Because a bare Git repository does not have reflogs, it is easier to migrate. To migrate a standard non-bare repository, reflogs must be pruned first. Therefore, any repository without reflogs or worktrees can be migrated. With these limitations in mind, this tool can be used to begin taking advantage of the reftables backend in your existing repositories.",[12,377,378,379,47],{},"This project was led by ",[16,380,383],{"href":381,"rel":382},"https://gitlab.com/pks-gitlab",[],"Patrick Steinhardt",[23,385,387],{"id":386},"transactional-symref-updates","Transactional symref updates",[12,389,390,391,396,397,400],{},"The ",[16,392,395],{"href":393,"rel":394},"https://git-scm.com/docs/git-update-ref",[],"git-update-ref(1)"," command\nperforms reference updates in a Git repository. These reference updates can also be performed atomically in bulk with transactions by using\n",[52,398,399],{},"git update-ref --stdin"," and passing update-ref instructions on stdin. Below is an example of how this is done.",[57,402,404],{"className":59,"code":403,"language":61,"meta":62,"style":62},"$ git init .\n$ git branch -m main\n$ git commit --allow-empty -m \"foo\" && git commit --allow-empty -m \"bar\"\n# Retrieve the object ID of the two commits created.\n$ git rev-parse main~ main\n567aac2b3d1fbf0bd2433f669eb0b82a0348775e\n3b13462a9a42e0a3130b9cbc472ab479d3ef0631\n# Start transaction, provide update-ref instructions, and commit.\n$ git update-ref --stdin \u003C\u003CEOF\n> start\n> create refs/heads/new-ref 3b13462a9a42e0a3130b9cbc472ab479d3ef0631\n> update refs/heads/main 567aac2b3d1fbf0bd2433f669eb0b82a0348775e\n> commit\n> EOF\n$ git for-each-ref\n567aac2b3d1fbf0bd2433f669eb0b82a0348775e commit refs/heads/main\n3b13462a9a42e0a3130b9cbc472ab479d3ef0631 commit refs/heads/my-ref\n",[52,405,406,416,428,458,463,477,482,487,492,511,516,521,526,531,536,541,546],{"__ignoreMap":62},[66,407,408,410,412,414],{"class":68,"line":69},[66,409,80],{"class":79},[66,411,84],{"class":83},[66,413,87],{"class":83},[66,415,94],{"class":83},[66,417,418,420,422,424,426],{"class":68,"line":76},[66,419,80],{"class":79},[66,421,84],{"class":83},[66,423,129],{"class":83},[66,425,110],{"class":90},[66,427,200],{"class":83},[66,429,430,432,434,436,438,440,443,446,449,451,453,455],{"class":68,"line":97},[66,431,80],{"class":79},[66,433,84],{"class":83},[66,435,104],{"class":83},[66,437,107],{"class":90},[66,439,110],{"class":90},[66,441,442],{"class":83}," \"foo\"",[66,444,445],{"class":292}," && ",[66,447,448],{"class":79},"git",[66,450,104],{"class":83},[66,452,107],{"class":90},[66,454,110],{"class":90},[66,456,457],{"class":83}," \"bar\"\n",[66,459,460],{"class":68,"line":116},[66,461,462],{"class":72},"# Retrieve the object ID of the two commits created.\n",[66,464,465,467,469,472,475],{"class":68,"line":122},[66,466,80],{"class":79},[66,468,84],{"class":83},[66,470,471],{"class":83}," rev-parse",[66,473,474],{"class":83}," main~",[66,476,200],{"class":83},[66,478,479],{"class":68,"line":135},[66,480,481],{"class":79},"567aac2b3d1fbf0bd2433f669eb0b82a0348775e\n",[66,483,484],{"class":68,"line":147},[66,485,486],{"class":79},"3b13462a9a42e0a3130b9cbc472ab479d3ef0631\n",[66,488,489],{"class":68,"line":158},[66,490,491],{"class":72},"# Start transaction, provide update-ref instructions, and commit.\n",[66,493,494,496,498,501,504,508],{"class":68,"line":164},[66,495,80],{"class":79},[66,497,84],{"class":83},[66,499,500],{"class":83}," update-ref",[66,502,503],{"class":90}," --stdin",[66,505,507],{"class":506},"sD7c4"," \u003C\u003C",[66,509,510],{"class":83},"EOF\n",[66,512,513],{"class":68,"line":173},[66,514,515],{"class":83},"> start\n",[66,517,518],{"class":68,"line":184},[66,519,520],{"class":83},"> create refs/heads/new-ref 3b13462a9a42e0a3130b9cbc472ab479d3ef0631\n",[66,522,523],{"class":68,"line":193},[66,524,525],{"class":83},"> update refs/heads/main 567aac2b3d1fbf0bd2433f669eb0b82a0348775e\n",[66,527,528],{"class":68,"line":203},[66,529,530],{"class":83},"> commit\n",[66,532,533],{"class":68,"line":212},[66,534,535],{"class":83},"> EOF\n",[66,537,538],{"class":68,"line":218},[66,539,540],{"class":83},"$ git for-each-ref\n",[66,542,543],{"class":68,"line":234},[66,544,545],{"class":83},"567aac2b3d1fbf0bd2433f669eb0b82a0348775e commit refs/heads/main\n",[66,547,548],{"class":68,"line":240},[66,549,550],{"class":83},"3b13462a9a42e0a3130b9cbc472ab479d3ef0631 commit refs/heads/my-ref\n",[12,552,553],{},"From this example, once the transaction is committed, a new branch is created pointing to the “bar” commit and the main branch is updated to point to the previous “foo” commit. Committing the transaction performs the specified reference updates atomically. If an individual reference update fails, the transaction is aborted and no reference updates are performed.",[12,555,556,557,560,561,560,564,567,568,571],{},"A notable absence here is instructions to support symref updates in these\ntransactions. If a user wants to update a symref along with other references\natomically in the same transaction, there is no tooling to do so. In this\nrelease, the ",[52,558,559],{},"symref-create",", ",[52,562,563],{},"symref-update",[52,565,566],{},"symref-delete",", and\n",[52,569,570],{},"symref-verify"," instructions are introduced to provide this functionality.",[57,573,575],{"className":59,"code":574,"language":61,"meta":62,"style":62},"# Create a symref that will be updated during the next operation.\n$ git symbolic-ref refs/heads/symref refs/heads/main\n# The --no-deref flag is required to ensure the symref itself is updated.\n$ git update-ref --stdin --no-deref \u003C\u003CEOF\n> start\n> symref-create refs/heads/new-symref refs/heads/main\n> symref-update refs/heads/symref refs/heads/new-ref\n> commit\n> EOF\n$ git symbolic-ref refs/heads/symref\nrefs/heads/new-ref\n$ git symbolic-ref refs/heads/new-symref\nrefs/heads/main\n",[52,576,577,582,597,602,619,623,628,633,637,641,646,651,656],{"__ignoreMap":62},[66,578,579],{"class":68,"line":69},[66,580,581],{"class":72},"# Create a symref that will be updated during the next operation.\n",[66,583,584,586,588,591,594],{"class":68,"line":76},[66,585,80],{"class":79},[66,587,84],{"class":83},[66,589,590],{"class":83}," symbolic-ref",[66,592,593],{"class":83}," refs/heads/symref",[66,595,596],{"class":83}," refs/heads/main\n",[66,598,599],{"class":68,"line":97},[66,600,601],{"class":72},"# The --no-deref flag is required to ensure the symref itself is updated.\n",[66,603,604,606,608,610,612,615,617],{"class":68,"line":116},[66,605,80],{"class":79},[66,607,84],{"class":83},[66,609,500],{"class":83},[66,611,503],{"class":90},[66,613,614],{"class":90}," --no-deref",[66,616,507],{"class":506},[66,618,510],{"class":83},[66,620,621],{"class":68,"line":122},[66,622,515],{"class":83},[66,624,625],{"class":68,"line":135},[66,626,627],{"class":83},"> symref-create refs/heads/new-symref refs/heads/main\n",[66,629,630],{"class":68,"line":147},[66,631,632],{"class":83},"> symref-update refs/heads/symref refs/heads/new-ref\n",[66,634,635],{"class":68,"line":158},[66,636,530],{"class":83},[66,638,639],{"class":68,"line":164},[66,640,535],{"class":83},[66,642,643],{"class":68,"line":173},[66,644,645],{"class":83},"$ git symbolic-ref refs/heads/symref\n",[66,647,648],{"class":68,"line":184},[66,649,650],{"class":83},"refs/heads/new-ref\n",[66,652,653],{"class":68,"line":193},[66,654,655],{"class":83},"$ git symbolic-ref refs/heads/new-symref\n",[66,657,658],{"class":68,"line":203},[66,659,660],{"class":83},"refs/heads/main\n",[12,662,663,664,668],{},"From the above example, a new symbolic reference is created and another is\nupdated in a transaction. These new symref instructions can be used in\ncombination with the pre-existing instructions to perform all manner of\nreference updates now in a single transaction. Check out the\n",[16,665,667],{"href":393,"rel":666},[],"documentation"," for more information regarding each of these new instructions.",[12,670,378,671,47],{},[16,672,675],{"href":673,"rel":674},"https://gitlab.com/knayakgl",[],"Karthik Nayak",[23,677,679],{"id":678},"ux-improvements-for-git-config1","UX improvements for git-config(1)",[12,681,682],{},"The git-config(1) command allows repository and global options to be viewed and configured. The modes used to interact with configuration can be selected explicitly using flags or determined implicitly based on the number of arguments provided to the command. For example:",[57,684,686],{"className":59,"code":685,"language":61,"meta":62,"style":62},"$ git config --list\n# Explicit retrieval of username configuration\n$ git config --get user.name\n# Implicit retrieval of username configuration\n$ git config user.name\n# Explicit setting of username configuration\n$ git config --set user.name \"Sidney Jones\"\n# Implicit setting of username configuration\n$ git config user.name \"Sidney Jones\"\n# An optional third argument is also accepted. What do you think this does?\n$ git config \u003Cname> [\u003Cvalue> [\u003Cvalue-pattern>]]\n",[52,687,688,700,705,719,724,734,739,756,761,773,778],{"__ignoreMap":62},[66,689,690,692,694,697],{"class":68,"line":69},[66,691,80],{"class":79},[66,693,84],{"class":83},[66,695,696],{"class":83}," config",[66,698,699],{"class":90}," --list\n",[66,701,702],{"class":68,"line":76},[66,703,704],{"class":72},"# Explicit retrieval of username configuration\n",[66,706,707,709,711,713,716],{"class":68,"line":97},[66,708,80],{"class":79},[66,710,84],{"class":83},[66,712,696],{"class":83},[66,714,715],{"class":90}," --get",[66,717,718],{"class":83}," user.name\n",[66,720,721],{"class":68,"line":116},[66,722,723],{"class":72},"# Implicit retrieval of username configuration\n",[66,725,726,728,730,732],{"class":68,"line":122},[66,727,80],{"class":79},[66,729,84],{"class":83},[66,731,696],{"class":83},[66,733,718],{"class":83},[66,735,736],{"class":68,"line":135},[66,737,738],{"class":72},"# Explicit setting of username configuration\n",[66,740,741,743,745,747,750,753],{"class":68,"line":147},[66,742,80],{"class":79},[66,744,84],{"class":83},[66,746,696],{"class":83},[66,748,749],{"class":90}," --set",[66,751,752],{"class":83}," user.name",[66,754,755],{"class":83}," \"Sidney Jones\"\n",[66,757,758],{"class":68,"line":158},[66,759,760],{"class":72},"# Implicit setting of username configuration\n",[66,762,763,765,767,769,771],{"class":68,"line":164},[66,764,80],{"class":79},[66,766,84],{"class":83},[66,768,696],{"class":83},[66,770,752],{"class":83},[66,772,755],{"class":83},[66,774,775],{"class":68,"line":173},[66,776,777],{"class":72},"# An optional third argument is also accepted. What do you think this does?\n",[66,779,780,782,784,786,789,792,795,798],{"class":68,"line":184},[66,781,80],{"class":79},[66,783,84],{"class":83},[66,785,696],{"class":83},[66,787,788],{"class":506}," \u003C",[66,790,791],{"class":83},"nam",[66,793,794],{"class":292},"e",[66,796,797],{"class":506},">",[66,799,800],{"class":292}," [\u003Cvalue> [\u003Cvalue-pattern>]]\n",[12,802,803,804,809,810,813,814,560,817,560,820,560,823,560,826,560,829,832,833,836],{},"Overall, the ",[16,805,808],{"href":806,"rel":807},"https://git-scm.com/docs/git-config",[],"git-config(1)"," user\ninterface is not consistent with how other more modern Git commands work where you usually use subcommands. For example, ",[52,811,812],{},"git remote list",". This release introduces ",[52,815,816],{},"list",[52,818,819],{},"get",[52,821,822],{},"set",[52,824,825],{},"unset",[52,827,828],{},"rename-section",[52,830,831],{},"remove-section",", and ",[52,834,835],{},"edit"," as subcommands for use with the config command while also keeping the old-style syntax available. This change aims to improve user experience by adapting the config command to follow more UI practices and better conform to other commands within Git. For example:",[57,838,840],{"className":59,"code":839,"language":61,"meta":62,"style":62},"$ git config list\n$ git config get user.name\n$ git config set user.name \"Sidney Jones\"\n",[52,841,842,853,866],{"__ignoreMap":62},[66,843,844,846,848,850],{"class":68,"line":69},[66,845,80],{"class":79},[66,847,84],{"class":83},[66,849,696],{"class":83},[66,851,852],{"class":83}," list\n",[66,854,855,857,859,861,864],{"class":68,"line":76},[66,856,80],{"class":79},[66,858,84],{"class":83},[66,860,696],{"class":83},[66,862,863],{"class":83}," get",[66,865,718],{"class":83},[66,867,868,870,872,874,877,879],{"class":68,"line":97},[66,869,80],{"class":79},[66,871,84],{"class":83},[66,873,696],{"class":83},[66,875,876],{"class":83}," set",[66,878,752],{"class":83},[66,880,755],{"class":83},[12,882,378,883,47],{},[16,884,383],{"href":381,"rel":885},[],[23,887,889],{"id":888},"addressed-performance-regression","Addressed performance regression",[12,891,892,893,896,897,900],{},"Git operations that leverage attributes rely on reading ",[52,894,895],{},".gitattributes"," files found in the repository’s working-tree. This is problematic for bare Git repositories because by definition they lack a working-tree. To get around this, Git has the ",[52,898,899],{},"attr.tree"," configuration that allows a source tree to be specified and used to lookup attributes from.",[12,902,903,904,907,908,910,911,913],{},"In Git release 2.43.0, Git started using the tree of ",[52,905,906],{},"HEAD"," as the source of Git attributes for bare repositories by default. Unfortunately, the additional overhead due to scanning for Git attributes files had severe performance impacts. This is because, when ",[52,909,899],{}," is set, each attribute lookup requires walking the source tree to check for an associated ",[52,912,895],{}," file. The larger and deeper the source tree of the repository is, the more pronounced the performance regression becomes. For example, benchmarks run on the linux.git repository showed\ngit-pack-objects(1) taking 1.68 times longer to complete. This could lead to slowdowns when performing clones or fetches.",[57,915,920],{"className":916,"code":918,"language":919,"meta":62},[917],"language-text","# attr.tree set to HEAD as done by default in Git version 2.43.0.\nBenchmark 1: git -c attr.tree=HEAD pack-objects --all --stdout \u003C/dev/null >/dev/null\n  Time (mean ± σ):     133.807 s ±  4.866 s    [User: 129.034 s, System: 6.671 s]\n  Range (min … max):   128.447 s … 137.945 s    3 runs\n\n# attr.tree is set to an empty tree to disable attribute lookup as done in Git versions prior to 2.43.0.\nBenchmark 2: git -c attr.tree=4b825dc642cb6eb9a060e54bf8d69288fbee4904 pack-objects --all --stdout \u003C/dev/null >/dev/null\n  Time (mean ± σ):     79.442 s ±  0.822 s    [User: 77.500 s, System: 6.056 s]\n  Range (min … max):   78.583 s … 80.221 s    3 runs\n\n","text",[52,921,918],{"__ignoreMap":62},[12,923,924,925,560,928,560,931,832,934,937,938,940,941,943,944,949],{},"Some of the most notable Git commands that were affected were ",[52,926,927],{},"clone",[52,929,930],{},"pull",[52,932,933],{},"fetch",[52,935,936],{},"diff"," when, as previously mentioned, used on repositories with large or deep trees. Consequently, the ",[52,939,899],{}," configuration was partially reverted to no longer be set to ",[52,942,906],{}," by default to address the performance regression. To learn more, check out this\n",[16,945,948],{"href":946,"rel":947},"https://lore.kernel.org/git/CAKOHPAn1btewYTdLYWpW+fOaXMY+JQZsLCQxUSwoUqnnFN_ohA@mail.gmail.com/",[],"thread"," on the mailing list.",[23,951,953],{"id":952},"unit-test-migration","Unit-test migration",[12,955,956],{},"Historically, testing in the Git project has been done via end-to-end tests\nimplemented as shell scripts. The Git project has relatively recently\nintroduced a unit-testing framework written in C. This new testing framework\nbrings opportunities for more in-depth testing of low-level implementation\ndetails at the individual function call level and helps complement the existing end-to-end tests. There are some existing end-to-end tests that are a better fit as unit-tests and thus are good candidates to be ported.",[12,958,959,960,965,966,971,972,977],{},"This year, GitLab is again helping mentor ",[16,961,964],{"href":962,"rel":963},"https://summerofcode.withgoogle.com/",[],"Google Summer of Code (GSoC)"," contributors working in the Git project. Thanks to efforts from these ongoing GSoC projects and also the wider Git community, some existing tests are being refactored and migrated to the unit-testing framework. During this last release cycle, there have been several contributions towards the goal of improving the testing in the Git project. To follow development progress for these GSoC contributor projects, check out ",[16,967,970],{"href":968,"rel":969},"https://chand-ra.github.io/",[],"Chandra’s"," and ",[16,973,976],{"href":974,"rel":975},"https://spectre10.github.io/posts/",[],"Ghanshyam’s"," blogs.",[23,979,981],{"id":980},"bundle-uri-fixes","Bundle URI fixes",[12,983,984,985,47],{},"Usually when a client fetches from a remote repository, all required objects\nare sent in a packfile computed by the remote server. To avoid some of this\ncomputation, servers can opt to advertise prebuilt “bundles” stored separately from the remote server which contain sets of references and objects that the client may need. The client can fetch these bundles first through a mechanism called ",[16,986,989],{"href":987,"rel":988},"https://git-scm.com/docs/bundle-uri",[],"bundle-uri",[12,991,992,993,998],{},"Thanks to ",[16,994,997],{"href":995,"rel":996},"https://lore.kernel.org/git/pull.1730.git.1715742069966.gitgitgadget@gmail.com/",[],"Xing Xin",", an issue was identified and fixed where Git, despite having downloaded some bundles, was still downloading everything from the remote as if there were no bundles. This was due to Git not correctly discovering all the downloaded bundles, which resulted in having to fetch the consecutive ones from the remote. With this fixed, remotes using the bundle-uri mechanism can avoid having to perform redundant work and improve performance.",[23,1000,1002],{"id":1001},"read-more","Read more",[12,1004,1005,1006,1010,1011,1016],{},"This article highlighted just a few of the contributions made by GitLab and\nthe wider Git community for this latest release. You can learn about these from the ",[16,1007,1009],{"href":18,"rel":1008},[],"official release announcement"," of the Git project. Also, check out our ",[16,1012,1015],{"href":1013,"rel":1014},"https://about.gitlab.com/blog/tags/git/",[],"previous Git release blog posts"," to see other past highlights of contributions from GitLab team members.",[1018,1019,1020],"style",{},"html pre.shiki code .sAwPA, html code.shiki .sAwPA{--shiki-default:#6A737D}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 .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);}html pre.shiki code .sD7c4, html code.shiki .sD7c4{--shiki-default:#D73A49}",{"title":62,"searchDepth":76,"depth":76,"links":1022},[1023,1024,1025,1026,1027,1028,1029],{"id":25,"depth":76,"text":26},{"id":386,"depth":76,"text":387},{"id":678,"depth":76,"text":679},{"id":888,"depth":76,"text":889},{"id":952,"depth":76,"text":953},{"id":980,"depth":76,"text":981},{"id":1001,"depth":76,"text":1002},"open-source","2024-07-29","Here are highlights of release contributions from GitLab's Git team and the wider Git community, including reference backend migration tooling and transactional symbolic reference updates.","md",null,true,"https://res.cloudinary.com/about-gitlab-com/image/upload/v1749660028/Blog/Hero%20Images/blog-image-template-1800x945__25_.png",{},"/en-us/blog/whats-new-in-git-2-46-0",{"title":5,"description":1032,"ogTitle":5,"ogDescription":1032,"noIndex":1040,"ogImage":1036,"ogUrl":1041,"ogSiteName":1042,"ogType":1043,"canonicalUrls":1041},false,"https://about.gitlab.com/blog/whats-new-in-git-2-46-0","https://about.gitlab.com","article","whats-new-in-git-2-46-0","en-us/blog/whats-new-in-git-2-46-0",[448,1047,1048],"open source","community","BlogPost","RohdjphEyJFXiuhtpBSVFsBXM-MXd5Gqq-FEGMt0upc",{"logo":1052,"freeTrial":1057,"sales":1062,"login":1067,"items":1072,"search":1398,"minimal":1429,"duo":1448,"switchNav":1457,"pricingDeployment":1468},{"config":1053},{"href":1054,"dataGaName":1055,"dataGaLocation":1056},"/","gitlab logo","header",{"text":1058,"config":1059},"Get free trial",{"href":1060,"dataGaName":1061,"dataGaLocation":1056},"https://gitlab.com/-/trial_registrations/new?glm_source=about.gitlab.com&glm_content=default-saas-trial/","free trial",{"text":1063,"config":1064},"Request a demo",{"href":1065,"dataGaName":1066,"dataGaLocation":1056},"/sales/?contact-topic=request-demo","sales",{"text":1068,"config":1069},"Sign in",{"href":1070,"dataGaName":1071,"dataGaLocation":1056},"https://gitlab.com/users/sign_in/","sign in",[1073,1102,1202,1207,1320,1376],{"text":1074,"config":1075,"menu":1077},"Platform",{"dataNavLevelOne":1076},"platform",{"type":1078,"columns":1079},"cards",[1080,1086,1094],{"title":1074,"description":1081,"link":1082},"The intelligent orchestration platform for DevSecOps",{"text":1083,"config":1084},"Explore our Platform",{"href":1085,"dataGaName":1076,"dataGaLocation":1056},"/platform/",{"title":1087,"description":1088,"link":1089},"GitLab Duo Agent Platform","Agentic AI for the entire software lifecycle",{"text":1090,"config":1091},"Meet GitLab Duo",{"href":1092,"dataGaName":1093,"dataGaLocation":1056},"/gitlab-duo-agent-platform/","gitlab duo agent platform",{"title":1095,"description":1096,"link":1097},"Why GitLab","See the top reasons enterprises choose GitLab",{"text":1098,"config":1099},"Learn more",{"href":1100,"dataGaName":1101,"dataGaLocation":1056},"/why-gitlab/","why gitlab",{"text":1103,"left":1035,"config":1104,"menu":1106},"Product",{"dataNavLevelOne":1105},"solutions",{"type":1107,"link":1108,"columns":1112,"feature":1181},"lists",{"text":1109,"config":1110},"View all Solutions",{"href":1111,"dataGaName":1105,"dataGaLocation":1056},"/solutions/",[1113,1137,1160],{"title":1114,"description":1115,"link":1116,"items":1121},"Automation","CI/CD and automation to accelerate deployment",{"config":1117},{"icon":1118,"href":1119,"dataGaName":1120,"dataGaLocation":1056},"AutomatedCodeAlt","/solutions/delivery-automation/","automated software delivery",[1122,1126,1129,1133],{"text":1123,"config":1124},"CI/CD",{"href":1125,"dataGaLocation":1056,"dataGaName":1123},"/solutions/continuous-integration/",{"text":1087,"config":1127},{"href":1092,"dataGaLocation":1056,"dataGaName":1128},"gitlab duo agent platform - product menu",{"text":1130,"config":1131},"Source Code Management",{"href":1132,"dataGaLocation":1056,"dataGaName":1130},"/solutions/source-code-management/",{"text":1134,"config":1135},"Automated Software Delivery",{"href":1119,"dataGaLocation":1056,"dataGaName":1136},"Automated software delivery",{"title":1138,"description":1139,"link":1140,"items":1145},"Security","Deliver code faster without compromising security",{"config":1141},{"href":1142,"dataGaName":1143,"dataGaLocation":1056,"icon":1144},"/solutions/application-security-testing/","security and compliance","ShieldCheckLight",[1146,1150,1155],{"text":1147,"config":1148},"Application Security Testing",{"href":1142,"dataGaName":1149,"dataGaLocation":1056},"Application security testing",{"text":1151,"config":1152},"Software Supply Chain Security",{"href":1153,"dataGaLocation":1056,"dataGaName":1154},"/solutions/supply-chain/","Software supply chain security",{"text":1156,"config":1157},"Software Compliance",{"href":1158,"dataGaName":1159,"dataGaLocation":1056},"/solutions/software-compliance/","software compliance",{"title":1161,"link":1162,"items":1167},"Measurement",{"config":1163},{"icon":1164,"href":1165,"dataGaName":1166,"dataGaLocation":1056},"DigitalTransformation","/solutions/visibility-measurement/","visibility and measurement",[1168,1172,1176],{"text":1169,"config":1170},"Visibility & Measurement",{"href":1165,"dataGaLocation":1056,"dataGaName":1171},"Visibility and Measurement",{"text":1173,"config":1174},"Value Stream Management",{"href":1175,"dataGaLocation":1056,"dataGaName":1173},"/solutions/value-stream-management/",{"text":1177,"config":1178},"Analytics & Insights",{"href":1179,"dataGaLocation":1056,"dataGaName":1180},"/solutions/analytics-and-insights/","Analytics and insights",{"title":1182,"type":1107,"items":1183},"GitLab for",[1184,1190,1196],{"text":1185,"config":1186},"Enterprise",{"icon":1187,"href":1188,"dataGaLocation":1056,"dataGaName":1189},"Building","/enterprise/","enterprise",{"text":1191,"config":1192},"Small Business",{"icon":1193,"href":1194,"dataGaLocation":1056,"dataGaName":1195},"Work","/small-business/","small business",{"text":1197,"config":1198},"Public Sector",{"icon":1199,"href":1200,"dataGaLocation":1056,"dataGaName":1201},"Organization","/solutions/public-sector/","public sector",{"text":1203,"config":1204},"Pricing",{"href":1205,"dataGaName":1206,"dataGaLocation":1056,"dataNavLevelOne":1206},"/pricing/","pricing",{"text":1208,"config":1209,"menu":1211},"Resources",{"dataNavLevelOne":1210},"resources",{"type":1107,"link":1212,"columns":1216,"feature":1309},{"text":1213,"config":1214},"View all resources",{"href":1215,"dataGaName":1210,"dataGaLocation":1056},"/resources/",[1217,1250,1277],{"title":1218,"items":1219},"Getting started",[1220,1225,1230,1235,1240,1245],{"text":1221,"config":1222},"Install",{"href":1223,"dataGaName":1224,"dataGaLocation":1056},"/install/","install",{"text":1226,"config":1227},"Quick start guides",{"href":1228,"dataGaName":1229,"dataGaLocation":1056},"/get-started/","quick setup checklists",{"text":1231,"config":1232},"Learn",{"href":1233,"dataGaLocation":1056,"dataGaName":1234},"https://university.gitlab.com/","learn",{"text":1236,"config":1237},"Product documentation",{"href":1238,"dataGaName":1239,"dataGaLocation":1056},"https://docs.gitlab.com/","product documentation",{"text":1241,"config":1242},"Best practice videos",{"href":1243,"dataGaName":1244,"dataGaLocation":1056},"/getting-started-videos/","best practice videos",{"text":1246,"config":1247},"Integrations",{"href":1248,"dataGaName":1249,"dataGaLocation":1056},"/integrations/","integrations",{"title":1251,"items":1252},"Discover",[1253,1258,1263,1268,1272],{"text":1254,"config":1255},"Customer success stories",{"href":1256,"dataGaName":1257,"dataGaLocation":1056},"/customers/","customer success stories",{"text":1259,"config":1260},"Blog",{"href":1261,"dataGaName":1262,"dataGaLocation":1056},"/blog/","blog",{"text":1264,"config":1265},"Demo Hub",{"href":1266,"dataGaName":1267,"dataGaLocation":1056},"/demo-hub/","demo hub",{"text":1269,"config":1270},"The Source",{"href":1271,"dataGaName":1262,"dataGaLocation":1056},"/the-source/",{"text":1273,"config":1274},"Remote",{"href":1275,"dataGaName":1276,"dataGaLocation":1056},"https://handbook.gitlab.com/handbook/company/culture/all-remote/","remote",{"title":1278,"items":1279},"Connect",[1280,1285,1290,1294,1299,1304],{"text":1281,"config":1282},"GitLab Services",{"href":1283,"dataGaName":1284,"dataGaLocation":1056},"/services/","services",{"text":1286,"config":1287},"Contribute",{"href":1288,"dataGaName":1289,"dataGaLocation":1056},"https://contributors.gitlab.com","contribute",{"text":1291,"config":1292},"Community",{"href":1293,"dataGaName":1048,"dataGaLocation":1056},"/community/",{"text":1295,"config":1296},"Forum",{"href":1297,"dataGaName":1298,"dataGaLocation":1056},"https://forum.gitlab.com/","forum",{"text":1300,"config":1301},"Events",{"href":1302,"dataGaName":1303,"dataGaLocation":1056},"/events/","events",{"text":1305,"config":1306},"Partners",{"href":1307,"dataGaName":1308,"dataGaLocation":1056},"/partners/","partners",{"config":1310,"title":1313,"text":1314,"link":1315},{"background":1311,"textColor":1312},"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":1316,"config":1317},"Read the latest",{"href":1318,"dataGaName":1319,"dataGaLocation":1056},"/whats-new/","whats new",{"text":1321,"config":1322,"menu":1324},"Company",{"dataNavLevelOne":1323},"company",{"type":1107,"columns":1325},[1326],{"items":1327},[1328,1333,1339,1341,1346,1351,1356,1361,1366,1371],{"text":1329,"config":1330},"About",{"href":1331,"dataGaName":1332,"dataGaLocation":1056},"/company/","about",{"text":1334,"config":1335,"footerGa":1338},"Jobs",{"href":1336,"dataGaName":1337,"dataGaLocation":1056},"/jobs/","jobs",{"dataGaName":1337},{"text":1300,"config":1340},{"href":1302,"dataGaName":1303,"dataGaLocation":1056},{"text":1342,"config":1343},"Leadership",{"href":1344,"dataGaName":1345,"dataGaLocation":1056},"/company/team/e-group/","leadership",{"text":1347,"config":1348},"Handbook",{"href":1349,"dataGaName":1350,"dataGaLocation":1056},"https://handbook.gitlab.com/","handbook",{"text":1352,"config":1353},"Investor relations",{"href":1354,"dataGaName":1355,"dataGaLocation":1056},"https://ir.gitlab.com/overview/default.aspx","investor relations",{"text":1357,"config":1358},"Trust Center",{"href":1359,"dataGaName":1360,"dataGaLocation":1056},"/security/","trust center",{"text":1362,"config":1363},"AI Transparency Center",{"href":1364,"dataGaName":1365,"dataGaLocation":1056},"/ai-transparency-center/","ai transparency center",{"text":1367,"config":1368},"Newsletter",{"href":1369,"dataGaName":1370,"dataGaLocation":1056},"/company/contact/#contact-forms","newsletter",{"text":1372,"config":1373},"Press",{"href":1374,"dataGaName":1375,"dataGaLocation":1056},"/press/","press",{"text":1377,"config":1378,"menu":1379},"Contact us",{"dataNavLevelOne":1323},{"type":1107,"columns":1380},[1381],{"items":1382},[1383,1388,1393],{"text":1384,"config":1385},"Talk to sales",{"href":1386,"dataGaName":1387,"dataGaLocation":1056},"/sales/","talk to sales",{"text":1389,"config":1390},"Support portal",{"href":1391,"dataGaName":1392,"dataGaLocation":1056},"https://support.gitlab.com/hc/en-us","support portal",{"text":1394,"config":1395},"Customer portal",{"href":1396,"dataGaName":1397,"dataGaLocation":1056},"https://customers.gitlab.com/customers/sign_in/","customer portal",{"close":1399,"login":1400,"suggestions":1407},"Close",{"text":1401,"link":1402},"To search repositories and projects, login to",{"text":1403,"config":1404},"gitlab.com",{"href":1070,"dataGaName":1405,"dataGaLocation":1406},"search login","search",{"text":1408,"default":1409},"Suggestions",[1410,1412,1416,1418,1422,1426],{"text":1087,"config":1411},{"href":1092,"dataGaName":1087,"dataGaLocation":1406},{"text":1413,"config":1414},"Code Suggestions (AI)",{"href":1415,"dataGaName":1413,"dataGaLocation":1406},"/solutions/code-suggestions/",{"text":1123,"config":1417},{"href":1125,"dataGaName":1123,"dataGaLocation":1406},{"text":1419,"config":1420},"GitLab on AWS",{"href":1421,"dataGaName":1419,"dataGaLocation":1406},"/partners/technology-partners/aws/",{"text":1423,"config":1424},"GitLab on Google Cloud",{"href":1425,"dataGaName":1423,"dataGaLocation":1406},"/partners/technology-partners/google-cloud-platform/",{"text":1427,"config":1428},"Why GitLab?",{"href":1100,"dataGaName":1427,"dataGaLocation":1406},{"freeTrial":1430,"mobileIcon":1435,"desktopIcon":1440,"secondaryButton":1443},{"text":1431,"config":1432},"Start free trial",{"href":1433,"dataGaName":1061,"dataGaLocation":1434},"https://gitlab.com/-/trials/new/","nav",{"altText":1436,"config":1437},"Gitlab Icon",{"src":1438,"dataGaName":1439,"dataGaLocation":1434},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1758203874/jypbw1jx72aexsoohd7x.svg","gitlab icon",{"altText":1436,"config":1441},{"src":1442,"dataGaName":1439,"dataGaLocation":1434},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1758203875/gs4c8p8opsgvflgkswz9.svg",{"text":1444,"config":1445},"Get Started",{"href":1446,"dataGaName":1447,"dataGaLocation":1434},"https://gitlab.com/-/trial_registrations/new?glm_source=about.gitlab.com/get-started/","get started",{"freeTrial":1449,"mobileIcon":1453,"desktopIcon":1455},{"text":1450,"config":1451},"Learn more about GitLab Duo",{"href":1092,"dataGaName":1452,"dataGaLocation":1434},"gitlab duo",{"altText":1436,"config":1454},{"src":1438,"dataGaName":1439,"dataGaLocation":1434},{"altText":1436,"config":1456},{"src":1442,"dataGaName":1439,"dataGaLocation":1434},{"button":1458,"mobileIcon":1463,"desktopIcon":1465},{"text":1459,"config":1460},"/switch",{"href":1461,"dataGaName":1462,"dataGaLocation":1434},"#contact","switch",{"altText":1436,"config":1464},{"src":1438,"dataGaName":1439,"dataGaLocation":1434},{"altText":1436,"config":1466},{"src":1467,"dataGaName":1439,"dataGaLocation":1434},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1773335277/ohhpiuoxoldryzrnhfrh.png",{"freeTrial":1469,"mobileIcon":1474,"desktopIcon":1476},{"text":1470,"config":1471},"Back to pricing",{"href":1205,"dataGaName":1472,"dataGaLocation":1434,"icon":1473},"back to pricing","GoBack",{"altText":1436,"config":1475},{"src":1438,"dataGaName":1439,"dataGaLocation":1434},{"altText":1436,"config":1477},{"src":1442,"dataGaName":1439,"dataGaLocation":1434},{"title":1479,"titleMobile":1480,"button":1481,"config":1486},"Duo Agent Platform delivers 400% ROI, per new Forrester Consulting study.","400% ROI: Forrester TEI for GitLab Duo",{"text":1098,"config":1482},{"href":1483,"dataGaName":1484,"dataGaLocation":1485},"https://about.gitlab.com/blog/gitlab-duo-agent-platform-delivers-400-percent-roi/","forrester-tei-dap-banner","global-banner",{"layout":1487,"disabled":1040},"release",{"data":1489},{"text":1490,"source":1491,"edit":1497,"contribute":1502,"config":1507,"items":1512,"minimal":1722},"Git is a trademark of Software Freedom Conservancy and our use of 'GitLab' is under license",{"text":1492,"config":1493},"View page source",{"href":1494,"dataGaName":1495,"dataGaLocation":1496},"https://gitlab.com/gitlab-com/marketing/digital-experience/about-gitlab-com/","page source","footer",{"text":1498,"config":1499},"Edit this page",{"href":1500,"dataGaName":1501,"dataGaLocation":1496},"https://gitlab.com/gitlab-com/marketing/digital-experience/about-gitlab-com/-/blob/main/content/","web ide",{"text":1503,"config":1504},"Please contribute",{"href":1505,"dataGaName":1506,"dataGaLocation":1496},"https://gitlab.com/gitlab-com/marketing/digital-experience/about-gitlab-com/-/blob/main/CONTRIBUTING.md/","please contribute",{"twitter":1508,"facebook":1509,"youtube":1510,"linkedin":1511},"https://twitter.com/gitlab","https://www.facebook.com/gitlab","https://www.youtube.com/channel/UCnMGQ8QHMAnVIsI3xJrihhg","https://www.linkedin.com/company/gitlab-com",[1513,1560,1614,1658,1690],{"title":1203,"links":1514,"subMenu":1529},[1515,1519,1524],{"text":1516,"config":1517},"View plans",{"href":1205,"dataGaName":1518,"dataGaLocation":1496},"view plans",{"text":1520,"config":1521},"Why Premium?",{"href":1522,"dataGaName":1523,"dataGaLocation":1496},"/pricing/premium/","why premium",{"text":1525,"config":1526},"Why Ultimate?",{"href":1527,"dataGaName":1528,"dataGaLocation":1496},"/pricing/ultimate/","why ultimate",[1530],{"title":1531,"links":1532},"Contact Us",[1533,1536,1538,1540,1545,1550,1555],{"text":1534,"config":1535},"Contact sales",{"href":1386,"dataGaName":1066,"dataGaLocation":1496},{"text":1389,"config":1537},{"href":1391,"dataGaName":1392,"dataGaLocation":1496},{"text":1394,"config":1539},{"href":1396,"dataGaName":1397,"dataGaLocation":1496},{"text":1541,"config":1542},"Status",{"href":1543,"dataGaName":1544,"dataGaLocation":1496},"https://status.gitlab.com/","status",{"text":1546,"config":1547},"Terms of use",{"href":1548,"dataGaName":1549,"dataGaLocation":1496},"/terms/","terms of use",{"text":1551,"config":1552},"Privacy statement",{"href":1553,"dataGaName":1554,"dataGaLocation":1496},"/privacy/","privacy statement",{"text":1556,"config":1557},"Cookie preferences",{"dataGaName":1558,"dataGaLocation":1496,"id":1559,"isOneTrustButton":1035},"cookie preferences","ot-sdk-btn",{"title":1103,"links":1561,"subMenu":1570},[1562,1566],{"text":1563,"config":1564},"DevSecOps platform",{"href":1085,"dataGaName":1565,"dataGaLocation":1496},"devsecops platform",{"text":1567,"config":1568},"AI-Assisted Development",{"href":1092,"dataGaName":1569,"dataGaLocation":1496},"ai-assisted development",[1571],{"title":1572,"links":1573},"Topics",[1574,1579,1584,1589,1594,1599,1604,1609],{"text":1575,"config":1576},"CICD",{"href":1577,"dataGaName":1578,"dataGaLocation":1496},"/topics/ci-cd/","cicd",{"text":1580,"config":1581},"GitOps",{"href":1582,"dataGaName":1583,"dataGaLocation":1496},"/topics/gitops/","gitops",{"text":1585,"config":1586},"DevOps",{"href":1587,"dataGaName":1588,"dataGaLocation":1496},"/topics/devops/","devops",{"text":1590,"config":1591},"Version Control",{"href":1592,"dataGaName":1593,"dataGaLocation":1496},"/topics/version-control/","version control",{"text":1595,"config":1596},"DevSecOps",{"href":1597,"dataGaName":1598,"dataGaLocation":1496},"/topics/devsecops/","devsecops",{"text":1600,"config":1601},"Cloud Native",{"href":1602,"dataGaName":1603,"dataGaLocation":1496},"/topics/cloud-native/","cloud native",{"text":1605,"config":1606},"AI for Coding",{"href":1607,"dataGaName":1608,"dataGaLocation":1496},"/topics/devops/ai-for-coding/","ai for coding",{"text":1610,"config":1611},"Agentic AI",{"href":1612,"dataGaName":1613,"dataGaLocation":1496},"/topics/agentic-ai/","agentic ai",{"title":1615,"links":1616},"Solutions",[1617,1619,1621,1626,1630,1633,1637,1640,1642,1645,1648,1653],{"text":1147,"config":1618},{"href":1142,"dataGaName":1147,"dataGaLocation":1496},{"text":1136,"config":1620},{"href":1119,"dataGaName":1120,"dataGaLocation":1496},{"text":1622,"config":1623},"Agile development",{"href":1624,"dataGaName":1625,"dataGaLocation":1496},"/solutions/agile-delivery/","agile delivery",{"text":1627,"config":1628},"SCM",{"href":1132,"dataGaName":1629,"dataGaLocation":1496},"source code management",{"text":1575,"config":1631},{"href":1125,"dataGaName":1632,"dataGaLocation":1496},"continuous integration & delivery",{"text":1634,"config":1635},"Value stream management",{"href":1175,"dataGaName":1636,"dataGaLocation":1496},"value stream management",{"text":1580,"config":1638},{"href":1639,"dataGaName":1583,"dataGaLocation":1496},"/solutions/gitops/",{"text":1185,"config":1641},{"href":1188,"dataGaName":1189,"dataGaLocation":1496},{"text":1643,"config":1644},"Small business",{"href":1194,"dataGaName":1195,"dataGaLocation":1496},{"text":1646,"config":1647},"Public sector",{"href":1200,"dataGaName":1201,"dataGaLocation":1496},{"text":1649,"config":1650},"Education",{"href":1651,"dataGaName":1652,"dataGaLocation":1496},"/solutions/education/","education",{"text":1654,"config":1655},"Financial services",{"href":1656,"dataGaName":1657,"dataGaLocation":1496},"/solutions/finance/","financial services",{"title":1208,"links":1659},[1660,1662,1664,1666,1669,1671,1674,1676,1678,1680,1682,1684,1686,1688],{"text":1221,"config":1661},{"href":1223,"dataGaName":1224,"dataGaLocation":1496},{"text":1226,"config":1663},{"href":1228,"dataGaName":1229,"dataGaLocation":1496},{"text":1231,"config":1665},{"href":1233,"dataGaName":1234,"dataGaLocation":1496},{"text":1236,"config":1667},{"href":1238,"dataGaName":1668,"dataGaLocation":1496},"docs",{"text":1259,"config":1670},{"href":1261,"dataGaName":1262,"dataGaLocation":1496},{"text":1672,"config":1673},"What's new",{"href":1318,"dataGaName":1319,"dataGaLocation":1496},{"text":1254,"config":1675},{"href":1256,"dataGaName":1257,"dataGaLocation":1496},{"text":1273,"config":1677},{"href":1275,"dataGaName":1276,"dataGaLocation":1496},{"text":1281,"config":1679},{"href":1283,"dataGaName":1284,"dataGaLocation":1496},{"text":1286,"config":1681},{"href":1288,"dataGaName":1289,"dataGaLocation":1496},{"text":1291,"config":1683},{"href":1293,"dataGaName":1048,"dataGaLocation":1496},{"text":1295,"config":1685},{"href":1297,"dataGaName":1298,"dataGaLocation":1496},{"text":1300,"config":1687},{"href":1302,"dataGaName":1303,"dataGaLocation":1496},{"text":1305,"config":1689},{"href":1307,"dataGaName":1308,"dataGaLocation":1496},{"title":1321,"links":1691},[1692,1694,1696,1698,1700,1702,1706,1711,1713,1715,1717],{"text":1329,"config":1693},{"href":1331,"dataGaName":1323,"dataGaLocation":1496},{"text":1334,"config":1695},{"href":1336,"dataGaName":1337,"dataGaLocation":1496},{"text":1342,"config":1697},{"href":1344,"dataGaName":1345,"dataGaLocation":1496},{"text":1347,"config":1699},{"href":1349,"dataGaName":1350,"dataGaLocation":1496},{"text":1352,"config":1701},{"href":1354,"dataGaName":1355,"dataGaLocation":1496},{"text":1703,"config":1704},"Sustainability",{"href":1705,"dataGaName":1703,"dataGaLocation":1496},"/sustainability/",{"text":1707,"config":1708},"Diversity, inclusion and belonging (DIB)",{"href":1709,"dataGaName":1710,"dataGaLocation":1496},"/diversity-inclusion-belonging/","Diversity, inclusion and belonging",{"text":1357,"config":1712},{"href":1359,"dataGaName":1360,"dataGaLocation":1496},{"text":1367,"config":1714},{"href":1369,"dataGaName":1370,"dataGaLocation":1496},{"text":1372,"config":1716},{"href":1374,"dataGaName":1375,"dataGaLocation":1496},{"text":1718,"config":1719},"Modern Slavery Transparency Statement",{"href":1720,"dataGaName":1721,"dataGaLocation":1496},"https://handbook.gitlab.com/handbook/legal/modern-slavery-act-transparency-statement/","modern slavery transparency statement",{"items":1723},[1724,1727,1730],{"text":1725,"config":1726},"Terms",{"href":1548,"dataGaName":1549,"dataGaLocation":1496},{"text":1728,"config":1729},"Cookies",{"dataGaName":1558,"dataGaLocation":1496,"id":1559,"isOneTrustButton":1035},{"text":1731,"config":1732},"Privacy",{"href":1553,"dataGaName":1554,"dataGaLocation":1496},[1734],{"id":1735,"title":7,"body":1034,"config":1736,"content":1738,"description":1034,"extension":1742,"meta":1743,"navigation":1035,"path":1744,"seo":1745,"stem":1746,"__hash__":1747},"blogAuthors/en-us/blog/authors/justin-tobler.yml",{"template":1737},"BlogAuthor",{"name":7,"config":1739},{"headshot":1740,"ctfId":1741},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1749664737/Blog/Author%20Headshots/james_tobler_headshot.png","5pnOIbNI1Sc5IFnReNHNtv","yml",{},"/en-us/blog/authors/justin-tobler",{},"en-us/blog/authors/justin-tobler","fZs0fJVrV3MQT0RHzrMvziLDriL7K4hf9Db4QlPsRvA",[1749,1757,1765],{"title":1750,"description":1751,"heroImage":1752,"category":1030,"date":1753,"authors":1754,"slug":1756,"externalUrl":1034},"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",[1755],"Toon Claes","whats-new-in-git-2-55-0",{"title":1758,"description":1759,"heroImage":1760,"category":1030,"date":1761,"authors":1762,"slug":1764,"externalUrl":1034},"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",[1763],"Nick Veenhof","gitlab-ai-hackathon-2026-meet-the-winners",{"title":1766,"description":1767,"heroImage":1768,"category":1030,"date":1769,"authors":1770,"slug":1771,"externalUrl":1034},"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",[383],"whats-new-in-git-2-54-0",{"promotions":1773},[1774,1788,1800,1812],{"id":1775,"categories":1776,"header":1778,"text":1779,"button":1780,"image":1785},"ai-modernization",[1777],"ai","Is AI achieving its promise at scale?","Quiz will take 5 minutes or less",{"text":1781,"config":1782},"Get your AI maturity score",{"href":1783,"dataGaName":1784,"dataGaLocation":1262},"/assessments/ai-modernization-assessment/","modernization assessment",{"config":1786},{"src":1787},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1772138786/qix0m7kwnd8x2fh1zq49.png",{"id":1789,"categories":1790,"header":1792,"text":1779,"button":1793,"image":1797},"devops-modernization",[1791,1598],"product","Are you just managing tools or shipping innovation?",{"text":1794,"config":1795},"Get your DevOps maturity score",{"href":1796,"dataGaName":1784,"dataGaLocation":1262},"/assessments/devops-modernization-assessment/",{"config":1798},{"src":1799},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1772138785/eg818fmakweyuznttgid.png",{"id":1801,"categories":1802,"header":1804,"text":1779,"button":1805,"image":1809},"security-modernization",[1803],"security","Are you trading speed for security?",{"text":1806,"config":1807},"Get your security maturity score",{"href":1808,"dataGaName":1784,"dataGaLocation":1262},"/assessments/security-modernization-assessment/",{"config":1810},{"src":1811},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1772138786/p4pbqd9nnjejg5ds6mdk.png",{"id":1813,"paths":1814,"header":1817,"text":1818,"button":1819,"image":1824},"github-azure-migration",[1815,1816],"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":1820,"config":1821},"See how GitLab compares to GitHub",{"href":1822,"dataGaName":1823,"dataGaLocation":1262},"/compare/gitlab-vs-github/github-azure-migration/","github azure migration",{"config":1825},{"src":1799},{"header":1827,"blurb":1828,"button":1829,"secondaryButton":1834},"Start building faster today","See what your team can do with the intelligent orchestration platform for DevSecOps.\n",{"text":1830,"config":1831},"Get your free trial",{"href":1832,"dataGaName":1061,"dataGaLocation":1833},"https://gitlab.com/-/trial_registrations/new?glm_content=default-saas-trial&glm_source=about.gitlab.com/","feature",{"text":1534,"config":1835},{"href":1386,"dataGaName":1066,"dataGaLocation":1833},1786803775109]