[{"data":1,"prerenderedAt":707},["ShallowReactive",2],{"/en-us/blog/better-code-reviews/":3,"navigation-en-us":36,"banner-en-us":453,"footer-en-us":468,"David O'Regan":678,"next-steps-en-us":692},{"_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/better-code-reviews","blog",false,"",{"title":9,"description":10,"ogTitle":9,"ogDescription":10,"noIndex":6,"ogImage":11,"ogUrl":12,"ogSiteName":13,"ogType":14,"canonicalUrls":12,"schema":15},"Better Code Reviews GitLab Style","Better Code Reviews - A selection of tools for your tool-belt when it comes to code reviews.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749663502/Blog/Hero%20Images/paperclips.jpg","https://about.gitlab.com/blog/better-code-reviews","https://about.gitlab.com","article","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"Better Code Reviews GitLab Style\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"David O'Regan\"}],\n        \"datePublished\": \"2020-06-08\",\n      }",{"title":9,"description":10,"authors":17,"heroImage":11,"date":19,"body":20,"category":21,"tags":22},[18],"David O'Regan","2020-06-08","\n\n{::options parse_block_html=\"true\" /}\n\n\n\n> A love letter to anyone that's ever reviewed or been reviewed.\n\nThis blog post originally started as a thank-you message inside the GitLab slack channel `#thanks`, however, the scope of the message grew to such a degree that I wanted to take it a step further and see if I could not only thank the amazing people this post is dedicated to, but also hopefully share some of the amazing things they taught me to help *you*, dear reader.\n\nI have always been rather passionate about feedback. For as long as I can remember, I have always sought feedback on everything I was interested in. It's as true for me in software as it is for my non computer related hobbies like bodybuilding or grammar.....**cough cough**. Feedback is so important for every aspect of life, and in software it is no different. Feedback matters and in GitLab, we deliver most if not all of our feedback to one another via the code review.\n\nThis post is designed to deliver a selection of the most fantastic things I have seen in code reviews here at GitLab, with two goals:\n\n1. Acknowledge the people who work hard to ensure the feedback cycle they provide is as good as it can be, because at GitLab we like to [say thanks](https://handbook.gitlab.com/handbook/values/#say-thanks).\n1. Offer you, the reader, a selection of tools for your toolbelt when it comes to code reviews.\n\nEnter - **Better Code Reviews**.\n\n## Self Reviews - Details Matter\n\n> Before assigning MRs to the reviewer I practice a self-review to help the reviewer and the maintainer understand quirks and caveats of the MR. I am trying to anticipate their concerns/questions. As a maintainer I find it also very valuable. - Peter Leitzen ([@splattael](https://gitlab.com/splattael))\n\nWe often take for granted that details are hard. Moreover, we often take for granted that details in software are even harder. The majority of software consists of layers upon layers of deep abstractions and obscure logic that can be difficult, if not impossible, to really understand without spending a significant amount of time parsing it line by line.\n\nThis process is made even harder when the details or context are incorrect. Though it's natural for this to happen, humans are not spell checkers, nor do the majority of us like to revisit a piece of work a fourth or fifth time to ensure it's as correct as it can be. If we all did this, nothing would ever be delivered.\n\nBut - there is a sweet spot to be found for this dilemma in software where we can keep the velocity of delivery high, and also reduce the feedback cycle time through a small amount of dedicated effort to the details. We talk about some of the details [here in the responsibility of the merge request author](https://docs.gitlab.com/ee/development/code_review.html#the-responsibility-of-the-merge-request-author).\n\nFor the merge request author, step through a checklist. Here is mine. If you can't read my chicken-scratch handwriting, I'll type it out too:\n\n![merge-checklist](https://about.gitlab.com/images/blogimages/merge-checklist.png)\n\nBefore every feedback cycle:\n\n- Re-read every line\n- Test your code locally\n- Write a test for every change (or as many as you can)\n- Write a clear description and update it after each feedback cycle\n- Include at least one screenshot per change. More is better\n- Check, re-check and re-check your labels\n- Consider using a `~\"workflow::refinement\"` label for issues ahead of time like we do in the Monitor:Health team\n- Review the code as if you were the reviewer. Be proactive, answer the likely questions, and open followup issues ahead of time\n\nIf you want to see the last and most important part in action, check out one of our frontend maintainers Natalia Tepluhina([@ntepluhina](https://gitlab.com/ntepluhina)) pre-answer a question she knew would be asked in [one of her merge requests](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/33587#note_353564612).\n\n## Conventional Comments - Communicate Intent\n\n>  **Shaming** This is horrible code. How about re-writing all of it so that it stops being that bad? - Frédéric Caplette ([@f_caplette](https://gitlab.com/f_caplette))\n\nOne of the hardest parts of getting a code review right is communicating the human touch. When we offer feedback and receive feedback, human habit creates cognitive distortion by defaulting to the most negative aspects of that feedback. At GitLab, we try to highlight that in our [value system](https://handbook.gitlab.com/handbook/values/#assume-positive-intent).\n\nIn the world of psychology, this is called **mental filtering**, and it's something that all humans have a tendency to do. Though in software this affliction can be more common, as working in software goes hand-in-hand with valuing yourself based on how intelligent others think you are.\n\nEnter [conventional comments](https://conventionalcomments.org/) by Paul Slaughter ([@pslaughter](https://gitlab.com/pslaughter)) - a well thought-out system for leaving comments in a useful way for both the reviewer and author of the merge request. It's so popular one amazing person made a [browser extension (chrome, firefox)](https://gitlab.com/conventionalcomments/conventional-comments-button) for it!\n\nSo why does adding a single bolded word to the top of a comment help with the human touch? Well, it's all about intent.\n\nWhen you start the comment with an eye-catching single word that defines the intent and tone for the comment, it gives the reader a chance to understand where your comment is coming from.\n\nLet's try an experiment. If you had submitted code for review, which comment would you prefer to read?\n\nOption one:\n\n```bash\nWhat do you think about X instead?\n```\n\nor option two:\n\n```bash\n**suggestion (non-blocking)**\n\nWhat do you think about X instead?\n```\n\nNow if you're anything like me, you took a preference to option two. It had context, communicated empathy, and was an invitation to try something different rather than a command.\n\nThe magic part of this comment is the first line `**suggestion (non-blocking)**`. Straightaway, before you even read the comment, you know the two most important things about it:\n\n1. It's a suggestion from the reviewer\n1. It's non-blocking, communicating it's more of a friendly suggestion then a hard change that's needed\n\nAnother massive advantage this style of commenting has: it allows merge request authors to understand the reviewer is neither trying to block nor act as a gatekeeper for their work. By highlighting what counts as a blocking and a non-blocking comment, merge authors get the full context of what the reviewer is trying to communicate.\n\nTo demonstrate this, let's try another thought experiment! You have submitted a merge request for review and your review comes back with eight comments.\n\n- **Scenario A: No context in comments.** All comments are treated equally because they lack context for what counts as a blocker and what doesn't.\n- **Scenario B:** Context added via conventional comments system.\n\nThe comments can be treated via priority:\n\n1. Blockers => What's needed to get the merge over the line.\n1. Non-blockers => What can be a separate merge or perhaps a discussion.\n\nNext time you're reviewing code, try using conventional comments and watch how it affects not only the way the merge request author feels about the review, but the way **you**, the reviewer, feel leaving the review. My guess is you'll feel a lot better.\n\nWe're currently looking at [integrating this feature directly into GitLab](https://gitlab.com/gitlab-org/gitlab/-/issues/26891) because we believe in making GitLab the best possible place for code reviews, and want you to have the best experience possible.\n\nIf you want to see a real-life example of some of Paul Slaughter's ([@pslaughter](https://gitlab.com/pslaughter)) awesome work using conventional comments, check out [his reviews of my community contributions](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/24897) here at GitLab. That empathy shines through.\n\n## The Patch File\n\n> Here's a patch file to better explain - Denys Mishunov ([@dmishunov](https://gitlab.com/dmishunov))\n\nWanna know a `git` secret? Patch files are the stuff of magic. If you want to read about them, [check the Git documentation for patches](https://git-scm.com/docs/git-format-patch).\n\n### How To Make A Patch File\n\nYou can make a patch file via your editor, or via the command line.\n\n#### Via The Editor\n\nRocking a nice fancy IDE or text editor? Most of them support patch files via plugins, or out of the box!\n\n- [VSCode](https://github.com/paragdiwan/vscode-git-patch)\n- [Webstorm](https://www.jetbrains.com/help/webstorm/using-patches.html)\n- [Atom](https://atom.io/packages/git-plus)\n- [Vim](https://vim.fandom.com/wiki/How_to_make_and_submit_a_patch) …life is what happens when you're trying to exit `vim`?\n\n#### Via The CLI\n\nOkay, you’ve made some commits, here’s your `git log`:\n\n```plaintext\ngit log --pretty=oneline -3\n* da33d1k - (feature_branch) Reviewer Commit 1 (7 minutes ago)\n* 66a84ah - (feature_branch) Developer 1 Commit (12 minutes ago)\n* adsc8cd - (REL-0.5.0, origin/master, origin/HEAD, master) Release 13.0 (2 weeks ago)\n```\n\nThis command creates a new file, `reviewer_commit.patch`, with all changes from the reviewer's latest commit against the feature branch:\n\n```plaintext\ngit format-patch HEAD~1 --stdout > reviewer_commit.patch\n```\n\n### Apply The Patch\n\nFirst, take a look at what changes are in the patch. You can do this easily with `git apply`:\n\n```plaintext\ngit apply --stat reviewer_commit.patch\n```\n\nJust a heads up! Despite the name, this command won't actually apply the patch. It will just show the statistics about what the patch will do.\n\nSo now that we've had a look, let's test it first, because not all patches are created equal:\n\n```plaintext\ngit apply --check reviewer_commit.patch\n```\n\nNo errors? Awesome! We can apply this patch without worry.\n\nTo apply the patch, you should use `git am` instead of `git apply`. The reason: `git am` allows you to sign off an applied patch with the reviewer's stamp.\n\n```plaintext\ngit am --signoff \u003C reviewer_commit.patch\nApplying: Reviewer Commit 1\n```\n\nNow run `git log` and you can see the `Signed-off-by` tag in the commit message. This tag makes it very easy to understand how this commit ended up in the code base.\n\n### Why to use them in code reviews\n\nSo now that you know how to make a shiny patch file, why would you use patch files as part of a code review process? There are a few reasons you might consider offering a patch file for a change you feel strongly about:\n\n1. It communicates you have invested a large amount of effort into understanding the author's solution and reasoning\n1. It demonstrates passion for reaching the best solution through teamwork\n1. It offers a willingness on the reviewer's part to accept responsibility for this merge past the point of just reading the code\n\nSome people might argue patch files are a cheeky way for a reviewer to force a change they would rather see make it into the code base, but I argue that anyone who has taken the time to check out a branch, run the project, implement a change, and then submit that change back for a discussion is embodying the value of collaboration to the fullest.\n\nWant to see a awesome example of a patch file in action? Check out one of our frontend maintainers Denys Mishunov ([@dmishunov](https://gitlab.com/dmishunov)) in action using a [patch file to its maximum potential](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/31686#note_341534370)!\n\nWe believe so much in creating the best code review experience here at GitLab, we're looking into how can we make this system a [seamless part of the merge request and code review flow](https://gitlab.com/gitlab-org/gitlab/-/issues/220044).\n\n## Fairness\n\n> Fairness is a person's ability to rise above their own prejudice.\n\nFairness is a odd word. Chris Voss, a former FBI negotiator, said in his book [Never Split The Difference](https://www.goodreads.com/book/show/26156469-never-split-the-difference) that:\n\n> “Fair”—the most powerful word in any negotiation scenario. To become a great negotiator, you must earn the reputation of being a fair one.\n\nCode reviews can be viewed as a negotiation. It's you and another human being having a negotiation, based upon the idea that at the end, the result of this negotiation should be a selection of code that is both of value and of a high standard. While you might think that FBI negotiations and code reviews have little to do with one another, the concept being a fair negotiator often can be the most useful tool in your toolbox as both an author and reviewer.\n\nYou can actually see it mentioned twice in the [permissions to play in points 2 and 7](https://handbook.gitlab.com/handbook/values/#permission-to-play) guidelines here at GitLab:\n\n- \"Be dependable, reliable, fair, and respectful.\"\n- \"Seek out ways to be fair to everyone.\"\n\n### Author Fairness\n\nBeing fair as an author is the easier of the two. When you think of being fair as an author you need to adhere to a few simple Do's and Don'ts:\n\nDo:\n- Write a proper description with screenshots (can't stress this one enough)\n- Understand a reviewers point of view when they make suggestions\n- Pre-address strange parts of your merge (we all have them)\n- Be open to [collaboration](https://handbook.gitlab.com/handbook/values/#collaboration) on your work\n\nDon't:\n- \"plz merge\"\n- Forget to write a description with screenshots\n- Be closed off or take offense to suggestions\n- Forget to include any steps needed to get the build running or in other words(reduce burden where possible!)\n\nHonestly, it's pretty simple to be a fair author of a merge request if you use a small amount of empathy and remember that the person reviewing your code **gets nothing extra** for their time spend reviewing their code. They just want to help take your merge to the next level.\n\n### Reviewer Fairness\n\nBeing fair as a reviewers is a tad harder than being fair as an author. But why, I hear you ask? The issue is something called \"bias\" - or [unconscious-bias](https://handbook.gitlab.com/handbook/values/#unconscious-bias), as the handbook defines it.\n\nBias is, for better or for worse, something we all deal with when it comes to how we *want* things to be. We all have our own styles, preferences, and ideas on how software should be written:\n\n> Eslint be damned I want you to use double quotes!\n\nThis creates issues when it comes to code reviews, because it's normal for a lot of your own bias to bleed into a comment. You begin thinking in absolutes and the unresolved discussion count rises.\n\nLet me ask you something. Have you ever reviewed a merge request and found yourself saying things like:\n\n- \"It should be written like this?\"\n- \"Why would they do it like that?\"\n- \"I would have done it *this* way.\"\n- \"That's not how that should be done!\"\n\nWell, my friends, welcome to another common cognitive distortion called \"Should/must statements\". Do you want to be a better code reviewer? The next time you write a comment and it includes the word \"should\" or \"must\", pause right there and really think about why you felt the need to use that word. Sometimes it will be fair and warranted - such as if your company follows a set of coding conventions like we do at GitLab - but stay vigilant for when those statements are a thin veil for a personal preference. Ask yourself if you're being fair with your review. As a reviewer, if you find yourself in need of using a should/must statement, be sure to supply a reference to supporting documentation that is driving your statement.\n\nOne lesson I have learned through my own experience is that there is almost always a reason for something to be done the way it is. The fair response to something you don't agree with is to ask *why* it's being done like that, not saying it *must* be another way. That is how you become a fair and great negotiator.\n\n## The Follow Up\n\n> I feel like the follow up issue should become a first class citizen. - Sarah Yasonik ([@syasonik](https://gitlab.com/syasonik))\n\nLong merges suck. They just do. And while the concept of \"big doesn't always mean good\" might have started with food, it bleeds into the world of software development through merge requests that are too big. They also directly conflict one of our [main values](https://handbook.gitlab.com/handbook/values/#make-small-merge-requests) of iteration. In GitLab, we take this so seriously that [Danger Bot](https://docs.gitlab.com/ee/development/dangerbot.html) will ask you to break down merges that are over a certain size, helping developers champion the [value of iteration](https://handbook.gitlab.com/handbook/values/#iteration).\n\nLarge merge requests create huge amounts of complexity, they're hard to test, they're hard to reason about, they hard to maintain or extend.....and that's just for the author!\n\nSo what's worse than a large merge request? Reviewing a large merge request. If you've ever been pinged to review a merge request that was longer than 1000 lines, you understand what I am talking about. If it hasn't happened to you yet, count your lucky stars that your teammates live and breathe some good habits like simple solutions and iteration, and value a lack of complexity.\n\nThis creates a bigger problem than a complex reading exercise for the reviewer: it creates a context block. When a review grows past a certain amount of lines, it simply becomes too difficult to reason about without checking out the branch, booting the project and smoke testing. While smoke testing complex reviews are a great idea, it should **not** become the default ideal for reviewing.\n\nIf the merge request is too long, the code review is too complex / too long. The code rots, your merge conflicts grow, you can't iterate, you're constantly addressing breaking conflicts … and you're stuck for days, maybe weeks, maybe forever.\n\nSo how do we fix this? In the Monitor:Health team's iteration retrospective, my teammate Sarah Yasonik ([@syasonik](https://gitlab.com/syasonik)) raised a point where she suggested the follow up issue / merge become a first class citizen. I thought she was onto something amazing. If your merge is too long, or your reviews are taking too long, break your merge down, keep the reviews small, and offer follow-ups.\n\nTreat the follow-up merge as a first-class citizen. Do it right there *while reading the reviewer's feedback* instead of adding more code to a already too big merge! Do **not** make a already bloated merge even worse by adding more scope. Divide and conquer where possible.\n\nI think a lot of developers and reviewers find this process difficult because it's a contract of faith: \n\n- I, the author, promise to deliver a follow-up.\n- I, the reviewer, put myself on the line by taking your word that you will in fact fix this issue later.\n\nIt's scary, and lacks polish. I get it, but you should never let tomorrow's perfect stop today's progress because - spoiler alert - tomorrow isn't here, and we really only have today.\n\n### The Author Follow Up\n\nIf you offer a follow up, deliver it. It's your only rule but you cannot break it. Your credit for wilding the follow up resides solely in your consistent ability to deliver on your promises over time. As a author you should also work with your PMs and EMs to help prioritize the follow up as part of a wider team effort.\n\n### The Reviewer Follow Up\n\n- If you are offered a follow up, accept it with grace and trust the developer to make good on their promise.\n- Be open to suggesting follow ups as part of your review.\n- Be patient with people.\n- Allow for wiggle room, but know when to say no. (A follow-up for a non-critical issue is fine, but not a blatant break that won't add more lines or context.)\n\n## The Art Of The GIF\n\n>  If a Picture Speaks 1,000 Words a animated GIF Speaks 100,000.\n\nWhile this is the least technical aspect of the entire post it is perhaps the most interesting and the easiest to implement.\n\nDid you know that 93% of communication is nonverbal? I didn't, until I started seeing GIFs in code reviews. When I began to see them pop up in reviews, they deeply caught my attention, and I began to wonder why they had such a lasting impression on me as a developer.\n\nWords are powerful, but images are particularly powerful because of their ties to our emotions. Images have the potential to create powerful emotional responses, and when you see something that sparks a sense of positivity, it sets the tone for the entire review. You **understand fully** that the reviewer really cares and wants to communicate that care non-verbally.\n\nSo how do you use GIFs in your merge requests and code reviews? Well, you could [start with our handbook instructions](/handbook/product/making-gifs/), but the short and sweet version:\n\n1. Use a screen recorder to capture the video you want to show as a GIF.\n2. Grab yourself a copy of [gifify](https://github.com/vvo/gifify).\n3. GIF all day long!\n\n### GIFs That Show You Care\n\nI won't ever forget the first time I saw a [funny GIF in a code review](https://gitlab.com/gitlab-org/gitlab-ui/-/merge_requests/1193#note_307290889). I never even made it to reading the comment, because all I could comprehend was this animated GIF of a thumbs-up and I remember thinking: *This merge would pass review. It would all be okay.* The sheer childlike giddy nature of seeing this image in action made me smile ear-to-ear. Every other comment could have been a rant about how awful my code was, but I wouldn't have cared.\n\nIf I can give you one piece of advice for your code reviews as a reviewer, use GIFs in a light-hearted way, because they are:\n\n- empathy-laden\n- soften the blow of a hard topic\n- foster positivity\n- make code reviews fun!\n\n![teamwork](https://media.giphy.com/media/vcHTRiZOglHNu/giphy.gif)\n\nWe're currently looking at making [Giphy a integrated feature here at GitLab](https://gitlab.com/gitlab-org/gitlab/-/issues/17379), making your code reviews even easier and more fun!\n\n## Tactical code reviews through the value of iteration\n\n> Can we make this smaller? - Clement Ho([@ClemMakesApps](https://gitlab.com/ClemMakesApps))\n\nOne thing I have noticed that help time and time again for better code reviews is the idea of breaking down a merge request into the smallest piece possible. A few people in my time here at GitLab have really put this across as a valuable way of working, but it was my frontend engineering manager Clement Ho([@ClemMakesApps](https://gitlab.com/ClemMakesApps)) that I really took notice championing this ideal. Given that I started paying close attention to this idea and began to notice benefits almost immediately when implementing the idea.\n\nIf we look at the GitLab value handbook's [suggestions iteration competency](https://handbook.gitlab.com/handbook/values/#iteration-competency) you can see that the value in small, digestible merge requests which translates into smaller code reviews:\n\n| Level | Demonstrates Iteration Competency by… |\n|","unfiltered",[23,24,25],"code review","zero trust","GitOps",{"slug":27,"featured":6,"template":28},"better-code-reviews","BlogPost","content:en-us:blog:better-code-reviews.yml","yaml","Better Code Reviews","content","en-us/blog/better-code-reviews.yml","en-us/blog/better-code-reviews","yml",{"_path":37,"_dir":38,"_draft":6,"_partial":6,"_locale":7,"data":39,"_id":449,"_type":30,"title":450,"_source":32,"_file":451,"_stem":452,"_extension":35},"/shared/en-us/main-navigation","en-us",{"logo":40,"freeTrial":45,"sales":50,"login":55,"items":60,"search":390,"minimal":421,"duo":440},{"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,201,206,311,371],{"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":183},"Product",true,{"dataNavLevelOne":109},"solutions",{"text":111,"config":112},"View all Solutions",{"href":113,"dataGaName":109,"dataGaLocation":44},"/solutions/",[115,140,162],{"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,152,157],{"text":150,"config":151},"Security & Compliance",{"href":145,"dataGaLocation":44,"dataGaName":150},{"text":153,"config":154},"Software Supply Chain Security",{"href":155,"dataGaLocation":44,"dataGaName":156},"/solutions/supply-chain/","Software supply chain security",{"text":158,"config":159},"Compliance & Governance",{"href":160,"dataGaLocation":44,"dataGaName":161},"/solutions/continuous-software-compliance/","Compliance and governance",{"title":163,"link":164,"items":169},"Measurement",{"config":165},{"icon":166,"href":167,"dataGaName":168,"dataGaLocation":44},"DigitalTransformation","/solutions/visibility-measurement/","visibility and measurement",[170,174,178],{"text":171,"config":172},"Visibility & Measurement",{"href":167,"dataGaLocation":44,"dataGaName":173},"Visibility and Measurement",{"text":175,"config":176},"Value Stream Management",{"href":177,"dataGaLocation":44,"dataGaName":175},"/solutions/value-stream-management/",{"text":179,"config":180},"Analytics & Insights",{"href":181,"dataGaLocation":44,"dataGaName":182},"/solutions/analytics-and-insights/","Analytics and insights",{"title":184,"items":185},"GitLab for",[186,191,196],{"text":187,"config":188},"Enterprise",{"href":189,"dataGaLocation":44,"dataGaName":190},"/enterprise/","enterprise",{"text":192,"config":193},"Small Business",{"href":194,"dataGaLocation":44,"dataGaName":195},"/small-business/","small business",{"text":197,"config":198},"Public Sector",{"href":199,"dataGaLocation":44,"dataGaName":200},"/solutions/public-sector/","public sector",{"text":202,"config":203},"Pricing",{"href":204,"dataGaName":205,"dataGaLocation":44,"dataNavLevelOne":205},"/pricing/","pricing",{"text":207,"config":208,"link":210,"lists":214,"feature":298},"Resources",{"dataNavLevelOne":209},"resources",{"text":211,"config":212},"View all resources",{"href":213,"dataGaName":209,"dataGaLocation":44},"/resources/",[215,248,270],{"title":216,"items":217},"Getting started",[218,223,228,233,238,243],{"text":219,"config":220},"Install",{"href":221,"dataGaName":222,"dataGaLocation":44},"/install/","install",{"text":224,"config":225},"Quick start guides",{"href":226,"dataGaName":227,"dataGaLocation":44},"/get-started/","quick setup checklists",{"text":229,"config":230},"Learn",{"href":231,"dataGaLocation":44,"dataGaName":232},"https://university.gitlab.com/","learn",{"text":234,"config":235},"Product documentation",{"href":236,"dataGaName":237,"dataGaLocation":44},"https://docs.gitlab.com/","product documentation",{"text":239,"config":240},"Best practice videos",{"href":241,"dataGaName":242,"dataGaLocation":44},"/getting-started-videos/","best practice videos",{"text":244,"config":245},"Integrations",{"href":246,"dataGaName":247,"dataGaLocation":44},"/integrations/","integrations",{"title":249,"items":250},"Discover",[251,256,260,265],{"text":252,"config":253},"Customer success stories",{"href":254,"dataGaName":255,"dataGaLocation":44},"/customers/","customer success stories",{"text":257,"config":258},"Blog",{"href":259,"dataGaName":5,"dataGaLocation":44},"/blog/",{"text":261,"config":262},"Remote",{"href":263,"dataGaName":264,"dataGaLocation":44},"https://handbook.gitlab.com/handbook/company/culture/all-remote/","remote",{"text":266,"config":267},"TeamOps",{"href":268,"dataGaName":269,"dataGaLocation":44},"/teamops/","teamops",{"title":271,"items":272},"Connect",[273,278,283,288,293],{"text":274,"config":275},"GitLab Services",{"href":276,"dataGaName":277,"dataGaLocation":44},"/services/","services",{"text":279,"config":280},"Community",{"href":281,"dataGaName":282,"dataGaLocation":44},"/community/","community",{"text":284,"config":285},"Forum",{"href":286,"dataGaName":287,"dataGaLocation":44},"https://forum.gitlab.com/","forum",{"text":289,"config":290},"Events",{"href":291,"dataGaName":292,"dataGaLocation":44},"/events/","events",{"text":294,"config":295},"Partners",{"href":296,"dataGaName":297,"dataGaLocation":44},"/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":44},"/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":44},"/company/","about",{"text":324,"config":325,"footerGa":328},"Jobs",{"href":326,"dataGaName":327,"dataGaLocation":44},"/jobs/","jobs",{"dataGaName":327},{"text":289,"config":330},{"href":291,"dataGaName":292,"dataGaLocation":44},{"text":332,"config":333},"Leadership",{"href":334,"dataGaName":335,"dataGaLocation":44},"/company/team/e-group/","leadership",{"text":337,"config":338},"Team",{"href":339,"dataGaName":340,"dataGaLocation":44},"/company/team/","team",{"text":342,"config":343},"Handbook",{"href":344,"dataGaName":345,"dataGaLocation":44},"https://handbook.gitlab.com/","handbook",{"text":347,"config":348},"Investor relations",{"href":349,"dataGaName":350,"dataGaLocation":44},"https://ir.gitlab.com/","investor relations",{"text":352,"config":353},"Trust Center",{"href":354,"dataGaName":355,"dataGaLocation":44},"/security/","trust center",{"text":357,"config":358},"AI Transparency Center",{"href":359,"dataGaName":360,"dataGaLocation":44},"/ai-transparency-center/","ai transparency center",{"text":362,"config":363},"Newsletter",{"href":364,"dataGaName":365,"dataGaLocation":44},"/company/contact/","newsletter",{"text":367,"config":368},"Press",{"href":369,"dataGaName":370,"dataGaLocation":44},"/press/","press",{"text":372,"config":373,"lists":374},"Contact us",{"dataNavLevelOne":314},[375],{"items":376},[377,380,385],{"text":51,"config":378},{"href":53,"dataGaName":379,"dataGaLocation":44},"talk to sales",{"text":381,"config":382},"Get help",{"href":383,"dataGaName":384,"dataGaLocation":44},"/support/","get help",{"text":386,"config":387},"Customer portal",{"href":388,"dataGaName":389,"dataGaLocation":44},"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":58,"dataGaName":397,"dataGaLocation":398},"search login","search",{"text":400,"default":401},"Suggestions",[402,404,408,410,414,418],{"text":73,"config":403},{"href":78,"dataGaName":73,"dataGaLocation":398},{"text":405,"config":406},"Code Suggestions (AI)",{"href":407,"dataGaName":405,"dataGaLocation":398},"/solutions/code-suggestions/",{"text":125,"config":409},{"href":127,"dataGaName":125,"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":86,"dataGaName":419,"dataGaLocation":398},{"freeTrial":422,"mobileIcon":427,"desktopIcon":432,"secondaryButton":435},{"text":423,"config":424},"Start free trial",{"href":425,"dataGaName":49,"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":78,"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":38,"_draft":6,"_partial":6,"_locale":7,"title":455,"button":456,"image":460,"config":463,"_id":465,"_type":30,"_source":32,"_file":466,"_stem":467,"_extension":35},"/shared/en-us/banner","is now in public beta!",{"text":84,"config":457},{"href":458,"dataGaName":459,"dataGaLocation":44},"/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":38,"_draft":6,"_partial":6,"_locale":7,"data":470,"_id":674,"_type":30,"title":675,"_source":32,"_file":676,"_stem":677,"_extension":35},"/shared/en-us/main-footer",{"text":471,"source":472,"edit":478,"contribute":483,"config":488,"items":493,"minimal":666},"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,573,602,636],{"title":62,"links":495,"subMenu":500},[496],{"text":497,"config":498},"DevSecOps platform",{"href":71,"dataGaName":499,"dataGaLocation":477},"devsecops platform",[501],{"title":202,"links":502},[503,507,512],{"text":504,"config":505},"View plans",{"href":204,"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,555,557,560,563,568],{"text":521,"config":522},"Digital transformation",{"href":523,"dataGaName":524,"dataGaLocation":477},"/topics/digital-transformation/","digital transformation",{"text":150,"config":526},{"href":145,"dataGaName":527,"dataGaLocation":477},"security & compliance",{"text":139,"config":529},{"href":121,"dataGaName":122,"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":135,"dataGaName":543,"dataGaLocation":477},"source code management",{"text":125,"config":545},{"href":127,"dataGaName":546,"dataGaLocation":477},"continuous integration & delivery",{"text":548,"config":549},"Value stream management",{"href":177,"dataGaName":550,"dataGaLocation":477},"value stream management",{"text":25,"config":552},{"href":553,"dataGaName":554,"dataGaLocation":477},"/solutions/gitops/","gitops",{"text":187,"config":556},{"href":189,"dataGaName":190,"dataGaLocation":477},{"text":558,"config":559},"Small business",{"href":194,"dataGaName":195,"dataGaLocation":477},{"text":561,"config":562},"Public sector",{"href":199,"dataGaName":200,"dataGaLocation":477},{"text":564,"config":565},"Education",{"href":566,"dataGaName":567,"dataGaLocation":477},"/solutions/education/","education",{"text":569,"config":570},"Financial services",{"href":571,"dataGaName":572,"dataGaLocation":477},"/solutions/finance/","financial services",{"title":207,"links":574},[575,577,579,581,584,586,588,590,592,594,596,598,600],{"text":219,"config":576},{"href":221,"dataGaName":222,"dataGaLocation":477},{"text":224,"config":578},{"href":226,"dataGaName":227,"dataGaLocation":477},{"text":229,"config":580},{"href":231,"dataGaName":232,"dataGaLocation":477},{"text":234,"config":582},{"href":236,"dataGaName":583,"dataGaLocation":477},"docs",{"text":257,"config":585},{"href":259,"dataGaName":5,"dataGaLocation":477},{"text":252,"config":587},{"href":254,"dataGaName":255,"dataGaLocation":477},{"text":261,"config":589},{"href":263,"dataGaName":264,"dataGaLocation":477},{"text":274,"config":591},{"href":276,"dataGaName":277,"dataGaLocation":477},{"text":266,"config":593},{"href":268,"dataGaName":269,"dataGaLocation":477},{"text":279,"config":595},{"href":281,"dataGaName":282,"dataGaLocation":477},{"text":284,"config":597},{"href":286,"dataGaName":287,"dataGaLocation":477},{"text":289,"config":599},{"href":291,"dataGaName":292,"dataGaLocation":477},{"text":294,"config":601},{"href":296,"dataGaName":297,"dataGaLocation":477},{"title":312,"links":603},[604,606,608,610,612,614,616,620,625,627,629,631],{"text":319,"config":605},{"href":321,"dataGaName":314,"dataGaLocation":477},{"text":324,"config":607},{"href":326,"dataGaName":327,"dataGaLocation":477},{"text":332,"config":609},{"href":334,"dataGaName":335,"dataGaLocation":477},{"text":337,"config":611},{"href":339,"dataGaName":340,"dataGaLocation":477},{"text":342,"config":613},{"href":344,"dataGaName":345,"dataGaLocation":477},{"text":347,"config":615},{"href":349,"dataGaName":350,"dataGaLocation":477},{"text":617,"config":618},"Sustainability",{"href":619,"dataGaName":617,"dataGaLocation":477},"/sustainability/",{"text":621,"config":622},"Diversity, inclusion and belonging (DIB)",{"href":623,"dataGaName":624,"dataGaLocation":477},"/diversity-inclusion-belonging/","Diversity, inclusion and belonging",{"text":352,"config":626},{"href":354,"dataGaName":355,"dataGaLocation":477},{"text":362,"config":628},{"href":364,"dataGaName":365,"dataGaLocation":477},{"text":367,"config":630},{"href":369,"dataGaName":370,"dataGaLocation":477},{"text":632,"config":633},"Modern Slavery Transparency Statement",{"href":634,"dataGaName":635,"dataGaLocation":477},"https://handbook.gitlab.com/handbook/legal/modern-slavery-act-transparency-statement/","modern slavery transparency statement",{"title":637,"links":638},"Contact Us",[639,642,644,646,651,656,661],{"text":640,"config":641},"Contact an expert",{"href":53,"dataGaName":54,"dataGaLocation":477},{"text":381,"config":643},{"href":383,"dataGaName":384,"dataGaLocation":477},{"text":386,"config":645},{"href":388,"dataGaName":389,"dataGaLocation":477},{"text":647,"config":648},"Status",{"href":649,"dataGaName":650,"dataGaLocation":477},"https://status.gitlab.com/","status",{"text":652,"config":653},"Terms of use",{"href":654,"dataGaName":655,"dataGaLocation":477},"/terms/","terms of use",{"text":657,"config":658},"Privacy statement",{"href":659,"dataGaName":660,"dataGaLocation":477},"/privacy/","privacy statement",{"text":662,"config":663},"Cookie preferences",{"dataGaName":664,"dataGaLocation":477,"id":665,"isOneTrustButton":107},"cookie preferences","ot-sdk-btn",{"items":667},[668,670,672],{"text":652,"config":669},{"href":654,"dataGaName":655,"dataGaLocation":477},{"text":657,"config":671},{"href":659,"dataGaName":660,"dataGaLocation":477},{"text":662,"config":673},{"dataGaName":664,"dataGaLocation":477,"id":665,"isOneTrustButton":107},"content:shared:en-us:main-footer.yml","Main Footer","shared/en-us/main-footer.yml","shared/en-us/main-footer",[679],{"_path":680,"_dir":681,"_draft":6,"_partial":6,"_locale":7,"content":682,"config":686,"_id":688,"_type":30,"title":689,"_source":32,"_file":690,"_stem":691,"_extension":35},"/en-us/blog/authors/david-oregan","authors",{"name":18,"config":683},{"headshot":684,"ctfId":685},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1749659853/Blog/Author%20Headshots/oregand-headshot.png","oregand",{"template":687},"BlogAuthor","content:en-us:blog:authors:david-oregan.yml","David Oregan","en-us/blog/authors/david-oregan.yml","en-us/blog/authors/david-oregan",{"_path":693,"_dir":38,"_draft":6,"_partial":6,"_locale":7,"header":694,"eyebrow":695,"blurb":696,"button":697,"secondaryButton":701,"_id":703,"_type":30,"title":704,"_source":32,"_file":705,"_stem":706,"_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":698},{"href":699,"dataGaName":49,"dataGaLocation":700},"https://gitlab.com/-/trial_registrations/new?glm_content=default-saas-trial&glm_source=about.gitlab.com/","feature",{"text":51,"config":702},{"href":53,"dataGaName":54,"dataGaLocation":700},"content:shared:en-us:next-steps.yml","Next Steps","shared/en-us/next-steps.yml","shared/en-us/next-steps",1753981633554]