[{"data":1,"prerenderedAt":760},["ShallowReactive",2],{"/en-us/blog/keep-git-history-clean-with-interactive-rebase":3,"navigation-en-us":35,"banner-en-us":463,"footer-en-us":480,"Tobias Günther":725,"next-steps-en-us":739,"footer-source-/en-us/blog/keep-git-history-clean-with-interactive-rebase/":754},{"_path":4,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":8,"content":16,"config":25,"_id":28,"_type":29,"title":30,"_source":31,"_file":32,"_stem":33,"_extension":34},"/en-us/blog/keep-git-history-clean-with-interactive-rebase","blog",false,"",{"title":9,"description":10,"ogTitle":9,"ogDescription":10,"noIndex":6,"ogImage":11,"ogUrl":12,"ogSiteName":13,"ogType":14,"canonicalUrls":12,"schema":15},"How to keep your Git history clean with interactive rebase","Interactive rebase is one of Git’s most versatile tools. Here's how to use it to correct commit messages, fix mistakes, and more.","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749662593/Blog/Hero%20Images/title-image.png","https://about.gitlab.com/blog/keep-git-history-clean-with-interactive-rebase","https://about.gitlab.com","article","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How to keep your Git history clean with interactive rebase\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Tobias Günther\"}],\n        \"datePublished\": \"2020-11-23\",\n      }",{"title":9,"description":10,"authors":17,"heroImage":11,"date":19,"body":20,"category":21,"tags":22},[18],"Tobias Günther","2020-11-23","## What is interactive rebase? \n\n\nInteractive [rebase](/solutions/source-code-management/), or\nGit rebase interactive, is sometimes called the \"Swiss Army Knife\" of Git –\nbecause it contains so many different tools, for so many different use\ncases! However, there's one main, overarching use case: _cleaning up your\nlocal commit history_.\n\n\nMind the word \"local\": it should only be used for cleaning up your own,\nlocal commit history, for example before integrating one of your feature\nbranches into a team branch. In contrast, it should NOT be used on commit\nhistory that has already been pushed and shared on a remote repository.\nInteractive rebase is one of those tools that \"rewrite\" Git history – and\nyou shouldn't do this on commits that have already been shared with others.\n\n\nWith this little warning message out of the way, let's look at some\npractical examples! \n\n\nNote: for easier visualization of the scenarios and workflows in this post,\nI’ve been using the [\"Tower\" Git desktop\nGUI](https://www.git-tower.com/?utm_source=gitlab&utm_medium=guestpost&utm_campaign=interactive-rebase)\nin some of my screenshots.\n\n{: .note}\n\n\n## Correcting an old commit message with Git rebase interactive\n\n\nSometimes you notice a typo in an **old commit message** – or you've\nforgotten to mention something in the description that is noteworthy. If we\nwere talking about the _very last_ commit, we could have simply used the\n`--amend` option of the `git commit` command. But for older commits you will\nhave to use interactive rebase to change them after the fact.\n\n\nHere's an example of a commit message gone horribly wrong that we want to\ncorrect:\n\n\n![A bad commit message that needs\ncorrection](https://about.gitlab.com/images/blogimages/how-to-keep-your-git-history-clean-with-interactive-rebase/bad-commit-message@2x.png){:\n.shadow.medium.center}\n\nA bad commit message that needs correction\n\n{: .note.text-center}\n\n\nThe first step in _any_ Git interactive rebase session is to **determine\nwhat part of commit history you want to manipulate**. To again take the\nabove example: in order to change this bad commit we have to start the\nsession at its _parent_ commit.\n\n\n![Starting our interactive rebase\nsession](https://about.gitlab.com/images/blogimages/how-to-keep-your-git-history-clean-with-interactive-rebase/start-at-parent-commit@2x.png){:\n.shadow.medium.center}\n\nStarting our interactive rebase session\n\n{: .note.text-center}\n\n\nWe can now feed this starting commit's hash to the Git rebase interactive\ncommand:\n\n\n```\n\n$ git rebase -i 0023cddd\n\n```\n\n\nAn editor window will now open, containing a list of the commits that you\njust selected for manipulation. And don't be surprised because they are in\n_reverse order_: in an interactive rebase session, Git will reapply the old\ncommits, item after item – which means that reversing the order is correct\nfrom Git's perspective.\n\n\n![Editor window with the selected\ncommits](https://about.gitlab.com/images/blogimages/how-to-keep-your-git-history-clean-with-interactive-rebase/editor-window-start-ir@2x.png){:\n.shadow.medium.center}\n\nEditor window with the selected commits\n\n{: .note.text-center}\n\n\nOne other important thing to note about this editor window: _you don't\nperform the actual manipulations here_! Or, in this concrete example, you do\nNOT go ahead and change the commit message here. Instead, you only mark the\ncommit you want to change with an action keyword. In our case, because we\nwant to change a commit’s message, we mark the line with \"reword\". If you\nthen save and close this editor window, a new one will open, containing the\nold commit’s message. Now is the time to finally make your changes:\n\n\n![Finally, we can make our\nchanges](https://about.gitlab.com/images/blogimages/how-to-keep-your-git-history-clean-with-interactive-rebase/correct-commit-message.gif){:\n.shadow.medium.center}\n\nFinally, we can make our changes\n\n{: .note.text-center}\n\n\nAfter saving and closing once more, the interactive rebase session is\ncomplete and our old commit message has been corrected!\n\n\n## Combining multiple commits into one using interactive rebase\n\n\nAnother use case for interactive rebase is when you want to **combine\nmultiple old commits into one**. Although, of course, the golden rule of\nversion control applies: in most situations, it's beneficial to create more\nand smaller commits instead of a few big ones. However, as with everything,\nwe might find that we have overdone this and now want to meld two or more\nold commits into a single one.\n\n\nTo make a concrete example, let's say we want to combine the following\nselected commits into a single one:\n\n\n![Let's combine multiple commits into\none](https://about.gitlab.com/images/blogimages/how-to-keep-your-git-history-clean-with-interactive-rebase/squash-selected-commits@2x.png){:\n.shadow.medium.center}\n\nLet's combine multiple commits into one\n\n{: .note.text-center}\n\n\nJust like in our first case, we begin by starting the interactive rebase\nsession at least at the parent commit of the one we want to manipulate.\n\n\n```\n\n$ git rebase -i 2b504bee\n\n```\n\n\nAgain, an editor window will open, listing that part of our commit history\nthat we want to manipulate:\n\n\n![Marking lines with\n\"squash\"](https://about.gitlab.com/images/blogimages/how-to-keep-your-git-history-clean-with-interactive-rebase/squash-mark-commit@2x.png){:\n.shadow.medium.center}\n\nMarking lines with \"squash\"\n\n{: .note.text-center}\n\n\nThe action keyword we are going to use here is called \"squash.\" And there's\nonly one important piece of information you need to know about squash in\norder to use it: _the line we mark up with the \"squash\" keyword will be\ncombined with the line directly above_. That’s why, as you can see in my\nscreenshot above, I’ve marked line #2 with \"squash\" in order to combine it\nwith line #1.\n\n\nWe can now save and close the editor window and again watch and a new window\nappear: we are now asked to provide a commit message for the new commit that\nis created when combining those two old ones.\n\n\n![Entering a new message for the new, squashed\ncommit](https://about.gitlab.com/images/blogimages/how-to-keep-your-git-history-clean-with-interactive-rebase/squash-enter-new-message@2x.png){:\n.shadow.medium.center}\n\nEntering a new message for the new, squashed commit\n\n{: .note.text-center}\n\n\nAfter saving and closing this editor window, you will see that a new commit\nwas created that contains the changesets of both old commits. Voila!\n\n\n## Fixing a mistake with interactive rebase\n\n\nAnother use case for interactive rebase is when you found a mistake in one\nof your earlier commits. And it doesn't matter what exactly you messed up:\nyou could have forgotten to add a certain change, should have deleted a\nfile, or simply introduced a typo...\n\n\nThe natural tendency, in such a situation, is to simply create a new commit\nthat corrects the mistake. But on the other hand, this will mess up our\ncommit history: making an original commit, and then adding a \"band-aid\"\ncommit just to fix some mistakes… that’s a messy way of working. Your commit\nhistory will soon become hard to understand, because it's littered with all\nthose little \"quick fix commits\"!\n\n\nThis is where \"fixup,\" one of the tools that come with interactive rebase,\ncomes in very handy. Fixup takes this \"quick fix\" commit, applies its\nchanges to the original commit (thereby correcting it), and then gets rid of\nthe band-aid commit:\n\n\n![How \"fixup\"\nworks](https://about.gitlab.com/images/blogimages/how-to-keep-your-git-history-clean-with-interactive-rebase/diagram-fixup.png){:\n.medium.center}\n\nHow \"fixup\" works\n\n{: .note.text-center}\n\n\nAfter we're done, it looks as if there had never been a problem with our\noriginal commit! So let's walk through this using a practical example. \n\n\nThe first step is to do whatever is necessary to fix the problem: this could\nmean adding a new file, making changes to existing ones, deleting obsolete\nfiles... you \"just\" need to produce the changes that correct the mistake.\n\n\nThe next step is to commit these changes to the repository – but with a\nlittle extra: when making the commit, we are going to use the `--fixup` flag\nand tell Git the commit hash of our bad commit:\n\n\n```\n\n$ git add corrections.txt\n\n$ git commit --fixup 2b504bee\n\n```\n\n\nWhen you now take a look at the commit history, you will see that a pretty\nordinarily looking commit has been created – probably not the magic and\nfireworks you would have expected. But if you take a closer look, you will\nsee that something’s going on: the new commit has automatically been\nprepended with \"fixup !\" and the commit subject of our bad commit.\n\n\n![The original commit and the fix\ncommit](https://about.gitlab.com/images/blogimages/how-to-keep-your-git-history-clean-with-interactive-rebase/fixup_create-fix-commit@2x.png){:\n.shadow.medium.center}\n\nThe original commit and the fix commit\n\n{: .note.text-center}\n\n\nThe third step now is to start the interactive rebase session. Again, we\nchoose the parent of our bad commit as the starting point...\n\n\n```\n\n$ git rebase -i 0023cddd --autosquash\n\n```\n\n\n... and as the second part of the secret sauce, we are using the\n`--autosquash` flag. This option makes sure that we don't have to do\n_anything_ in the editor window that is now open. Take a close look at the\nsituation:\n\n\n![Our fix commit is marked \"fixup\" and sorted to the right\nposition](https://about.gitlab.com/images/blogimages/how-to-keep-your-git-history-clean-with-interactive-rebase/fixup_editor@2x.png){:\n.shadow.medium.center}\n\nOur fix commit is marked \"fixup\" and sorted to the right position\n\n{: .note.text-center}\n\n\nYou will see that Git automatically did two things for us:\n\n1. It marked our band-aid commit as \"fixup.\"\n\n2. It re-ordered the lines so that our band-aid commit appears directly\nbelow our bad commit. This is because fixup works exactly like squash in\nthat it _combines with the line above_.\n\n\nIn other words: there's nothing left to do for us but save and close the\neditor window.\n\n\nLet's take another look at the commit history:\n\n\n![A happy\nending!](https://about.gitlab.com/images/blogimages/how-to-keep-your-git-history-clean-with-interactive-rebase/fixup_final-corrected@2x.png){:\n.shadow.medium.center}\n\nA happy ending!\n\n{: .note.text-center}\n\n\nNot only does our originally bad commit now contain the changes from our\nband-aid commit. But on top of that, the ugly band-aid commit has\ndisappeared from the commit history! Everything is nice and clean, just as\nif there had never been a problem!\n\n\n## Discover the power of Git rebase interactive\n\n\nThere are lots of use cases for interactive rebase – and most of them in the\ndepartment of “fixing mistakes”. For an overview of other useful things you\ncan do, I recommend the _free_ [\"First Aid Kit for\nGit\"](https://www.git-tower.com/learn/git/first-aid-kit?utm_source=gitlab&utm_medium=guestpost&utm_campaign=interactive-rebase):\nit’s a collection of short videos (2-3 min per episode) that help you learn\nto undo mistakes using interactive rebase and other Git tools.\n\n\nEditor's note: I had to use interactive rebase when reviewing this very\npost! One of my commits included an image that was greater than 1MB which is\nagainst the rules for GitLab website project. I had to go back and fix that\ncommit to include a correctly sized image instead. Thanks for the lesson,\nuniverse! 😁\n\n{: .note}\n\n\n## More Git tips and tricks\n\n\n- [15 Git tips to improve your\nworkflow](/blog/15-git-tips-improve-workflow/)\n\n- [How Git Partial Clone lets you fetch only the large file you\nneed](/blog/partial-clone-for-massive-repositories/)\n\n- [Git happens! 6 Common Git mistakes and how to fix\nthem](/blog/git-happens/)\n\n\n### About the guest author\n\n\n_[Tobias Günther](https://twitter.com/gntr) is the CEO of\n[Tower](https://www.git-tower.com/?utm_source=gitlab&utm_medium=guestpost&utm_campaign=interactive-rebase),\nthe popular Git desktop client that helps more than 100,000 developers\naround the world to be more productive with Git._\n\n\nCover image by [David Taljat](https://www.pexels.com/@david-taljat-3748658)\non\n[Pexels](https://www.pexels.com/photo/yellow-and-blue-line-on-gray-asphalt-road-5690623/)\n\n{: .note}\n","engineering",[23,24],"git","tutorial",{"slug":26,"featured":6,"template":27},"keep-git-history-clean-with-interactive-rebase","BlogPost","content:en-us:blog:keep-git-history-clean-with-interactive-rebase.yml","yaml","Keep Git History Clean With Interactive Rebase","content","en-us/blog/keep-git-history-clean-with-interactive-rebase.yml","en-us/blog/keep-git-history-clean-with-interactive-rebase","yml",{"_path":36,"_dir":37,"_draft":6,"_partial":6,"_locale":7,"data":38,"_id":459,"_type":29,"title":460,"_source":31,"_file":461,"_stem":462,"_extension":34},"/shared/en-us/main-navigation","en-us",{"logo":39,"freeTrial":44,"sales":49,"login":54,"items":59,"search":390,"minimal":421,"duo":440,"pricingDeployment":449},{"config":40},{"href":41,"dataGaName":42,"dataGaLocation":43},"/","gitlab logo","header",{"text":45,"config":46},"Get free trial",{"href":47,"dataGaName":48,"dataGaLocation":43},"https://gitlab.com/-/trial_registrations/new?glm_source=about.gitlab.com&glm_content=default-saas-trial/","free trial",{"text":50,"config":51},"Talk to sales",{"href":52,"dataGaName":53,"dataGaLocation":43},"/sales/","sales",{"text":55,"config":56},"Sign in",{"href":57,"dataGaName":58,"dataGaLocation":43},"https://gitlab.com/users/sign_in/","sign in",[60,104,201,206,311,371],{"text":61,"config":62,"cards":64,"footer":87},"Platform",{"dataNavLevelOne":63},"platform",[65,71,79],{"title":61,"description":66,"link":67},"The most comprehensive AI-powered DevSecOps Platform",{"text":68,"config":69},"Explore our Platform",{"href":70,"dataGaName":63,"dataGaLocation":43},"/platform/",{"title":72,"description":73,"link":74},"GitLab Duo (AI)","Build software faster with AI at every stage of development",{"text":75,"config":76},"Meet GitLab Duo",{"href":77,"dataGaName":78,"dataGaLocation":43},"/gitlab-duo/","gitlab duo ai",{"title":80,"description":81,"link":82},"Why GitLab","10 reasons why Enterprises choose GitLab",{"text":83,"config":84},"Learn more",{"href":85,"dataGaName":86,"dataGaLocation":43},"/why-gitlab/","why gitlab",{"title":88,"items":89},"Get started with",[90,95,100],{"text":91,"config":92},"Platform Engineering",{"href":93,"dataGaName":94,"dataGaLocation":43},"/solutions/platform-engineering/","platform engineering",{"text":96,"config":97},"Developer Experience",{"href":98,"dataGaName":99,"dataGaLocation":43},"/developer-experience/","Developer experience",{"text":101,"config":102},"MLOps",{"href":103,"dataGaName":101,"dataGaLocation":43},"/topics/devops/the-role-of-ai-in-devops/",{"text":105,"left":106,"config":107,"link":109,"lists":113,"footer":183},"Product",true,{"dataNavLevelOne":108},"solutions",{"text":110,"config":111},"View all Solutions",{"href":112,"dataGaName":108,"dataGaLocation":43},"/solutions/",[114,139,162],{"title":115,"description":116,"link":117,"items":122},"Automation","CI/CD and automation to accelerate deployment",{"config":118},{"icon":119,"href":120,"dataGaName":121,"dataGaLocation":43},"AutomatedCodeAlt","/solutions/delivery-automation/","automated software delivery",[123,127,131,135],{"text":124,"config":125},"CI/CD",{"href":126,"dataGaLocation":43,"dataGaName":124},"/solutions/continuous-integration/",{"text":128,"config":129},"AI-Assisted Development",{"href":77,"dataGaLocation":43,"dataGaName":130},"AI assisted development",{"text":132,"config":133},"Source Code Management",{"href":134,"dataGaLocation":43,"dataGaName":132},"/solutions/source-code-management/",{"text":136,"config":137},"Automated Software Delivery",{"href":120,"dataGaLocation":43,"dataGaName":138},"Automated software delivery",{"title":140,"description":141,"link":142,"items":147},"Security","Deliver code faster without compromising security",{"config":143},{"href":144,"dataGaName":145,"dataGaLocation":43,"icon":146},"/solutions/application-security-testing/","security and compliance","ShieldCheckLight",[148,152,157],{"text":149,"config":150},"Application Security Testing",{"href":144,"dataGaName":151,"dataGaLocation":43},"Application security testing",{"text":153,"config":154},"Software Supply Chain Security",{"href":155,"dataGaLocation":43,"dataGaName":156},"/solutions/supply-chain/","Software supply chain security",{"text":158,"config":159},"Software Compliance",{"href":160,"dataGaName":161,"dataGaLocation":43},"/solutions/software-compliance/","software compliance",{"title":163,"link":164,"items":169},"Measurement",{"config":165},{"icon":166,"href":167,"dataGaName":168,"dataGaLocation":43},"DigitalTransformation","/solutions/visibility-measurement/","visibility and measurement",[170,174,178],{"text":171,"config":172},"Visibility & Measurement",{"href":167,"dataGaLocation":43,"dataGaName":173},"Visibility and Measurement",{"text":175,"config":176},"Value Stream Management",{"href":177,"dataGaLocation":43,"dataGaName":175},"/solutions/value-stream-management/",{"text":179,"config":180},"Analytics & Insights",{"href":181,"dataGaLocation":43,"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":43,"dataGaName":190},"/enterprise/","enterprise",{"text":192,"config":193},"Small Business",{"href":194,"dataGaLocation":43,"dataGaName":195},"/small-business/","small business",{"text":197,"config":198},"Public Sector",{"href":199,"dataGaLocation":43,"dataGaName":200},"/solutions/public-sector/","public sector",{"text":202,"config":203},"Pricing",{"href":204,"dataGaName":205,"dataGaLocation":43,"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":43},"/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":43},"/install/","install",{"text":224,"config":225},"Quick start guides",{"href":226,"dataGaName":227,"dataGaLocation":43},"/get-started/","quick setup checklists",{"text":229,"config":230},"Learn",{"href":231,"dataGaLocation":43,"dataGaName":232},"https://university.gitlab.com/","learn",{"text":234,"config":235},"Product documentation",{"href":236,"dataGaName":237,"dataGaLocation":43},"https://docs.gitlab.com/","product documentation",{"text":239,"config":240},"Best practice videos",{"href":241,"dataGaName":242,"dataGaLocation":43},"/getting-started-videos/","best practice videos",{"text":244,"config":245},"Integrations",{"href":246,"dataGaName":247,"dataGaLocation":43},"/integrations/","integrations",{"title":249,"items":250},"Discover",[251,256,260,265],{"text":252,"config":253},"Customer success stories",{"href":254,"dataGaName":255,"dataGaLocation":43},"/customers/","customer success stories",{"text":257,"config":258},"Blog",{"href":259,"dataGaName":5,"dataGaLocation":43},"/blog/",{"text":261,"config":262},"Remote",{"href":263,"dataGaName":264,"dataGaLocation":43},"https://handbook.gitlab.com/handbook/company/culture/all-remote/","remote",{"text":266,"config":267},"TeamOps",{"href":268,"dataGaName":269,"dataGaLocation":43},"/teamops/","teamops",{"title":271,"items":272},"Connect",[273,278,283,288,293],{"text":274,"config":275},"GitLab Services",{"href":276,"dataGaName":277,"dataGaLocation":43},"/services/","services",{"text":279,"config":280},"Community",{"href":281,"dataGaName":282,"dataGaLocation":43},"/community/","community",{"text":284,"config":285},"Forum",{"href":286,"dataGaName":287,"dataGaLocation":43},"https://forum.gitlab.com/","forum",{"text":289,"config":290},"Events",{"href":291,"dataGaName":292,"dataGaLocation":43},"/events/","events",{"text":294,"config":295},"Partners",{"href":296,"dataGaName":297,"dataGaLocation":43},"/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},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1758208064/dzl0dbift9xdizyelkk4.svg",{"text":307,"config":308},"Read the latest",{"href":309,"dataGaName":310,"dataGaLocation":43},"/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":43},"/company/","about",{"text":324,"config":325,"footerGa":328},"Jobs",{"href":326,"dataGaName":327,"dataGaLocation":43},"/jobs/","jobs",{"dataGaName":327},{"text":289,"config":330},{"href":291,"dataGaName":292,"dataGaLocation":43},{"text":332,"config":333},"Leadership",{"href":334,"dataGaName":335,"dataGaLocation":43},"/company/team/e-group/","leadership",{"text":337,"config":338},"Team",{"href":339,"dataGaName":340,"dataGaLocation":43},"/company/team/","team",{"text":342,"config":343},"Handbook",{"href":344,"dataGaName":345,"dataGaLocation":43},"https://handbook.gitlab.com/","handbook",{"text":347,"config":348},"Investor relations",{"href":349,"dataGaName":350,"dataGaLocation":43},"https://ir.gitlab.com/","investor relations",{"text":352,"config":353},"Trust Center",{"href":354,"dataGaName":355,"dataGaLocation":43},"/security/","trust center",{"text":357,"config":358},"AI Transparency Center",{"href":359,"dataGaName":360,"dataGaLocation":43},"/ai-transparency-center/","ai transparency center",{"text":362,"config":363},"Newsletter",{"href":364,"dataGaName":365,"dataGaLocation":43},"/company/contact/","newsletter",{"text":367,"config":368},"Press",{"href":369,"dataGaName":370,"dataGaLocation":43},"/press/","press",{"text":372,"config":373,"lists":374},"Contact us",{"dataNavLevelOne":314},[375],{"items":376},[377,380,385],{"text":50,"config":378},{"href":52,"dataGaName":379,"dataGaLocation":43},"talk to sales",{"text":381,"config":382},"Support portal",{"href":383,"dataGaName":384,"dataGaLocation":43},"https://support.gitlab.com","support portal",{"text":386,"config":387},"Customer portal",{"href":388,"dataGaName":389,"dataGaLocation":43},"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":57,"dataGaName":397,"dataGaLocation":398},"search login","search",{"text":400,"default":401},"Suggestions",[402,404,408,410,414,418],{"text":72,"config":403},{"href":77,"dataGaName":72,"dataGaLocation":398},{"text":405,"config":406},"Code Suggestions (AI)",{"href":407,"dataGaName":405,"dataGaLocation":398},"/solutions/code-suggestions/",{"text":124,"config":409},{"href":126,"dataGaName":124,"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":85,"dataGaName":419,"dataGaLocation":398},{"freeTrial":422,"mobileIcon":427,"desktopIcon":432,"secondaryButton":435},{"text":423,"config":424},"Start free trial",{"href":425,"dataGaName":48,"dataGaLocation":426},"https://gitlab.com/-/trials/new/","nav",{"altText":428,"config":429},"Gitlab Icon",{"src":430,"dataGaName":431,"dataGaLocation":426},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1758203874/jypbw1jx72aexsoohd7x.svg","gitlab icon",{"altText":428,"config":433},{"src":434,"dataGaName":431,"dataGaLocation":426},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1758203875/gs4c8p8opsgvflgkswz9.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":77,"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},{"freeTrial":450,"mobileIcon":455,"desktopIcon":457},{"text":451,"config":452},"Back to pricing",{"href":204,"dataGaName":453,"dataGaLocation":426,"icon":454},"back to pricing","GoBack",{"altText":428,"config":456},{"src":430,"dataGaName":431,"dataGaLocation":426},{"altText":428,"config":458},{"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":464,"_dir":37,"_draft":6,"_partial":6,"_locale":7,"title":465,"button":466,"image":471,"config":475,"_id":477,"_type":29,"_source":31,"_file":478,"_stem":479,"_extension":34},"/shared/en-us/banner","is now in public beta!",{"text":467,"config":468},"Try the Beta",{"href":469,"dataGaName":470,"dataGaLocation":43},"/gitlab-duo/agent-platform/","duo banner",{"altText":472,"config":473},"GitLab Duo Agent Platform",{"src":474},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1753720689/somrf9zaunk0xlt7ne4x.svg",{"layout":476},"release","content:shared:en-us:banner.yml","shared/en-us/banner.yml","shared/en-us/banner",{"_path":481,"_dir":37,"_draft":6,"_partial":6,"_locale":7,"data":482,"_id":721,"_type":29,"title":722,"_source":31,"_file":723,"_stem":724,"_extension":34},"/shared/en-us/main-footer",{"text":483,"source":484,"edit":490,"contribute":495,"config":500,"items":505,"minimal":713},"Git is a trademark of Software Freedom Conservancy and our use of 'GitLab' is under license",{"text":485,"config":486},"View page source",{"href":487,"dataGaName":488,"dataGaLocation":489},"https://gitlab.com/gitlab-com/marketing/digital-experience/about-gitlab-com/","page source","footer",{"text":491,"config":492},"Edit this page",{"href":493,"dataGaName":494,"dataGaLocation":489},"https://gitlab.com/gitlab-com/marketing/digital-experience/about-gitlab-com/-/blob/main/content/","web ide",{"text":496,"config":497},"Please contribute",{"href":498,"dataGaName":499,"dataGaLocation":489},"https://gitlab.com/gitlab-com/marketing/digital-experience/about-gitlab-com/-/blob/main/CONTRIBUTING.md/","please contribute",{"twitter":501,"facebook":502,"youtube":503,"linkedin":504},"https://twitter.com/gitlab","https://www.facebook.com/gitlab","https://www.youtube.com/channel/UCnMGQ8QHMAnVIsI3xJrihhg","https://www.linkedin.com/company/gitlab-com",[506,553,606,650,679],{"title":202,"links":507,"subMenu":522},[508,512,517],{"text":509,"config":510},"View plans",{"href":204,"dataGaName":511,"dataGaLocation":489},"view plans",{"text":513,"config":514},"Why Premium?",{"href":515,"dataGaName":516,"dataGaLocation":489},"/pricing/premium/","why premium",{"text":518,"config":519},"Why Ultimate?",{"href":520,"dataGaName":521,"dataGaLocation":489},"/pricing/ultimate/","why ultimate",[523],{"title":524,"links":525},"Contact Us",[526,529,531,533,538,543,548],{"text":527,"config":528},"Contact sales",{"href":52,"dataGaName":53,"dataGaLocation":489},{"text":381,"config":530},{"href":383,"dataGaName":384,"dataGaLocation":489},{"text":386,"config":532},{"href":388,"dataGaName":389,"dataGaLocation":489},{"text":534,"config":535},"Status",{"href":536,"dataGaName":537,"dataGaLocation":489},"https://status.gitlab.com/","status",{"text":539,"config":540},"Terms of use",{"href":541,"dataGaName":542,"dataGaLocation":489},"/terms/","terms of use",{"text":544,"config":545},"Privacy statement",{"href":546,"dataGaName":547,"dataGaLocation":489},"/privacy/","privacy statement",{"text":549,"config":550},"Cookie preferences",{"dataGaName":551,"dataGaLocation":489,"id":552,"isOneTrustButton":106},"cookie preferences","ot-sdk-btn",{"title":105,"links":554,"subMenu":562},[555,559],{"text":556,"config":557},"DevSecOps platform",{"href":70,"dataGaName":558,"dataGaLocation":489},"devsecops platform",{"text":128,"config":560},{"href":77,"dataGaName":561,"dataGaLocation":489},"ai-assisted development",[563],{"title":564,"links":565},"Topics",[566,571,576,581,586,591,596,601],{"text":567,"config":568},"CICD",{"href":569,"dataGaName":570,"dataGaLocation":489},"/topics/ci-cd/","cicd",{"text":572,"config":573},"GitOps",{"href":574,"dataGaName":575,"dataGaLocation":489},"/topics/gitops/","gitops",{"text":577,"config":578},"DevOps",{"href":579,"dataGaName":580,"dataGaLocation":489},"/topics/devops/","devops",{"text":582,"config":583},"Version Control",{"href":584,"dataGaName":585,"dataGaLocation":489},"/topics/version-control/","version control",{"text":587,"config":588},"DevSecOps",{"href":589,"dataGaName":590,"dataGaLocation":489},"/topics/devsecops/","devsecops",{"text":592,"config":593},"Cloud Native",{"href":594,"dataGaName":595,"dataGaLocation":489},"/topics/cloud-native/","cloud native",{"text":597,"config":598},"AI for Coding",{"href":599,"dataGaName":600,"dataGaLocation":489},"/topics/devops/ai-for-coding/","ai for coding",{"text":602,"config":603},"Agentic AI",{"href":604,"dataGaName":605,"dataGaLocation":489},"/topics/agentic-ai/","agentic ai",{"title":607,"links":608},"Solutions",[609,611,613,618,622,625,629,632,634,637,640,645],{"text":149,"config":610},{"href":144,"dataGaName":149,"dataGaLocation":489},{"text":138,"config":612},{"href":120,"dataGaName":121,"dataGaLocation":489},{"text":614,"config":615},"Agile development",{"href":616,"dataGaName":617,"dataGaLocation":489},"/solutions/agile-delivery/","agile delivery",{"text":619,"config":620},"SCM",{"href":134,"dataGaName":621,"dataGaLocation":489},"source code management",{"text":567,"config":623},{"href":126,"dataGaName":624,"dataGaLocation":489},"continuous integration & delivery",{"text":626,"config":627},"Value stream management",{"href":177,"dataGaName":628,"dataGaLocation":489},"value stream management",{"text":572,"config":630},{"href":631,"dataGaName":575,"dataGaLocation":489},"/solutions/gitops/",{"text":187,"config":633},{"href":189,"dataGaName":190,"dataGaLocation":489},{"text":635,"config":636},"Small business",{"href":194,"dataGaName":195,"dataGaLocation":489},{"text":638,"config":639},"Public sector",{"href":199,"dataGaName":200,"dataGaLocation":489},{"text":641,"config":642},"Education",{"href":643,"dataGaName":644,"dataGaLocation":489},"/solutions/education/","education",{"text":646,"config":647},"Financial services",{"href":648,"dataGaName":649,"dataGaLocation":489},"/solutions/finance/","financial services",{"title":207,"links":651},[652,654,656,658,661,663,665,667,669,671,673,675,677],{"text":219,"config":653},{"href":221,"dataGaName":222,"dataGaLocation":489},{"text":224,"config":655},{"href":226,"dataGaName":227,"dataGaLocation":489},{"text":229,"config":657},{"href":231,"dataGaName":232,"dataGaLocation":489},{"text":234,"config":659},{"href":236,"dataGaName":660,"dataGaLocation":489},"docs",{"text":257,"config":662},{"href":259,"dataGaName":5,"dataGaLocation":489},{"text":252,"config":664},{"href":254,"dataGaName":255,"dataGaLocation":489},{"text":261,"config":666},{"href":263,"dataGaName":264,"dataGaLocation":489},{"text":274,"config":668},{"href":276,"dataGaName":277,"dataGaLocation":489},{"text":266,"config":670},{"href":268,"dataGaName":269,"dataGaLocation":489},{"text":279,"config":672},{"href":281,"dataGaName":282,"dataGaLocation":489},{"text":284,"config":674},{"href":286,"dataGaName":287,"dataGaLocation":489},{"text":289,"config":676},{"href":291,"dataGaName":292,"dataGaLocation":489},{"text":294,"config":678},{"href":296,"dataGaName":297,"dataGaLocation":489},{"title":312,"links":680},[681,683,685,687,689,691,693,697,702,704,706,708],{"text":319,"config":682},{"href":321,"dataGaName":314,"dataGaLocation":489},{"text":324,"config":684},{"href":326,"dataGaName":327,"dataGaLocation":489},{"text":332,"config":686},{"href":334,"dataGaName":335,"dataGaLocation":489},{"text":337,"config":688},{"href":339,"dataGaName":340,"dataGaLocation":489},{"text":342,"config":690},{"href":344,"dataGaName":345,"dataGaLocation":489},{"text":347,"config":692},{"href":349,"dataGaName":350,"dataGaLocation":489},{"text":694,"config":695},"Sustainability",{"href":696,"dataGaName":694,"dataGaLocation":489},"/sustainability/",{"text":698,"config":699},"Diversity, inclusion and belonging (DIB)",{"href":700,"dataGaName":701,"dataGaLocation":489},"/diversity-inclusion-belonging/","Diversity, inclusion and belonging",{"text":352,"config":703},{"href":354,"dataGaName":355,"dataGaLocation":489},{"text":362,"config":705},{"href":364,"dataGaName":365,"dataGaLocation":489},{"text":367,"config":707},{"href":369,"dataGaName":370,"dataGaLocation":489},{"text":709,"config":710},"Modern Slavery Transparency Statement",{"href":711,"dataGaName":712,"dataGaLocation":489},"https://handbook.gitlab.com/handbook/legal/modern-slavery-act-transparency-statement/","modern slavery transparency statement",{"items":714},[715,717,719],{"text":539,"config":716},{"href":541,"dataGaName":542,"dataGaLocation":489},{"text":544,"config":718},{"href":546,"dataGaName":547,"dataGaLocation":489},{"text":549,"config":720},{"dataGaName":551,"dataGaLocation":489,"id":552,"isOneTrustButton":106},"content:shared:en-us:main-footer.yml","Main Footer","shared/en-us/main-footer.yml","shared/en-us/main-footer",[726],{"_path":727,"_dir":728,"_draft":6,"_partial":6,"_locale":7,"content":729,"config":733,"_id":735,"_type":29,"title":736,"_source":31,"_file":737,"_stem":738,"_extension":34},"/en-us/blog/authors/tobias-gnther","authors",{"name":18,"config":730},{"headshot":731,"ctfId":732},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1749659488/Blog/Author%20Headshots/gitlab-logo-extra-whitespace.png","Tobias-Gnther",{"template":734},"BlogAuthor","content:en-us:blog:authors:tobias-gnther.yml","Tobias Gnther","en-us/blog/authors/tobias-gnther.yml","en-us/blog/authors/tobias-gnther",{"_path":740,"_dir":37,"_draft":6,"_partial":6,"_locale":7,"header":741,"eyebrow":742,"blurb":743,"button":744,"secondaryButton":748,"_id":750,"_type":29,"title":751,"_source":31,"_file":752,"_stem":753,"_extension":34},"/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":45,"config":745},{"href":746,"dataGaName":48,"dataGaLocation":747},"https://gitlab.com/-/trial_registrations/new?glm_content=default-saas-trial&glm_source=about.gitlab.com/","feature",{"text":50,"config":749},{"href":52,"dataGaName":53,"dataGaLocation":747},"content:shared:en-us:next-steps.yml","Next Steps","shared/en-us/next-steps.yml","shared/en-us/next-steps",{"_path":4,"_dir":5,"_draft":6,"_partial":6,"_locale":7,"seo":755,"content":756,"config":759,"_id":28,"_type":29,"title":30,"_source":31,"_file":32,"_stem":33,"_extension":34},{"title":9,"description":10,"ogTitle":9,"ogDescription":10,"noIndex":6,"ogImage":11,"ogUrl":12,"ogSiteName":13,"ogType":14,"canonicalUrls":12,"schema":15},{"title":9,"description":10,"authors":757,"heroImage":11,"date":19,"body":20,"category":21,"tags":758},[18],[23,24],{"slug":26,"featured":6,"template":27},1761814433532]