{"id":102485,"date":"2019-05-09T07:00:00","date_gmt":"2019-05-09T14:00:00","guid":{"rendered":"http:\/\/devblogs.microsoft.com\/oldnewthing\/?p=102485"},"modified":"2020-07-02T07:31:49","modified_gmt":"2020-07-02T14:31:49","slug":"20190509-00","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20190509-00\/?p=102485","title":{"rendered":"Mundane git commit-tree tricks, Part 4: Changing a squash to a merge"},"content":{"rendered":"<p>Suppose you performed a <code>git merge --squash<\/code>, and then later realized that you meant it to be a true merge rather than a squash merge.<\/p>\n<p>In diagrams, suppose you have this:<\/p>\n<div id=\"p20190509_head\" style=\"display: none;\">\u00a0<\/div>\n<div id=\"p20190509_defs\" style=\"height: 0;\">\u00a0<\/div>\n<table style=\"text-align: center;\" title=\"Described in text.\" border=\"0\" cellspacing=\"1\">\n<tbody>\n<tr>\n<td style=\"border: solid 1px black; width: 50px; font-size: 120%;\">A<\/td>\n<td id=\"p20190509_larr\">\u2190<\/td>\n<td style=\"border: solid 1px black; width: 50px; font-size: 120%;\">M1<\/td>\n<td id=\"p20190509_larr3\" colspan=\"3\">\u2190 \u2190 \u2190<\/td>\n<td style=\"border: solid 1px black; width: 50px; font-size: 120%;\">M2<\/td>\n<td>&nbsp;<\/td>\n<td>master<\/td>\n<\/tr>\n<tr>\n<td>&nbsp;<\/td>\n<td id=\"p20190509_nwarr\">\u2196\ufe0e<\/td>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td id=\"p20190509_swarrd\">\u22f0<\/td>\n<\/tr>\n<tr>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td style=\"border: solid 1px black; width: 50px; font-size: 120%;\">F1<\/td>\n<td id=\"p20190509_larr\">\u2190<\/td>\n<td style=\"border: solid 1px black; width: 50px; font-size: 120%;\">F2<\/td>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td>feature<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>From a starting commit A, the master branch continues with a commit M1. From that same starting commit A, a feature branch adds commits F1 and F2. Now you decide to take the feature branch into the master branch, and you resolve the merge as a squash. This means that the resulting commit M2 technically has only a single parent M1. The other alleged parent F2 is just a dotted line, indicating that it is just a figment of your imagination.<\/p>\n<p>You then realize that you should have accepted the feature branch as a true merge rather than a squash. What can you do?<\/p>\n<p>Naturally, you could hard reset the master branch back to M1 and redo the merge. But that means you have to redo all the merge conflicts, and that may have been quite an ordeal. And if that was a large merge, then even in the absence of conflicts, you still have a lot of files being churned in your working directory.<\/p>\n<p>Much faster is simply to create the commit you want and reset to it.<\/p>\n<pre>git commit-tree HEAD^{tree} -p HEAD~ -p F2 -m comment\r\n<\/pre>\n<p><b>Note<\/b>: If using the Windows <code>CMD<\/code> command prompt, you need to type<\/p>\n<pre>git commit-tree HEAD^^{tree} -p HEAD~ -p F2 -m comment\r\n<\/pre>\n<p>for reasons discussed earlier.<\/p>\n<p>This creates a tree identical to what is currently checked in (which is the merge result), whose parents are M1 and F2. In other words, it colors in the dotted line.<\/p>\n<table style=\"text-align: center;\" title=\"Described in text.\" border=\"0\" cellspacing=\"1\">\n<tbody>\n<tr>\n<td style=\"border: solid 1px black; width: 50px; font-size: 120%;\">A<\/td>\n<td id=\"p20190509_larr\">\u2190<\/td>\n<td style=\"border: solid 1px black; width: 50px; font-size: 120%;\">M1<\/td>\n<td id=\"p20190509_larr3\" colspan=\"3\">\u2190 \u2190 \u2190<\/td>\n<td style=\"border: solid 1px black; width: 50px; font-size: 120%;\">*<\/td>\n<td>&nbsp;<\/td>\n<td>master<\/td>\n<\/tr>\n<tr>\n<td>&nbsp;<\/td>\n<td id=\"p20190509_nwarr\">\u2196\ufe0e<\/td>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td id=\"p20190509_swarr\">\u2199\ufe0e<\/td>\n<\/tr>\n<tr>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td style=\"border: solid 1px black; width: 50px; font-size: 120%;\">F1<\/td>\n<td id=\"p20190509_larr\">\u2190<\/td>\n<td style=\"border: solid 1px black; width: 50px; font-size: 120%;\">F2<\/td>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td>&nbsp;<\/td>\n<td>feature<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>The result of the <code>git commit-tree<\/code> command is a hash printed to stdout. You can <code>git reset<\/code> to that hash to make that the branch head.<\/p>\n<p>\n<script>\nwindow.addEventListener(\"load\", function() {\n  var fullFF = getComputedStyle(document.body).fontFamily;\n  var simpleFF = fullFF.replace(\/ Emoji\/g, \"\");\n  \/\/ break up \"style\" to prevent wordpress from injecting random junk\n  document.getElementById(\"p20190509_head\").innerHTML =\n`<s` + `tyle>\nbody { font-family: ${simpleFF}; }\n.emoji { font-family: ${fullFF}; }\n<\/s` + `tyle>`;\n}); \/\/ wacky comment to prevent wordpress from injecting random junk\n(function() {\n  var svg = {\n    defs: `<svg width=\"0\" height=\"0\">\n <defs>\n  <marker id=\"arrowhead\" markerWidth=\"5\" markerHeight=\"5\" refX=\"-2\" refY=\"0\"\n    viewBox=\"-6 -6 12 12\" orient=\"auto\">\n    <polygon points=\"-2,0 -5,5 5,0 -5,-5\" fill=\"black\" stroke=\"black\"\n      stroke-dasharray=\"1 0\" \/>\n  <\/marker>\n  <path id=\"larr\" d=\"M20,10 L3,10\" stroke=\"black\"\n   marker-end=\"url(#arrowhead)\" \/>\n  <path id=\"larr3\" d=\"M98,10 L3,10\" stroke=\"black\"\n   marker-end=\"url(#arrowhead)\" \/>\n  <path id=\"nwarr\" d=\"M20,20 L3,3\" stroke=\"black\"\n   marker-end=\"url(#arrowhead)\" \/>\n  <path id=\"swarr\" d=\"M20,2 L3,17\" stroke=\"black\"\n   marker-end=\"url(#arrowhead)\" \/>\n  <path id=\"swarrd\" d=\"M20,0 L3,17\" stroke=\"black\" stroke-dasharray=\"4 2\"\n   marker-end=\"url(#arrowhead)\" \/>\n <\/defs>\n<\/svg>`,\n    larr: `<svg width=\"20\" height=\"20\"><use href=\"#larr\"\/><\/svg>`,\n    larr3: `<svg width=\"98\" height=\"20\"><use href=\"#larr3\"\/><\/svg>`,\n    nwarr: `<svg width=\"20\" height=\"20\"><use href=\"#nwarr\"\/><\/svg>`,\n    swarrd: `<svg width=\"20\" height=\"20\"><use href=\"#swarrd\"\/><\/svg>`,\n    swarr: `<svg width=\"20\" height=\"20\"><use href=\"#swarr\"\/><\/svg>`\n  };\n  Object.keys(svg).forEach(function (key) {\n    Array.prototype.forEach.call(document.querySelectorAll(\"#p20190509_\" + key),\n      function (e) {\n        e.innerHTML = svg[key];\n      });\n  });\n})();\n<\/script><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Retroactively removing a command line switch.<\/p>\n","protected":false},"author":1069,"featured_media":111744,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[26],"class_list":["post-102485","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-other"],"acf":[],"blog_post_summary":"<p>Retroactively removing a command line switch.<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/102485","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/users\/1069"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/comments?post=102485"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/102485\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/media\/111744"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/media?parent=102485"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=102485"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=102485"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}