[{"data":1,"prerenderedAt":719},["ShallowReactive",2],{"/en-us/blog/keeping-git-commit-history-clean/":3,"navigation-en-us":35,"banner-en-us":464,"footer-en-us":481,"Kushal Pandya":691,"next-steps-en-us":704},{"_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/keeping-git-commit-history-clean","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 (and why!) to keep your Git commit history clean","Git commit history is very easy to mess up, here's how you can fix it!","https://res.cloudinary.com/about-gitlab-com/image/upload/v1749659457/Blog/Hero%20Images/keep-git-commit-history-clean.jpg","https://about.gitlab.com/blog/keeping-git-commit-history-clean","https://about.gitlab.com","article","\n                        {\n        \"@context\": \"https://schema.org\",\n        \"@type\": \"Article\",\n        \"headline\": \"How (and why!) to keep your Git commit history clean\",\n        \"author\": [{\"@type\":\"Person\",\"name\":\"Kushal Pandya\"}],\n        \"datePublished\": \"2018-06-07\",\n      }",{"title":9,"description":10,"authors":17,"heroImage":11,"date":19,"body":20,"category":21,"tags":22},[18],"Kushal Pandya","2018-06-07","Git commits are one of the key parts of a [Git\nrepository](/solutions/source-code-management/), and more so,\nthe _commit message_ is a life log for the repository. As the\nproject/repository evolves over time (new features getting added, bugs being\nfixed, architecture being refactored), commit messages are the place where\none can see what was changed and how. So it's important that these messages\nreflect the underlying change in a short, precise manner.\n\n\n## Why a meaningful Git commit history is important\n\n\nWhat does Git commit do? Git commit messages are the fingerprints that you\nleave on the code you touch. Any code that you commit today, a year from now\nwhen you look at the same change; you would be thankful for a clear,\nmeaningful commit message that you wrote, and it will also make the lives of\nyour fellow developers easier. When Git commits are isolated based on\ncontext, a bug which was introduced by a single commit becomes quicker to\nfind, and the easier it is to revert the commit which caused the bug in the\nfirst place.\n\n\nWhile working on a large project, we often deal with a lot of moving parts\nthat are updated, added or removed. Ensuring that commit messages are\nmaintained in such cases could be tricky, especially when development spans\nacross days, weeks, or even months. So to simplify the effort of maintaining\nconcise commit history, this article will use some of the common situations\nthat a developer might face while working on a Git repository.\n\n\n- [Situation 1: I need to change the most recent\ncommit](#situation-1-i-need-to-change-the-most-recent-commit)\n\n- [Situation 2: I need to change a specific\ncommit](#situation-2-i-need-to-change-a-specific-commit)\n\n- [Situation 3: I need to add, remove, or combine\ncommits](#situation-3-i-need-to-add-remove-or-combine-commits)\n\n- [Situation 4: My commit history doesn't make sense, I need a fresh\nstart!](#situation-4-my-commit-history-doesnt-make-sense-i-need-a-fresh-start)\n\n\nBut before we dive in, let's quickly go through what a typical development\nworkflow looks like in our hypothetical Ruby application.\n\n\n**Note:** This article assumes that you are aware about basics of Git, how\nbranches work, how to add uncommitted changes of a branch to stage and how\nto commit the changes. If you're unsure of these flows, [our\ndocumentation](https://docs.gitlab.com/ee/topics/git/index.html) is a great\nstarting point.\n\n\n## A day in the life\n\n\nHere, we are working on a small Ruby on Rails project where we need to add a\nnavigation view on the homepage and that involves updating and adding\nseveral files. Following is a step by step breakdown of the entire flow:\n\n\n- You start working on a feature with updating a single file; let's call it\n`application_controller.rb`\n\n- This feature requires you to also update a view: `index.html.haml`\n\n- You added a partial which is used in index page: `_navigation.html.haml`\n\n- Styles for the page also need to be updated to reflect the partial we\nadded: `styles.css.scss`\n\n- Feature is now ready with the desired changes, time to also update tests;\nfiles to be updated are as follows:\n  - `application_controller_spec.rb`\n  - `navigation_spec.rb`\n- Tests are updated and passing as expected, now time to commit the changes!\n\n\nSince all the files belong to different territories of the architecture, we\ncommit the changes isolated of each other to ensure that each commit\nrepresents a certain context and is made in a certain order. I usually\nprefer backend -> frontend order where most backend-centric change is\ncommitted first, followed by the middle layer and then by frontend-centric\nchanges in the Git list commits.\n\n\n\n1.  `application_controller.rb` & `application_controller_spec.rb`; **Add\nroutes for navigation**.\n\n2.  `_navigation.html.haml` &  `navigation_spec.rb`; **Page Navigation\nView**.\n\n3.  `index.html.haml`; **Render navigation partial**.\n\n4.  `styles.css.scss`; **Add styles for navigation**.\n\n\nNow that we have our changes committed, we create a merge request with the\nbranch. Once you have merge request open, it typically gets reviewed by your\npeer before the changes are merged into repo's `master` branch. Now let's\nlearn what different situations we may end up with during code review.\n\n\n## Situation 1: How to change the most recent Git commit\n\n\nImagine a case where the reviewer looked at `styles.css.scss` and suggested\na change. In such a case, it is very simple to do the change as the\nstylesheet changes are part of **last** commit on your branch. Here's how we\ncan handle this;\n\n\n- You directly do the necessary changes to `styles.css.scss` in your current\nbranch.\n\n- Once you're done with the changes, add these changes to stage; run `git\nadd styles.css.scss`.\n\n- Once changes are staged, we need to _add_ these changes to our last\ncommit; run `git commit --amend`.\n  -  **Command breakdown**: Here, we're asking the `git commit` command to _amend_ whatever changes are present in stage to the most recent commit.\n- This will open your last commit in your Git-defined text editor which has\nthe commit message **Add styles for navigation**.\n\n- Since we only updated the CSS declaration, we don't need to alter the\ncommit message. At this point, you can just save and exit the text editor\nthat Git opened for you and your changes will be reflected in the commit.\n\n\nSince you modified an existing Git commit, these changes are required to be\n_force pushed_ to your remote repo using `git push --force-with-lease\n\u003Cremote_name> \u003Cbranch_name>`. This command will override the commit `Add\nstyles for navigation` on remote repo with updated commit that we just made\nin our local repo.\n\n\nOne thing to keep in mind while force pushing branches is that if you are\nworking on the same branch with multiple people, force pushing may cause\ntrouble for other users when they try to normally push their changes on a\nremote branch that has new commits force pushed. Hence, use this feature\nwisely. You can learn more about Git force push options\n[here](https://git-scm.com/docs/git-push#git-push---no-force-with-lease).\n\n\n## Situation 2: How to change a specific Git commit changes\n\n\nIn the previous situation, the Git commit change was rather simple as we had\nto modify only our last Git commit, but imagine if reviewer suggested to\nchange something in `_navigation.html.haml`. In this case, it is second\ncommit from the top, so changing it won't be as direct as it was in the\nfirst situation. Let's see how we can handle this:\n\n\nWhenever a commit is made in a branch, it is identified by a unique SHA-1\nhash string. Think of it as a unique ID that separates one commit from\nanother. You can view all the previous commits, along with their SHA-1\nhashes in a branch by running the `git log` command. With this, you would\nsee an output that looks somewhat as follows and is a list of commits, where\nthe most recent commits are at the top;\n\n\n```\n\ncommit aa0a35a867ed2094da60042062e8f3d6000e3952 (HEAD ->\nadd-page-navigation)\n\nAuthor: Kushal Pandya \u003Ckushal@gitlab.com>\n\nDate: Wed May 2 15:24:02 2018 +0530\n\n    Add styles for navigation\n\ncommit c22a3fa0c5cdc175f2b8232b9704079d27c619d0\n\nAuthor: Kushal Pandya \u003Ckushal@gitlab.com>\n\nDate: Wed May 2 08:42:52 2018 +0000\n\n    Render navigation partial\n\ncommit 4155df1cdc7be01c98b0773497ff65c22ba1549f\n\nAuthor: Kushal Pandya \u003Ckushal@gitlab.com>\n\nDate: Wed May 2 08:42:51 2018 +0000\n\n    Page Navigation View\n\ncommit 8d74af102941aa0b51e1a35b8ad731284e4b5a20\n\nAuthor: Kushal Pandya \u003Ckushal@gitlab.com>\n\nDate: Wed May 2 08:12:20 2018 +0000\n\n    Add routes for navigation\n```\n\n\nThis is where `git rebase` command comes into play. Whenever we wish to edit\na specific commit with `git rebase`, we need to first rebase our branch by\nmoving back HEAD to the point right _before_ the commit we wish to edit. In\nour case, we need to change the commit that reads `Page Navigation View`.\n\n\n![Commit\nLog](https://about.gitlab.com/images/blogimages/keeping-git-commit-history-clean/GitRebase.png){:\n.shadow.center.medium}\n\n\nHere, notice the hash of commit which is right before the commit we want to\nmodify; copy the hash and perform the following steps:\n\n\n- Rebase the branch to move to commit before our target commit; run `git\nrebase -i 8d74af102941aa0b51e1a35b8ad731284e4b5a20`\n  -  **Git command breakdown**: Here we're running Git's `rebase` command with _interactive_ mode with provided SHA-1 hash as commit to rebase to.\n- This will run rebase command for Git in interactive mode and will open\nyour text editor showing all of your commits that came _after_ the commit\nyou rebased to. It will look somewhat like this:\n\n\n```\n\npick 4155df1cdc7 Page Navigation View\n\npick c22a3fa0c5c Render navigation partial\n\npick aa0a35a867e Add styles for navigation\n\n\n# Rebase 8d74af10294..aa0a35a867e onto 8d74af10294 (3 commands)\n\n#\n\n# Commands:\n\n# p, pick = use commit\n\n# r, reword = use commit, but edit the commit message\n\n# e, edit = use commit, but stop for amending\n\n# s, squash = use commit, but meld into previous commit\n\n# f, fixup = like \"squash\", but discard this commit's log message\n\n# x, exec = run command (the rest of the line) using shell\n\n# d, drop = remove Git commit\n\n#\n\n# These lines can be re-ordered; they are executed from top to bottom.\n\n#\n\n# If you remove a line here THAT COMMIT WILL BE LOST.\n\n#\n\n# However, if you remove everything, the rebase will be aborted.\n\n#\n\n# Note that empty commits are commented out\n\n```\n\n\nNotice how each commit has a word `pick` in front of it, and in the contents\nbelow, there are all possible keywords we can use. Since we want to _edit_ a\ncommit, we need to change `pick 4155df1cdc7 Page Navigation View` to `edit\n4155df1cdc7 Page Navigation View`. Save the changes and exit editor.\n\n\nNow your branch is rebased to the point in time right before the commit you\nmade which included `_navigation.html.haml`. Open the file and perform\ndesired changes as per the review feedback. Once you're done with the\nchanges, stage them by running `git add _navigation.html.haml`.\n\n\nSince we have staged the changes, it is time to move branch HEAD back to the\ncommit we originally had (while also including the new changes we added),\nrun `git rebase --continue`, this will open your default editor in the\nterminal and show you the commit message that we edited during rebase; `Page\nNavigation View`. You can change this message if you wish, but we would\nleave it as it is for now, so save and exit the editor. At this point, Git\nwill replay all the commits that followed after the commit you just edited\nand now branch `HEAD` is back to the top commit we originally had, and it\nalso includes the new changes you made to one of the commits.\n\n\nSince we again modified a commit that's already present in remote repo, we\nneed force push this branch again using `git push --force-with-lease\n\u003Cremote_name> \u003Cbranch_name>`.\n\n\n## Situation 3: How to add, remove, or combine Git commits\n\n\nA common situation is when you've made several commits just to fix something\npreviously committed. Now let's reduce them as much as we can, combining\nthem with the original commits.\n\n\nAll you need to do is start the interactive rebase as you would in the other\nscenarios.\n\n\n```\n\npick 4155df1cdc7 Page Navigation View\n\npick c22a3fa0c5c Render navigation partial\n\npick aa0a35a867e Add styles for navigation\n\npick 62e858a322 Fix a typo\n\npick 5c25eb48c8 Ops another fix\n\npick 7f0718efe9 Fix 2\n\npick f0ffc19ef7 Argh Another fix!\n\n```\n\n\nNow imagine you want to combine all those fixes into `c22a3fa0c5c Render\nnavigation partial`. You just need to:\n\n\n1. Move the fixes up so that they are right below the commit you want to\nkeep in the end.\n\n2. Change `pick` to `squash` or `fixup` for each of the fixes.\n\n\n*Note:* `squash` keeps the git fix commit messages in the description.\n`fixup` will forget the commit messages of the fixes and keep the original.\n\n\nYou'll end up with something like this:\n\n\n```\n\npick 4155df1cdc7 Page Navigation View\n\npick c22a3fa0c5c Render navigation partial\n\nfixup 62e858a322 Fix a typo\n\nfixup 5c25eb48c8 Ops another fix\n\nfixup 7f0718efe9 Fix 2\n\nfixup f0ffc19ef7 Argh Another fix!\n\npick aa0a35a867e Add styles for navigation\n\n```\n\n\nSave the changes, exit the editor, and you're done! This is the resulting\nhistory:\n\n\n```\n\npick 4155df1cdc7 Page Navigation View\n\npick 96373c0bcf Render navigation partial\n\npick aa0a35a867e Add styles for navigation\n\n```\n\n\nAs before, all you need to do now is `git push --force-with-lease\n\u003Cremote_name> \u003Cbranch_name>` and the changes are up.\n\n\nIf you want to remove a Git commit from branch altogether, instead of\n`squash` or `fixup`, just write `drop` or simply delete that line.\n\n\n### How to avoid Git commit conflicts\n\n\nTo avoid conflicts, make sure the commits you're moving up the timeline\naren't touching the same files touched by the commits left after them.\n\n\n```\n\npick 4155df1cdc7 Page Navigation View\n\npick c22a3fa0c5c Render navigation partial\n\nfixup 62e858a322 Fix a typo                 # this changes styles.css\n\nfixup 5c25eb48c8 Ops another fix            # this changes image/logo.svg\n\nfixup 7f0718efe9 Fix 2                      # this changes styles.css\n\nfixup f0ffc19ef7 Argh Another fix!          # this changes styles.css\n\npick aa0a35a867e Add styles for navigation  # this changes index.html (no\nconflict)\n\n```\n\n\n### Pro-tip: Quick Git commit `fixup`s\n\n\nIf you know exactly which commit you want to fixup, when committing you\ndon't have to waste brain cycles thinking of good temporary names for \"Fix\n1\", \"Fix 2\", ..., \"Fix 42\".\n\n\n**Step 1: Meet `--fixup`**\n\n\nAfter you've staged the changes fixing whatever it is that needs fixing,\njust Git commit all the changes like this:\n\n\n```\n\ngit commit --fixup c22a3fa0c5c\n\n```\n\n(Note that this is the hash for the commit `c22a3fa0c5c Render navigation\npartial`)\n\n\nThis will generate this commit message: `fixup! Render navigation partial`.\n\n\n**Step 2: And the sidekick `--autosquash`**\n\n\nEasy interactive rebase. You can have `git` place the `fixup`s automatically\nin the right place.\n\n\n`git rebase -i 4155df1cdc7 --autosquash`\n\n\nHistory will be shown like so:\n\n```\n\npick 4155df1cdc7 Page Navigation View\n\npick c22a3fa0c5c Render navigation partial\n\nfixup 62e858a322 Fix a typo\n\nfixup 5c25eb48c8 Ops another fix\n\nfixup 7f0718efe9 Fix 2\n\nfixup f0ffc19ef7 Argh Another fix!\n\npick aa0a35a867e Add styles for navigation\n\n```\n\n\nReady for you to just review and proceed.\n\n\nIf you're feeling adventurous you can do a non-interactive rebase `git\nrebase --autosquash`, but only if you like living dangerously, as you'll\nhave no opportunity to review the squashes being made before they're\napplied.\n\n\n## Situation 4: My Git commit history doesn't make sense, I need a fresh\nstart!\n\n\nIf we're working on a large feature, it is common to have several fixup and\nreview-feedback changes that are being committed frequently. Instead of\nconstantly rebasing the branch, we can leave the cleaning up of Git commits\nuntil the end of development.\n\n\nThis is where creating patch files is extremely handy. In fact, patch files\nwere the primary way of sharing code over email while collaborating on large\nopen source projects before Git-based services like GitLab were available to\ndevelopers. Imagine you have one such branch (eg; `add-page-navigation`)\nwhere there are tons of commits that don't convey the underlying changes\nclearly. Here's how you can create a patch file for all the changes you made\nin this branch:\n\n\n- The first step to create the patch file is to make sure that your branch\nhas all the changes present from `master` branch and has no conflicts with\nthe same.\n\n- You can run `git rebase master` or `git merge master` while you're checked\nout in `add-page-navigation` branch to get all the changes from `master` on\nto your branch.\n\n- Now create the patch file; run `git diff master add-page-navigation >\n~/add_page_navigation.patch`.\n  -  **Command breakdown**: Here we're using Git's _diff_ feature, and asking for a diff between `master` branch and `add-page-navigation` branch, and _redirecting_ the output (via `>` symbol) to a file named `add_page_navigation.patch` in our user home directory (typically `~/` in *nix operating systems).\n- You can specify any path you wish to keep this file in and the file name\nand extension could be anything you want.\n\n- Once the command is run and you don't see any errors, the patch file is\ngenerated.\n\n- Now checkout `master` branch; run `git checkout master`.\n\n- Delete the branch `add-page-navigation` from local repo; run `git branch\n-D add-page-navigation`. Remember, we already have changes of this branch in\na created patch file.\n\n- Now create a new branch with the same name (while `master` is checked\nout); run `git checkout -b add-page-navigation`.\n\n- At this point, this is a fresh branch and doesn't have any of your\nchanges.\n\n- Finally, apply your changes from the patch file; `git apply\n~/add_page_navigation.patch`.\n\n- Here, all of your changes are applied in a branch and they will appear as\nuncommitted, as if all your modification where done, but none of the\nmodifications were actually committed in the branch.\n\n- Now you can go ahead and commit individual files or files grouped by area\nof impact in the order you want with concise commit messages.\n\n\nAs with previous situations, we basically modified the whole branch, so it\nis time to force push!\n\n\n## Git commit history: Conclusion\n\n\nWhile we have covered most common and basic situations that arise in a\nday-to-day workflow with Git, rewriting Git history is a vast topic and as\nyou get familiar with above tips, you can learn more advanced concepts\naround the subject in the [Git Official\nDocumentation](https://git-scm.com/book/en/v2/Git-Tools-Rewriting-History).\nHappy git'ing!\n\n\nPhoto by [pan\nxiaozhen](https://unsplash.com/photos/pj-BrFZ9eAA?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)\non\n[Unsplash](https://unsplash.com/search/photos/clean?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)\n\n{: .note}\n","engineering",[23,24],"git","workflow",{"slug":26,"featured":6,"template":27},"keeping-git-commit-history-clean","BlogPost","content:en-us:blog:keeping-git-commit-history-clean.yml","yaml","Keeping Git Commit History Clean","content","en-us/blog/keeping-git-commit-history-clean.yml","en-us/blog/keeping-git-commit-history-clean","yml",{"_path":36,"_dir":37,"_draft":6,"_partial":6,"_locale":7,"data":38,"_id":460,"_type":29,"title":461,"_source":31,"_file":462,"_stem":463,"_extension":34},"/shared/en-us/main-navigation","en-us",{"logo":39,"freeTrial":44,"sales":49,"login":54,"items":59,"search":391,"minimal":422,"duo":441,"pricingDeployment":450},{"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,202,207,312,372],{"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":184},"Product",true,{"dataNavLevelOne":108},"solutions",{"text":110,"config":111},"View all Solutions",{"href":112,"dataGaName":108,"dataGaLocation":43},"/solutions/",[114,139,163],{"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/security-compliance/","security and compliance","ShieldCheckLight",[148,153,158],{"text":149,"config":150},"Application Security Testing",{"href":151,"dataGaName":152,"dataGaLocation":43},"/solutions/application-security-testing/","Application security testing",{"text":154,"config":155},"Software Supply Chain Security",{"href":156,"dataGaLocation":43,"dataGaName":157},"/solutions/supply-chain/","Software supply chain security",{"text":159,"config":160},"Software Compliance",{"href":161,"dataGaName":162,"dataGaLocation":43},"/solutions/software-compliance/","software compliance",{"title":164,"link":165,"items":170},"Measurement",{"config":166},{"icon":167,"href":168,"dataGaName":169,"dataGaLocation":43},"DigitalTransformation","/solutions/visibility-measurement/","visibility and measurement",[171,175,179],{"text":172,"config":173},"Visibility & Measurement",{"href":168,"dataGaLocation":43,"dataGaName":174},"Visibility and Measurement",{"text":176,"config":177},"Value Stream Management",{"href":178,"dataGaLocation":43,"dataGaName":176},"/solutions/value-stream-management/",{"text":180,"config":181},"Analytics & Insights",{"href":182,"dataGaLocation":43,"dataGaName":183},"/solutions/analytics-and-insights/","Analytics and insights",{"title":185,"items":186},"GitLab for",[187,192,197],{"text":188,"config":189},"Enterprise",{"href":190,"dataGaLocation":43,"dataGaName":191},"/enterprise/","enterprise",{"text":193,"config":194},"Small Business",{"href":195,"dataGaLocation":43,"dataGaName":196},"/small-business/","small business",{"text":198,"config":199},"Public Sector",{"href":200,"dataGaLocation":43,"dataGaName":201},"/solutions/public-sector/","public sector",{"text":203,"config":204},"Pricing",{"href":205,"dataGaName":206,"dataGaLocation":43,"dataNavLevelOne":206},"/pricing/","pricing",{"text":208,"config":209,"link":211,"lists":215,"feature":299},"Resources",{"dataNavLevelOne":210},"resources",{"text":212,"config":213},"View all resources",{"href":214,"dataGaName":210,"dataGaLocation":43},"/resources/",[216,249,271],{"title":217,"items":218},"Getting started",[219,224,229,234,239,244],{"text":220,"config":221},"Install",{"href":222,"dataGaName":223,"dataGaLocation":43},"/install/","install",{"text":225,"config":226},"Quick start guides",{"href":227,"dataGaName":228,"dataGaLocation":43},"/get-started/","quick setup checklists",{"text":230,"config":231},"Learn",{"href":232,"dataGaLocation":43,"dataGaName":233},"https://university.gitlab.com/","learn",{"text":235,"config":236},"Product documentation",{"href":237,"dataGaName":238,"dataGaLocation":43},"https://docs.gitlab.com/","product documentation",{"text":240,"config":241},"Best practice videos",{"href":242,"dataGaName":243,"dataGaLocation":43},"/getting-started-videos/","best practice videos",{"text":245,"config":246},"Integrations",{"href":247,"dataGaName":248,"dataGaLocation":43},"/integrations/","integrations",{"title":250,"items":251},"Discover",[252,257,261,266],{"text":253,"config":254},"Customer success stories",{"href":255,"dataGaName":256,"dataGaLocation":43},"/customers/","customer success stories",{"text":258,"config":259},"Blog",{"href":260,"dataGaName":5,"dataGaLocation":43},"/blog/",{"text":262,"config":263},"Remote",{"href":264,"dataGaName":265,"dataGaLocation":43},"https://handbook.gitlab.com/handbook/company/culture/all-remote/","remote",{"text":267,"config":268},"TeamOps",{"href":269,"dataGaName":270,"dataGaLocation":43},"/teamops/","teamops",{"title":272,"items":273},"Connect",[274,279,284,289,294],{"text":275,"config":276},"GitLab Services",{"href":277,"dataGaName":278,"dataGaLocation":43},"/services/","services",{"text":280,"config":281},"Community",{"href":282,"dataGaName":283,"dataGaLocation":43},"/community/","community",{"text":285,"config":286},"Forum",{"href":287,"dataGaName":288,"dataGaLocation":43},"https://forum.gitlab.com/","forum",{"text":290,"config":291},"Events",{"href":292,"dataGaName":293,"dataGaLocation":43},"/events/","events",{"text":295,"config":296},"Partners",{"href":297,"dataGaName":298,"dataGaLocation":43},"/partners/","partners",{"backgroundColor":300,"textColor":301,"text":302,"image":303,"link":307},"#2f2a6b","#fff","Insights for the future of software development",{"altText":304,"config":305},"the source promo card",{"src":306},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1758208064/dzl0dbift9xdizyelkk4.svg",{"text":308,"config":309},"Read the latest",{"href":310,"dataGaName":311,"dataGaLocation":43},"/the-source/","the source",{"text":313,"config":314,"lists":316},"Company",{"dataNavLevelOne":315},"company",[317],{"items":318},[319,324,330,332,337,342,347,352,357,362,367],{"text":320,"config":321},"About",{"href":322,"dataGaName":323,"dataGaLocation":43},"/company/","about",{"text":325,"config":326,"footerGa":329},"Jobs",{"href":327,"dataGaName":328,"dataGaLocation":43},"/jobs/","jobs",{"dataGaName":328},{"text":290,"config":331},{"href":292,"dataGaName":293,"dataGaLocation":43},{"text":333,"config":334},"Leadership",{"href":335,"dataGaName":336,"dataGaLocation":43},"/company/team/e-group/","leadership",{"text":338,"config":339},"Team",{"href":340,"dataGaName":341,"dataGaLocation":43},"/company/team/","team",{"text":343,"config":344},"Handbook",{"href":345,"dataGaName":346,"dataGaLocation":43},"https://handbook.gitlab.com/","handbook",{"text":348,"config":349},"Investor relations",{"href":350,"dataGaName":351,"dataGaLocation":43},"https://ir.gitlab.com/","investor relations",{"text":353,"config":354},"Trust Center",{"href":355,"dataGaName":356,"dataGaLocation":43},"/security/","trust center",{"text":358,"config":359},"AI Transparency Center",{"href":360,"dataGaName":361,"dataGaLocation":43},"/ai-transparency-center/","ai transparency center",{"text":363,"config":364},"Newsletter",{"href":365,"dataGaName":366,"dataGaLocation":43},"/company/contact/","newsletter",{"text":368,"config":369},"Press",{"href":370,"dataGaName":371,"dataGaLocation":43},"/press/","press",{"text":373,"config":374,"lists":375},"Contact us",{"dataNavLevelOne":315},[376],{"items":377},[378,381,386],{"text":50,"config":379},{"href":52,"dataGaName":380,"dataGaLocation":43},"talk to sales",{"text":382,"config":383},"Get help",{"href":384,"dataGaName":385,"dataGaLocation":43},"/support/","get help",{"text":387,"config":388},"Customer portal",{"href":389,"dataGaName":390,"dataGaLocation":43},"https://customers.gitlab.com/customers/sign_in/","customer portal",{"close":392,"login":393,"suggestions":400},"Close",{"text":394,"link":395},"To search repositories and projects, login to",{"text":396,"config":397},"gitlab.com",{"href":57,"dataGaName":398,"dataGaLocation":399},"search login","search",{"text":401,"default":402},"Suggestions",[403,405,409,411,415,419],{"text":72,"config":404},{"href":77,"dataGaName":72,"dataGaLocation":399},{"text":406,"config":407},"Code Suggestions (AI)",{"href":408,"dataGaName":406,"dataGaLocation":399},"/solutions/code-suggestions/",{"text":124,"config":410},{"href":126,"dataGaName":124,"dataGaLocation":399},{"text":412,"config":413},"GitLab on AWS",{"href":414,"dataGaName":412,"dataGaLocation":399},"/partners/technology-partners/aws/",{"text":416,"config":417},"GitLab on Google Cloud",{"href":418,"dataGaName":416,"dataGaLocation":399},"/partners/technology-partners/google-cloud-platform/",{"text":420,"config":421},"Why GitLab?",{"href":85,"dataGaName":420,"dataGaLocation":399},{"freeTrial":423,"mobileIcon":428,"desktopIcon":433,"secondaryButton":436},{"text":424,"config":425},"Start free trial",{"href":426,"dataGaName":48,"dataGaLocation":427},"https://gitlab.com/-/trials/new/","nav",{"altText":429,"config":430},"Gitlab Icon",{"src":431,"dataGaName":432,"dataGaLocation":427},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1758203874/jypbw1jx72aexsoohd7x.svg","gitlab icon",{"altText":429,"config":434},{"src":435,"dataGaName":432,"dataGaLocation":427},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1758203875/gs4c8p8opsgvflgkswz9.svg",{"text":437,"config":438},"Get Started",{"href":439,"dataGaName":440,"dataGaLocation":427},"https://gitlab.com/-/trial_registrations/new?glm_source=about.gitlab.com/compare/gitlab-vs-github/","get started",{"freeTrial":442,"mobileIcon":446,"desktopIcon":448},{"text":443,"config":444},"Learn more about GitLab Duo",{"href":77,"dataGaName":445,"dataGaLocation":427},"gitlab duo",{"altText":429,"config":447},{"src":431,"dataGaName":432,"dataGaLocation":427},{"altText":429,"config":449},{"src":435,"dataGaName":432,"dataGaLocation":427},{"freeTrial":451,"mobileIcon":456,"desktopIcon":458},{"text":452,"config":453},"Back to pricing",{"href":205,"dataGaName":454,"dataGaLocation":427,"icon":455},"back to pricing","GoBack",{"altText":429,"config":457},{"src":431,"dataGaName":432,"dataGaLocation":427},{"altText":429,"config":459},{"src":435,"dataGaName":432,"dataGaLocation":427},"content:shared:en-us:main-navigation.yml","Main Navigation","shared/en-us/main-navigation.yml","shared/en-us/main-navigation",{"_path":465,"_dir":37,"_draft":6,"_partial":6,"_locale":7,"title":466,"button":467,"image":472,"config":476,"_id":478,"_type":29,"_source":31,"_file":479,"_stem":480,"_extension":34},"/shared/en-us/banner","is now in public beta!",{"text":468,"config":469},"Try the Beta",{"href":470,"dataGaName":471,"dataGaLocation":43},"/gitlab-duo/agent-platform/","duo banner",{"altText":473,"config":474},"GitLab Duo Agent Platform",{"src":475},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1753720689/somrf9zaunk0xlt7ne4x.svg",{"layout":477},"release","content:shared:en-us:banner.yml","shared/en-us/banner.yml","shared/en-us/banner",{"_path":482,"_dir":37,"_draft":6,"_partial":6,"_locale":7,"data":483,"_id":687,"_type":29,"title":688,"_source":31,"_file":689,"_stem":690,"_extension":34},"/shared/en-us/main-footer",{"text":484,"source":485,"edit":491,"contribute":496,"config":501,"items":506,"minimal":679},"Git is a trademark of Software Freedom Conservancy and our use of 'GitLab' is under license",{"text":486,"config":487},"View page source",{"href":488,"dataGaName":489,"dataGaLocation":490},"https://gitlab.com/gitlab-com/marketing/digital-experience/about-gitlab-com/","page source","footer",{"text":492,"config":493},"Edit this page",{"href":494,"dataGaName":495,"dataGaLocation":490},"https://gitlab.com/gitlab-com/marketing/digital-experience/about-gitlab-com/-/blob/main/content/","web ide",{"text":497,"config":498},"Please contribute",{"href":499,"dataGaName":500,"dataGaLocation":490},"https://gitlab.com/gitlab-com/marketing/digital-experience/about-gitlab-com/-/blob/main/CONTRIBUTING.md/","please contribute",{"twitter":502,"facebook":503,"youtube":504,"linkedin":505},"https://twitter.com/gitlab","https://www.facebook.com/gitlab","https://www.youtube.com/channel/UCnMGQ8QHMAnVIsI3xJrihhg","https://www.linkedin.com/company/gitlab-com",[507,530,586,615,649],{"title":61,"links":508,"subMenu":513},[509],{"text":510,"config":511},"DevSecOps platform",{"href":70,"dataGaName":512,"dataGaLocation":490},"devsecops platform",[514],{"title":203,"links":515},[516,520,525],{"text":517,"config":518},"View plans",{"href":205,"dataGaName":519,"dataGaLocation":490},"view plans",{"text":521,"config":522},"Why Premium?",{"href":523,"dataGaName":524,"dataGaLocation":490},"/pricing/premium/","why premium",{"text":526,"config":527},"Why Ultimate?",{"href":528,"dataGaName":529,"dataGaLocation":490},"/pricing/ultimate/","why ultimate",{"title":531,"links":532},"Solutions",[533,538,540,542,547,552,556,559,563,568,570,573,576,581],{"text":534,"config":535},"Digital transformation",{"href":536,"dataGaName":537,"dataGaLocation":490},"/topics/digital-transformation/","digital transformation",{"text":149,"config":539},{"href":151,"dataGaName":149,"dataGaLocation":490},{"text":138,"config":541},{"href":120,"dataGaName":121,"dataGaLocation":490},{"text":543,"config":544},"Agile development",{"href":545,"dataGaName":546,"dataGaLocation":490},"/solutions/agile-delivery/","agile delivery",{"text":548,"config":549},"Cloud transformation",{"href":550,"dataGaName":551,"dataGaLocation":490},"/topics/cloud-native/","cloud transformation",{"text":553,"config":554},"SCM",{"href":134,"dataGaName":555,"dataGaLocation":490},"source code management",{"text":124,"config":557},{"href":126,"dataGaName":558,"dataGaLocation":490},"continuous integration & delivery",{"text":560,"config":561},"Value stream management",{"href":178,"dataGaName":562,"dataGaLocation":490},"value stream management",{"text":564,"config":565},"GitOps",{"href":566,"dataGaName":567,"dataGaLocation":490},"/solutions/gitops/","gitops",{"text":188,"config":569},{"href":190,"dataGaName":191,"dataGaLocation":490},{"text":571,"config":572},"Small business",{"href":195,"dataGaName":196,"dataGaLocation":490},{"text":574,"config":575},"Public sector",{"href":200,"dataGaName":201,"dataGaLocation":490},{"text":577,"config":578},"Education",{"href":579,"dataGaName":580,"dataGaLocation":490},"/solutions/education/","education",{"text":582,"config":583},"Financial services",{"href":584,"dataGaName":585,"dataGaLocation":490},"/solutions/finance/","financial services",{"title":208,"links":587},[588,590,592,594,597,599,601,603,605,607,609,611,613],{"text":220,"config":589},{"href":222,"dataGaName":223,"dataGaLocation":490},{"text":225,"config":591},{"href":227,"dataGaName":228,"dataGaLocation":490},{"text":230,"config":593},{"href":232,"dataGaName":233,"dataGaLocation":490},{"text":235,"config":595},{"href":237,"dataGaName":596,"dataGaLocation":490},"docs",{"text":258,"config":598},{"href":260,"dataGaName":5,"dataGaLocation":490},{"text":253,"config":600},{"href":255,"dataGaName":256,"dataGaLocation":490},{"text":262,"config":602},{"href":264,"dataGaName":265,"dataGaLocation":490},{"text":275,"config":604},{"href":277,"dataGaName":278,"dataGaLocation":490},{"text":267,"config":606},{"href":269,"dataGaName":270,"dataGaLocation":490},{"text":280,"config":608},{"href":282,"dataGaName":283,"dataGaLocation":490},{"text":285,"config":610},{"href":287,"dataGaName":288,"dataGaLocation":490},{"text":290,"config":612},{"href":292,"dataGaName":293,"dataGaLocation":490},{"text":295,"config":614},{"href":297,"dataGaName":298,"dataGaLocation":490},{"title":313,"links":616},[617,619,621,623,625,627,629,633,638,640,642,644],{"text":320,"config":618},{"href":322,"dataGaName":315,"dataGaLocation":490},{"text":325,"config":620},{"href":327,"dataGaName":328,"dataGaLocation":490},{"text":333,"config":622},{"href":335,"dataGaName":336,"dataGaLocation":490},{"text":338,"config":624},{"href":340,"dataGaName":341,"dataGaLocation":490},{"text":343,"config":626},{"href":345,"dataGaName":346,"dataGaLocation":490},{"text":348,"config":628},{"href":350,"dataGaName":351,"dataGaLocation":490},{"text":630,"config":631},"Sustainability",{"href":632,"dataGaName":630,"dataGaLocation":490},"/sustainability/",{"text":634,"config":635},"Diversity, inclusion and belonging (DIB)",{"href":636,"dataGaName":637,"dataGaLocation":490},"/diversity-inclusion-belonging/","Diversity, inclusion and belonging",{"text":353,"config":639},{"href":355,"dataGaName":356,"dataGaLocation":490},{"text":363,"config":641},{"href":365,"dataGaName":366,"dataGaLocation":490},{"text":368,"config":643},{"href":370,"dataGaName":371,"dataGaLocation":490},{"text":645,"config":646},"Modern Slavery Transparency Statement",{"href":647,"dataGaName":648,"dataGaLocation":490},"https://handbook.gitlab.com/handbook/legal/modern-slavery-act-transparency-statement/","modern slavery transparency statement",{"title":650,"links":651},"Contact Us",[652,655,657,659,664,669,674],{"text":653,"config":654},"Contact an expert",{"href":52,"dataGaName":53,"dataGaLocation":490},{"text":382,"config":656},{"href":384,"dataGaName":385,"dataGaLocation":490},{"text":387,"config":658},{"href":389,"dataGaName":390,"dataGaLocation":490},{"text":660,"config":661},"Status",{"href":662,"dataGaName":663,"dataGaLocation":490},"https://status.gitlab.com/","status",{"text":665,"config":666},"Terms of use",{"href":667,"dataGaName":668,"dataGaLocation":490},"/terms/","terms of use",{"text":670,"config":671},"Privacy statement",{"href":672,"dataGaName":673,"dataGaLocation":490},"/privacy/","privacy statement",{"text":675,"config":676},"Cookie preferences",{"dataGaName":677,"dataGaLocation":490,"id":678,"isOneTrustButton":106},"cookie preferences","ot-sdk-btn",{"items":680},[681,683,685],{"text":665,"config":682},{"href":667,"dataGaName":668,"dataGaLocation":490},{"text":670,"config":684},{"href":672,"dataGaName":673,"dataGaLocation":490},{"text":675,"config":686},{"dataGaName":677,"dataGaLocation":490,"id":678,"isOneTrustButton":106},"content:shared:en-us:main-footer.yml","Main Footer","shared/en-us/main-footer.yml","shared/en-us/main-footer",[692],{"_path":693,"_dir":694,"_draft":6,"_partial":6,"_locale":7,"content":695,"config":699,"_id":701,"_type":29,"title":18,"_source":31,"_file":702,"_stem":703,"_extension":34},"/en-us/blog/authors/kushal-pandya","authors",{"name":18,"config":696},{"headshot":697,"ctfId":698},"https://res.cloudinary.com/about-gitlab-com/image/upload/v1749659454/Blog/Author%20Headshots/kushalpandya-headshot.png","kushalpandya",{"template":700},"BlogAuthor","content:en-us:blog:authors:kushal-pandya.yml","en-us/blog/authors/kushal-pandya.yml","en-us/blog/authors/kushal-pandya",{"_path":705,"_dir":37,"_draft":6,"_partial":6,"_locale":7,"header":706,"eyebrow":707,"blurb":708,"button":709,"secondaryButton":713,"_id":715,"_type":29,"title":716,"_source":31,"_file":717,"_stem":718,"_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":710},{"href":711,"dataGaName":48,"dataGaLocation":712},"https://gitlab.com/-/trial_registrations/new?glm_content=default-saas-trial&glm_source=about.gitlab.com/","feature",{"text":50,"config":714},{"href":52,"dataGaName":53,"dataGaLocation":712},"content:shared:en-us:next-steps.yml","Next Steps","shared/en-us/next-steps.yml","shared/en-us/next-steps",1759347849094]