{"id":73390,"date":"2023-07-27T09:00:54","date_gmt":"2023-07-27T16:00:54","guid":{"rendered":"https:\/\/github.blog\/?p=73390"},"modified":"2023-07-27T09:03:15","modified_gmt":"2023-07-27T16:03:15","slug":"scaling-merge-ort-across-github","status":"publish","type":"post","link":"https:\/\/github.blog\/engineering\/infrastructure\/scaling-merge-ort-across-github\/","title":{"rendered":"Scaling merge-ort across GitHub"},"content":{"rendered":"<p>At GitHub, we perform a lot of merges and rebases in the background. For example, when you\u2019re ready to merge your pull request, we already have the resulting merge assembled. Speeding up merge and rebase performance saves both user-visible time and backend resources. Git has recently <a href=\"https:\/\/github.blog\/2021-08-16-highlights-from-git-2-33\/#merge-ort-a-new-merge-strategy\">learned some new tricks<\/a> which we\u2019re using at scale across GitHub. This post walks through what\u2019s changed and how the experience has improved.<\/p>\n<h2 id=\"our-requirements-for-a-merge-strategy\"><a class=\"heading-link\" href=\"#our-requirements-for-a-merge-strategy\">Our requirements for a merge strategy<span class=\"heading-hash pl-2 text-italic text-bold\" aria-hidden=\"true\"><\/span><\/a><\/h2>\n<p>There are a few non-negotiable parts of any merge strategy we want to employ:<\/p>\n<ul>\n<li><strong>It has to be fast.<\/strong> At GitHub\u2019s scale, even a small slowdown is multiplied by the millions of activities going on in repositories we host each day.<\/li>\n<li><strong>It has to be correct.<\/strong> For merge strategies, what\u2019s \u201ccorrect\u201d is occasionally a matter of debate. In those cases, we try to match what users <em>expect<\/em> (which is often whatever the Git command line does).<\/li>\n<li><strong>It can\u2019t check out the repository.<\/strong> There are both scalability and security implications to having a working directory, so we simply don\u2019t.<\/li>\n<\/ul>\n<p><a href=\"https:\/\/github.blog\/2015-12-15-move-fast\/\">Previously<\/a>, we used <code>libgit2<\/code> to tick these boxes: it was faster than <a href=\"https:\/\/git-scm.com\/docs\/merge-strategies#Documentation\/merge-strategies.txt-recursive\">Git\u2019s default merge strategy<\/a> and it didn\u2019t require a working directory. On the correctness front, we either performed the merge <em>or<\/em> reported a merge conflict and halted. However, because of additional code related to<a href=\"https:\/\/public-inbox.org\/git\/539A25BF.4060501@alum.mit.edu\/\"> merge base selection<\/a>, sometimes a user\u2019s local Git could easily merge what our implementation could not. This led to a steady stream of support tickets asking why the GitHub web UI couldn\u2019t merge two files when the local command line could. We weren\u2019t meeting those users\u2019 expectations, so from their perspective, we weren\u2019t correct.<\/p>\n<h2 id=\"a-new-strategy-emerges\"><a class=\"heading-link\" href=\"#a-new-strategy-emerges\">A new strategy emerges<span class=\"heading-hash pl-2 text-italic text-bold\" aria-hidden=\"true\"><\/span><\/a><\/h2>\n<p>Two years ago, Git learned a new merge strategy, <code>merge-ort<\/code>. As the author <a href=\"https:\/\/lore.kernel.org\/git\/4a0f088f3669a95c7f75e885d06c0a3bdaf31f42.1628055482.git.gitgitgadget@gmail.com\/\">details on the mailing list<\/a>, <code>merge-ort<\/code> is fast, correct, and addresses many shortcomings of the older default strategy. Even better, unlike <code>merge-recursive<\/code>, it doesn\u2019t need a working directory. <code>merge-ort<\/code> is much faster even than our optimized, <code>libgit2<\/code>-based strategy. What\u2019s more, <code>merge-ort<\/code> has since become Git\u2019s default. That meant our strategy would fall even further behind on correctness.<\/p>\n<p>It was clear that GitHub needed to upgrade to <code>merge-ort<\/code>. We split this effort into two parts: first deploy <code>merge-ort<\/code> for merges, then deploy it for rebases.<\/p>\n<h2 id=\"merge-ort-for-merges\"><a class=\"heading-link\" href=\"#merge-ort-for-merges\"><code>merge-ort<\/code> for merges<span class=\"heading-hash pl-2 text-italic text-bold\" aria-hidden=\"true\"><\/span><\/a><\/h2>\n<p>Last September, we <a href=\"https:\/\/github.blog\/changelog\/2022-09-12-merge-commits-now-created-using-the-merge-ort-strategy\/\">announced<\/a> that we\u2019re using <code>merge-ort<\/code> for merge commits. We used <a href=\"https:\/\/github.blog\/2016-02-03-scientist\/\">Scientist<\/a> to run <em>both<\/em> code paths in production so we can compare timing, correctness, etc. without risking much. The customer still gets the result of the old code path, while the GitHub feature team gets to compare and contrast the behavior of the new code path. Our process was:<\/p>\n<ol>\n<li>Create and enable a Scientist experiment with the new code path.<\/li>\n<li>Roll it out to a fraction of traffic. In our case, we started with some GitHub-internal repositories first before moving to a percentage-based rollout across all of production.<\/li>\n<li>Measure gains, check correctness, and fix bugs iteratively.<\/li>\n<\/ol>\n<p>We saw dramatic speedups across the board, especially on large, heavily-trafficked repositories. For our own <code>github\/github<\/code> monolith, we saw a 10x speedup in both the average and P99 case. Across the entire experiment, our P50 saw the same 10x speedup and P99 case got nearly a 5x boost.<\/p>\n<p><img data-recalc-dims=\"1\" decoding=\"async\" loading=\"lazy\" src=\"https:\/\/github.blog\/wp-content\/uploads\/2023\/07\/merge-ort-1.png?w=1024&#038;resize=1024%2C459\" alt=\"Chart showing experimental candidate versus control at P50. The candidate implementation fairly consistently stays below 0.1 seconds.\" width=\"1024\" height=\"459\" class=\"aligncenter size-large wp-image-73391 width-fit\" srcset=\"https:\/\/github.blog\/wp-content\/uploads\/2023\/07\/merge-ort-1.png?w=1124 1124w, https:\/\/github.blog\/wp-content\/uploads\/2023\/07\/merge-ort-1.png?w=300 300w, https:\/\/github.blog\/wp-content\/uploads\/2023\/07\/merge-ort-1.png?w=768 768w, https:\/\/github.blog\/wp-content\/uploads\/2023\/07\/merge-ort-1.png?w=1024 1024w\" sizes=\"auto, (max-width: 1000px) 100vw, 1000px\" \/><\/p>\n<p><img data-recalc-dims=\"1\" decoding=\"async\" loading=\"lazy\" src=\"https:\/\/github.blog\/wp-content\/uploads\/2023\/07\/merge-ort-2.png?w=1024&#038;resize=1024%2C458\" alt=\"Chart showing experimental candidate versus control at P99. The candidate implementation follows the same spiky pattern as the control, but its peaks are much lower.\" width=\"1024\" height=\"458\" class=\"aligncenter size-large wp-image-73392 width-fit\" srcset=\"https:\/\/github.blog\/wp-content\/uploads\/2023\/07\/merge-ort-2.png?w=1122 1122w, https:\/\/github.blog\/wp-content\/uploads\/2023\/07\/merge-ort-2.png?w=300 300w, https:\/\/github.blog\/wp-content\/uploads\/2023\/07\/merge-ort-2.png?w=768 768w, https:\/\/github.blog\/wp-content\/uploads\/2023\/07\/merge-ort-2.png?w=1024 1024w\" sizes=\"auto, (max-width: 1000px) 100vw, 1000px\" \/><\/p>\n<p><img data-recalc-dims=\"1\" decoding=\"async\" loading=\"lazy\" src=\"https:\/\/github.blog\/wp-content\/uploads\/2023\/07\/merge-ort-3.png?w=1024&#038;resize=1024%2C216\" alt=\"Dashboard widgets showing P50 average times for experimental candidate versus control. The control averages 71.07 milliseconds while the candidate averages 7.74 milliseconds.\" width=\"1024\" height=\"216\" class=\"aligncenter size-large wp-image-73393 width-fit\" srcset=\"https:\/\/github.blog\/wp-content\/uploads\/2023\/07\/merge-ort-3.png?w=1600 1600w, https:\/\/github.blog\/wp-content\/uploads\/2023\/07\/merge-ort-3.png?w=300 300w, https:\/\/github.blog\/wp-content\/uploads\/2023\/07\/merge-ort-3.png?w=768 768w, https:\/\/github.blog\/wp-content\/uploads\/2023\/07\/merge-ort-3.png?w=1024 1024w, https:\/\/github.blog\/wp-content\/uploads\/2023\/07\/merge-ort-3.png?w=1536 1536w\" sizes=\"auto, (max-width: 1000px) 100vw, 1000px\" \/><\/p>\n<p><img data-recalc-dims=\"1\" decoding=\"async\" loading=\"lazy\" src=\"https:\/\/github.blog\/wp-content\/uploads\/2023\/07\/merge-ort-4.png?w=1024&#038;resize=1024%2C215\" alt=\"Dashboard widgets showing P99 average times for experimental candidate versus control. The control averages 1.63 seconds while the candidate averages 329.82 milliseconds.\" width=\"1024\" height=\"215\" class=\"aligncenter size-large wp-image-73394 width-fit\" srcset=\"https:\/\/github.blog\/wp-content\/uploads\/2023\/07\/merge-ort-4.png?w=1600 1600w, https:\/\/github.blog\/wp-content\/uploads\/2023\/07\/merge-ort-4.png?w=300 300w, https:\/\/github.blog\/wp-content\/uploads\/2023\/07\/merge-ort-4.png?w=768 768w, https:\/\/github.blog\/wp-content\/uploads\/2023\/07\/merge-ort-4.png?w=1024 1024w, https:\/\/github.blog\/wp-content\/uploads\/2023\/07\/merge-ort-4.png?w=1536 1536w\" sizes=\"auto, (max-width: 1000px) 100vw, 1000px\" \/><\/p>\n<h2 id=\"merge-ort-for-rebases\"><a class=\"heading-link\" href=\"#merge-ort-for-rebases\"><code>merge-ort<\/code> for rebases<span class=\"heading-hash pl-2 text-italic text-bold\" aria-hidden=\"true\"><\/span><\/a><\/h2>\n<p>Like merges, we also do a huge number of rebases. Customers may choose <a href=\"https:\/\/docs.github.com\/pull-requests\/collaborating-with-pull-requests\/proposing-changes-to-your-work-with-pull-requests\/keeping-your-pull-request-in-sync-with-the-base-branch#updating-your-pull-request-branch\">rebase workflows<\/a> in their pull requests. We also perform test rebases and other \u201cbehind the scenes\u201d operations, so we also<a href=\"https:\/\/github.blog\/changelog\/2023-06-28-rebase-commits-now-created-using-the-merge-ort-strategy\/\"> brought merge-ort to rebases<\/a>.<\/p>\n<p>This time around, we powered rebases using a new Git subcommand: <code>git-replay<\/code>. <code>git replay<\/code> was written by the original author of <code>merge-ort<\/code>, <a href=\"https:\/\/github.com\/newren\">Elijah Newren<\/a> (a prolific Git contributor). With this tool, we could perform rebases using <code>merge-ort<\/code> and without needing a worktree. Once again, the path was pretty similar:<\/p>\n<ol>\n<li>Merge <code>git-replay<\/code> into our fork of Git. (We were running the experiment with Git 2.39, which didn\u2019t include the <code>git-replay<\/code> feature.)<\/li>\n<li>Before shipping, leverage our test suite to detect discrepancies between the old and the new implementations.<\/li>\n<li>Write automation to flush out bugs by performing test rebases of all open pull requests in <code>github\/github<\/code> and comparing the results.<\/li>\n<li>Set up a Scientist experiment to measure the performance delta between <code>libgit2<\/code>-powered rebases and monitor for unexpected mismatches in behavior.<\/li>\n<li>Measure gains, check correctness, and fix bugs iteratively.<\/li>\n<\/ol>\n<p>Once again, we were amazed at the results. The following is a  great anecdote from testing, as relayed by <a href=\"https:\/\/github.com\/wincent\">@wincent<\/a> (one of the GitHub engineers on this project):<\/p>\n<blockquote><p>Another way to think of this is in terms of resource usage. We ran the experiment over 730k times. In that interval, our computers spent 2.56 hours performing rebases with <code>libgit2<\/code>, but under 10 minutes doing the same work with <code>merge-ort<\/code>. And this was running the experiment for 0.5% of actors. Extrapolating those numbers out to 100%, if we had done all rebases during that interval with <code>merge-ort<\/code>, it would have taken us 2,000 minutes, or about 33 hours. That same work done with <code>libgit2<\/code> would have taken 512 hours!<\/p><\/blockquote>\n<h2 id=\"whats-next\"><a class=\"heading-link\" href=\"#whats-next\">What\u2019s next<span class=\"heading-hash pl-2 text-italic text-bold\" aria-hidden=\"true\"><\/span><\/a><\/h2>\n<p>While we\u2019ve covered the most common uses, this is not the end of the story for <code>merge-ort<\/code> at GitHub. There are still other places in which we can leverage its superpowers to bring better performance, greater accuracy, and improved availability. Squashing and reverting are on our radar for the future, as well as considering what new product features it could unlock down the road.<\/p>\n<h3 id=\"appreciation\"><a class=\"heading-link\" href=\"#appreciation\">Appreciation<span class=\"heading-hash pl-2 text-italic text-bold\" aria-hidden=\"true\"><\/span><\/a><\/h3>\n<p>Many thanks to all the GitHub folks who worked on these two projects. Also, GitHub continues to be grateful for the hundreds of volunteer contributors to the Git open source project, including <a href=\"https:\/\/github.com\/newren\">Elijah Newren<\/a> for designing, implementing, and continually improving <code>merge-ort<\/code>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>GitHub switched to performing merges and rebases using merge-ort. Come behind the scenes to see why and how we made this change.<\/p>\n","protected":false},"author":1914,"featured_media":73018,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_gh_post_show_toc":"no","_gh_post_is_no_robots":"no","_gh_post_is_featured":"no","_gh_post_is_excluded":"no","_gh_post_is_unlisted":"no","_gh_post_related_link_1":"","_gh_post_related_link_2":"","_gh_post_related_link_3":"","_gh_post_sq_img":"https:\/\/github.blog\/wp-content\/uploads\/2023\/03\/git-240-1.png","_gh_post_sq_img_id":"70712","_gh_post_cta_title":"","_gh_post_cta_text":"","_gh_post_cta_link":"","_gh_post_cta_button":"Click Here to Learn More","_gh_post_recirc_hide":"no","_gh_post_recirc_col_1":"gh-auto-select","_gh_post_recirc_col_2":"65301","_gh_post_recirc_col_3":"65308","_gh_post_recirc_col_4":"65316","_featured_video":"","_gh_post_additional_query_params":"","_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_feature_clip_id":0,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_publicize_message":"{title}\n\n{excerpt}\n\n{url}","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":true,"jetpack_social_options":{"image_generator_settings":{"template":"highway","default_image_id":0,"font":"","enabled":false},"version":2},"_wpas_customize_per_network":false,"jetpack_post_was_ever_published":false,"_links_to":"","_links_to_target":""},"categories":[72,3309],"tags":[132,2944,2992],"coauthors":[1989],"class_list":["post-73390","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-engineering","category-infrastructure","tag-git","tag-how-github-builds-github","tag-scale"],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v28.6 (Yoast SEO v28.6) - https:\/\/yoast.com\/product\/yoast-seo-premium-wordpress\/ -->\n<title>Scaling merge-ort across GitHub - The GitHub Blog<\/title>\n<meta name=\"description\" content=\"GitHub switched to performing merges and rebases using merge-ort. Come behind the scenes to see why and how we made this change.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/github.blog\/engineering\/infrastructure\/scaling-merge-ort-across-github\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Scaling merge-ort across GitHub\" \/>\n<meta property=\"og:description\" content=\"GitHub switched to performing merges and rebases using merge-ort. Come behind the scenes to see why and how we made this change.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/github.blog\/engineering\/infrastructure\/scaling-merge-ort-across-github\/\" \/>\n<meta property=\"og:site_name\" content=\"The GitHub Blog\" \/>\n<meta property=\"article:published_time\" content=\"2023-07-27T16:00:54+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2023-07-27T16:03:15+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/github.blog\/wp-content\/uploads\/2023\/07\/Open-Source-Engineering@2x.png?fit=2400%2C1260\" \/>\n\t<meta property=\"og:image:width\" content=\"2400\" \/>\n\t<meta property=\"og:image:height\" content=\"1260\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"author\" content=\"Matt Cooper\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Matt Cooper\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"5 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/github.blog\\\/engineering\\\/infrastructure\\\/scaling-merge-ort-across-github\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/github.blog\\\/engineering\\\/infrastructure\\\/scaling-merge-ort-across-github\\\/\"},\"author\":{\"name\":\"Matt Cooper\",\"@id\":\"https:\\\/\\\/github.blog\\\/#\\\/schema\\\/person\\\/adfc69d83d14fd2c3b32253199f1038f\"},\"headline\":\"Scaling merge-ort across GitHub\",\"datePublished\":\"2023-07-27T16:00:54+00:00\",\"dateModified\":\"2023-07-27T16:03:15+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/github.blog\\\/engineering\\\/infrastructure\\\/scaling-merge-ort-across-github\\\/\"},\"wordCount\":925,\"image\":{\"@id\":\"https:\\\/\\\/github.blog\\\/engineering\\\/infrastructure\\\/scaling-merge-ort-across-github\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/github.blog\\\/wp-content\\\/uploads\\\/2023\\\/07\\\/Open-Source-Engineering@2x.png?fit=2400%2C1260\",\"keywords\":[\"Git\",\"How GitHub builds GitHub\",\"scale\"],\"articleSection\":[\"Engineering\",\"Infrastructure\"],\"inLanguage\":\"en-US\"},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/github.blog\\\/engineering\\\/infrastructure\\\/scaling-merge-ort-across-github\\\/\",\"url\":\"https:\\\/\\\/github.blog\\\/engineering\\\/infrastructure\\\/scaling-merge-ort-across-github\\\/\",\"name\":\"Scaling merge-ort across GitHub - The GitHub Blog\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/github.blog\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/github.blog\\\/engineering\\\/infrastructure\\\/scaling-merge-ort-across-github\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/github.blog\\\/engineering\\\/infrastructure\\\/scaling-merge-ort-across-github\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/github.blog\\\/wp-content\\\/uploads\\\/2023\\\/07\\\/Open-Source-Engineering@2x.png?fit=2400%2C1260\",\"datePublished\":\"2023-07-27T16:00:54+00:00\",\"dateModified\":\"2023-07-27T16:03:15+00:00\",\"author\":{\"@id\":\"https:\\\/\\\/github.blog\\\/#\\\/schema\\\/person\\\/adfc69d83d14fd2c3b32253199f1038f\"},\"description\":\"GitHub switched to performing merges and rebases using merge-ort. Come behind the scenes to see why and how we made this change.\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/github.blog\\\/engineering\\\/infrastructure\\\/scaling-merge-ort-across-github\\\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/github.blog\\\/engineering\\\/infrastructure\\\/scaling-merge-ort-across-github\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/github.blog\\\/engineering\\\/infrastructure\\\/scaling-merge-ort-across-github\\\/#primaryimage\",\"url\":\"https:\\\/\\\/github.blog\\\/wp-content\\\/uploads\\\/2023\\\/07\\\/Open-Source-Engineering@2x.png?fit=2400%2C1260\",\"contentUrl\":\"https:\\\/\\\/github.blog\\\/wp-content\\\/uploads\\\/2023\\\/07\\\/Open-Source-Engineering@2x.png?fit=2400%2C1260\",\"width\":2400,\"height\":1260},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/github.blog\\\/engineering\\\/infrastructure\\\/scaling-merge-ort-across-github\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/github.blog\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Engineering\",\"item\":\"https:\\\/\\\/github.blog\\\/engineering\\\/\"},{\"@type\":\"ListItem\",\"position\":3,\"name\":\"Infrastructure\",\"item\":\"https:\\\/\\\/github.blog\\\/engineering\\\/infrastructure\\\/\"},{\"@type\":\"ListItem\",\"position\":4,\"name\":\"Scaling merge-ort across GitHub\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/github.blog\\\/#website\",\"url\":\"https:\\\/\\\/github.blog\\\/\",\"name\":\"The GitHub Blog\",\"description\":\"Updates, ideas, and inspiration from GitHub to help developers build and design software.\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/github.blog\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/github.blog\\\/#\\\/schema\\\/person\\\/adfc69d83d14fd2c3b32253199f1038f\",\"name\":\"Matt Cooper\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/38d57f197fa1b710a53b4c3a2683a6d9fd58542ffc371d7c2599a5875f56cb2a?s=96&d=mm&r=gff8fb540eaf8516c1a2b82d2af61d103\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/38d57f197fa1b710a53b4c3a2683a6d9fd58542ffc371d7c2599a5875f56cb2a?s=96&d=mm&r=g\",\"contentUrl\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/38d57f197fa1b710a53b4c3a2683a6d9fd58542ffc371d7c2599a5875f56cb2a?s=96&d=mm&r=g\",\"caption\":\"Matt Cooper\"},\"url\":\"https:\\\/\\\/github.blog\\\/author\\\/vtbassmatt\\\/\"}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"Scaling merge-ort across GitHub - The GitHub Blog","description":"GitHub switched to performing merges and rebases using merge-ort. Come behind the scenes to see why and how we made this change.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/github.blog\/engineering\/infrastructure\/scaling-merge-ort-across-github\/","og_locale":"en_US","og_type":"article","og_title":"Scaling merge-ort across GitHub","og_description":"GitHub switched to performing merges and rebases using merge-ort. Come behind the scenes to see why and how we made this change.","og_url":"https:\/\/github.blog\/engineering\/infrastructure\/scaling-merge-ort-across-github\/","og_site_name":"The GitHub Blog","article_published_time":"2023-07-27T16:00:54+00:00","article_modified_time":"2023-07-27T16:03:15+00:00","og_image":[{"width":2400,"height":1260,"url":"https:\/\/github.blog\/wp-content\/uploads\/2023\/07\/Open-Source-Engineering@2x.png?fit=2400%2C1260","type":"image\/png"}],"author":"Matt Cooper","twitter_card":"summary_large_image","twitter_misc":{"Written by":"Matt Cooper","Est. reading time":"5 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/github.blog\/engineering\/infrastructure\/scaling-merge-ort-across-github\/#article","isPartOf":{"@id":"https:\/\/github.blog\/engineering\/infrastructure\/scaling-merge-ort-across-github\/"},"author":{"name":"Matt Cooper","@id":"https:\/\/github.blog\/#\/schema\/person\/adfc69d83d14fd2c3b32253199f1038f"},"headline":"Scaling merge-ort across GitHub","datePublished":"2023-07-27T16:00:54+00:00","dateModified":"2023-07-27T16:03:15+00:00","mainEntityOfPage":{"@id":"https:\/\/github.blog\/engineering\/infrastructure\/scaling-merge-ort-across-github\/"},"wordCount":925,"image":{"@id":"https:\/\/github.blog\/engineering\/infrastructure\/scaling-merge-ort-across-github\/#primaryimage"},"thumbnailUrl":"https:\/\/github.blog\/wp-content\/uploads\/2023\/07\/Open-Source-Engineering@2x.png?fit=2400%2C1260","keywords":["Git","How GitHub builds GitHub","scale"],"articleSection":["Engineering","Infrastructure"],"inLanguage":"en-US"},{"@type":"WebPage","@id":"https:\/\/github.blog\/engineering\/infrastructure\/scaling-merge-ort-across-github\/","url":"https:\/\/github.blog\/engineering\/infrastructure\/scaling-merge-ort-across-github\/","name":"Scaling merge-ort across GitHub - The GitHub Blog","isPartOf":{"@id":"https:\/\/github.blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/github.blog\/engineering\/infrastructure\/scaling-merge-ort-across-github\/#primaryimage"},"image":{"@id":"https:\/\/github.blog\/engineering\/infrastructure\/scaling-merge-ort-across-github\/#primaryimage"},"thumbnailUrl":"https:\/\/github.blog\/wp-content\/uploads\/2023\/07\/Open-Source-Engineering@2x.png?fit=2400%2C1260","datePublished":"2023-07-27T16:00:54+00:00","dateModified":"2023-07-27T16:03:15+00:00","author":{"@id":"https:\/\/github.blog\/#\/schema\/person\/adfc69d83d14fd2c3b32253199f1038f"},"description":"GitHub switched to performing merges and rebases using merge-ort. Come behind the scenes to see why and how we made this change.","breadcrumb":{"@id":"https:\/\/github.blog\/engineering\/infrastructure\/scaling-merge-ort-across-github\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/github.blog\/engineering\/infrastructure\/scaling-merge-ort-across-github\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/github.blog\/engineering\/infrastructure\/scaling-merge-ort-across-github\/#primaryimage","url":"https:\/\/github.blog\/wp-content\/uploads\/2023\/07\/Open-Source-Engineering@2x.png?fit=2400%2C1260","contentUrl":"https:\/\/github.blog\/wp-content\/uploads\/2023\/07\/Open-Source-Engineering@2x.png?fit=2400%2C1260","width":2400,"height":1260},{"@type":"BreadcrumbList","@id":"https:\/\/github.blog\/engineering\/infrastructure\/scaling-merge-ort-across-github\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/github.blog\/"},{"@type":"ListItem","position":2,"name":"Engineering","item":"https:\/\/github.blog\/engineering\/"},{"@type":"ListItem","position":3,"name":"Infrastructure","item":"https:\/\/github.blog\/engineering\/infrastructure\/"},{"@type":"ListItem","position":4,"name":"Scaling merge-ort across GitHub"}]},{"@type":"WebSite","@id":"https:\/\/github.blog\/#website","url":"https:\/\/github.blog\/","name":"The GitHub Blog","description":"Updates, ideas, and inspiration from GitHub to help developers build and design software.","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/github.blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Person","@id":"https:\/\/github.blog\/#\/schema\/person\/adfc69d83d14fd2c3b32253199f1038f","name":"Matt Cooper","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/secure.gravatar.com\/avatar\/38d57f197fa1b710a53b4c3a2683a6d9fd58542ffc371d7c2599a5875f56cb2a?s=96&d=mm&r=gff8fb540eaf8516c1a2b82d2af61d103","url":"https:\/\/secure.gravatar.com\/avatar\/38d57f197fa1b710a53b4c3a2683a6d9fd58542ffc371d7c2599a5875f56cb2a?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/38d57f197fa1b710a53b4c3a2683a6d9fd58542ffc371d7c2599a5875f56cb2a?s=96&d=mm&r=g","caption":"Matt Cooper"},"url":"https:\/\/github.blog\/author\/vtbassmatt\/"}]}},"jetpack_publicize_connections":[],"jetpack_shortlink":"https:\/\/wp.me\/pamS32-j5I","jetpack_sharing_enabled":true,"jetpack_featured_media_url":"https:\/\/github.blog\/wp-content\/uploads\/2023\/07\/Open-Source-Engineering@2x.png?fit=2400%2C1260","_links":{"self":[{"href":"https:\/\/github.blog\/wp-json\/wp\/v2\/posts\/73390","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/github.blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/github.blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/github.blog\/wp-json\/wp\/v2\/users\/1914"}],"replies":[{"embeddable":true,"href":"https:\/\/github.blog\/wp-json\/wp\/v2\/comments?post=73390"}],"version-history":[{"count":4,"href":"https:\/\/github.blog\/wp-json\/wp\/v2\/posts\/73390\/revisions"}],"predecessor-version":[{"id":73396,"href":"https:\/\/github.blog\/wp-json\/wp\/v2\/posts\/73390\/revisions\/73396"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/github.blog\/wp-json\/wp\/v2\/media\/73018"}],"wp:attachment":[{"href":"https:\/\/github.blog\/wp-json\/wp\/v2\/media?parent=73390"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/github.blog\/wp-json\/wp\/v2\/categories?post=73390"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/github.blog\/wp-json\/wp\/v2\/tags?post=73390"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/github.blog\/wp-json\/wp\/v2\/coauthors?post=73390"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}