{"id":12631,"date":"2016-03-15T13:50:30","date_gmt":"2016-03-15T13:50:30","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/visualstudioalm\/?p=12631"},"modified":"2019-02-14T17:36:16","modified_gmt":"2019-02-15T01:36:16","slug":"squash-a-whole-new-way-to-merge-pull-requests","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/devops\/squash-a-whole-new-way-to-merge-pull-requests\/","title":{"rendered":"Squash: A Whole New Way to Merge Pull Requests"},"content":{"rendered":"<p>Are you the type of developer that loves to keep your repos neat and tidy? \u00a0Are you a fan of interactive rebase and fixing up your commits until they&#8217;re just right? \u00a0Do you wish you had an alternative to &#8211;no-ff merges when completing your pull request? \u00a0In the <a href=\"https:\/\/www.visualstudio.com\/news\/2016-mar-3-vso\">March 3rd\u00a0release<\/a>\u00a0of Visual Studio Team Services, a new option was added to the PR merge process to allow the topic branch changes to be squash merged, greatly simplifying target branch history.<\/p>\n<h2>What is squash merge?<\/h2>\n<p>A squash merge is a merge option in Git that will produce a merge commit with only one parent. \u00a0The files are\u00a0merged exactly as they would be in a normal merge, but the commit metadata is changed to show only one of the parent commits. \u00a0The result is a single commit on the target branch with all of the changes from a normal merge.<\/p>\n<h2>Why would I use a squash merge?<\/h2>\n<p>Simply put, a squash merge produces a cleaner history. \u00a0When working with topic branches, and especially when responding to code review feedback, a small change can easily grow to span multiple commits. \u00a0Interactive rebasing and force pushing is often the way to clean up these intermediate commits, but even then a new merge commit is created if you&#8217;re using pull requests and merging on the server.<\/p>\n<p>When it comes to merging and history graphs,\u00a0I think illustrations are really helpful. \u00a0So, let&#8217;s suppose I had a repo with a master branch and a topic branch, with a graph that looked like this:<\/p>\n<p style=\"padding-left: 30px\"><a href=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/6\/2019\/05\/Branches-topic-master.png\"><img decoding=\"async\" class=\"alignnone size-full wp-image-13244\" src=\"https:\/\/devblogs.microsoft.com\/devops\/wp-content\/uploads\/sites\/6\/2016\/03\/Branches-topic-master.png\" alt=\"A git graph with a master and topic branch, before merging\" width=\"407\" height=\"350\" \/><\/a><\/p>\n<p>&nbsp;<\/p>\n<p>Now, let&#8217;s suppose I created two copies of this repo. \u00a0In the first repo, I&#8217;ll perform a normal merge of of topic into master.<\/p>\n<pre>    git checkout master \n    git merge topic\n<\/pre>\n<p>That results in a graph that looks like this:<\/p>\n<p style=\"padding-left: 30px\"><a href=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/6\/2019\/05\/regular-merge.png\"><img decoding=\"async\" class=\"alignnone size-full wp-image-13234\" src=\"https:\/\/devblogs.microsoft.com\/devops\/wp-content\/uploads\/sites\/6\/2016\/03\/regular-merge.png\" alt=\"A git graph with a master and topic branch, after a normal merge\" width=\"532\" height=\"350\" \/><\/a><\/p>\n<p>As expected, the new merge commit F is created, and it has two parents: E from master, and D from topic. \u00a0This is the same graph that you would expect if you perform a normal pull request merge.<\/p>\n<p>Now, let&#8217;s go to the second repo, and instead, I&#8217;ll perform a squash merge.<\/p>\n<pre>    git checkout master \n    git merge --squash topic\n<\/pre>\n<p>That results in a graph that looks like this:<\/p>\n<p style=\"padding-left: 30px\"><a href=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/6\/2019\/05\/squash-merge.png\"><img decoding=\"async\" class=\"alignnone size-full wp-image-13224\" src=\"https:\/\/devblogs.microsoft.com\/devops\/wp-content\/uploads\/sites\/6\/2016\/03\/squash-merge.png\" alt=\"A git graph with a master and topic branch, after a squash merge\" width=\"533\" height=\"352\" \/><\/a><\/p>\n<p>There is a new commit that is created, F&#8217; but it only has one parent: E from master. \u00a0At a glance, this doesn&#8217;t look like a merge at all. \u00a0However, the contents of F&#8217; will contain the contents from both master and topic. \u00a0If you were to\u00a0compare the contents of F and F&#8217; you would see that they in fact contain the exact same contents &#8211; only the metadata is different. \u00a0It&#8217;s worth noting that the commits B and D won&#8217;t be reachable from the master branch, and if you delete the topic branch, they&#8217;ll be orphaned. \u00a0But don&#8217;t worry, the file changes have been merged so none of the content is lost.<\/p>\n<p>If you&#8217;re playing along at home, try running this command in each repo and comparing the output:<\/p>\n<pre>    git cat-file -p &lt;commit ID&gt;\n<\/pre>\n<p>The trees will be identical for the two merge commits, and the repo with the squash merge will only have one parent commit.<\/p>\n<h2>Squash merging when completing your PR<\/h2>\n<p>The example above shows how you can use the git command line to squash merge changes into a branch, but if you&#8217;re working on a team that&#8217;s using pull requests, it&#8217;s not much help. \u00a0This is where the new squash merge option in pull requests comes in.<\/p>\n<p>Using this option is easy &#8211; your workflow remains unchanged up until the point you&#8217;re ready to merge your PR. \u00a0On the merge dialog, check the &#8220;Squash changes when merging&#8221; option and the server side merge will use the &#8211;squash option.<\/p>\n<p style=\"padding-left: 30px\">\u00a0<a href=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/6\/2019\/05\/merge-dialog-with-squash.png\"><img decoding=\"async\" class=\"alignnone size-full wp-image-13253\" src=\"https:\/\/devblogs.microsoft.com\/devops\/wp-content\/uploads\/sites\/6\/2016\/03\/merge-dialog-with-squash.png\" alt=\"Squash merge option in pull request\" width=\"562\" height=\"427\" \/><\/a><\/p>\n<p>That&#8217;s it. \u00a0Your git graph will now be clean and simple.<\/p>\n<p>Happy merging!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Are you the type of developer that loves to keep your repos neat and tidy? \u00a0Are you a fan of interactive rebase and fixing up your commits until they&#8217;re just right? \u00a0Do you wish you had an alternative to &#8211;no-ff merges when completing your pull request? \u00a0In the March 3rd\u00a0release\u00a0of Visual Studio Team Services, a [&hellip;]<\/p>\n","protected":false},"author":198,"featured_media":45953,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1,225],"tags":[],"class_list":["post-12631","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-devops","category-git"],"acf":[],"blog_post_summary":"<p>Are you the type of developer that loves to keep your repos neat and tidy? \u00a0Are you a fan of interactive rebase and fixing up your commits until they&#8217;re just right? \u00a0Do you wish you had an alternative to &#8211;no-ff merges when completing your pull request? \u00a0In the March 3rd\u00a0release\u00a0of Visual Studio Team Services, a [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/devops\/wp-json\/wp\/v2\/posts\/12631","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/devops\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/devops\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/devops\/wp-json\/wp\/v2\/users\/198"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/devops\/wp-json\/wp\/v2\/comments?post=12631"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/devops\/wp-json\/wp\/v2\/posts\/12631\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/devops\/wp-json\/wp\/v2\/media\/45953"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/devops\/wp-json\/wp\/v2\/media?parent=12631"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/devops\/wp-json\/wp\/v2\/categories?post=12631"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/devops\/wp-json\/wp\/v2\/tags?post=12631"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}