[{"data":1,"prerenderedAt":720},["ShallowReactive",2],{"/en-us/blog/a-single-codebase-for-gitlab-community-and-enterprise-edition/":3,"navigation-en-us":36,"banner-en-us":465,"footer-en-us":482,"Yorick Peterse":692,"next-steps-en-us":705},{"_path":4,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":8,"content":16,"config":26,"_id":29,"_type":30,"title":31,"_source":32,"_file":33,"_stem":34,"_extension":35},"/en-us/blog/a-single-codebase-for-gitlab-community-and-enterprise-edition","blog",false,"",{"title":9,"description":10,"ogTitle":9,"ogDescription":10,"noIndex":6,"ogImage":11,"ogUrl":12,"ogSiteName":13,"ogType":14,"canonicalUrls":12,"schema":15},"Why GitLab uses one codebase for Community & Enterprise","Dive into our decision to switch GitLab over to a single codebase as we review some of the benefits and challenges. Learn more here!","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749671631/Blog/Hero%20Images/merge-ce-ee-codebases.jpg","https://about.gitlab.com/blog/a-single-codebase-for-gitlab-community-and-enterprise-edition","https://about.gitlab.com","article","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Update: Why GitLab uses a single codebase for Community and Enterprise editions\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Yorick Peterse\"}],\n        \"datePublished\": \"2019-08-23\",\n      }",{"title":17,"description":10,"authors":18,"heroImage":11,"date":20,"body":21,"category":22,"tags":23},"Update: Why GitLab uses a single codebase for Community and Enterprise editions",[19],"Yorick Peterse","2019-08-23","In [\"GitLab might move to a single Rails\n\ncodebase\"](/blog/merging-ce-and-ee-codebases/), we announced that GitLab\n\nmight move to using a single codebase for GitLab Community Edition (CE) and\n\nGitLab Enterprise Edition (EE). Since then we have decided to continue\nmoving\n\ntoward a single codebase. In this article, I highlight some of the\nchallenges,\n\nrequired work, and steps remaining to complete the switch.\n\n\n## What is codebase?\n\n\nWhat is a codebase, I hear you ask? Well, a codebase (which is at times\nspelled as code base) is essentially the entire collection of source \n\ncode that is required for a program or application to function properly.\nThis can include things like configuration \n\nfiles, libraries, and other dependencies, in addition to the actual\napplication code. The codebase is \n\ntypically stored in a single location, often within a source control\nrepository, where multiple developers \n\ncan access and make contributions to it.\n\n\nMultiple developers can use and contribute to a single codebase, which is\ngenerally retained within a source control \n\nrepository. As such, it can assist with the backup and versioning of\noverlapping code \n\nmodifications/alterations. This can be especially important for larger\nprojects that require a lot of coordination \n\nand communication between team members. With everyone working from the same\ncodebase, it becomes easier \n\nto ensure that changes are made consistently and in a way that does not\nbreak the application.\n\n\n## Why GitLab uses a single codebase?\n\n\nPrior to using a single codebase, for years CE and EE used two different\nrepositories for the Rails application.\n\nBy using separate repositories we could separate proprietary code from code\nthat\n\nis free software. On the surface this seems like a good idea for different\n\nreasons (e.g., licensing), but over the years the drawbacks\n\nbegan to outweigh the benefits.\n\n\nWe [mention some of these drawbacks in a previous\n\narticle](/blog/merging-ce-and-ee-codebases/), but more or less they all\n\ncome down to the same core problem: It made the development process more\ncomplex\n\nthan necessary. For example, we ended up with around 150 merge requests\nspread\n\nacross CE and EE for a security release from several months ago. While the\n\nprocess of merging these merge requests is automated, we ran into a variety\nof\n\nissues (e.g. failing tests) that required manual intervention. We could have\n\nreduced the number of merge requests by half if we used a single repository,\n\ncreating less work for developers and release managers.\n\n\nToward the end of 2018, I felt that we were running out of time and had to\ndo\n\nsomething about the separation of CE and EE. We had always tried to avoid\n\nmerging the two repositories due to the complexity and time involved, but it\n\nstarted to become more and more clear we had no other option. [Marin\n\nJankovski](/company/team/#maxlazio), Delivery engineering manager, and I\nmade a\n\nplan to merge the two repositories. Marin wrote a [design\n\ndocument](/handbook/engineering/infrastructure/library/merge-ce-ee-codebases/)\n\nthat outlined the details of it all. The design document showed what\nchallenges\n\nwe faced, and gathered the critical support required for the largest\nengineering\n\nprojects at GitLab to date.\n\n\n## What is the difference between a codebase and a repository?\n\n\nThe basic difference between a codebase and a repository is that one is for\nold code and one is for new code. \n\n\nBut more specifically...\n\n\nA codebase can be either a public or private place to store large amounts of\ncode that is actively being iterated on in a version control system, and\ntypically stored in a source control repository in a version control system.\n\n\nA source code repository is where an archived version of the code being\nworked on is kept. It’s also a place to house documentation, notes, web\npages, and other items in your repository. \n \n## Working toward a single codebase\n\n\nMoving to a single codebase is not something we can do overnight for a\nproject\n\nthe size of GitLab. Workflows must be adapted, developers need to adjust to\nthe\n\nnew setup, and automation requires extensive changes.\n\n\nOne of the biggest challenges from an engineering perspective was to come up\n\nwith a way to transparently remove proprietary code from GitLab when\nbuilding a\n\nCE release. A naive approach might involve a script that removes known bits\nof\n\nproprietary code. While this might work for small projects that don't change\n\noften, this was not going to work for a project the size of GitLab.\n\n\nRuby provides us with a solution to this problem. In Ruby, you can create a\n\nmodule and inject it into another module or class. Once injected, the\n\nfunctionality of the module becomes available to the target module or class.\n\nThis is best illustrated with a simple example:\n\n\n```ruby\n\nclass Person\n  def initialize(name)\n    @name = name\n  end\n\n  def name\n    @name\n  end\nend\n\n\nmodule Greet\n  def greet\n    \"Hello #{name}\"\n  end\nend\n\n\nPerson.include(Greet)\n\n\nalice = Person.new('Alice')\n\n\nalice.greet # => \"Hello Alice\"\n\n```\n\n\nHere we define a class `Person`, followed by a module that is used to create\na\n\nmessage greeting a person. Next, we include it into the `Person` class, at\nwhich\n\npoint we can use the module's methods for instances of the `Person` class.\nThe\n\nresult is the message \"Hello Alice.\"\n\n\nWhile this example is not exciting, using a setup like this allows us to\n\nmove proprietary code to separate modules, and inject these modules when\nGitLab\n\nEE is used. For GitLab CE, we would remove these modules, and the code\ninjecting\n\nthese modules would have to disable itself transparently and automatically.\n\n\nGitLab EE has been using this setup since late 2016 with all EE modules\nresiding\n\nin a separate \"ee\" directory, but in a limited number of places. This meant\nthat\n\nin some places EE and CE code got mixed together, while in other places the\ntwo\n\nare separate. For example, we had code like this:\n\n\n```diff\n def lfs_upload_access?\n   return false unless project.lfs_enabled?\n   return false unless has_authentication_ability?(:push_code)\n+  return false if project.above_size_limit? || objects_exceed_repo_limit?\n\n   lfs_deploy_token? || can?(user, :push_code, project)\n end\n```\n\n\nHere EE added a line into an existing method without using a separate\nmodule,\n\nmaking it difficult to remove the EE-specific code when for CE.\n\n\nBefore we could move to a single codebase, we had to separate EE-specific\ncode from code shared between CE and EE. Due to the amount\n\nof work necessary, we divided the work into two departments: backend and\n\nfrontend. For every department we created issues outlining the work to do\nfor\n\nthe various parts of the codebase. We even included the [exact lines of code\n\nthat had to change directly in the created\n\nissues](https://gitlab.com/gitlab-org/gitlab-ee/issues/9506), making it\nsimple\n\nto see what one had to do. Each department also had an engineer assigned as\nthe\n\nlead engineer, responsible for taking on the most difficult challenges. \n[Filipa\n\nLacerda](/company/team/#FilipaLacerda), senior frontend engineer of Verify\n(CI)\n\nand Delivery, was in charge of frontend code. [As the Delivery backend\nengineer,\n\nI myself](/company/team/#yorickpeterse) was in charge of backend code.\n\n\nSome changes were small and took a short amount of time, with others were\nbig\n\nand took weeks. One of my big challenges was to make sure CE and EE [use the\nsame\n\ndatabase\nschema](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/26940),\n\nchanging just under 24,000 lines of code over a two-month period.\n\n\n>In total the work involved 55\n\ndifferent engineers submitting more than 600 merge requests, closing just\nunder\n\n400 issues, and changing nearly 1.5 million lines of code\n\n\nFilipa spent a lot of time creating 168 frontend issues outlining specific\ntasks\n\nas well as submitting 124 merge requests to address the majority of these\n\nissues. Resolving some of these issues required getting rid of some\n\ntechnical debt first, such as [breaking up large chunks of code into smaller\n\nchunks](https://gitlab.com/gitlab-org/gitlab-ee/merge_requests/14592), and\n\ncoming up with a way [to create EE-specific Vue.js\n\ntemplates](https://gitlab.com/gitlab-org/gitlab-ce/merge_requests/25650).\n\n\nWhile Filipa and I took on the biggest challenges, in total the work\ninvolved 55\n\ndifferent engineers submitting more than 600 merge requests, closing just\nunder\n\n400 issues, and changing nearly 1.5 million lines of code.\n\n\n## Moving toward a single codebase\n\n\nWith most of the work done, we could start looking into what project setup\nwe\n\nwould use for a single codebase. We came up with three different approaches:\n\n\n### 1. Single codebase: moving all development into gitlab-ce\n\n\nAll code and development is moved into the gitlab-ce repository. The\ngitlab-ee\n\nrepository is archived, and a separate repository is set up as a mirror of\n\ngitlab-ce, called gitlab-foss. Proprietary code is removed from this mirror\n\nautomatically.\n\n\nSince most of GitLab's development takes place in the current gitlab-ce\n\nrepository, this setup would reduce the number of issues to move as well as\nmerge requests to close. A downside of this approach is that clones of\n\nthe gitlab-ce repository will include proprietary code.\n\n\n### 2. Single codebase: moving all development into gitlab-ee\n\n\nAll code and development is moved into the gitlab-ee repository. The\ngitlab-ce\n\nrepository remains as is in terms of code, and will become a mirror of\ngitlab-ee. Like\n\nthe first option, proprietary code is removed from this mirror\nautomatically.\n\n\nThis setup means that users cloning gitlab-ce don't end up with proprietary\ncode\n\nin their copy of gitlab-ce.\n\n\n### 3. Single codebase: moving all development into a new repository\n\n\nWe set up an entirely new repository called \"gitlab,\" and move all code and\n\ndevelopment into this repository. The gitlab-ce and gitlab-ee repositories\nwill\n\nbecome read-only. A mirror is set up (called \"gitlab-foss\") that mirrors the\nnew\n\n\"gitlab\" repository, without including proprietary code.\n\n\n## Deciding which single codebase approach to take\n\n\n[Having evaluated all the benefits and\n\ndrawbacks](https://www.youtube.com/watch?v=LV_AHeL5sIo), we decided to go\nwith\n\noption two: move development into gitlab-ee. This approach has several\nbenefits:\n\n\n1. The code of the gitlab-ce repository remains as is, and won't include any\n   proprietary code.\n1. We do not need a separate mirror repository that does not include\nproprietary\n   code. Instead, we rename the gitlab-ce repository to \"gitlab-foss.\" We are\n   renaming the repository since having \"gitlab\" and \"gitlab-ce\" as project\n   names could be confusing.\n1. Users building CE from source don't end up with proprietary code in their\n   copy of the gitlab-ce repository.\n1. We keep the Git logs of both gitlab-ce and gitlab-ee, instead of losing\nthe\n   logs (this depends a bit on how we'd move repositories around).\n1. It requires the least amount of changes to our workflow and tooling.\n\n1. Using a single project and issue tracker for both CE and EE makes it\neasier\n   to search for issues.\n\nIssues created in the gitlab-ce project will move to the gitlab-ee project,\n\nwhich we will rename to just \"gitlab\" (or \"gitlab-org/gitlab\" if you include\nthe\n\ngroup name). This project then becomes the single source of truth, and is\nused\n\nfor creating issues for both the CE and EE distributions.\n\n\nMoving merge requests across projects is not possible, so we will close any\nopen\n\nmerge requests. Authors of these merge requests will have to resubmit them\nto\n\nthe \"gitlab\" (called \"gitlab-ee\" before the rename) project.\n\n\nWhen moving issues or closing merge requests, a bot will also post a comment\n\nexplaining why this is done, what steps the author of a merge request has to\n\ntake, and where one might find more information about these procedures.\n\n\nPrior to the single codebase setup, GitLab community contributions would be\nsubmitted\n\nto the gitlab-ce repository. In the single codebase, contributions are\ninstead\n\nsubmitted to the new gitlab repository (\"gitlab-org/gitlab\"). EE-specific\ncode\n\nresides in a \"ee\" directory in the repository. Code outside of this\ndirectory\n\nwill be free and open source software, using the same license as the\ngitlab-ce\n\nrepository currently uses. This means that as long as you do not change\nanything\n\nin this \"ee\" directory, the only change for GitLab community contributions\nis the use\n\nof a different repository.\n\n\nOur current plan is to have a single codebase the first week of September. \nGitLab 12.3 will be the first release based on a single codebase.\n\n\nUsers that clone GitLab EE and/or GitLab CE from source should update their\nGit\n\nremote URLs after the projects are renamed. This is not strictly necessary\nas\n\nGitLab will redirect Git operations to the new repository. For users of our\n\nOmnibus packages and Docker images nothing changes.\n\n\nThose interested in learning more about what went on behind the scenes can\nrefer\n\nto the following resources:\n\n\n* [A video in which we discusses the benefits and drawbacks of the various\n  project setups](https://www.youtube.com/watch?v=LV_AHeL5sIo)\n* [The issue detailing the remaining work to\ndo](https://gitlab.com/gitlab-org/gitlab-ee/issues/13304)\n\n* [A list of all the single codebase merge\nrequests](https://gitlab.com/groups/gitlab-org/-/merge_requests?scope=all&utf8=%E2%9C%93&state=merged&label_name%5B%5D=single%20codebase)\n\n\nCover image from\n[Unsplash](https://images.unsplash.com/photo-1512217536414-d92543c79ca1)\n\n{: .note}\n","engineering",[24,25],"inside GitLab","open source",{"slug":27,"featured":6,"template":28},"a-single-codebase-for-gitlab-community-and-enterprise-edition","BlogPost","content:en-us:blog:a-single-codebase-for-gitlab-community-and-enterprise-edition.yml","yaml","A Single Codebase For Gitlab Community And Enterprise Edition","content","en-us/blog/a-single-codebase-for-gitlab-community-and-enterprise-edition.yml","en-us/blog/a-single-codebase-for-gitlab-community-and-enterprise-edition","yml",{"_path":37,"_dir":38,"_draft":6,"_partial":6,"_locale":7,"data":39,"_id":461,"_type":30,"title":462,"_source":32,"_file":463,"_stem":464,"_extension":35},"/shared/en-us/main-navigation","en-us",{"logo":40,"freeTrial":45,"sales":50,"login":55,"items":60,"search":392,"minimal":423,"duo":442,"pricingDeployment":451},{"config":41},{"href":42,"dataGaName":43,"dataGaLocation":44},"/","gitlab logo","header",{"text":46,"config":47},"Get free trial",{"href":48,"dataGaName":49,"dataGaLocation":44},"https://gitlab.com/-/trial_registrations/new?glm_source=about.gitlab.com&glm_content=default-saas-trial/","free trial",{"text":51,"config":52},"Talk to sales",{"href":53,"dataGaName":54,"dataGaLocation":44},"/sales/","sales",{"text":56,"config":57},"Sign in",{"href":58,"dataGaName":59,"dataGaLocation":44},"https://gitlab.com/users/sign_in/","sign in",[61,105,203,208,313,373],{"text":62,"config":63,"cards":65,"footer":88},"Platform",{"dataNavLevelOne":64},"platform",[66,72,80],{"title":62,"description":67,"link":68},"The most comprehensive AI-powered DevSecOps Platform",{"text":69,"config":70},"Explore our Platform",{"href":71,"dataGaName":64,"dataGaLocation":44},"/platform/",{"title":73,"description":74,"link":75},"GitLab Duo (AI)","Build software faster with AI at every stage of development",{"text":76,"config":77},"Meet GitLab Duo",{"href":78,"dataGaName":79,"dataGaLocation":44},"/gitlab-duo/","gitlab duo ai",{"title":81,"description":82,"link":83},"Why GitLab","10 reasons why Enterprises choose GitLab",{"text":84,"config":85},"Learn more",{"href":86,"dataGaName":87,"dataGaLocation":44},"/why-gitlab/","why gitlab",{"title":89,"items":90},"Get started with",[91,96,101],{"text":92,"config":93},"Platform Engineering",{"href":94,"dataGaName":95,"dataGaLocation":44},"/solutions/platform-engineering/","platform engineering",{"text":97,"config":98},"Developer Experience",{"href":99,"dataGaName":100,"dataGaLocation":44},"/developer-experience/","Developer experience",{"text":102,"config":103},"MLOps",{"href":104,"dataGaName":102,"dataGaLocation":44},"/topics/devops/the-role-of-ai-in-devops/",{"text":106,"left":107,"config":108,"link":110,"lists":114,"footer":185},"Product",true,{"dataNavLevelOne":109},"solutions",{"text":111,"config":112},"View all Solutions",{"href":113,"dataGaName":109,"dataGaLocation":44},"/solutions/",[115,140,164],{"title":116,"description":117,"link":118,"items":123},"Automation","CI/CD and automation to accelerate deployment",{"config":119},{"icon":120,"href":121,"dataGaName":122,"dataGaLocation":44},"AutomatedCodeAlt","/solutions/delivery-automation/","automated software delivery",[124,128,132,136],{"text":125,"config":126},"CI/CD",{"href":127,"dataGaLocation":44,"dataGaName":125},"/solutions/continuous-integration/",{"text":129,"config":130},"AI-Assisted Development",{"href":78,"dataGaLocation":44,"dataGaName":131},"AI assisted development",{"text":133,"config":134},"Source Code Management",{"href":135,"dataGaLocation":44,"dataGaName":133},"/solutions/source-code-management/",{"text":137,"config":138},"Automated Software Delivery",{"href":121,"dataGaLocation":44,"dataGaName":139},"Automated software delivery",{"title":141,"description":142,"link":143,"items":148},"Security","Deliver code faster without compromising security",{"config":144},{"href":145,"dataGaName":146,"dataGaLocation":44,"icon":147},"/solutions/security-compliance/","security and compliance","ShieldCheckLight",[149,154,159],{"text":150,"config":151},"Application Security Testing",{"href":152,"dataGaName":153,"dataGaLocation":44},"/solutions/application-security-testing/","Application security testing",{"text":155,"config":156},"Software Supply Chain Security",{"href":157,"dataGaLocation":44,"dataGaName":158},"/solutions/supply-chain/","Software supply chain security",{"text":160,"config":161},"Software Compliance",{"href":162,"dataGaName":163,"dataGaLocation":44},"/solutions/software-compliance/","software compliance",{"title":165,"link":166,"items":171},"Measurement",{"config":167},{"icon":168,"href":169,"dataGaName":170,"dataGaLocation":44},"DigitalTransformation","/solutions/visibility-measurement/","visibility and measurement",[172,176,180],{"text":173,"config":174},"Visibility & Measurement",{"href":169,"dataGaLocation":44,"dataGaName":175},"Visibility and Measurement",{"text":177,"config":178},"Value Stream Management",{"href":179,"dataGaLocation":44,"dataGaName":177},"/solutions/value-stream-management/",{"text":181,"config":182},"Analytics & Insights",{"href":183,"dataGaLocation":44,"dataGaName":184},"/solutions/analytics-and-insights/","Analytics and insights",{"title":186,"items":187},"GitLab for",[188,193,198],{"text":189,"config":190},"Enterprise",{"href":191,"dataGaLocation":44,"dataGaName":192},"/enterprise/","enterprise",{"text":194,"config":195},"Small Business",{"href":196,"dataGaLocation":44,"dataGaName":197},"/small-business/","small business",{"text":199,"config":200},"Public Sector",{"href":201,"dataGaLocation":44,"dataGaName":202},"/solutions/public-sector/","public sector",{"text":204,"config":205},"Pricing",{"href":206,"dataGaName":207,"dataGaLocation":44,"dataNavLevelOne":207},"/pricing/","pricing",{"text":209,"config":210,"link":212,"lists":216,"feature":300},"Resources",{"dataNavLevelOne":211},"resources",{"text":213,"config":214},"View all resources",{"href":215,"dataGaName":211,"dataGaLocation":44},"/resources/",[217,250,272],{"title":218,"items":219},"Getting started",[220,225,230,235,240,245],{"text":221,"config":222},"Install",{"href":223,"dataGaName":224,"dataGaLocation":44},"/install/","install",{"text":226,"config":227},"Quick start guides",{"href":228,"dataGaName":229,"dataGaLocation":44},"/get-started/","quick setup checklists",{"text":231,"config":232},"Learn",{"href":233,"dataGaLocation":44,"dataGaName":234},"https://university.gitlab.com/","learn",{"text":236,"config":237},"Product documentation",{"href":238,"dataGaName":239,"dataGaLocation":44},"https://docs.gitlab.com/","product documentation",{"text":241,"config":242},"Best practice videos",{"href":243,"dataGaName":244,"dataGaLocation":44},"/getting-started-videos/","best practice videos",{"text":246,"config":247},"Integrations",{"href":248,"dataGaName":249,"dataGaLocation":44},"/integrations/","integrations",{"title":251,"items":252},"Discover",[253,258,262,267],{"text":254,"config":255},"Customer success stories",{"href":256,"dataGaName":257,"dataGaLocation":44},"/customers/","customer success stories",{"text":259,"config":260},"Blog",{"href":261,"dataGaName":5,"dataGaLocation":44},"/blog/",{"text":263,"config":264},"Remote",{"href":265,"dataGaName":266,"dataGaLocation":44},"https://handbook.gitlab.com/handbook/company/culture/all-remote/","remote",{"text":268,"config":269},"TeamOps",{"href":270,"dataGaName":271,"dataGaLocation":44},"/teamops/","teamops",{"title":273,"items":274},"Connect",[275,280,285,290,295],{"text":276,"config":277},"GitLab Services",{"href":278,"dataGaName":279,"dataGaLocation":44},"/services/","services",{"text":281,"config":282},"Community",{"href":283,"dataGaName":284,"dataGaLocation":44},"/community/","community",{"text":286,"config":287},"Forum",{"href":288,"dataGaName":289,"dataGaLocation":44},"https://forum.gitlab.com/","forum",{"text":291,"config":292},"Events",{"href":293,"dataGaName":294,"dataGaLocation":44},"/events/","events",{"text":296,"config":297},"Partners",{"href":298,"dataGaName":299,"dataGaLocation":44},"/partners/","partners",{"backgroundColor":301,"textColor":302,"text":303,"image":304,"link":308},"#2f2a6b","#fff","Insights for the future of software development",{"altText":305,"config":306},"the source promo card",{"src":307},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1758208064/dzl0dbift9xdizyelkk4.svg",{"text":309,"config":310},"Read the latest",{"href":311,"dataGaName":312,"dataGaLocation":44},"/the-source/","the source",{"text":314,"config":315,"lists":317},"Company",{"dataNavLevelOne":316},"company",[318],{"items":319},[320,325,331,333,338,343,348,353,358,363,368],{"text":321,"config":322},"About",{"href":323,"dataGaName":324,"dataGaLocation":44},"/company/","about",{"text":326,"config":327,"footerGa":330},"Jobs",{"href":328,"dataGaName":329,"dataGaLocation":44},"/jobs/","jobs",{"dataGaName":329},{"text":291,"config":332},{"href":293,"dataGaName":294,"dataGaLocation":44},{"text":334,"config":335},"Leadership",{"href":336,"dataGaName":337,"dataGaLocation":44},"/company/team/e-group/","leadership",{"text":339,"config":340},"Team",{"href":341,"dataGaName":342,"dataGaLocation":44},"/company/team/","team",{"text":344,"config":345},"Handbook",{"href":346,"dataGaName":347,"dataGaLocation":44},"https://handbook.gitlab.com/","handbook",{"text":349,"config":350},"Investor relations",{"href":351,"dataGaName":352,"dataGaLocation":44},"https://ir.gitlab.com/","investor relations",{"text":354,"config":355},"Trust Center",{"href":356,"dataGaName":357,"dataGaLocation":44},"/security/","trust center",{"text":359,"config":360},"AI Transparency Center",{"href":361,"dataGaName":362,"dataGaLocation":44},"/ai-transparency-center/","ai transparency center",{"text":364,"config":365},"Newsletter",{"href":366,"dataGaName":367,"dataGaLocation":44},"/company/contact/","newsletter",{"text":369,"config":370},"Press",{"href":371,"dataGaName":372,"dataGaLocation":44},"/press/","press",{"text":374,"config":375,"lists":376},"Contact us",{"dataNavLevelOne":316},[377],{"items":378},[379,382,387],{"text":51,"config":380},{"href":53,"dataGaName":381,"dataGaLocation":44},"talk to sales",{"text":383,"config":384},"Get help",{"href":385,"dataGaName":386,"dataGaLocation":44},"/support/","get help",{"text":388,"config":389},"Customer portal",{"href":390,"dataGaName":391,"dataGaLocation":44},"https://customers.gitlab.com/customers/sign_in/","customer portal",{"close":393,"login":394,"suggestions":401},"Close",{"text":395,"link":396},"To search repositories and projects, login to",{"text":397,"config":398},"gitlab.com",{"href":58,"dataGaName":399,"dataGaLocation":400},"search login","search",{"text":402,"default":403},"Suggestions",[404,406,410,412,416,420],{"text":73,"config":405},{"href":78,"dataGaName":73,"dataGaLocation":400},{"text":407,"config":408},"Code Suggestions (AI)",{"href":409,"dataGaName":407,"dataGaLocation":400},"/solutions/code-suggestions/",{"text":125,"config":411},{"href":127,"dataGaName":125,"dataGaLocation":400},{"text":413,"config":414},"GitLab on AWS",{"href":415,"dataGaName":413,"dataGaLocation":400},"/partners/technology-partners/aws/",{"text":417,"config":418},"GitLab on Google Cloud",{"href":419,"dataGaName":417,"dataGaLocation":400},"/partners/technology-partners/google-cloud-platform/",{"text":421,"config":422},"Why GitLab?",{"href":86,"dataGaName":421,"dataGaLocation":400},{"freeTrial":424,"mobileIcon":429,"desktopIcon":434,"secondaryButton":437},{"text":425,"config":426},"Start free trial",{"href":427,"dataGaName":49,"dataGaLocation":428},"https://gitlab.com/-/trials/new/","nav",{"altText":430,"config":431},"Gitlab Icon",{"src":432,"dataGaName":433,"dataGaLocation":428},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1758203874/jypbw1jx72aexsoohd7x.svg","gitlab icon",{"altText":430,"config":435},{"src":436,"dataGaName":433,"dataGaLocation":428},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1758203875/gs4c8p8opsgvflgkswz9.svg",{"text":438,"config":439},"Get Started",{"href":440,"dataGaName":441,"dataGaLocation":428},"https://gitlab.com/-/trial_registrations/new?glm_source=about.gitlab.com/compare/gitlab-vs-github/","get started",{"freeTrial":443,"mobileIcon":447,"desktopIcon":449},{"text":444,"config":445},"Learn more about GitLab Duo",{"href":78,"dataGaName":446,"dataGaLocation":428},"gitlab duo",{"altText":430,"config":448},{"src":432,"dataGaName":433,"dataGaLocation":428},{"altText":430,"config":450},{"src":436,"dataGaName":433,"dataGaLocation":428},{"freeTrial":452,"mobileIcon":457,"desktopIcon":459},{"text":453,"config":454},"Back to pricing",{"href":206,"dataGaName":455,"dataGaLocation":428,"icon":456},"back to pricing","GoBack",{"altText":430,"config":458},{"src":432,"dataGaName":433,"dataGaLocation":428},{"altText":430,"config":460},{"src":436,"dataGaName":433,"dataGaLocation":428},"content:shared:en-us:main-navigation.yml","Main Navigation","shared/en-us/main-navigation.yml","shared/en-us/main-navigation",{"_path":466,"_dir":38,"_draft":6,"_partial":6,"_locale":7,"title":467,"button":468,"image":473,"config":477,"_id":479,"_type":30,"_source":32,"_file":480,"_stem":481,"_extension":35},"/shared/en-us/banner","is now in public beta!",{"text":469,"config":470},"Try the Beta",{"href":471,"dataGaName":472,"dataGaLocation":44},"/gitlab-duo/agent-platform/","duo banner",{"altText":474,"config":475},"GitLab Duo Agent Platform",{"src":476},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1753720689/somrf9zaunk0xlt7ne4x.svg",{"layout":478},"release","content:shared:en-us:banner.yml","shared/en-us/banner.yml","shared/en-us/banner",{"_path":483,"_dir":38,"_draft":6,"_partial":6,"_locale":7,"data":484,"_id":688,"_type":30,"title":689,"_source":32,"_file":690,"_stem":691,"_extension":35},"/shared/en-us/main-footer",{"text":485,"source":486,"edit":492,"contribute":497,"config":502,"items":507,"minimal":680},"Git is a trademark of Software Freedom Conservancy and our use of 'GitLab' is under license",{"text":487,"config":488},"View page source",{"href":489,"dataGaName":490,"dataGaLocation":491},"https://gitlab.com/gitlab-com/marketing/digital-experience/about-gitlab-com/","page source","footer",{"text":493,"config":494},"Edit this page",{"href":495,"dataGaName":496,"dataGaLocation":491},"https://gitlab.com/gitlab-com/marketing/digital-experience/about-gitlab-com/-/blob/main/content/","web ide",{"text":498,"config":499},"Please contribute",{"href":500,"dataGaName":501,"dataGaLocation":491},"https://gitlab.com/gitlab-com/marketing/digital-experience/about-gitlab-com/-/blob/main/CONTRIBUTING.md/","please contribute",{"twitter":503,"facebook":504,"youtube":505,"linkedin":506},"https://twitter.com/gitlab","https://www.facebook.com/gitlab","https://www.youtube.com/channel/UCnMGQ8QHMAnVIsI3xJrihhg","https://www.linkedin.com/company/gitlab-com",[508,531,587,616,650],{"title":62,"links":509,"subMenu":514},[510],{"text":511,"config":512},"DevSecOps platform",{"href":71,"dataGaName":513,"dataGaLocation":491},"devsecops platform",[515],{"title":204,"links":516},[517,521,526],{"text":518,"config":519},"View plans",{"href":206,"dataGaName":520,"dataGaLocation":491},"view plans",{"text":522,"config":523},"Why Premium?",{"href":524,"dataGaName":525,"dataGaLocation":491},"/pricing/premium/","why premium",{"text":527,"config":528},"Why Ultimate?",{"href":529,"dataGaName":530,"dataGaLocation":491},"/pricing/ultimate/","why ultimate",{"title":532,"links":533},"Solutions",[534,539,541,543,548,553,557,560,564,569,571,574,577,582],{"text":535,"config":536},"Digital transformation",{"href":537,"dataGaName":538,"dataGaLocation":491},"/topics/digital-transformation/","digital transformation",{"text":150,"config":540},{"href":152,"dataGaName":150,"dataGaLocation":491},{"text":139,"config":542},{"href":121,"dataGaName":122,"dataGaLocation":491},{"text":544,"config":545},"Agile development",{"href":546,"dataGaName":547,"dataGaLocation":491},"/solutions/agile-delivery/","agile delivery",{"text":549,"config":550},"Cloud transformation",{"href":551,"dataGaName":552,"dataGaLocation":491},"/topics/cloud-native/","cloud transformation",{"text":554,"config":555},"SCM",{"href":135,"dataGaName":556,"dataGaLocation":491},"source code management",{"text":125,"config":558},{"href":127,"dataGaName":559,"dataGaLocation":491},"continuous integration & delivery",{"text":561,"config":562},"Value stream management",{"href":179,"dataGaName":563,"dataGaLocation":491},"value stream management",{"text":565,"config":566},"GitOps",{"href":567,"dataGaName":568,"dataGaLocation":491},"/solutions/gitops/","gitops",{"text":189,"config":570},{"href":191,"dataGaName":192,"dataGaLocation":491},{"text":572,"config":573},"Small business",{"href":196,"dataGaName":197,"dataGaLocation":491},{"text":575,"config":576},"Public sector",{"href":201,"dataGaName":202,"dataGaLocation":491},{"text":578,"config":579},"Education",{"href":580,"dataGaName":581,"dataGaLocation":491},"/solutions/education/","education",{"text":583,"config":584},"Financial services",{"href":585,"dataGaName":586,"dataGaLocation":491},"/solutions/finance/","financial services",{"title":209,"links":588},[589,591,593,595,598,600,602,604,606,608,610,612,614],{"text":221,"config":590},{"href":223,"dataGaName":224,"dataGaLocation":491},{"text":226,"config":592},{"href":228,"dataGaName":229,"dataGaLocation":491},{"text":231,"config":594},{"href":233,"dataGaName":234,"dataGaLocation":491},{"text":236,"config":596},{"href":238,"dataGaName":597,"dataGaLocation":491},"docs",{"text":259,"config":599},{"href":261,"dataGaName":5,"dataGaLocation":491},{"text":254,"config":601},{"href":256,"dataGaName":257,"dataGaLocation":491},{"text":263,"config":603},{"href":265,"dataGaName":266,"dataGaLocation":491},{"text":276,"config":605},{"href":278,"dataGaName":279,"dataGaLocation":491},{"text":268,"config":607},{"href":270,"dataGaName":271,"dataGaLocation":491},{"text":281,"config":609},{"href":283,"dataGaName":284,"dataGaLocation":491},{"text":286,"config":611},{"href":288,"dataGaName":289,"dataGaLocation":491},{"text":291,"config":613},{"href":293,"dataGaName":294,"dataGaLocation":491},{"text":296,"config":615},{"href":298,"dataGaName":299,"dataGaLocation":491},{"title":314,"links":617},[618,620,622,624,626,628,630,634,639,641,643,645],{"text":321,"config":619},{"href":323,"dataGaName":316,"dataGaLocation":491},{"text":326,"config":621},{"href":328,"dataGaName":329,"dataGaLocation":491},{"text":334,"config":623},{"href":336,"dataGaName":337,"dataGaLocation":491},{"text":339,"config":625},{"href":341,"dataGaName":342,"dataGaLocation":491},{"text":344,"config":627},{"href":346,"dataGaName":347,"dataGaLocation":491},{"text":349,"config":629},{"href":351,"dataGaName":352,"dataGaLocation":491},{"text":631,"config":632},"Sustainability",{"href":633,"dataGaName":631,"dataGaLocation":491},"/sustainability/",{"text":635,"config":636},"Diversity, inclusion and belonging (DIB)",{"href":637,"dataGaName":638,"dataGaLocation":491},"/diversity-inclusion-belonging/","Diversity, inclusion and belonging",{"text":354,"config":640},{"href":356,"dataGaName":357,"dataGaLocation":491},{"text":364,"config":642},{"href":366,"dataGaName":367,"dataGaLocation":491},{"text":369,"config":644},{"href":371,"dataGaName":372,"dataGaLocation":491},{"text":646,"config":647},"Modern Slavery Transparency Statement",{"href":648,"dataGaName":649,"dataGaLocation":491},"https://handbook.gitlab.com/handbook/legal/modern-slavery-act-transparency-statement/","modern slavery transparency statement",{"title":651,"links":652},"Contact Us",[653,656,658,660,665,670,675],{"text":654,"config":655},"Contact an expert",{"href":53,"dataGaName":54,"dataGaLocation":491},{"text":383,"config":657},{"href":385,"dataGaName":386,"dataGaLocation":491},{"text":388,"config":659},{"href":390,"dataGaName":391,"dataGaLocation":491},{"text":661,"config":662},"Status",{"href":663,"dataGaName":664,"dataGaLocation":491},"https://status.gitlab.com/","status",{"text":666,"config":667},"Terms of use",{"href":668,"dataGaName":669,"dataGaLocation":491},"/terms/","terms of use",{"text":671,"config":672},"Privacy statement",{"href":673,"dataGaName":674,"dataGaLocation":491},"/privacy/","privacy statement",{"text":676,"config":677},"Cookie preferences",{"dataGaName":678,"dataGaLocation":491,"id":679,"isOneTrustButton":107},"cookie preferences","ot-sdk-btn",{"items":681},[682,684,686],{"text":666,"config":683},{"href":668,"dataGaName":669,"dataGaLocation":491},{"text":671,"config":685},{"href":673,"dataGaName":674,"dataGaLocation":491},{"text":676,"config":687},{"dataGaName":678,"dataGaLocation":491,"id":679,"isOneTrustButton":107},"content:shared:en-us:main-footer.yml","Main Footer","shared/en-us/main-footer.yml","shared/en-us/main-footer",[693],{"_path":694,"_dir":695,"_draft":6,"_partial":6,"_locale":7,"content":696,"config":700,"_id":702,"_type":30,"title":19,"_source":32,"_file":703,"_stem":704,"_extension":35},"/en-us/blog/authors/yorick-peterse","authors",{"name":19,"config":697},{"headshot":698,"ctfId":699},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1749659488/Blog/Author%20Headshots/gitlab-logo-extra-whitespace.png","Yorick-Peterse",{"template":701},"BlogAuthor","content:en-us:blog:authors:yorick-peterse.yml","en-us/blog/authors/yorick-peterse.yml","en-us/blog/authors/yorick-peterse",{"_path":706,"_dir":38,"_draft":6,"_partial":6,"_locale":7,"header":707,"eyebrow":708,"blurb":709,"button":710,"secondaryButton":714,"_id":716,"_type":30,"title":717,"_source":32,"_file":718,"_stem":719,"_extension":35},"/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":46,"config":711},{"href":712,"dataGaName":49,"dataGaLocation":713},"https://gitlab.com/-/trial_registrations/new?glm_content=default-saas-trial&glm_source=about.gitlab.com/","feature",{"text":51,"config":715},{"href":53,"dataGaName":54,"dataGaLocation":713},"content:shared:en-us:next-steps.yml","Next Steps","shared/en-us/next-steps.yml","shared/en-us/next-steps",1758326207978]