[{"data":1,"prerenderedAt":707},["ShallowReactive",2],{"/en-us/blog/contributions-to-git-2-42-release/":3,"navigation-en-us":37,"banner-en-us":453,"footer-en-us":468,"Christian Couder":679,"next-steps-en-us":692},{"_path":4,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":8,"content":16,"config":27,"_id":30,"_type":31,"title":32,"_source":33,"_file":34,"_stem":35,"_extension":36},"/en-us/blog/contributions-to-git-2-42-release","blog",false,"",{"title":9,"description":10,"ogTitle":9,"ogDescription":10,"noIndex":6,"ogImage":11,"ogUrl":12,"ogSiteName":13,"ogType":14,"canonicalUrls":12,"schema":15},"Git 2.42 release: Here are four of our contributions in detail","Find out how GitLab's Git team helped improve Git 2.42.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749667792/Blog/Hero%20Images/git-241.jpg","https://about.gitlab.com/blog/contributions-to-git-2-42-release","https://about.gitlab.com","article","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Git 2.42 release: Here are four of our contributions in detail\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Christian Couder\"}],\n        \"datePublished\": \"2023-10-12\",\n      }",{"title":9,"description":10,"authors":17,"heroImage":11,"date":19,"body":20,"category":21,"tags":22},[18],"Christian Couder","2023-10-12","\n\n[Git 2.42](https://gitlab.com/gitlab-org/git/-/raw/master/Documentation/RelNotes/2.42.0.txt)\nwas officially released on August 21, 2023, and included some\nimprovements from GitLab's Git team. Git is the foundation of\nrepository data at GitLab. GitLab's Git team works on new features, performance improvements, documentation improvements,\nand growing the Git community. Often our contributions to Git have a\nlot to do with the way we integrate Git into our services at\nGitLab.\n\nWe previously shared [some of our improvements that were included in the Git 2.41 release](https://about.gitlab.com/blog/contributions-to-latest-git-release/). Here are some highlights from the Git 2.42 release, and a\nwindow into how we use Git on the server side at GitLab.\n\n## 1. Prevent certain refs from being packed\n\n### Write-ahead logging\nIn [Gitaly](https://docs.gitlab.com/ee/administration/gitaly/), we\nwant to use a [write-ahead log](https://gitlab.com/groups/gitlab-org/-/epics/8911)\nto replicate Git operations on different machines.\n\nThis means that the Git objects and references that should be changed\nby a Git operation are first kept in a log entry. Then, when all the\nmachines have agreed that the operation should proceed, the log entry\nis applied so the corresponding Git objects and references are\nactually added to the repositories on all the machines.\n\n### Need for temporary references\nBetween the time when a specific log entry is first written and when\nit is applied, other log entries could be applied which could remove\nsome objects and references. It could happen that these objects and\nreferences are needed to apply the specific log entry though.\n\nSo when we log an entry, we have to make sure that all the objects and\nreferences that it needs to be properly applied will not be removed\nuntil that entry is either actually applied or discarded.\n\nThe best way to make sure things are kept in Git is to create new Git\nreferences pointing to these things. So we decided to use temporary\nreferences for that purpose. They would be created when a log entry is\nwritten, and then deleted when that entry is either applied or\ndiscarded.\n\n### Packed-refs performance\nGit can store references in \"loose\" files, with one reference per\nfile, or in the `packed-refs` file, which contains many of them. The\n`git pack-refs` command is used to pack some references from \"loose\"\nfiles into the `packed-refs` file.\n\nFor reading a lot of references, the `packed-refs` file is very\nefficient, but for writing or deleting a single reference, it is not\nso efficient as rewriting the whole `packed-refs` file is required.\n\nAs temporary references are to be created and then deleted soon after,\nstoring them in the `packed-refs` file would not be efficient. It\nwould be better to store them in \"loose\" files.\n\nThe `git pack-refs` command had no way to be told precisely which refs\nshould be packed or not though. By default it would repack all the\ntags (which are refs in `refs/tags/`) and all the refs that are\nalready packed. With the `--all` option one could tell it to repack\nall the refs except the hidden refs, broken refs, and symbolic refs,\nbut that was the only thing that could be controlled.\n\n### Improving `git pack-refs`\nWe decided to improve `git pack-refs` by adding two new options to it:\n  - `--include \u003Cpattern>` which can be used to specify which refs should be packed\n  - `--exclude \u003Cpattern>` which can be used to specify which refs should not be packed\n\n[John Cai](https://gitlab.com/jcaigitlab), Gitaly:Git team engineering manager, implemented these options.\n\nFor example, if the refs managed by the write-ahead log are in\n`refs/wal/`, it's now possible the exclude them from being moved into\nthe `packed-refs` file by using:\n\n```\n$ git pack-refs --exclude \"refs/wal/*\"\n```\n\nDetails of the patch series, including discussions, can be found\n[here](https://lore.kernel.org/git/pull.1501.git.git.1683215331910.gitgitgadget@gmail.com/).\n\n## 2. Get machine-readable output from `git cat-file --batch`\n\n### Efficiently retrieving Git object information\nIn GitLab, we often retrieve Git object information. For example, when a\nuser navigates into the files and directories in a repository, we need\nto get the content of the corresponding Git blobs and trees so that\nwe can show it.\n\nIn Gitaly, we use `git cat-file` to retrieve Git object information\nfrom a Git repository. As it's a frequent operation, it needs to be\nperformed efficiently, so we use the batch modes of `git cat-file`\navailable through the `--batch`, `--batch-check` and `--batch-command`\noptions.\n\nIn these modes, a pointer to a Git object can be repeatedly sent to\nthe standard input, called 'stdin', of a `git cat-file` command, while\nthe corresponding object information is read from the standard ouput,\ncalled 'stdout' of the command. This way we don't need to launch a\nnew `git cat-file` command for each object.\n\nGitLab can keep, for example, a `git cat-file --batch-command` process\nrunning in the background while feeding it commands like\n`info \u003Cobject>` or `contents \u003Cobject>` through its stdin to\nget either information about an object or its content.\n\n### Newlines in stdin, stdout, and filenames\nThe commands or pointers to Git objects that are sent through stdin\nshould be delimited using newline characters, and in the same way `git\ncat-file` will use newline characters to delimit the information from\ndifferent Git objects in its output. This is a common shell practice\nto make it easy to chain commands together. For example, one can\neasily get the size (in bytes) of the last three commits on the current\nbranch using the following:\n\n```\n$ git log -3 --format='%H' | git cat-file --batch-check='%(objectsize)'\n285\n646\n428\n```\n\nSometimes, though, the pointer to a Git object can contain a filename\nor a directory name, as such a pointer is allowed to be in the form\n`\u003Cbranch>:\u003Cpath>`. For example `HEAD:Documentation` is a valid\npointer to the blob or the tree corresponding to the `Documentation`\npath on the current branch.\n\nThis used to be an issue because on some systems newline characters\nare allowed in file or directory names. So the `-z` option was\nintroduced last year in Git 2.38 to allow users to change the input\ndelimiter in batch modes to the NUL character.\n\n### Error output\nWhen the `-z` option was introduced, it wasn't considered useful to\nchange the output delimiter to be also the NUL character. This is\nbecause only tree objects can contain paths and the internal format\nof tree objects already uses NUL characters to delimit paths.\n\nUnfortunately, it was overlooked that in case of an error the pointer\nto the object is displayed in the error message:\n\n```\n$ echo 'HEAD:does-not-exist' | git cat-file --batch\nHEAD:does-not-exist missing\n```\n\nAs the error messages are printed along with the regular ouput of the\ncommand on stdout, passing in an invalid pointer with a number of\nnewline characters in it could make it very difficult to parse the\noutput.\n\n### -Z comes to the rescue\n[Toon Claes](https://gitlab.com/toon), Gitaly senior engineer, initially worked on a\npatch to just quote the pointer in the error message, but it was\ndecided in the Git mailing list discussions related to the patch that\nit would be better to just create a new `-Z` option. This option would\nchange both the input and the output delimiter to the NUL character,\nwhile the old `-z` option would be deprecated over time.\n\nSo [Patrick Steinhardt](https://gitlab.com/pks-gitlab), Gitaly staff engineer, implemented that new `-Z` option.\n\nDetails of the patch series, including discussions, can be found\n[here](https://lore.kernel.org/git/20221209150048.2400648-1-toon@iotcl.com/)\nand [here](https://lore.kernel.org/git/cover.1685710884.git.ps@pks.im/).\n\n## 3. Pass pseudo-options to `git rev-list --stdin`\n\n### Computing sizes\nIn GitLab, we need to have different ways to compute the size of Git\nrelated content. For example, we need to know:\n  - how much disk space a repository is using\n  - how big a specific Git object is\n  - how much additional space on a repository is required by a\n    specific set of revisions (and the objects they reference)\n\nKnowing \"how much disk space a repository is using\" is useful to\nenforce repository-related quotas and is easy to get using regular\nshell and OS features.\n\nSize information about a specific Git object is useful to enforce\nquotas related to maximum file size. It can be obtained using, for\nexample, `git cat-file -s \u003Cobject>` or\n`echo \u003Cobject> | git cat-file --batch-check='%(objectsize)'`\nas already seen above.\n\nComputing the space required by a set of revisions is useful, too, as\nforks can share Git content in what we call\n\"[pool repositories](https://docs.gitlab.com/ee/development/git_object_deduplication.html),\"\nand we want to discriminate how much content belongs to each forked\nrepository. Fortunately, `git rev-list` has a `--disk-usage` option\nfor this purpose.\n\n### Passing arguments to `git rev-list`\n`git rev-list` can take a number of different arguments and has a lot\nof different options. It's a fundamental command to traverse commit\ngraphs, and it should be flexible enough to fulfill a lot of different\nuser needs.\n\nWhen repositories grow, they often store a lot of references and a lot\nof files and directories, so there is often the need to pass a big\nnumber of references or paths as arguments to the\ncommand. References and paths can be quite long though.\n\nTo avoid hitting platform limits related to command line length, long\nago, a `--stdin` mode was added that allowed users to pass revisions\nand paths through stdin, instead of as command line\narguments. However, when that was implemented, it was not considered\nnecessary to allow options or pseudo-options, like `--not`,\n`--glob=...`, or `--all` to be passed through stdin.\n\nThis appeared to be a problem for GitLab, as for computing sizes for\nforked repositories we needed some of the pseudo-options, and it would\nhave been intricate and possibly buggy to pass some of them and their\narguments as arguments on the command line while others were passed\nthrough stdin.\n\n### Allowing pseudo-options\nTo fix this issue, Patrick Steinhardt implemented a small patch series to\nallow pseudo-options through stdin.\n\nWith it, in Git 2.42, one can now pass pseudo-options, like `--not`,\n`--glob=...`, or `--all` through stdin when the `--stdin` mode is used.\n\nDetails of the patch series, including discussions, can be found\n[here](https://lore.kernel.org/git/cover.1686744685.git.ps@pks.im/).\n\n## 4. Code and test improvements\nWhile looking at some Git code, we are often tempted to modify nearby\ncode, either to change only its style when the code is ancient and it\nwould look better using Git's current code style, or to refactor it to\nmake it cleaner. This is why we sometimes send small patch series that\ndon't have a real GitLab related purpose.\n\nIn Git 2.42, examples of style code improvements we made are the\n[part1](https://lore.kernel.org/git/pull.1513.git.git.1684440205.gitgitgadget@gmail.com/)\nand\n[part2](https://lore.kernel.org/git/pull.1514.git.git.1684599239.gitgitgadget@gmail.com/)\ntest code modernization patches from John Cai.\n\nAnd [here](https://lore.kernel.org/git/cover.1684324059.git.ps@pks.im/) is\nan example of a refactoring to cleanup some code by Patrick Steinhardt.\n","product",[23,24,25,26],"git","news","open source","community",{"slug":28,"featured":6,"template":29},"contributions-to-git-2-42-release","BlogPost","content:en-us:blog:contributions-to-git-2-42-release.yml","yaml","Contributions To Git 2 42 Release","content","en-us/blog/contributions-to-git-2-42-release.yml","en-us/blog/contributions-to-git-2-42-release","yml",{"_path":38,"_dir":39,"_draft":6,"_partial":6,"_locale":7,"data":40,"_id":449,"_type":31,"title":450,"_source":33,"_file":451,"_stem":452,"_extension":36},"/shared/en-us/main-navigation","en-us",{"logo":41,"freeTrial":46,"sales":51,"login":56,"items":61,"search":390,"minimal":421,"duo":440},{"config":42},{"href":43,"dataGaName":44,"dataGaLocation":45},"/","gitlab logo","header",{"text":47,"config":48},"Get free trial",{"href":49,"dataGaName":50,"dataGaLocation":45},"https://gitlab.com/-/trial_registrations/new?glm_source=about.gitlab.com&glm_content=default-saas-trial/","free trial",{"text":52,"config":53},"Talk to sales",{"href":54,"dataGaName":55,"dataGaLocation":45},"/sales/","sales",{"text":57,"config":58},"Sign in",{"href":59,"dataGaName":60,"dataGaLocation":45},"https://gitlab.com/users/sign_in/","sign in",[62,106,202,207,311,371],{"text":63,"config":64,"cards":66,"footer":89},"Platform",{"dataNavLevelOne":65},"platform",[67,73,81],{"title":63,"description":68,"link":69},"The most comprehensive AI-powered DevSecOps Platform",{"text":70,"config":71},"Explore our Platform",{"href":72,"dataGaName":65,"dataGaLocation":45},"/platform/",{"title":74,"description":75,"link":76},"GitLab Duo (AI)","Build software faster with AI at every stage of development",{"text":77,"config":78},"Meet GitLab Duo",{"href":79,"dataGaName":80,"dataGaLocation":45},"/gitlab-duo/","gitlab duo ai",{"title":82,"description":83,"link":84},"Why GitLab","10 reasons why Enterprises choose GitLab",{"text":85,"config":86},"Learn more",{"href":87,"dataGaName":88,"dataGaLocation":45},"/why-gitlab/","why gitlab",{"title":90,"items":91},"Get started with",[92,97,102],{"text":93,"config":94},"Platform Engineering",{"href":95,"dataGaName":96,"dataGaLocation":45},"/solutions/platform-engineering/","platform engineering",{"text":98,"config":99},"Developer Experience",{"href":100,"dataGaName":101,"dataGaLocation":45},"/developer-experience/","Developer experience",{"text":103,"config":104},"MLOps",{"href":105,"dataGaName":103,"dataGaLocation":45},"/topics/devops/the-role-of-ai-in-devops/",{"text":107,"left":108,"config":109,"link":111,"lists":115,"footer":184},"Product",true,{"dataNavLevelOne":110},"solutions",{"text":112,"config":113},"View all Solutions",{"href":114,"dataGaName":110,"dataGaLocation":45},"/solutions/",[116,141,163],{"title":117,"description":118,"link":119,"items":124},"Automation","CI/CD and automation to accelerate deployment",{"config":120},{"icon":121,"href":122,"dataGaName":123,"dataGaLocation":45},"AutomatedCodeAlt","/solutions/delivery-automation/","automated software delivery",[125,129,133,137],{"text":126,"config":127},"CI/CD",{"href":128,"dataGaLocation":45,"dataGaName":126},"/solutions/continuous-integration/",{"text":130,"config":131},"AI-Assisted Development",{"href":79,"dataGaLocation":45,"dataGaName":132},"AI assisted development",{"text":134,"config":135},"Source Code Management",{"href":136,"dataGaLocation":45,"dataGaName":134},"/solutions/source-code-management/",{"text":138,"config":139},"Automated Software Delivery",{"href":122,"dataGaLocation":45,"dataGaName":140},"Automated software delivery",{"title":142,"description":143,"link":144,"items":149},"Security","Deliver code faster without compromising security",{"config":145},{"href":146,"dataGaName":147,"dataGaLocation":45,"icon":148},"/solutions/security-compliance/","security and compliance","ShieldCheckLight",[150,153,158],{"text":151,"config":152},"Security & Compliance",{"href":146,"dataGaLocation":45,"dataGaName":151},{"text":154,"config":155},"Software Supply Chain Security",{"href":156,"dataGaLocation":45,"dataGaName":157},"/solutions/supply-chain/","Software supply chain security",{"text":159,"config":160},"Compliance & Governance",{"href":161,"dataGaLocation":45,"dataGaName":162},"/solutions/continuous-software-compliance/","Compliance and governance",{"title":164,"link":165,"items":170},"Measurement",{"config":166},{"icon":167,"href":168,"dataGaName":169,"dataGaLocation":45},"DigitalTransformation","/solutions/visibility-measurement/","visibility and measurement",[171,175,179],{"text":172,"config":173},"Visibility & Measurement",{"href":168,"dataGaLocation":45,"dataGaName":174},"Visibility and Measurement",{"text":176,"config":177},"Value Stream Management",{"href":178,"dataGaLocation":45,"dataGaName":176},"/solutions/value-stream-management/",{"text":180,"config":181},"Analytics & Insights",{"href":182,"dataGaLocation":45,"dataGaName":183},"/solutions/analytics-and-insights/","Analytics and insights",{"title":185,"items":186},"GitLab for",[187,192,197],{"text":188,"config":189},"Enterprise",{"href":190,"dataGaLocation":45,"dataGaName":191},"/enterprise/","enterprise",{"text":193,"config":194},"Small Business",{"href":195,"dataGaLocation":45,"dataGaName":196},"/small-business/","small business",{"text":198,"config":199},"Public Sector",{"href":200,"dataGaLocation":45,"dataGaName":201},"/solutions/public-sector/","public sector",{"text":203,"config":204},"Pricing",{"href":205,"dataGaName":206,"dataGaLocation":45,"dataNavLevelOne":206},"/pricing/","pricing",{"text":208,"config":209,"link":211,"lists":215,"feature":298},"Resources",{"dataNavLevelOne":210},"resources",{"text":212,"config":213},"View all resources",{"href":214,"dataGaName":210,"dataGaLocation":45},"/resources/",[216,249,271],{"title":217,"items":218},"Getting started",[219,224,229,234,239,244],{"text":220,"config":221},"Install",{"href":222,"dataGaName":223,"dataGaLocation":45},"/install/","install",{"text":225,"config":226},"Quick start guides",{"href":227,"dataGaName":228,"dataGaLocation":45},"/get-started/","quick setup checklists",{"text":230,"config":231},"Learn",{"href":232,"dataGaLocation":45,"dataGaName":233},"https://university.gitlab.com/","learn",{"text":235,"config":236},"Product documentation",{"href":237,"dataGaName":238,"dataGaLocation":45},"https://docs.gitlab.com/","product documentation",{"text":240,"config":241},"Best practice videos",{"href":242,"dataGaName":243,"dataGaLocation":45},"/getting-started-videos/","best practice videos",{"text":245,"config":246},"Integrations",{"href":247,"dataGaName":248,"dataGaLocation":45},"/integrations/","integrations",{"title":250,"items":251},"Discover",[252,257,261,266],{"text":253,"config":254},"Customer success stories",{"href":255,"dataGaName":256,"dataGaLocation":45},"/customers/","customer success stories",{"text":258,"config":259},"Blog",{"href":260,"dataGaName":5,"dataGaLocation":45},"/blog/",{"text":262,"config":263},"Remote",{"href":264,"dataGaName":265,"dataGaLocation":45},"https://handbook.gitlab.com/handbook/company/culture/all-remote/","remote",{"text":267,"config":268},"TeamOps",{"href":269,"dataGaName":270,"dataGaLocation":45},"/teamops/","teamops",{"title":272,"items":273},"Connect",[274,279,283,288,293],{"text":275,"config":276},"GitLab Services",{"href":277,"dataGaName":278,"dataGaLocation":45},"/services/","services",{"text":280,"config":281},"Community",{"href":282,"dataGaName":26,"dataGaLocation":45},"/community/",{"text":284,"config":285},"Forum",{"href":286,"dataGaName":287,"dataGaLocation":45},"https://forum.gitlab.com/","forum",{"text":289,"config":290},"Events",{"href":291,"dataGaName":292,"dataGaLocation":45},"/events/","events",{"text":294,"config":295},"Partners",{"href":296,"dataGaName":297,"dataGaLocation":45},"/partners/","partners",{"backgroundColor":299,"textColor":300,"text":301,"image":302,"link":306},"#2f2a6b","#fff","Insights for the future of software development",{"altText":303,"config":304},"the source promo card",{"src":305},"/images/navigation/the-source-promo-card.svg",{"text":307,"config":308},"Read the latest",{"href":309,"dataGaName":310,"dataGaLocation":45},"/the-source/","the source",{"text":312,"config":313,"lists":315},"Company",{"dataNavLevelOne":314},"company",[316],{"items":317},[318,323,329,331,336,341,346,351,356,361,366],{"text":319,"config":320},"About",{"href":321,"dataGaName":322,"dataGaLocation":45},"/company/","about",{"text":324,"config":325,"footerGa":328},"Jobs",{"href":326,"dataGaName":327,"dataGaLocation":45},"/jobs/","jobs",{"dataGaName":327},{"text":289,"config":330},{"href":291,"dataGaName":292,"dataGaLocation":45},{"text":332,"config":333},"Leadership",{"href":334,"dataGaName":335,"dataGaLocation":45},"/company/team/e-group/","leadership",{"text":337,"config":338},"Team",{"href":339,"dataGaName":340,"dataGaLocation":45},"/company/team/","team",{"text":342,"config":343},"Handbook",{"href":344,"dataGaName":345,"dataGaLocation":45},"https://handbook.gitlab.com/","handbook",{"text":347,"config":348},"Investor relations",{"href":349,"dataGaName":350,"dataGaLocation":45},"https://ir.gitlab.com/","investor relations",{"text":352,"config":353},"Trust Center",{"href":354,"dataGaName":355,"dataGaLocation":45},"/security/","trust center",{"text":357,"config":358},"AI Transparency Center",{"href":359,"dataGaName":360,"dataGaLocation":45},"/ai-transparency-center/","ai transparency center",{"text":362,"config":363},"Newsletter",{"href":364,"dataGaName":365,"dataGaLocation":45},"/company/contact/","newsletter",{"text":367,"config":368},"Press",{"href":369,"dataGaName":370,"dataGaLocation":45},"/press/","press",{"text":372,"config":373,"lists":374},"Contact us",{"dataNavLevelOne":314},[375],{"items":376},[377,380,385],{"text":52,"config":378},{"href":54,"dataGaName":379,"dataGaLocation":45},"talk to sales",{"text":381,"config":382},"Get help",{"href":383,"dataGaName":384,"dataGaLocation":45},"/support/","get help",{"text":386,"config":387},"Customer portal",{"href":388,"dataGaName":389,"dataGaLocation":45},"https://customers.gitlab.com/customers/sign_in/","customer portal",{"close":391,"login":392,"suggestions":399},"Close",{"text":393,"link":394},"To search repositories and projects, login to",{"text":395,"config":396},"gitlab.com",{"href":59,"dataGaName":397,"dataGaLocation":398},"search login","search",{"text":400,"default":401},"Suggestions",[402,404,408,410,414,418],{"text":74,"config":403},{"href":79,"dataGaName":74,"dataGaLocation":398},{"text":405,"config":406},"Code Suggestions (AI)",{"href":407,"dataGaName":405,"dataGaLocation":398},"/solutions/code-suggestions/",{"text":126,"config":409},{"href":128,"dataGaName":126,"dataGaLocation":398},{"text":411,"config":412},"GitLab on AWS",{"href":413,"dataGaName":411,"dataGaLocation":398},"/partners/technology-partners/aws/",{"text":415,"config":416},"GitLab on Google Cloud",{"href":417,"dataGaName":415,"dataGaLocation":398},"/partners/technology-partners/google-cloud-platform/",{"text":419,"config":420},"Why GitLab?",{"href":87,"dataGaName":419,"dataGaLocation":398},{"freeTrial":422,"mobileIcon":427,"desktopIcon":432,"secondaryButton":435},{"text":423,"config":424},"Start free trial",{"href":425,"dataGaName":50,"dataGaLocation":426},"https://gitlab.com/-/trials/new/","nav",{"altText":428,"config":429},"Gitlab Icon",{"src":430,"dataGaName":431,"dataGaLocation":426},"/images/brand/gitlab-logo-tanuki.svg","gitlab icon",{"altText":428,"config":433},{"src":434,"dataGaName":431,"dataGaLocation":426},"/images/brand/gitlab-logo-type.svg",{"text":436,"config":437},"Get Started",{"href":438,"dataGaName":439,"dataGaLocation":426},"https://gitlab.com/-/trial_registrations/new?glm_source=about.gitlab.com/compare/gitlab-vs-github/","get started",{"freeTrial":441,"mobileIcon":445,"desktopIcon":447},{"text":442,"config":443},"Learn more about GitLab Duo",{"href":79,"dataGaName":444,"dataGaLocation":426},"gitlab duo",{"altText":428,"config":446},{"src":430,"dataGaName":431,"dataGaLocation":426},{"altText":428,"config":448},{"src":434,"dataGaName":431,"dataGaLocation":426},"content:shared:en-us:main-navigation.yml","Main Navigation","shared/en-us/main-navigation.yml","shared/en-us/main-navigation",{"_path":454,"_dir":39,"_draft":6,"_partial":6,"_locale":7,"title":455,"button":456,"image":460,"config":463,"_id":465,"_type":31,"_source":33,"_file":466,"_stem":467,"_extension":36},"/shared/en-us/banner","is now in public beta!",{"text":85,"config":457},{"href":458,"dataGaName":459,"dataGaLocation":45},"/gitlab-duo/agent-platform/","duo banner",{"config":461},{"src":462},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1753720689/somrf9zaunk0xlt7ne4x.svg",{"layout":464},"release","content:shared:en-us:banner.yml","shared/en-us/banner.yml","shared/en-us/banner",{"_path":469,"_dir":39,"_draft":6,"_partial":6,"_locale":7,"data":470,"_id":675,"_type":31,"title":676,"_source":33,"_file":677,"_stem":678,"_extension":36},"/shared/en-us/main-footer",{"text":471,"source":472,"edit":478,"contribute":483,"config":488,"items":493,"minimal":667},"Git is a trademark of Software Freedom Conservancy and our use of 'GitLab' is under license",{"text":473,"config":474},"View page source",{"href":475,"dataGaName":476,"dataGaLocation":477},"https://gitlab.com/gitlab-com/marketing/digital-experience/about-gitlab-com/","page source","footer",{"text":479,"config":480},"Edit this page",{"href":481,"dataGaName":482,"dataGaLocation":477},"https://gitlab.com/gitlab-com/marketing/digital-experience/about-gitlab-com/-/blob/main/content/","web ide",{"text":484,"config":485},"Please contribute",{"href":486,"dataGaName":487,"dataGaLocation":477},"https://gitlab.com/gitlab-com/marketing/digital-experience/about-gitlab-com/-/blob/main/CONTRIBUTING.md/","please contribute",{"twitter":489,"facebook":490,"youtube":491,"linkedin":492},"https://twitter.com/gitlab","https://www.facebook.com/gitlab","https://www.youtube.com/channel/UCnMGQ8QHMAnVIsI3xJrihhg","https://www.linkedin.com/company/gitlab-com",[494,517,574,603,637],{"title":63,"links":495,"subMenu":500},[496],{"text":497,"config":498},"DevSecOps platform",{"href":72,"dataGaName":499,"dataGaLocation":477},"devsecops platform",[501],{"title":203,"links":502},[503,507,512],{"text":504,"config":505},"View plans",{"href":205,"dataGaName":506,"dataGaLocation":477},"view plans",{"text":508,"config":509},"Why Premium?",{"href":510,"dataGaName":511,"dataGaLocation":477},"/pricing/premium/","why premium",{"text":513,"config":514},"Why Ultimate?",{"href":515,"dataGaName":516,"dataGaLocation":477},"/pricing/ultimate/","why ultimate",{"title":518,"links":519},"Solutions",[520,525,528,530,535,540,544,547,551,556,558,561,564,569],{"text":521,"config":522},"Digital transformation",{"href":523,"dataGaName":524,"dataGaLocation":477},"/topics/digital-transformation/","digital transformation",{"text":151,"config":526},{"href":146,"dataGaName":527,"dataGaLocation":477},"security & compliance",{"text":140,"config":529},{"href":122,"dataGaName":123,"dataGaLocation":477},{"text":531,"config":532},"Agile development",{"href":533,"dataGaName":534,"dataGaLocation":477},"/solutions/agile-delivery/","agile delivery",{"text":536,"config":537},"Cloud transformation",{"href":538,"dataGaName":539,"dataGaLocation":477},"/topics/cloud-native/","cloud transformation",{"text":541,"config":542},"SCM",{"href":136,"dataGaName":543,"dataGaLocation":477},"source code management",{"text":126,"config":545},{"href":128,"dataGaName":546,"dataGaLocation":477},"continuous integration & delivery",{"text":548,"config":549},"Value stream management",{"href":178,"dataGaName":550,"dataGaLocation":477},"value stream management",{"text":552,"config":553},"GitOps",{"href":554,"dataGaName":555,"dataGaLocation":477},"/solutions/gitops/","gitops",{"text":188,"config":557},{"href":190,"dataGaName":191,"dataGaLocation":477},{"text":559,"config":560},"Small business",{"href":195,"dataGaName":196,"dataGaLocation":477},{"text":562,"config":563},"Public sector",{"href":200,"dataGaName":201,"dataGaLocation":477},{"text":565,"config":566},"Education",{"href":567,"dataGaName":568,"dataGaLocation":477},"/solutions/education/","education",{"text":570,"config":571},"Financial services",{"href":572,"dataGaName":573,"dataGaLocation":477},"/solutions/finance/","financial services",{"title":208,"links":575},[576,578,580,582,585,587,589,591,593,595,597,599,601],{"text":220,"config":577},{"href":222,"dataGaName":223,"dataGaLocation":477},{"text":225,"config":579},{"href":227,"dataGaName":228,"dataGaLocation":477},{"text":230,"config":581},{"href":232,"dataGaName":233,"dataGaLocation":477},{"text":235,"config":583},{"href":237,"dataGaName":584,"dataGaLocation":477},"docs",{"text":258,"config":586},{"href":260,"dataGaName":5,"dataGaLocation":477},{"text":253,"config":588},{"href":255,"dataGaName":256,"dataGaLocation":477},{"text":262,"config":590},{"href":264,"dataGaName":265,"dataGaLocation":477},{"text":275,"config":592},{"href":277,"dataGaName":278,"dataGaLocation":477},{"text":267,"config":594},{"href":269,"dataGaName":270,"dataGaLocation":477},{"text":280,"config":596},{"href":282,"dataGaName":26,"dataGaLocation":477},{"text":284,"config":598},{"href":286,"dataGaName":287,"dataGaLocation":477},{"text":289,"config":600},{"href":291,"dataGaName":292,"dataGaLocation":477},{"text":294,"config":602},{"href":296,"dataGaName":297,"dataGaLocation":477},{"title":312,"links":604},[605,607,609,611,613,615,617,621,626,628,630,632],{"text":319,"config":606},{"href":321,"dataGaName":314,"dataGaLocation":477},{"text":324,"config":608},{"href":326,"dataGaName":327,"dataGaLocation":477},{"text":332,"config":610},{"href":334,"dataGaName":335,"dataGaLocation":477},{"text":337,"config":612},{"href":339,"dataGaName":340,"dataGaLocation":477},{"text":342,"config":614},{"href":344,"dataGaName":345,"dataGaLocation":477},{"text":347,"config":616},{"href":349,"dataGaName":350,"dataGaLocation":477},{"text":618,"config":619},"Sustainability",{"href":620,"dataGaName":618,"dataGaLocation":477},"/sustainability/",{"text":622,"config":623},"Diversity, inclusion and belonging (DIB)",{"href":624,"dataGaName":625,"dataGaLocation":477},"/diversity-inclusion-belonging/","Diversity, inclusion and belonging",{"text":352,"config":627},{"href":354,"dataGaName":355,"dataGaLocation":477},{"text":362,"config":629},{"href":364,"dataGaName":365,"dataGaLocation":477},{"text":367,"config":631},{"href":369,"dataGaName":370,"dataGaLocation":477},{"text":633,"config":634},"Modern Slavery Transparency Statement",{"href":635,"dataGaName":636,"dataGaLocation":477},"https://handbook.gitlab.com/handbook/legal/modern-slavery-act-transparency-statement/","modern slavery transparency statement",{"title":638,"links":639},"Contact Us",[640,643,645,647,652,657,662],{"text":641,"config":642},"Contact an expert",{"href":54,"dataGaName":55,"dataGaLocation":477},{"text":381,"config":644},{"href":383,"dataGaName":384,"dataGaLocation":477},{"text":386,"config":646},{"href":388,"dataGaName":389,"dataGaLocation":477},{"text":648,"config":649},"Status",{"href":650,"dataGaName":651,"dataGaLocation":477},"https://status.gitlab.com/","status",{"text":653,"config":654},"Terms of use",{"href":655,"dataGaName":656,"dataGaLocation":477},"/terms/","terms of use",{"text":658,"config":659},"Privacy statement",{"href":660,"dataGaName":661,"dataGaLocation":477},"/privacy/","privacy statement",{"text":663,"config":664},"Cookie preferences",{"dataGaName":665,"dataGaLocation":477,"id":666,"isOneTrustButton":108},"cookie preferences","ot-sdk-btn",{"items":668},[669,671,673],{"text":653,"config":670},{"href":655,"dataGaName":656,"dataGaLocation":477},{"text":658,"config":672},{"href":660,"dataGaName":661,"dataGaLocation":477},{"text":663,"config":674},{"dataGaName":665,"dataGaLocation":477,"id":666,"isOneTrustButton":108},"content:shared:en-us:main-footer.yml","Main Footer","shared/en-us/main-footer.yml","shared/en-us/main-footer",[680],{"_path":681,"_dir":682,"_draft":6,"_partial":6,"_locale":7,"content":683,"config":687,"_id":689,"_type":31,"title":18,"_source":33,"_file":690,"_stem":691,"_extension":36},"/en-us/blog/authors/christian-couder","authors",{"name":18,"config":684},{"headshot":685,"ctfId":686},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1749663687/Blog/Author%20Headshots/chriscool-headshot.jpg","chriscool",{"template":688},"BlogAuthor","content:en-us:blog:authors:christian-couder.yml","en-us/blog/authors/christian-couder.yml","en-us/blog/authors/christian-couder",{"_path":693,"_dir":39,"_draft":6,"_partial":6,"_locale":7,"header":694,"eyebrow":695,"blurb":696,"button":697,"secondaryButton":701,"_id":703,"_type":31,"title":704,"_source":33,"_file":705,"_stem":706,"_extension":36},"/shared/en-us/next-steps","Start shipping better software faster","50%+ of the Fortune 100 trust GitLab","See what your team can do with the intelligent\n\n\nDevSecOps platform.\n",{"text":47,"config":698},{"href":699,"dataGaName":50,"dataGaLocation":700},"https://gitlab.com/-/trial_registrations/new?glm_content=default-saas-trial&glm_source=about.gitlab.com/","feature",{"text":52,"config":702},{"href":54,"dataGaName":55,"dataGaLocation":700},"content:shared:en-us:next-steps.yml","Next Steps","shared/en-us/next-steps.yml","shared/en-us/next-steps",1753981640692]