{"id":69083,"date":"2022-12-12T07:50:38","date_gmt":"2022-12-12T15:50:38","guid":{"rendered":"https:\/\/github.blog\/?p=69083"},"modified":"2022-12-12T07:50:38","modified_gmt":"2022-12-12T15:50:38","slug":"highlights-from-git-2-39","status":"publish","type":"post","link":"https:\/\/github.blog\/open-source\/git\/highlights-from-git-2-39\/","title":{"rendered":"Highlights from Git 2.39"},"content":{"rendered":"<p>The open source Git project just <a href=\"https:\/\/lore.kernel.org\/git\/xmqqlencspnl.fsf@gitster.g\/\">released Git 2.39<\/a>, with features and bug fixes from over 86 contributors, 31 of them new. We last caught up with you on the latest in Git back <a href=\"https:\/\/github.blog\/2022-10-03-highlights-from-git-2-38\/\">when 2.38 was released<\/a>.<\/p>\n<p>To celebrate this most recent release, here&#8217;s GitHub&#8217;s look at some of the most interesting features and changes introduced since last time.<\/p>\n<hr \/>\n<p>If you use Git on the command-line, you have almost certainly used <code>git log<\/code> to peruse your project&#8217;s history. But you may not be as familiar with its cousin, <code>git shortlog<\/code>.<\/p>\n<p><code>git shortlog<\/code> is used to summarize the output produced by <code>git log<\/code>. For example, many projects (including Git<sup id=\"fnref-69083-1\"><a href=\"#fn-69083-1\" class=\"jetpack-footnote\" title=\"Read footnote.\">1<\/a><\/sup>) use <code>git shortlog -ns<\/code> to produce a list of unique contributors in a release, along with the number of commits they authored, like this:<\/p>\n<pre><code>$ git shortlog -ns v2.38.0.. | head -10\n   166  Junio C Hamano\n   118  Taylor Blau\n   115  \u00c6var Arnfj\u00f6r\u00f0 Bjarmason\n    43  Jeff King\n    26  Phillip Wood\n    21  Ren\u00e9 Scharfe\n    15  Derrick Stolee\n    11  Johannes Schindelin\n     9  Eric Sunshine\n     9  Jeff Hostetler\n  [...]\n<\/code><\/pre>\n<p>We&#8217;ve talked about <code>git shortlog<\/code> in the past, most recently when <a href=\"https:\/\/github.blog\/2020-10-19-git-2-29-released\/#user-content-new-git-shortlog-tricks\">2.29 was released<\/a> to show off its more flexible <code>--group<\/code> option, which allows you to group commits by fields other than their author or committer. For example, something like:<\/p>\n<pre><code>$ git shortlog -ns --group=author --group=trailer:co-authored-by\n<\/code><\/pre>\n<p>would count each commit to its author as well as any individuals in the <code>Co-authored-by<\/code> trailer.<\/p>\n<p>This release, <code>git shortlog<\/code> became even more flexible by learning how to aggregate commits based on arbitrary formatting specifiers, like the ones mentioned in the <a href=\"https:\/\/git-scm.com\/docs\/pretty-formats\/2.39.0\">pretty formats<\/a> section of Git&#8217;s documentation.<\/p>\n<p>One neat use is being able to get a view of how many commits were committed each month during a release cycle. Before, you might have written something like this monstrosity:<\/p>\n<pre><code>$ git log v2.38.0.. --date='format:%Y-%m' --format='%cd' | sort | uniq -c\n<\/code><\/pre>\n<p>There, <code>--date='format:%Y-%m'<\/code> tells Git to output each date field like <code>YYYY-MM<\/code>, and <code>--format='%cd'<\/code> tells Git to output only the committer date (using the aforementioned format) when printing each commit. Then, we sort the output, and count the number of unique values.<\/p>\n<p>Now, you can ask Git to do all of that for you, by writing:<\/p>\n<pre><code>$ git shortlog v2.38.0.. --date='format:%Y-%m' --group='%cd' -s\n     2  2022-08\n    47  2022-09\n   405  2022-10\n   194  2022-11\n     5  2022-12\n<\/code><\/pre>\n<p>Where <code>-s<\/code> tells <code>git shortlog<\/code> output a summary where the left-hand column is the number of commits attributed to each unique group (in this case, the year and month combo), and the right-hand column is the identity of each group itself.<\/p>\n<p>Since you can pass any format specifier to the <code>--group<\/code> option, the flexibility here is limited only by the <a href=\"https:\/\/git-scm.com\/docs\/pretty-formats\/2.39.0\">pretty formats<\/a> available, and your own creativity.<\/p>\n<p>[<a href=\"https:\/\/github.com\/git\/git\/compare\/71aa6e3d85eb033ec3300298a132d7898d9969bb...7b11234e3bee123d6d48ed175f11b26b54fa67c6\">source<\/a>]<\/p>\n<hr \/>\n<p><a href=\"https:\/\/github.blog\/2022-06-27-highlights-from-git-2-37\/#a-new-mechanism-for-pruning-unreachable-objects\">Returning readers<\/a> may remember our discussion on Git&#8217;s new object pruning mechanism, <a href=\"https:\/\/git-scm.com\/docs\/cruft-packs\/2.39.0\">cruft packs<\/a>. In case you&#8217;re new around here, no problem: here&#8217;s a refresher.<\/p>\n<p>When you want to tell Git to remove unreachable objects (those which can&#8217;t be found by walking along the history of any branch or tag), you might run something like:<\/p>\n<pre><code>$ git gc --cruft --prune=5.minutes.ago\n<\/code><\/pre>\n<p>That instructs Git to divvy your repository&#8217;s objects into two packs: one containing reachable objects, and another<sup id=\"fnref-69083-2\"><a href=\"#fn-69083-2\" class=\"jetpack-footnote\" title=\"Read footnote.\">2<\/a><\/sup> containing unreachable objects modified within the last five minutes. This makes sure that a <code>git gc<\/code> process doesn&#8217;t <a href=\"https:\/\/en.wikipedia.org\/wiki\/Race_condition\">race<\/a> with incoming reference updates that might leave the repository in a corrupt state. As those objects continue to age, they will be removed from the repository via subsequent <code>git gc<\/code> invocations. For (many) more details, see our post, <a href=\"https:\/\/github.blog\/2022-09-13-scaling-gits-garbage-collection\">Scaling Git&#8217;s garbage collection<\/a>.<\/p>\n<p>Even though the <code>--prune=&lt;date&gt;<\/code> mechanism of adding a grace period before permanently removing objects from the repository is relatively effective at avoiding corruption in practice, it is not completely fool-proof. And when we do encounter repository corruption, it is useful to have the missing objects close by to allow us to recover a corrupted repository.<\/p>\n<p>In Git 2.39, <code>git repack<\/code> learned a new option to create an external copy of any objects removed from the repository: <code>--expire-to<\/code>. When combined with <code>--cruft<\/code> options like so:<\/p>\n<pre><code>$ git repack --cruft --cruft-expiration=5.minutes.ago -d --expire-to=..\/backup.git\n<\/code><\/pre>\n<p>any unreachable objects which haven&#8217;t been modified in the last five minutes are collected together and stored in a <a href=\"https:\/\/github.blog\/2022-08-29-gits-database-internals-i-packed-object-store\/\">packfile<\/a> that is written to <code>..\/backup.git<\/code>. Then, objects you may be missing after garbage collection are readily available in the pack stored in <code>..\/backup.git<\/code>.<\/p>\n<p>These ideas are identical to the ones described in <a href=\"https:\/\/github.blog\/2022-09-13-scaling-gits-garbage-collection\/#limbo-repositories\">the &#8220;limbo repository&#8221; section<\/a> of our Scaling Git&#8217;s garbage collection <a href=\"https:\/\/github.blog\/2022-09-13-scaling-gits-garbage-collection\">blog post<\/a>. At the time of writing that post, those patches were still under review. Thanks to careful feedback from the Git community, the same tools that power GitHub&#8217;s own garbage collection are now available to you via Git 2.39.<\/p>\n<p>On a related note, careful readers may have noticed that in order to write a cruft pack, you have to explicitly pass <code>--cruft<\/code> to both <code>git gc<\/code> and <code>git repack<\/code>. This is still the case. But in Git 2.39, users who enable the <code>feature.experimental<\/code> configuration and are running the bleeding edge of Git will now use cruft packs by default when running <code>git gc<\/code>.<\/p>\n<p>[<a href=\"https:\/\/github.com\/git\/git\/compare\/e53598a5ab745fb633dc99ed11cbe4b1bee066fa...91badeba32d31d4dcc695a8888e5b697b4c3d90c\">source<\/a>, <a href=\"https:\/\/github.com\/git\/git\/compare\/098b1d07bce86358d0d3aeb2ea6f1932362709b0...c695592850a3b4b7857fc11721cbc7d2b332f41e\">source<\/a>]<\/p>\n<hr \/>\n<p>If you&#8217;ve been following along with the gradual introduction of <a href=\"https:\/\/github.blog\/2021-11-10-make-your-monorepo-feel-small-with-gits-sparse-index\/\">sparse index compatibility<\/a> in Git commands, this one&#8217;s for you.<\/p>\n<p>In previous versions of Git, using <code>git grep --cached<\/code> (to search through the index instead of the blobs in your working copy) you might have noticed that Git first has to expand your index when using the sparse index feature.<\/p>\n<p>In large repositories where the sparse portion of the repository is significantly smaller than the repository as a whole, this adds a substantial delay before <code>git grep --cached<\/code> outputs any matches.<\/p>\n<p>Thanks to the work of <a href=\"https:\/\/summerofcode.withgoogle.com\/\">Google Summer of Code<\/a> student, <a href=\"https:\/\/summerofcode.withgoogle.com\/programs\/2022\/projects\/hz4rcOUB\">Shaoxuan Yuan<\/a>, this is no longer the case. This can lead to some dramatic performance enhancements: when searching in a location within your sparse cone (for example., <code>git grep --cached $pattern -- 'path\/in\/sparse\/cone'<\/code>), Git 2.39 outperforms the previous version by nearly 70%.<\/p>\n<p>[<a href=\"https:\/\/github.com\/git\/git\/compare\/4b4d97cfdaaaf2ae4bdfb6914ac2bdaf44e0a4f9...7cae7627c459ae5d0cd8f4c1ff76601e6c952bf3\">source<\/a>]<\/p>\n<hr \/>\n<p>This one is a little bit technical, but bear with us, since it ends with a nifty performance optimization that may be coming to a Git server near you.<\/p>\n<p>Before receiving a push, a Git server must first tell the pusher about all of the branches and tags it already knows about. This lets the client omit any objects that it knows the server already has, and results in less data being transferred overall.<\/p>\n<p>Once the server has all of the new objects, it ensures that they are &#8220;connected&#8221; before entering them into the repository. Generally speaking, this &#8220;connectivity check&#8221; ensures that none of the new objects mention nonexistent objects; in other words, that the push will not corrupt the repository.<\/p>\n<p>One additional factor worth noting is that some Git servers are <a href=\"https:\/\/git-scm.com\/docs\/git-config\/2.39.0#Documentation\/git-config.txt-transferhideRefs\">configured<\/a> to avoid advertising certain references. But those references are still used as part of the connectivity check. Taking into account the extra work necessary to incorporate those hidden references into the connectivity check, the additional runtime adds up, especially if there are a large number of hidden references.<\/p>\n<p>In Git 2.39, the connectivity check was enhanced to only consider the references that were advertised, in addition to those that were pushed. In a test repository with nearly 7 million references (only ~3% of which are advertised), the resulting speed-up makes Git 2.39 outperform the previous version by roughly a factor of 4.5.<\/p>\n<p>As your server operators upgrade to the latest version of Git, you should notice an improvement in how fast they are able to process incoming pushes.<\/p>\n<p>[<a href=\"https:\/\/github.com\/git\/git\/compare\/173fc54b005c92dc0da0fe5e71034128eddbacc8...bcec6780b2ec77ea5f846d5448771f97110041e1\">source<\/a>]<\/p>\n<hr \/>\n<p>Last but not least, let&#8217;s round out our recap of some of the highlights from Git 2.39 with a look at a handful of new security measures.<\/p>\n<p>Git added two new &#8220;defense-in-depth&#8221; changes in the latest release. First, <code>git apply<\/code> was updated to refuse to apply patches larger than ~1 GiB in size to avoid potential integer overflows in the apply code. Git was also updated to correctly redact sensitive header information with <code>GIT_TRACE_CURL=1<\/code> or <code>GIT_CURL_VERBOSE=1<\/code> when using HTTP\/2.<\/p>\n<p>If you happen to notice a security vulnerability in Git, you can follow <a href=\"https:\/\/github.com\/git\/git\/blob\/v2.39.0\/SECURITY.md\">Git&#8217;s own documentation<\/a> on how to responsibly report the issue. Most importantly, if you&#8217;ve ever been curious about how Git handles coordinating and disclosing embargoed releases, this release cycle saw a significant effort to codify and write down exactly how Git handles these types of issues.<\/p>\n<p>To read more about Git&#8217;s disclosure policy (and learn about how to participate yourself!), you can find more <a href=\"https:\/\/github.com\/git\/git\/blob\/v2.39.0\/Documentation\/howto\/coordinate-embargoed-releases.txt\">in the repository<\/a>.<\/p>\n<p>[<a href=\"https:\/\/github.com\/git\/git\/compare\/c7ccd4eae92a551f5237fc04e2997274d543ec5b...f1c0e3946e0bdec16d6440fb7e52edbe78cf12b3\">source<\/a>, <a href=\"https:\/\/github.com\/git\/git\/compare\/4b76998ff0e960759f492f1390e00b24c90537b8...b637a41ebe0e65b6d64dd65efaf848b4705dcbed\">source<\/a>, <a href=\"https:\/\/github.com\/git\/git\/compare\/969230b64fe76972d55b55cee8136e43a7e84752...a294443fa1f0e5e3d363f6649b59109416a23e9f\">source<\/a>]<\/p>\n<h2 id=\"the-rest-of-the-iceberg\"><a class=\"heading-link\" href=\"#the-rest-of-the-iceberg\">The rest of the iceberg<span class=\"heading-hash pl-2 text-italic text-bold\" aria-hidden=\"true\"><\/span><\/a><\/h2>\n<p>That&#8217;s just a sample of changes from the latest release. For more, check out the <a href=\"https:\/\/github.com\/git\/git\/blob\/v2.39.0\/Documentation\/RelNotes\/2.39.0.txt\">release notes for 2.39<\/a>, or <a href=\"https:\/\/github.com\/git\/git\/tree\/v2.39.0\/Documentation\/RelNotes\">any previous version<\/a> in <a href=\"https:\/\/github.com\/git\/git\">the Git repository<\/a>.<\/p>\n<p><!-- Footnotes themselves at the bottom. --><\/p>\n<h2 id=\"notes\"><a class=\"heading-link\" href=\"#notes\">Notes<span class=\"heading-hash pl-2 text-italic text-bold\" aria-hidden=\"true\"><\/span><\/a><\/h2>\n<div class=\"footnotes\">\n<hr \/>\n<ol>\n<li id=\"fn-69083-1\">\nIt&#8217;s true. In fact, the list at the bottom of <a href=\"https:\/\/lore.kernel.org\/git\/xmqqlencspnl.fsf@gitster.g\/\">the release announcement<\/a> is <a href=\"https:\/\/github.com\/git\/git\/blob\/ecaae0c78185918cb24292407354f58c043b6ca8\/Announce#L185-L186\">generated<\/a> by running <code>git shortlog<\/code> on the <code>git log --no-merges<\/code> between the last and current release. Calculating the number of new and existing contributors in each release is also <a href=\"https:\/\/github.com\/git\/git\/blob\/ecaae0c78185918cb24292407354f58c043b6ca8\/Announce#L47-L68\">powered by git shortlog<\/a>.&#160;<a href=\"#fnref-69083-1\" title=\"Return to main content.\">&#8617;<\/a>\n<\/li>\n<li id=\"fn-69083-2\">\nThis is a bit of an oversimplification. In addition to storing the object modification times in an adjacent <code>*.mtimes<\/code> file, the cruft pack also contains unreachable objects that are reachable from anything modified within the last five minutes, regardless of its age. See the <a href=\"https:\/\/github.blog\/2022-09-13-scaling-gits-garbage-collection\/#mitigating-object-deletion-raciness\">&#8220;mitigating object deletion raciness&#8221;<\/a> section for more.&#160;<a href=\"#fnref-69083-2\" title=\"Return to main content.\">&#8617;<\/a>\n<\/li>\n<\/ol>\n<\/div>\n","protected":false},"excerpt":{"rendered":"<p>Another new release of Git is here to end the year! Take a look at some of our highlights on what&#8217;s new in Git 2.39.<\/p>\n","protected":false},"author":1282,"featured_media":69084,"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":"","_gh_post_sq_img_id":"","_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":[3330,67],"tags":[132],"coauthors":[2189],"class_list":["post-69083","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-git","category-open-source","tag-git"],"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>Highlights from Git 2.39 - The GitHub Blog<\/title>\n<meta name=\"description\" content=\"Another new release of Git is here to end the year! Take a look at some of our highlights on what&#039;s new in Git 2.39.\" \/>\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\/open-source\/git\/highlights-from-git-2-39\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Highlights from Git 2.39\" \/>\n<meta property=\"og:description\" content=\"Another new release of Git is here to end the year! Take a look at some of our highlights on what&#039;s new in Git 2.39.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/github.blog\/open-source\/git\/highlights-from-git-2-39\/\" \/>\n<meta property=\"og:site_name\" content=\"The GitHub Blog\" \/>\n<meta property=\"article:published_time\" content=\"2022-12-12T15:50:38+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/github.blog\/wp-content\/uploads\/2022\/12\/git239.png?fit=4800%2C2520\" \/>\n\t<meta property=\"og:image:width\" content=\"4800\" \/>\n\t<meta property=\"og:image:height\" content=\"2520\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"author\" content=\"Taylor Blau\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:image\" content=\"https:\/\/github.blog\/wp-content\/uploads\/2022\/12\/git239-1.png?fit=2400%2C1260\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Taylor Blau\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"7 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/github.blog\\\/open-source\\\/git\\\/highlights-from-git-2-39\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/github.blog\\\/open-source\\\/git\\\/highlights-from-git-2-39\\\/\"},\"author\":{\"name\":\"Taylor Blau\",\"@id\":\"https:\\\/\\\/github.blog\\\/#\\\/schema\\\/person\\\/f2a5dc09d09f41c8c731679cc07da524\"},\"headline\":\"Highlights from Git 2.39\",\"datePublished\":\"2022-12-12T15:50:38+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/github.blog\\\/open-source\\\/git\\\/highlights-from-git-2-39\\\/\"},\"wordCount\":1401,\"image\":{\"@id\":\"https:\\\/\\\/github.blog\\\/open-source\\\/git\\\/highlights-from-git-2-39\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/github.blog\\\/wp-content\\\/uploads\\\/2022\\\/12\\\/git239.png?fit=4800%2C2520\",\"keywords\":[\"Git\"],\"articleSection\":[\"Git\",\"Open Source\"],\"inLanguage\":\"en-US\"},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/github.blog\\\/open-source\\\/git\\\/highlights-from-git-2-39\\\/\",\"url\":\"https:\\\/\\\/github.blog\\\/open-source\\\/git\\\/highlights-from-git-2-39\\\/\",\"name\":\"Highlights from Git 2.39 - The GitHub Blog\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/github.blog\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/github.blog\\\/open-source\\\/git\\\/highlights-from-git-2-39\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/github.blog\\\/open-source\\\/git\\\/highlights-from-git-2-39\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/github.blog\\\/wp-content\\\/uploads\\\/2022\\\/12\\\/git239.png?fit=4800%2C2520\",\"datePublished\":\"2022-12-12T15:50:38+00:00\",\"author\":{\"@id\":\"https:\\\/\\\/github.blog\\\/#\\\/schema\\\/person\\\/f2a5dc09d09f41c8c731679cc07da524\"},\"description\":\"Another new release of Git is here to end the year! Take a look at some of our highlights on what's new in Git 2.39.\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/github.blog\\\/open-source\\\/git\\\/highlights-from-git-2-39\\\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/github.blog\\\/open-source\\\/git\\\/highlights-from-git-2-39\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/github.blog\\\/open-source\\\/git\\\/highlights-from-git-2-39\\\/#primaryimage\",\"url\":\"https:\\\/\\\/github.blog\\\/wp-content\\\/uploads\\\/2022\\\/12\\\/git239.png?fit=4800%2C2520\",\"contentUrl\":\"https:\\\/\\\/github.blog\\\/wp-content\\\/uploads\\\/2022\\\/12\\\/git239.png?fit=4800%2C2520\",\"width\":4800,\"height\":2520},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/github.blog\\\/open-source\\\/git\\\/highlights-from-git-2-39\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/github.blog\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Open Source\",\"item\":\"https:\\\/\\\/github.blog\\\/open-source\\\/\"},{\"@type\":\"ListItem\",\"position\":3,\"name\":\"Git\",\"item\":\"https:\\\/\\\/github.blog\\\/open-source\\\/git\\\/\"},{\"@type\":\"ListItem\",\"position\":4,\"name\":\"Highlights from Git 2.39\"}]},{\"@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\\\/f2a5dc09d09f41c8c731679cc07da524\",\"name\":\"Taylor Blau\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/d5f3476f26b6f99cbb6b467e7ed7482f5762c8157bc73f569196e428bdcbea25?s=96&d=mm&r=g2ce44289191883c54a58a554d8fc874a\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/d5f3476f26b6f99cbb6b467e7ed7482f5762c8157bc73f569196e428bdcbea25?s=96&d=mm&r=g\",\"contentUrl\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/d5f3476f26b6f99cbb6b467e7ed7482f5762c8157bc73f569196e428bdcbea25?s=96&d=mm&r=g\",\"caption\":\"Taylor Blau\"},\"description\":\"Taylor Blau is a Principal Software Engineer at GitHub where he works on Git.\",\"sameAs\":[\"https:\\\/\\\/ttaylorr.com\"],\"url\":\"https:\\\/\\\/github.blog\\\/author\\\/ttaylorr\\\/\"}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"Highlights from Git 2.39 - The GitHub Blog","description":"Another new release of Git is here to end the year! Take a look at some of our highlights on what's new in Git 2.39.","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\/open-source\/git\/highlights-from-git-2-39\/","og_locale":"en_US","og_type":"article","og_title":"Highlights from Git 2.39","og_description":"Another new release of Git is here to end the year! Take a look at some of our highlights on what's new in Git 2.39.","og_url":"https:\/\/github.blog\/open-source\/git\/highlights-from-git-2-39\/","og_site_name":"The GitHub Blog","article_published_time":"2022-12-12T15:50:38+00:00","og_image":[{"width":4800,"height":2520,"url":"https:\/\/github.blog\/wp-content\/uploads\/2022\/12\/git239.png?fit=4800%2C2520","type":"image\/png"}],"author":"Taylor Blau","twitter_card":"summary_large_image","twitter_image":"https:\/\/github.blog\/wp-content\/uploads\/2022\/12\/git239-1.png?fit=2400%2C1260","twitter_misc":{"Written by":"Taylor Blau","Est. reading time":"7 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/github.blog\/open-source\/git\/highlights-from-git-2-39\/#article","isPartOf":{"@id":"https:\/\/github.blog\/open-source\/git\/highlights-from-git-2-39\/"},"author":{"name":"Taylor Blau","@id":"https:\/\/github.blog\/#\/schema\/person\/f2a5dc09d09f41c8c731679cc07da524"},"headline":"Highlights from Git 2.39","datePublished":"2022-12-12T15:50:38+00:00","mainEntityOfPage":{"@id":"https:\/\/github.blog\/open-source\/git\/highlights-from-git-2-39\/"},"wordCount":1401,"image":{"@id":"https:\/\/github.blog\/open-source\/git\/highlights-from-git-2-39\/#primaryimage"},"thumbnailUrl":"https:\/\/github.blog\/wp-content\/uploads\/2022\/12\/git239.png?fit=4800%2C2520","keywords":["Git"],"articleSection":["Git","Open Source"],"inLanguage":"en-US"},{"@type":"WebPage","@id":"https:\/\/github.blog\/open-source\/git\/highlights-from-git-2-39\/","url":"https:\/\/github.blog\/open-source\/git\/highlights-from-git-2-39\/","name":"Highlights from Git 2.39 - The GitHub Blog","isPartOf":{"@id":"https:\/\/github.blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/github.blog\/open-source\/git\/highlights-from-git-2-39\/#primaryimage"},"image":{"@id":"https:\/\/github.blog\/open-source\/git\/highlights-from-git-2-39\/#primaryimage"},"thumbnailUrl":"https:\/\/github.blog\/wp-content\/uploads\/2022\/12\/git239.png?fit=4800%2C2520","datePublished":"2022-12-12T15:50:38+00:00","author":{"@id":"https:\/\/github.blog\/#\/schema\/person\/f2a5dc09d09f41c8c731679cc07da524"},"description":"Another new release of Git is here to end the year! Take a look at some of our highlights on what's new in Git 2.39.","breadcrumb":{"@id":"https:\/\/github.blog\/open-source\/git\/highlights-from-git-2-39\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/github.blog\/open-source\/git\/highlights-from-git-2-39\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/github.blog\/open-source\/git\/highlights-from-git-2-39\/#primaryimage","url":"https:\/\/github.blog\/wp-content\/uploads\/2022\/12\/git239.png?fit=4800%2C2520","contentUrl":"https:\/\/github.blog\/wp-content\/uploads\/2022\/12\/git239.png?fit=4800%2C2520","width":4800,"height":2520},{"@type":"BreadcrumbList","@id":"https:\/\/github.blog\/open-source\/git\/highlights-from-git-2-39\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/github.blog\/"},{"@type":"ListItem","position":2,"name":"Open Source","item":"https:\/\/github.blog\/open-source\/"},{"@type":"ListItem","position":3,"name":"Git","item":"https:\/\/github.blog\/open-source\/git\/"},{"@type":"ListItem","position":4,"name":"Highlights from Git 2.39"}]},{"@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\/f2a5dc09d09f41c8c731679cc07da524","name":"Taylor Blau","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/secure.gravatar.com\/avatar\/d5f3476f26b6f99cbb6b467e7ed7482f5762c8157bc73f569196e428bdcbea25?s=96&d=mm&r=g2ce44289191883c54a58a554d8fc874a","url":"https:\/\/secure.gravatar.com\/avatar\/d5f3476f26b6f99cbb6b467e7ed7482f5762c8157bc73f569196e428bdcbea25?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/d5f3476f26b6f99cbb6b467e7ed7482f5762c8157bc73f569196e428bdcbea25?s=96&d=mm&r=g","caption":"Taylor Blau"},"description":"Taylor Blau is a Principal Software Engineer at GitHub where he works on Git.","sameAs":["https:\/\/ttaylorr.com"],"url":"https:\/\/github.blog\/author\/ttaylorr\/"}]}},"jetpack_publicize_connections":[],"jetpack_shortlink":"https:\/\/wp.me\/pamS32-hYf","jetpack_sharing_enabled":true,"jetpack_featured_media_url":"https:\/\/github.blog\/wp-content\/uploads\/2022\/12\/git239.png?fit=4800%2C2520","_links":{"self":[{"href":"https:\/\/github.blog\/wp-json\/wp\/v2\/posts\/69083","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\/1282"}],"replies":[{"embeddable":true,"href":"https:\/\/github.blog\/wp-json\/wp\/v2\/comments?post=69083"}],"version-history":[{"count":9,"href":"https:\/\/github.blog\/wp-json\/wp\/v2\/posts\/69083\/revisions"}],"predecessor-version":[{"id":69087,"href":"https:\/\/github.blog\/wp-json\/wp\/v2\/posts\/69083\/revisions\/69087"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/github.blog\/wp-json\/wp\/v2\/media\/69084"}],"wp:attachment":[{"href":"https:\/\/github.blog\/wp-json\/wp\/v2\/media?parent=69083"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/github.blog\/wp-json\/wp\/v2\/categories?post=69083"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/github.blog\/wp-json\/wp\/v2\/tags?post=69083"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/github.blog\/wp-json\/wp\/v2\/coauthors?post=69083"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}