{"id":57,"date":"2014-10-10T11:40:02","date_gmt":"2014-10-10T15:40:02","guid":{"rendered":"http:\/\/www.jmdawson.net\/blog\/?p=57"},"modified":"2014-10-10T13:26:10","modified_gmt":"2014-10-10T17:26:10","slug":"git-recovery","status":"publish","type":"post","link":"https:\/\/www.jmdawson.net\/blog\/2014\/10\/10\/git-recovery\/","title":{"rendered":"Git Recovery (or Reverting a Gitpocalypse)"},"content":{"rendered":"<p>This morning I ran into a minor issue where someone pushed a totally different project into one of our repositories, turning our FreeRADIUS Configuration repository into a functional clone of the FreeRADIUS source repository. As you might imagine, this was&#8230;somewhat disruptive. After casting about for a bit, I found that recovery was not as bad as it seemed. There might be some missing branches after this, but as most of them should have been deleted, I&#8217;m not feeling too bad.<\/p>\n<p>This works best (at all?) if you have some repositories floating around with recent, good copies of what you want to recover.<\/p>\n<p>From that machine, I did the following:<br \/>\n<code><br \/>\n$ git checkout master<br \/>\nAlready on 'master'<br \/>\nYour branch is up-to-date with 'origin\/master'.<\/code><\/p>\n<p>$ git log -n 1<br \/>\ncommit f019fb8e8d15a28e721441d21a3d8a754e0d210d<br \/>\nAuthor: Jacob M. Dawson &lt;dawson@vt.edu&gt;<br \/>\nDate: Wed Oct 8 10:55:17 2014 -0400<\/p>\n<p>Implemented forgotten correct ldap clients config in load-balancing<\/p>\n<p>$ git push -f origin f019fb8e8d15a28e721441d21a3d8a754e0d210d:master<\/p>\n<p>So that reset the master to something decent (the last update we&#8217;d made to it, thankfully). From there, I pushed the branches I cared about, as they&#8217;d also been removed:<br \/>\n<code><br \/>\n$ git checkout netadmin<br \/>\n$ git push -u origin netadmin<br \/>\n$ git checkout eduroam<br \/>\n$ git push -u origin eduroam<br \/>\n<\/code><br \/>\nEtc.<\/p>\n<p>Finally, I went about removing all the bad branches and tags (this snapshot is after I&#8217;d already nixed most of the branches and moved onto tags, but the point remains).<br \/>\n<code><br \/>\n$ git ls-remote origin<br \/>\n8bde98501d3657dfb183913be8cbf187769fed56 HEAD<br \/>\n8aca08fe308044c0aacd9d7947600b4f866de1c1 refs\/heads\/eduroam<br \/>\n8bde98501d3657dfb183913be8cbf187769fed56 refs\/heads\/master<br \/>\n8a9d093e110f84391f512080daea89fffcac39e0 refs\/heads\/netadmin<br \/>\na687717f49aca81d45c96d636eaf42cd5c7b5d94 refs\/remotes\/upstream\/HEAD<br \/>\nc7119ee310ab13d4a526fbdfc50a798622595bf9 refs\/remotes\/upstream\/coverity_scan<br \/>\na687717f49aca81d45c96d636eaf42cd5c7b5d94 refs\/remotes\/upstream\/master<br \/>\n5f715dba4d2dbdb268bf60fcc656352274930941 refs\/remotes\/upstream\/v1.1.x<br \/>\n6040566cfa969da1bce085ee48b4cd3e433e87d8 refs\/remotes\/upstream\/v2.1.x-apple<br \/>\n7df037e8f4f6d8309a896aed53c360a90d380e34 refs\/remotes\/upstream\/v2.x.x<br \/>\nf46e3f1e4b983d905de956144035bbcaced666c2 refs\/remotes\/upstream\/v3.0.x<br \/>\n15a2d332a02b99fbf04ca4dd41310ea1ab109fbe refs\/tags\/release_0_9_2<br \/>\n8e6b04132fd49c6fa145851e4ba919385cd0b3ba refs\/tags\/release_0_9_3<br \/>\n05a08578990a46fb0d3e52c85ab276d462f5511f refs\/tags\/release_1_0_0<br \/>\n815f3cebf703ed5354211299c3be36d0fde6cc1d refs\/tags\/release_1_0_0_pre1<br \/>\nee92544adaea26d89148ea5da7f40730629fd2d1 refs\/tags\/release_1_0_0_pre2<br \/>\nab5ebe15a89b5e63914a7b3772a76c35b078055f refs\/tags\/release_1_0_0_pre3<br \/>\n8c6451806c5af7f5a812098dfc1fef4807c6da42 refs\/tags\/release_1_0_1<br \/>\n90600a278338ec9d680c43a97e0a636d81b52f2e refs\/tags\/release_1_0_2<br \/>\n334d34a539e869b054fc473f20ab16a1f5e98493 refs\/tags\/release_1_0_3<br \/>\n198f900c5d6521f92938f8927f893a9879437b8d refs\/tags\/release_1_0_4<br \/>\nc13c8bdb58aa100edb6cf678b6c8bdaeefe427c4 refs\/tags\/release_1_0_5<br \/>\n5b757a36fe84b2cf24df6a367afdaf6294d78997 refs\/tags\/release_1_1_0<br \/>\n8102de9efd8d6b690bad3aa3ee687fccfbd0a55d refs\/tags\/release_1_1_0_pre0<br \/>\n6efc0c7c54d93c28c79dcd4b7d45d42774fee2ac refs\/tags\/release_1_1_1<br \/>\n1c8bd5567bb5e73d28e8350102f4e961d37cb735 refs\/tags\/release_1_1_2<br \/>\n4a44f2aad41216ae9aa0a9dc49b0b1e093f07143 refs\/tags\/release_1_1_3<br \/>\n2289360fec804c1b560cbf98f4a06baccea45de5 refs\/tags\/release_1_1_4<br \/>\n6cdb8bec5014efd32327346c989814bedb4c80be refs\/tags\/release_1_1_5<br \/>\necea7d7baa5b24abd3b0aa016f873ff0a9307dd1 refs\/tags\/release_1_1_6<br \/>\n2ee0fbe67ef0c8c04e88036c98692079f5179165 refs\/tags\/release_1_1_7<br \/>\n139e62a134fbaceb28eee001ab87f1d1e3092c33 refs\/tags\/release_1_1_8<br \/>\n74ef9b64f7cd631b13d7a61bd1588a2bfc75ba39 refs\/tags\/release_2_0_0<br \/>\n64c447ee26d79773230ddf37631058128fe301fe refs\/tags\/release_2_0_0_pre1<br \/>\na22023e192fb491903f1e492d74989b0a4324cb9 refs\/tags\/release_2_0_0_pre2<br \/>\ndfb32dca4abfaf76ed59b81c6b333bcc91be0ee9 refs\/tags\/release_2_0_1<br \/>\ndb35d2eba513c9aa0fdf127b7e66c5c9bb036bc0 refs\/tags\/release_2_0_2<br \/>\n7cd6369a90399dc8836242dde3ce8a3e9595cb42 refs\/tags\/release_2_0_3<br \/>\nae87fd0cf769498d5ae9a809cc2d703a7494561e refs\/tags\/release_2_0_4<br \/>\nedf2361c554fe2fe2a1b9a50e81369aaa44a74f9 refs\/tags\/release_2_0_5<br \/>\nbacf36805f38d059f58c5c62141f91611e8a1bbc refs\/tags\/release_2_1_0<br \/>\n1c8d4d4cad8a07e96c0898fcf1cda8d2f3982495 refs\/tags\/release_2_1_1<br \/>\n1d1e9b7372abecfc0942b127e5faf90df547e198 refs\/tags\/release_2_1_10<br \/>\n34c68ba800632ccca564f6bdcb186e32886684c1 refs\/tags\/release_2_1_11<br \/>\n70c228536c4a9113caf509fbfeab305ccfcd25c8 refs\/tags\/release_2_1_12<br \/>\n239ba3f92884be49adc90b1383aa8b54cb150fe9 refs\/tags\/release_2_1_2<br \/>\n4c44a40e68c08b445123100b39855f36b65bf5f9 refs\/tags\/release_2_1_3<br \/>\na2c610854bef0f961573f15022d77b1088e8c819 refs\/tags\/release_2_1_4<br \/>\n29ce823f72ffdfb2051765a6417126ee91e22552 refs\/tags\/release_2_1_6<br \/>\naf07ace2815910610c0d39de90e4c0cf0735188d refs\/tags\/release_2_1_7<br \/>\n4d396a436e73b0331167907e2d84931645b72648 refs\/tags\/release_2_1_8<br \/>\n7c4c5199e6631d1e93c06025a45e8ba967276986 refs\/tags\/release_2_1_9<br \/>\n393dd3c3a1a9582040c419c9be35fd4ce56d38cd refs\/tags\/release_2_2_0<br \/>\nb511525f17d3f40ba28d11d7797a827298df1333 refs\/tags\/release_2_2_1<br \/>\n96c47460fad08af8822769d75636ab6d5253d3bf refs\/tags\/release_2_2_2<br \/>\n28e67574dc8011e86c462b7e8204e180a3667ac5 refs\/tags\/release_2_2_3<br \/>\n127137c63569fbb61555df9f8f9c7364a0fa830d refs\/tags\/release_2_2_4<br \/>\nb75980dc5b8b38f562948492695b9d6151a2cb94 refs\/tags\/release_2_2_5<br \/>\n580424ea12feeb5933f1aaac33fd5f9e2fa2ee60 refs\/tags\/release_3_0_0<br \/>\n335a2add3c5da124b4585bd51afed3681c3c5aea refs\/tags\/release_3_0_0_beta0<br \/>\n4571cd3cc6150ad61e136bf28de8f47e8fca8459 refs\/tags\/release_3_0_0_beta1<br \/>\n82961d74ffcbf1ec4a4f13b6cc79ddc35d7e656d refs\/tags\/release_3_0_0_rc0<br \/>\n484451695676f1d38ecd376c37d7e648731d8d77 refs\/tags\/release_3_0_0_rc1<br \/>\n9dbdad73ca823f5d2fbb0cbc5c34aec714a9e0d3 refs\/tags\/release_3_0_1<br \/>\n808a9b3a8ff7ebac794519a1e842507c9a99107b refs\/tags\/release_3_0_2<br \/>\n3366cf0a98513ee15e1b96e3996f929ba5e611a4 refs\/tags\/release_3_0_3<br \/>\n7c9d5fbe83a67934bff42c1093d50daacbf1c083 refs\/tags\/release_3_0_4<br \/>\n3d44fdde2fc3b6d4173747b4cf2e2471688f9651 refs\/tags\/release_3_0_4_rc0<br \/>\n4039aa19fbbea4503a81be519b0c3703783cb38d refs\/tags\/release_3_0_4_rc1<br \/>\n7053bedffefec30c8d1a70c12ed47dd0325ab8ca refs\/tags\/release_3_0_4_rc2<br \/>\n<\/code><\/p>\n<p>There were quite a few, so after digging around some more, I located <a href=\"http:\/\/blog.siyelo.com\/how-to-bulk-delete-remote-git-tags\/\">a post on how to bulk delete remote tags.<\/a><\/p>\n<p>This was most helpful, but I found I needed a little bit of tinkering with the regex to get it to fly, ending up with something like this:<br \/>\n<code><br \/>\n$ git ls-remote --tags origin \\<br \/>\n| awk '\/^([0-9a-f]+)\\t(refs\\\/tags\\\/release.*$)\/ {print \":\" $2}' \\<br \/>\n| xargs git push origin<br \/>\n<\/code><\/p>\n<p>The proposed solution is fairly destructive, so I checked my work:<br \/>\n<code><br \/>\n$ git ls-remote origin \\<br \/>\n| awk '\/^([0-9a-f]+)\\t(refs\\\/tags\\\/release.*$)\/ {print \":\" $2}'<\/code><\/p>\n<p>:refs\/tags\/release_0_9_2<br \/>\n:refs\/tags\/release_0_9_3<br \/>\n:refs\/tags\/release_1_0_0<br \/>\n:refs\/tags\/release_1_0_0_pre1<br \/>\n:refs\/tags\/release_1_0_0_pre2<br \/>\n:refs\/tags\/release_1_0_0_pre3<br \/>\n:refs\/tags\/release_1_0_1<br \/>\n:refs\/tags\/release_1_0_2<br \/>\n:refs\/tags\/release_1_0_3<br \/>\n:refs\/tags\/release_1_0_4<br \/>\n:refs\/tags\/release_1_0_5<br \/>\n:refs\/tags\/release_1_1_0<br \/>\n:refs\/tags\/release_1_1_0_pre0<br \/>\n:refs\/tags\/release_1_1_1<br \/>\n:refs\/tags\/release_1_1_2<br \/>\n:refs\/tags\/release_1_1_3<br \/>\n:refs\/tags\/release_1_1_4<br \/>\n:refs\/tags\/release_1_1_5<br \/>\n:refs\/tags\/release_1_1_6<br \/>\n:refs\/tags\/release_1_1_7<br \/>\n:refs\/tags\/release_1_1_8<br \/>\n:refs\/tags\/release_2_0_0<br \/>\n:refs\/tags\/release_2_0_0_pre1<br \/>\n:refs\/tags\/release_2_0_0_pre2<br \/>\n:refs\/tags\/release_2_0_1<br \/>\n:refs\/tags\/release_2_0_2<br \/>\n:refs\/tags\/release_2_0_3<br \/>\n:refs\/tags\/release_2_0_4<br \/>\n:refs\/tags\/release_2_0_5<br \/>\n:refs\/tags\/release_2_1_0<br \/>\n:refs\/tags\/release_2_1_1<br \/>\n:refs\/tags\/release_2_1_10<br \/>\n:refs\/tags\/release_2_1_11<br \/>\n:refs\/tags\/release_2_1_12<br \/>\n:refs\/tags\/release_2_1_2<br \/>\n:refs\/tags\/release_2_1_3<br \/>\n:refs\/tags\/release_2_1_4<br \/>\n:refs\/tags\/release_2_1_6<br \/>\n:refs\/tags\/release_2_1_7<br \/>\n:refs\/tags\/release_2_1_8<br \/>\n:refs\/tags\/release_2_1_9<br \/>\n:refs\/tags\/release_2_2_0<br \/>\n:refs\/tags\/release_2_2_1<br \/>\n:refs\/tags\/release_2_2_2<br \/>\n:refs\/tags\/release_2_2_3<br \/>\n:refs\/tags\/release_2_2_4<br \/>\n:refs\/tags\/release_2_2_5<br \/>\n:refs\/tags\/release_3_0_0<br \/>\n:refs\/tags\/release_3_0_0_beta0<br \/>\n:refs\/tags\/release_3_0_0_beta0^{}<br \/>\n:refs\/tags\/release_3_0_0_beta1<br \/>\n:refs\/tags\/release_3_0_0_rc0<br \/>\n:refs\/tags\/release_3_0_0_rc1<br \/>\n:refs\/tags\/release_3_0_1<br \/>\n:refs\/tags\/release_3_0_2<br \/>\n:refs\/tags\/release_3_0_3<br \/>\n:refs\/tags\/release_3_0_4<br \/>\n:refs\/tags\/release_3_0_4_rc0<br \/>\n:refs\/tags\/release_3_0_4_rc1<br \/>\n:refs\/tags\/release_3_0_4_rc2<\/p>\n<p>Work checked, let fly:<br \/>\n<code><br \/>\n$ git ls-remote --tags origin \\<br \/>\n| awk '\/^([0-9a-f]+)\\t(refs\\\/tags\\\/release_[01].*$)\/ {print \":\" $2}' \\<br \/>\n| xargs git push origin<\/code><\/p>\n<p>To git@git.it.vt.edu:cns\/freeradius-config.git<br \/>\n&#8211; [deleted] release_0_9_2<br \/>\n&#8211; [deleted] release_0_9_3<br \/>\n&#8211; [deleted] release_1_0_0<br \/>\n&#8211; [deleted] release_1_0_0_pre1<br \/>\n&#8211; [deleted] release_1_0_0_pre2<br \/>\n&#8211; [deleted] release_1_0_0_pre3<br \/>\n&#8211; [deleted] release_1_0_1<br \/>\n&#8211; [deleted] release_1_0_2<br \/>\n&#8211; [deleted] release_1_0_3<br \/>\n&#8211; [deleted] release_1_0_4<br \/>\n&#8211; [deleted] release_1_0_5<br \/>\n&#8211; [deleted] release_1_1_0<br \/>\n&#8211; [deleted] release_1_1_0_pre0<br \/>\n&#8211; [deleted] release_1_1_1<br \/>\n&#8211; [deleted] release_1_1_2<br \/>\n&#8211; [deleted] release_1_1_3<br \/>\n&#8211; [deleted] release_1_1_4<br \/>\n&#8211; [deleted] release_1_1_5<br \/>\n&#8211; [deleted] release_1_1_6<br \/>\n&#8211; [deleted] release_1_1_7<br \/>\n&#8211; [deleted] release_1_1_8<\/p>\n<h3>Remediation<\/h3>\n<p>This was clearly a suboptimal event.  Fortunately, remediation steps in this case were fairly easy.  Most of the other members of the team for this repo are in the &#8216;Developer&#8217; role, while only I and one other person are in &#8216;Master&#8217; or &#8216;Owner.&#8217;  As such, I set the master branch to protected, which will prevent these from surprising me in the future.<\/p>\n<hr \/>\n<p>As an aside, you&#8217;ll notice I chopped up the work a bit. The following pair of tags made git fairly unhappy:<br \/>\n<code><br \/>\n:refs\/tags\/release_3_0_0_beta0<br \/>\n:refs\/tags\/release_3_0_0_beta0^{}<br \/>\n<\/code><\/p>\n<p>Removing the plain boring beta0 took the wonky one with it, as I discovered, so in the end, it worked out ok.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>This morning I ran into a minor issue where someone pushed a totally different project into one of our repositories, turning our FreeRADIUS Configuration repository into a functional clone of the FreeRADIUS source repository. As you might imagine, this was&#8230;somewhat &hellip; <a href=\"https:\/\/www.jmdawson.net\/blog\/2014\/10\/10\/git-recovery\/\">Continue reading <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[10,11,12],"tags":[],"class_list":["post-57","post","type-post","status-publish","format-standard","hentry","category-git","category-remote","category-reset"],"_links":{"self":[{"href":"https:\/\/www.jmdawson.net\/blog\/wp-json\/wp\/v2\/posts\/57","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.jmdawson.net\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.jmdawson.net\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.jmdawson.net\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.jmdawson.net\/blog\/wp-json\/wp\/v2\/comments?post=57"}],"version-history":[{"count":8,"href":"https:\/\/www.jmdawson.net\/blog\/wp-json\/wp\/v2\/posts\/57\/revisions"}],"predecessor-version":[{"id":66,"href":"https:\/\/www.jmdawson.net\/blog\/wp-json\/wp\/v2\/posts\/57\/revisions\/66"}],"wp:attachment":[{"href":"https:\/\/www.jmdawson.net\/blog\/wp-json\/wp\/v2\/media?parent=57"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.jmdawson.net\/blog\/wp-json\/wp\/v2\/categories?post=57"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.jmdawson.net\/blog\/wp-json\/wp\/v2\/tags?post=57"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}