{"id":64204,"date":"2022-04-18T09:44:50","date_gmt":"2022-04-18T16:44:50","guid":{"rendered":"https:\/\/github.blog\/?p=64204"},"modified":"2022-04-19T08:39:26","modified_gmt":"2022-04-19T15:39:26","slug":"highlights-from-git-2-36","status":"publish","type":"post","link":"https:\/\/github.blog\/open-source\/git\/highlights-from-git-2-36\/","title":{"rendered":"Highlights from Git 2.36"},"content":{"rendered":"<p>The open source Git project just <a href=\"https:\/\/lore.kernel.org\/git\/xmqqh76qz791.fsf@gitster.g\/T\/#u\">released Git 2.36,<\/a> with features and bug fixes from over 96 contributors, 26 of them new. We last caught up with you on the latest in Git back <a href=\"https:\/\/github.blog\/2022-01-24-highlights-from-git-2-35\/\">when 2.35 was released<\/a>.<\/p>\n<p>To celebrate this most recent release, here\u2019s GitHub\u2019s look at some of the most interesting features and changes introduced since last time.<\/p>\n<h2 id=\"review-merge-conflict-resolution-with-remerge-diff\"><a class=\"heading-link\" href=\"#review-merge-conflict-resolution-with-remerge-diff\">Review merge conflict resolution with &#8211;remerge-diff<span class=\"heading-hash pl-2 text-italic text-bold\" aria-hidden=\"true\"><\/span><\/a><\/h2>\n<p>Returning readers may remember our coverage of <a href=\"https:\/\/github.blog\/2021-08-16-highlights-from-git-2-33\/\">merge <code>ort<\/code><\/a>, the from-scratch rewrite of Git&#8217;s <a href=\"https:\/\/git-scm.com\/docs\/merge-strategies#Documentation\/merge-strategies.txt-recursive\"><code>recursive<\/code><\/a> merge engine.<\/p>\n<p>This release brings another new feature powered by <code>ort<\/code>, which is the <code>--remerge-diff<\/code> option. To explain what <code>--remerge-diff<\/code> is and why you might be excited about it, let&#8217;s take a step back and talk about <code>git show<\/code>.<\/p>\n<p>When given a commit <code>git show<\/code> will print out that commit&#8217;s log message as well as its diff. But it has slightly different behavior when given a merge commit, especially one that had merge conflicts. If you&#8217;ve ever passed a conflicted merge to <code>git show<\/code>, you might be familiar with this output:<\/p>\n<p><img data-recalc-dims=\"1\" decoding=\"async\" loading=\"lazy\" src=\"https:\/\/github.blog\/wp-content\/uploads\/2022\/04\/git-1.png?resize=1024%2C472\" alt=\"\" width=\"1024\" height=\"472\" class=\"alignnone size-full wp-image-64234 width-fit\" srcset=\"https:\/\/github.blog\/wp-content\/uploads\/2022\/04\/git-1.png?w=1884 1884w, https:\/\/github.blog\/wp-content\/uploads\/2022\/04\/git-1.png?w=300 300w, https:\/\/github.blog\/wp-content\/uploads\/2022\/04\/git-1.png?w=768 768w, https:\/\/github.blog\/wp-content\/uploads\/2022\/04\/git-1.png?w=1024 1024w, https:\/\/github.blog\/wp-content\/uploads\/2022\/04\/git-1.png?w=1536 1536w\" sizes=\"auto, (max-width: 1000px) 100vw, 1000px\" \/><\/p>\n<p>If you look closely, you might notice that there are actually two columns of diff markers (the <code>+<\/code> and <code>-<\/code> characters to indicate lines added and removed). These come from the output of <code>git diff-tree -cc<\/code>, which is showing us the diff between each parent and the post-image of the given commit simultaneously.<\/p>\n<p>In this particular example, the conflict occurs because one side has an extra argument in the <code>dwim_ref()<\/code> call, and the other includes an updated comment to use reflect renaming a variable from <code>sha1<\/code> to <code>oid<\/code>. The left-most markers show the latter resolution, and the right-most markers show the former.<\/p>\n<p>But this output can be understandably difficult to interpret. In Git 2.36, <code>--remerge-diff<\/code> takes a different approach. Instead of showing you the diffs between the merge resolution and each parent simultaneously, <code>--remerge-diff<\/code> shows you the diff between the file with merge conflicts, and the resolution.<\/p>\n<p><img data-recalc-dims=\"1\" decoding=\"async\" loading=\"lazy\" src=\"https:\/\/github.blog\/wp-content\/uploads\/2022\/04\/git-2.png?resize=1024%2C472\" alt=\"\" width=\"1024\" height=\"472\" class=\"alignnone size-full wp-image-64235 width-fit\" srcset=\"https:\/\/github.blog\/wp-content\/uploads\/2022\/04\/git-2.png?w=1884 1884w, https:\/\/github.blog\/wp-content\/uploads\/2022\/04\/git-2.png?w=300 300w, https:\/\/github.blog\/wp-content\/uploads\/2022\/04\/git-2.png?w=768 768w, https:\/\/github.blog\/wp-content\/uploads\/2022\/04\/git-2.png?w=1024 1024w, https:\/\/github.blog\/wp-content\/uploads\/2022\/04\/git-2.png?w=1536 1536w\" sizes=\"auto, (max-width: 1000px) 100vw, 1000px\" \/><\/p>\n<p>The above shows the output of <code>git show<\/code> with <code>--remerge-diff<\/code> on the same conflicted merge commit as before. Here, we can see the <a href=\"https:\/\/git-scm.com\/docs\/git-config#Documentation\/git-config.txt-mergeconflictStyle\"><code>diff3<\/code>-style<\/a> conflicts (shown in red, since the merge commit <em>removes<\/em> the conflict markers during resolution) along with the resolution. By more clearly indicating which parts of the conflict were left as-is, we can more easily see how the given commit resolved its conflicts, instead of trying to weave-together the simultaneous diff output from <code>git diff-tree -cc<\/code>.<\/p>\n<p>Reconstructing these merges is made possible using <code>ort<\/code>. The <code>ort<\/code> engine is significantly faster than its predecessor, <code>recursive<\/code>, and can reconstruct all conflicted merge in linux.git in about 3 seconds (as compared to <code>diff-tree -cc<\/code>, which takes more than 30 seconds to perform the same operation<br \/>\n&#91;<a href=\"https:\/\/lore.kernel.org\/git\/pull.1103.git.1640109948.gitgitgadget@gmail.com\/\">source<\/a>&#93;).<\/p>\n<p>Give it a whirl in your Git repositories on 2.36 by running <code>git show --remerge-diff<\/code> on some merge conflicts in your history.<\/p>\n<p>&#91;<a href=\"https:\/\/github.com\/git\/git\/compare\/34230514b83f55ea0f4531e8486533ac5c3e2ffe...0dec322d31db3920872f43bdd2a7ddd282a5be67\">source<\/a>&#93;<\/p>\n<h2 id=\"more-flexible-fsync-configuration\"><a class=\"heading-link\" href=\"#more-flexible-fsync-configuration\">More flexible fsync configuration<span class=\"heading-hash pl-2 text-italic text-bold\" aria-hidden=\"true\"><\/span><\/a><\/h2>\n<p>If you have ever looked around in your repository&#8217;s <code>.git<\/code> directory, you&#8217;ll notice a variety of files: objects, references, reflogs, packfiles, configuration, and the like. Git writes these objects to keep track of the state of your repository, creating new object files when you make new commits, update references, repack your repository, and so on.<\/p>\n<p>Most likely, you haven&#8217;t had to think too hard about how these files are written and updated. If you&#8217;re curious about these details, then read on! When any application writes changes to your filesystem, those changes aren&#8217;t immediately persisted, since writing to the external storage medium is <a href=\"https:\/\/gist.github.com\/jboner\/2841832\">significantly slower<\/a> than updating your filesystem&#8217;s in-memory caches.<\/p>\n<p>Instead, changes are staged in <a href=\"https:\/\/en.wikipedia.org\/wiki\/Page_cache\">memory<\/a> and periodically flushed to disk at which point the changes are (usually, though disks and controllers can have their own write caches, too) written to the physical storage medium.<\/p>\n<p>Aside from following standard best-practices (like writing new files to a temporary location and then atomically moving them into place), Git has had a somewhat limited set of configuration available to tune how and when it calls <code>fsync<\/code>, mostly limited to <a href=\"https:\/\/git-scm.com\/docs\/git-config\/2.36.0#Documentation\/git-config.txt-corefsyncObjectFiles\"><code>core.fsyncObjectFiles<\/code><\/a>, which, when set, causes Git to call <code>fsync()<\/code> when creating new <a href=\"https:\/\/git-scm.com\/book\/en\/v2\/Git-Internals-Git-Objects\">loose object files<\/a>. (Git has had non-configurable <code>fsync()<\/code> calls scattered throughout its codebase for things like writing packfiles, the commit-graph, multi-pack index, and so on).<\/p>\n<p>Git 2.36 introduces a significantly more flexible set of configuration options to tune how and when Git will explicitly <code>fsync<\/code> lots of different kinds of files, not just if it <code>fsync<\/code>s loose objects.<\/p>\n<p>At the heart of this new change are two new configuration variables:<br \/>\n<a href=\"https:\/\/git-scm.com\/docs\/git-config\/2.36.0#Documentation\/git-config.txt-corefsync\"><code>core.fsync<\/code><\/a> and <a href=\"https:\/\/git-scm.com\/docs\/git-config\/2.36.0#Documentation\/git-config.txt-corefsyncMethod\"><code>core.fsyncMethod<\/code><\/a>. The former lets you pick a comma-separated list of which parts of Git&#8217;s internal data structures you want to be explicitly flushed after writing. The full list can be found in the documentation, but you can pick from things like <code>pack<\/code> (to fsync files in <code>$GIT_DIR\/objects\/pack<\/code>) or <code>loose-object<\/code> (to fsync loose objects), to <code>reference<\/code> (to fsync references in the <code>$GIT_DIR\/refs<\/code> directory). There are also aggregate options like <code>objects<\/code> (which implies both <code>loose-object<\/code> and <code>pack<\/code>), along with others like <code>derived-metadata<\/code>, <code>committed<\/code>, and <code>all<\/code>.<\/p>\n<p>You can also tune how Git ensures the durability of components included in your <code>core.fsync<\/code> configuration by setting the <code>core.fsyncMethod<\/code> to either <code>fsync<\/code> (which calls <code>fsync()<\/code>, or issues a special <a href=\"https:\/\/man7.org\/linux\/man-pages\/man2\/fcntl.2.html\"><code>fcntl()<\/code><\/a> on macOS), or <code>writeout-only<\/code>, which schedules the written data for flushing, though does not guarantee that metadata like directory entries are updated as part of the flush operation.<\/p>\n<p>Most users won&#8217;t need to change these defaults. But for server operators who have many Git repositories living on hardware that may suddenly lose power, having these new knobs to tune will provide new opportunities to enhance the durability of written data.<\/p>\n<p>&#91;<a href=\"https:\/\/github.com\/git\/git\/compare\/a68dfadae5e95c7f255cf38c9efdcbc2e36d1931...b9f5d0358d2e882d47f496c1a5589f6cebc25578\">source<\/a>, <a href=\"https:\/\/github.com\/git\/git\/compare\/eb804cd405618ef78b772072685c39392aea4ac1...bc22d845c4328f5bd896d019b3729f776ad4be4c\">source<\/a>, <a href=\"https:\/\/github.com\/git\/git\/compare\/da95e25656690e4b585b73677e9db746bd796a67...9a4987677d3f65e8cd93b9e77216f0f1026cd9b2\">source<\/a>&#93;<\/p>\n<h2 id=\"stricter-repository-ownership-checks\"><a class=\"heading-link\" href=\"#stricter-repository-ownership-checks\">Stricter repository ownership checks<span class=\"heading-hash pl-2 text-italic text-bold\" aria-hidden=\"true\"><\/span><\/a><\/h2>\n<p>If you haven&#8217;t seen <a href=\"https:\/\/github.blog\/2022-04-12-git-security-vulnerability-announced\/\">our blog post from last week<\/a> announcing the security patches for versions 2.35 and earlier, let me give you a brief recap.<\/p>\n<p>Beginning in Git 2.35.2, Git changed its default behavior to prevent you from executing <code>git<\/code> commands in a repository owned by a different user than the current one. This is designed to prevent <code>git<\/code> invocations from unintentionally executing commands which the repository owner configured.<\/p>\n<p>You can bypass this check by setting the new <a href=\"https:\/\/git-scm.com\/docs\/git-config\/#Documentation\/git-config.txt-safedirectory\"><code>safe.directory<\/code> configuration<\/a> to include trusted repositories owned by other users. If you can&#8217;t upgrade immediately, our <a href=\"https:\/\/github.blog\/2022-04-12-git-security-vulnerability-announced\/\">blog post<\/a> outlines some steps you can take to mitigate your risk, though the safest thing you can do is upgrade to the latest version of Git.<\/p>\n<p>Since publishing <a href=\"https:\/\/github.blog\/2022-04-12-git-security-vulnerability-announced\/\">that blog post<\/a>, the <code>safe.directory<\/code> option now interprets the value <code>*<\/code> to consider all Git repositories as safe, regardless of their owner.  You can set this in your <code>--global<\/code> config to opt-out of the new behavior in situations where it makes sense.<\/p>\n<p>&#91;<a href=\"https:\/\/github.com\/git\/git\/compare\/ab1f2765f78e75ee51dface57e1071b3b7f42b09...53ef17d3ee0f7fcb151f428ee3bd736b8046825f\">source<\/a>&#93;<\/p>\n<h2 id=\"tidbits\"><a class=\"heading-link\" href=\"#tidbits\">Tidbits<span class=\"heading-hash pl-2 text-italic text-bold\" aria-hidden=\"true\"><\/span><\/a><\/h2>\n<p>Now that we have looked at some of the bigger features in detail, let&#8217;s turn to a handful of smaller topics from this release.<\/p>\n<ul>\n<li>If you&#8217;ve ever spent time poking around in the internals of one of your Git repositories, you may have come across the <code>git cat-file<\/code> command. Reminiscent of <code>cat<\/code>, this command is useful for printing out the raw contents of Git objects in your repository. <code>cat-file<\/code> has a handful of other modes that go beyond just printing the contents of an object. Instead of printing out one object at a time, it can accept a stream of objects (via stdin) when passed the <code>--batch<\/code> or <code>--batch-check<\/code> command-line arguments. These two similarly-named options have slightly different outputs: <code>--batch<\/code> instructs <code>cat-file<\/code> to just print out each object&#8217;s contents, while <code>--batch-check<\/code> is used to print out information about the object itself, like its type and size<sup id=\"fnref-64204-1\"><a href=\"#fn-64204-1\" class=\"jetpack-footnote\" title=\"Read footnote.\">1<\/a><\/sup>.\n<p>But what if you want to dynamically switch between the two? Before, the only way was to run two separate copies of the <code>cat-file<\/code> command in the same repository, one in <code>--batch<\/code> mode and the other in <code>--batch-check<\/code> mode. In Git 2.36, you no longer need to do this.  You can instead run a single <code>git cat-file<\/code> command with the new <code>--batch-command<\/code> mode. This mode lets you ask for the type of output you want for each object. Its input looks either like <code>contents &lt;object&gt;<\/code>, or <code>info &lt;object&gt;<\/code>, which correspond to the output you&#8217;d get from <code>--batch<\/code>, or <code>--batch-check<\/code>, respectively.<\/p>\n<p>For server operators who may have long-running <code>cat-file<\/code> commands intended to service multiple requests, <code>--batch-command<\/code> accepts a new <code>flush<\/code> command, which flushes the output buffer upon receipt.<\/p>\n<p>&#91;<a href=\"https:\/\/github.com\/git\/git\/compare\/47be28e51e6a3b390e694d868b7da04181e99e96...440c705ea63253642c8f4761f80eb7a97a62b614\">source<\/a>, <a href=\"https:\/\/github.com\/git\/git\/compare\/07135d6be732aca61dfa77d03a3aa06120767c03...473fa2df08d9c6e2a4ff81ddc74f53f4b94a7983\">source<\/a>&#93;<\/p>\n<\/li>\n<li>\n<p>Speaking of Git internals, if you&#8217;ve ever needed to script around the contents of a tree object in your repository, then there&#8217;s no doubt that <code>git ls-tree<\/code> has come in handy.<\/p>\n<p>If you aren&#8217;t familiar with <code>ls-tree<\/code>, the gist is that it allows you to list the contents of a tree objects, optionally recursing through nested sub-trees. Its output looks something like this:<\/p>\n<pre><code class=\"language-ShellSession\">$ git ls-tree HEAD -- builtin\/\n100644 blob 3ffb86a43384f21cad4fdcc0d8549e37dba12227  builtin\/add.c\n100644 blob 0f4111bafa0b0810ae29903509a0af74073013ff  builtin\/am.c\n100644 blob 58ff977a2314e2878ee0c7d3bcd9874b71bfdeef  builtin\/annotate.c\n100644 blob 3f099b960565ff2944209ba514ea7274dad852f5  builtin\/apply.c\n100644 blob 7176b041b6d85b5760c91f94fcdde551a38d147f  builtin\/archive.c\n[...]\n<\/code><\/pre>\n<p>Previously, the customizability of <code>ls-tree<\/code>&#8216;s output was somewhat limited. You could restrict the output to just the filenames with <code>--name-only<\/code>, print absolute paths with <code>--full-name<\/code>, or abbreviate the object IDs with <code>--abbrev<\/code>, but that was about it.<\/p>\n<p>In Git 2.36, you have a lot more control about how <code>ls-tree<\/code>&#8216;s should look. There&#8217;s a new <code>--object-only<\/code> option to complement <code>--name-only<\/code>. But if you really want to customize its output, the new <code>--format<\/code> option is your best bet. You can select from any combination and order of the each entry&#8217;s mode, type, name, and size.<\/p>\n<p>Here&#8217;s a fun example of where something like this might come in handy. Let&#8217;s say you&#8217;re interested in the distribution of file-sizes of blobs in your repository. Before, to get a list of object sizes, you would have had to do either:<\/p>\n<pre><code class=\"language-ShellSession\">$ git ls-tree ... | awk '{ print $3 }' | git cat-file --batch-check='%(objectsize)'\n<\/code><\/pre>\n<p>or (ab)use the <code>--long<\/code> format and pull out the file sizes of blobs:<\/p>\n<pre><code class=\"language-ShellSession\">$ git ls-tree -l | awk '{ print $4 }'\n<\/code><\/pre>\n<p>but now you can ask for just the file sizes directly, making it much more convenient to script around them:<\/p>\n<pre><code class=\"language-ShellSession\">$ dist () {\n ruby -lne 'print 10 ** (Math.log10($_.to_i).ceil)' | sort -n | uniq -c\n}\n$ git ls-tree --format='%(objectsize)' HEAD:builtin\/ | dist\n  8 1000\n 59 10000\n 53 100000\n  2 1000000\n<\/code><\/pre>\n<p>&#8230;showing us that we have 8 files that are between 1-10 KiB in size, 59 files between 10-100 KiB, 53 files between 100 KiB and 1 MiB, and 2 files larger than 1 MiB.<\/p>\n<p>&#91;<a href=\"https:\/\/github.com\/git\/git\/compare\/3ff8cbfe8a333f55931fa9b588f106e060a67079...9c4d58ff2c385f49585197c8650356955e1fa02e\">source<\/a>, <a href=\"https:\/\/github.com\/git\/git\/compare\/95acb13a550cbc07a5ef38ffceb5678fac61acff...350296cc78912c245847ec65e55143053450cce1\">source<\/a>, <a href=\"https:\/\/github.com\/git\/git\/compare\/07330a41d66a2c9589b585a3a24ecdcf19994f19...5e65dac9c88d02f569cc87cdf630ecb5a780c6a6\">source<\/a>, <a href=\"https:\/\/github.com\/git\/git\/compare\/bf23fe5c37d62f37267d31d4afa1a1444f70cdac...acd34fd5f60ab01e871dfa3a3bb8b81828ac181d\">source<\/a>&#93;<\/p>\n<\/li>\n<li>\n<p>If you&#8217;ve ever tried to track down a bug using Git, then you&#8217;re familiar with the <code>git bisect<\/code> command. If you haven&#8217;t, here&#8217;s a quick primer. <code>git bisect<\/code> takes two revisions of your repository, one corresponding to a known &#8220;good&#8221; state, and another corresponding to some broken state. The idea is then to run a <a href=\"https:\/\/en.wikipedia.org\/wiki\/Binary_search_algorithm\">binary search<\/a> between those two points in history to find the first commit which transitioned the good state to the broken state.<\/p>\n<p>If you aren&#8217;t a frequent bisect user, you may not have heard of the <code>git bisect run<\/code> command. Instead of requiring you to classify whether each point along the search is good or bad, you can supply a script which Git will execute for you, using its <a href=\"https:\/\/en.wikipedia.org\/wiki\/Exit_status\">exit status<\/a> to classify each revision for you.<\/p>\n<p>This can be useful when trying to figure out which commit broke the build, which you can do by running:<\/p>\n<pre><code class=\"language-ShellSession\">$ git bisect start &lt;bad&gt; &lt;good&gt;\n$ git bisect run make\n<\/code><\/pre>\n<p>which will run <code>make<\/code> along the binary search between <code>&lt;bad&gt;<\/code> and <code>&lt;good&gt;<\/code>, outputting the first commit which broke compilation.<\/p>\n<p>But what about automating more complicated tests? It can often be useful to write a one-off shell script which runs some test for you, and then hand that off to <code>git bisect<\/code>. Here, you might do something like:<\/p>\n<pre><code class=\"language-ShellSession\">$ vi test.sh\n# type type type\n$ git bisect run test.sh\n<\/code><\/pre>\n<p>See the problem? We forgot to mark <code>test.sh<\/code> as <a href=\"https:\/\/en.wikipedia.org\/wiki\/File-system_permissions#Permissions\">executable<\/a>! In previous versions of Git, <code>git bisect<\/code> would incorrectly carry on the search, classifying each revision as broken. In Git 2.36, <code>git bisect<\/code> will detect that you forgot to mark the script as executable, and halt the search early.<\/p>\n<p>&#91;<a href=\"https:\/\/github.com\/git\/git\/compare\/967176465a62fe3f71008e20c5959c12542ef2b0...48af1fdee374e205c9774c163fbd4683d1110d11\">source<\/a>&#93;<\/p>\n<\/li>\n<li>\n<p>When you run <code>git fetch<\/code>, your Git client communicates with the remote to carry out a process called <a href=\"https:\/\/git-scm.com\/docs\/pack-protocol\/2.2.3#_packfile_negotiation\">negotiation<\/a> to determine which objects the server needs to send to complete your request. Roughly speaking, your client and the server mutually advertise what they have at the tips of each <a href=\"https:\/\/git-scm.com\/book\/en\/v2\/Git-Internals-Git-References\">reference<\/a>, then your client lists which objects it wants, and the server sends back all objects <em>between<\/em> the requested objects and the ones you already have.<\/p>\n<p>This works well because Git always expects to maintain <a href=\"https:\/\/en.wikipedia.org\/wiki\/Closure_(mathematics)\">closure<\/a> over reachable objects<sup id=\"fnref-64204-2\"><a href=\"#fn-64204-2\" class=\"jetpack-footnote\" title=\"Read footnote.\">2<\/a><\/sup>, meaning that if you have some reachable object in your repository, you also have all of its ancestors.<\/p>\n<p>In other words, it&#8217;s fine for the Git server to omit objects you already have, since the combination of the objects it sends along with the ones you already have should be sufficient to assemble the branches and tags your client asked for.<\/p>\n<p>But if your repository is corrupt, then you may need the server to send you objects which are reachable from ones you already have, in which case it isn&#8217;t good enough for the server to just send you the objects between what you have and want. In the past, getting into a situation like this may have led you to re-clone your entire repository.<\/p>\n<p>Git 2.36 ships with a new option to <code>git fetch<\/code> which makes it easier to recover from certain kinds of repository corruption. By passing the new  <code>--refetch<\/code> option, you can instruct <code>git fetch<\/code> to fetch <em>all<\/em> objects from the remote, regardless of which objects you already have, which is useful when the contents of your <code>objects<\/code> directory are suspect.<\/p>\n<p>&#91;<a href=\"https:\/\/github.com\/git\/git\/compare\/1b54f5b89ac2efb5256b1870fabef28ea55e2f20...4963d3e41fa454500760fe6f8fb1bab890c1c3eb\">source<\/a>&#93;<\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/github.blog\/2022-01-24-highlights-from-git-2-35\/\">Returning readers<\/a> may remember our earlier discussions about <a href=\"https:\/\/github.blog\/2021-11-10-make-your-monorepo-feel-small-with-gits-sparse-index\/\">the sparse index<\/a> and <a href=\"https:\/\/github.blog\/2020-01-17-bring-your-monorepo-down-to-size-with-sparse-checkout\/\">sparse checkouts<\/a>, which make it possible to only have part of your repository checked out at a time.<\/p>\n<p>Over the last handful of releases, more and more commands have become compatible with the sparse index. This release is no exception, with four more Git commands joining the pack. Git 2.36 brings sparse index support to <code>git clean<\/code>, <code>git checkout-index<\/code>, <code>git update-index<\/code>, and <code>git read-tree<\/code>.<\/p>\n<p>If you haven&#8217;t used these commands, there&#8217;s no need to worry: adding support to these <a href=\"https:\/\/git-scm.com\/book\/en\/v2\/Git-Internals-Plumbing-and-Porcelain\">plumbing<\/a> commands is designed to lay the ground work for building a sparse index-aware <code>git stash<\/code>. In the meantime, sparse index support already exists in the commands that you are most likely already familiar with, like <code>git status<\/code>, <code>git commit<\/code>, <code>git checkout<\/code>, and more.<\/p>\n<p>As an added bonus, <code>git sparse-checkout<\/code> (which is used to enable the sparse checkout feature and dictate which parts of your repository you want checked out) gained support for the command-line completion Git ships in its <a href=\"https:\/\/github.com\/git\/git\/tree\/v2.36.0\/contrib\"><code>contrib<\/code> directory<\/a>.<\/p>\n<p>&#91;<a href=\"https:\/\/github.com\/git\/git\/compare\/708cbef33a2c905c920e94b70d0946f9f4ff3a4e...b9ca5e26579ceb820103b49648c01187a4a0dddd\">source<\/a>, <a href=\"https:\/\/github.com\/git\/git\/compare\/430883a70c79614e52279f2800a9a383ffc68fe5...f27c170f645e6b8ed642c49c503964893ee26a4f\">source<\/a>, <a href=\"https:\/\/github.com\/git\/git\/compare\/b80121027d1247a0754b3cc46897fee75c050b44...48803821b1712687d6e06e9d7a0e911eabecf4d1\">source<\/a>&#93;<\/p>\n<\/li>\n<li>\n<p>Returning readers may remember our <a href=\"https:\/\/github.blog\/2020-12-21-get-up-to-speed-with-partial-clone-and-shallow-clone\/\">previous coverage on partial clones<\/a>, a relatively new feature in Git which allows you to initialize your clones by downloading just some of the objects in your repository.<\/p>\n<p>If you used this feature in the past with <code>git clone<\/code>&#8216;s <code>--recurse-submodules<\/code> flag, the partial clone filter was only applied to the top-level repository, cloning all of the objects in the submodules.<\/p>\n<p>This has been fixed in the latest release, where the <code>--filter<\/code> specification you use in your top-level clone is applied recursively to any submodules your repository might contain, too.<\/p>\n<p>&#91;<a href=\"https:\/\/github.com\/git\/git\/compare\/d21d5ddfe675f9dbcdbb94ab01776115a2d1fdde...f05da2b48b48a46db65fc768b3ffecaf996dd655\">source<\/a>, <a href=\"https:\/\/github.com\/git\/git\/compare\/77da6db57f90bb0478df4d2a111363c80f0c0748...5da9560ebc8a089807920a7548141e4e5b60a4dc\">source<\/a>&#93;<\/p>\n<\/li>\n<li>\n<p>While we&#8217;re talking about partial clones, now is a good time to mention partial <em>bundles<\/em>, which are new in Git 2.36. You may not have heard of <a href=\"https:\/\/git-scm.com\/book\/en\/v2\/Git-Tools-Bundling\">Git bundles<\/a>, which is a different way of transferring around parts of your repository.<\/p>\n<p>Roughly speaking, a bundle combines the data in a <a href=\"https:\/\/git-scm.com\/book\/en\/v2\/Git-Internals-Packfiles\">packfile<\/a>, along with a list of references that are contained in the bundle. This allows you to capture information about the state of your repository into a single file that you can share. For example, the Git project uses bundles to <a href=\"https:\/\/github.com\/git\/git\/blob\/v2.36.0\/Documentation\/howto\/coordinate-embargoed-releases.txt#L59-L65\">share embargoed security releases with various Linux distribution maintainers<\/a>. This allows us to send all of the objects which comprise a new release, along with the tags that point at them in a single file over email.<\/p>\n<p>In previous releases of Git, it was impossible to prepare a filtered bundle which you could apply to a partial clone. In Git 2.36, you can now prepare filtered bundles, whose contents are unpacked as if they arrived during a partial clone<sup id=\"fnref-64204-3\"><a href=\"#fn-64204-3\" class=\"jetpack-footnote\" title=\"Read footnote.\">3<\/a><\/sup>. You can&#8217;t yet initialize a new clone from a partial bundle, but you can use it to fetch objects into a bare repository:<\/p>\n<pre><code class=\"language-ShellSession\">$ git bundle create --filter=blob:none ..\/partial.bundle v2.36.0\n$ cd ..\n$ git init --bare example.repo\n$ git fetch --filter=blob:none ..\/partial.bundle 'refs\/tags\/*:refs\/tags\/*'\n[ ... ]\nFrom ..\/example.bundle\n* [new tag]             v2.36.0 -&gt; v2.36.0\n<\/code><\/pre>\n<p>&#91;<a href=\"https:\/\/github.com\/git\/git\/compare\/b6763af74ba55570deae38ce118c1d803d7b825c...86fdd94d723b7fa1870a64e8080d3540a434f29b\">source<\/a>, <a href=\"https:\/\/github.com\/git\/git\/compare\/1041d58b4d9c587b2b6c76c3dfb14fbe78ccf196...5cb28270a1ff94a0a23e67b479bbbec3bc993518\">source<\/a>&#93;<\/p>\n<\/li>\n<li>\n<p>Lastly, let&#8217;s discuss a bug fix concerning Git&#8217;s <a href=\"https:\/\/github.blog\/2021-04-29-scaling-monorepo-maintenance\/\">multi-pack reachability bitmaps<\/a>. If you have started to use this new feature, you may have noticed a handful of new files in your <code>.git\/objects\/pack<\/code> directory:<\/p>\n<pre><code class=\"language-ShellSession\">$ ls .git\/objects\/pack\/multi-pack-index*\n.git\/objects\/pack\/multi-pack-index\n.git\/objects\/pack\/multi-pack-index-33cd13fb5d4166389dbbd51cabdb04b9df882582.bitmap\n.git\/objects\/pack\/multi-pack-index-33cd13fb5d4166389dbbd51cabdb04b9df882582.rev\n<\/code><\/pre>\n<p>In order, these are: the <a href=\"https:\/\/git-scm.com\/docs\/multi-pack-index\">multi-pack index<\/a> (MIDX) itself, the reachability bitmap data, and the reverse-index which tells Git which bits correspond to what objects in your repository.<\/p>\n<p>These are all associated back to the MIDX via the MIDX&#8217;s <a href=\"https:\/\/en.wikipedia.org\/wiki\/Checksum\">checksum<\/a>, which is how Git knows that the three belong together. This release fixes a bug where the <code>.rev<\/code> file could fall out-of-sync with the MIDX and its bitmap, leading Git to report incorrect results when using a multi-pack bitmap. This happens when changing the object order of the MIDX without changing the set of objects tracked by the MIDX.<\/p>\n<p>If your <code>.rev<\/code> file has a modification time that is significantly older than the MIDX and <code>.bitmap<\/code>, you may have been bitten by this bug<sup id=\"fnref-64204-4\"><a href=\"#fn-64204-4\" class=\"jetpack-footnote\" title=\"Read footnote.\">4<\/a><\/sup>. Luckily this bug can be resolved by dropping and regenerating your bitmaps<sup id=\"fnref-64204-5\"><a href=\"#fn-64204-5\" class=\"jetpack-footnote\" title=\"Read footnote.\">5<\/a><\/sup>. To prevent a MIDX bitmap and its <code>.rev<\/code> file from falling out of sync again, the contents of the <code>.rev<\/code> are now included in the MIDX itself, forcing the MIDX&#8217;s checksum to change whenever the object order changes.<\/p>\n<p>&#91;<a href=\"https:\/\/github.com\/git\/git\/compare\/90b7153806af46ca62b85a92a2810015be2453d4...f8b60cf99b0ab10d915c7bfd4802a1af45d0d439\">source<\/a>&#93;<\/p>\n<\/li>\n<\/ul>\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\u2019s just a sample of changes from the latest release. For more, check out the <a href=\"https:\/\/github.com\/git\/git\/blob\/v2.36.0\/Documentation\/RelNotes\/2.36.0.txt\">release notes for 2.36<\/a>, or <a href=\"https:\/\/github.com\/git\/git\/tree\/v2.36.0\/Documentation\/RelNotes\">any previous version<\/a> in the Git repository.<\/p>\n<div class=\"footnotes\">\n<hr \/>\n<ol>\n<li id=\"fn-64204-1\">\nYou can ask for other attributes, too, like <code>%(objectsize:disk)<\/code> which shows how many bytes it takes Git to store the object on disk (which can be smaller than <code>%(objectsize)<\/code> if, for example, the object is stored as a <a href=\"https:\/\/git-scm.com\/book\/en\/v2\/Git-Internals-Packfiles\">delta<\/a> against some other, similar object).&#160;<a href=\"#fnref-64204-1\" title=\"Return to main content.\">&#8617;<\/a>\n<\/li>\n<li id=\"fn-64204-2\">\nThis isn&#8217;t quite true, because of things like <a href=\"https:\/\/git-scm.com\/docs\/shallow\">shallow<\/a> and <a href=\"https:\/\/git-scm.com\/docs\/partial-clone\">partial clones<\/a>, along with <a href=\"https:\/\/git-scm.com\/docs\/git-replace\">grafts<\/a>, but the assumption is good enough for our purposes here. What matters it that outside of scenarios where we expect to be missing objects, the only time we don&#8217;t have a reachability closure is when the repository itself is corrupt.&#160;<a href=\"#fnref-64204-2\" title=\"Return to main content.\">&#8617;<\/a>\n<\/li>\n<li id=\"fn-64204-3\">\nIn Git parlance, this would be a packfile from a <a href=\"https:\/\/git-scm.com\/docs\/partial-clone\">promisor remote<\/a>.&#160;<a href=\"#fnref-64204-3\" title=\"Return to main content.\">&#8617;<\/a>\n<\/li>\n<li id=\"fn-64204-4\">\nThis isn&#8217;t entirely fool-proof, since it&#8217;s possible  way of detecting that this bug occurred, since it&#8217;s possible your bitmaps were rewritten after first falling out-of-sync. When this happens, it&#8217;s possible that the corrupt bitmaps are propagated forward when generating new bitmaps. You can use <code>git rev-list --test-bitmap HEAD<\/code> to check if your bitmaps are OK.&#160;<a href=\"#fnref-64204-4\" title=\"Return to main content.\">&#8617;<\/a>\n<\/li>\n<li id=\"fn-64204-5\">\nBy first running <code>rm -f .git\/objects\/pack\/multi-pack-index*<\/code>, and then<br \/>\n<code>git repack -d --write-midx --write-bitmap-index<\/code>.&#160;<a href=\"#fnref-64204-5\" 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! Take a look at some of our highlights on what&#8217;s new in Git 2.36.<\/p>\n","protected":false},"author":1282,"featured_media":64224,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_gh_post_show_toc":"no","_gh_post_is_no_robots":"","_gh_post_is_featured":"no","_gh_post_is_excluded":"no","_gh_post_is_unlisted":"","_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\/2022\/01\/git-thumbnail.png","_gh_post_sq_img_id":"62621","_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":"","_gh_post_recirc_col_1":"","_gh_post_recirc_col_2":"","_gh_post_recirc_col_3":"","_gh_post_recirc_col_4":"","_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-64204","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 v27.7 (Yoast SEO v27.7) - https:\/\/yoast.com\/product\/yoast-seo-premium-wordpress\/ -->\n<title>Highlights from Git 2.36 - The GitHub Blog<\/title>\n<meta name=\"description\" content=\"Another new release of Git is here! Take a look at some of our highlights on what&#039;s new in Git 2.36.\" \/>\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-36\/\" \/>\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.36\" \/>\n<meta property=\"og:description\" content=\"Another new release of Git is here! Take a look at some of our highlights on what&#039;s new in Git 2.36.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/github.blog\/open-source\/git\/highlights-from-git-2-36\/\" \/>\n<meta property=\"og:site_name\" content=\"The GitHub Blog\" \/>\n<meta property=\"article:published_time\" content=\"2022-04-18T16:44:50+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2022-04-19T15:39:26+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/github.blog\/wp-content\/uploads\/2022\/04\/git-2.36.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:description\" content=\"Another new release of Git is here! Take a look at some of our highlights on what&#039;s new in Git 2.36.\" \/>\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=\"16 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-36\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/github.blog\\\/open-source\\\/git\\\/highlights-from-git-2-36\\\/\"},\"author\":{\"name\":\"Taylor Blau\",\"@id\":\"https:\\\/\\\/github.blog\\\/#\\\/schema\\\/person\\\/f2a5dc09d09f41c8c731679cc07da524\"},\"headline\":\"Highlights from Git 2.36\",\"datePublished\":\"2022-04-18T16:44:50+00:00\",\"dateModified\":\"2022-04-19T15:39:26+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/github.blog\\\/open-source\\\/git\\\/highlights-from-git-2-36\\\/\"},\"wordCount\":2925,\"image\":{\"@id\":\"https:\\\/\\\/github.blog\\\/open-source\\\/git\\\/highlights-from-git-2-36\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/github.blog\\\/wp-content\\\/uploads\\\/2022\\\/04\\\/git-2.36.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-36\\\/\",\"url\":\"https:\\\/\\\/github.blog\\\/open-source\\\/git\\\/highlights-from-git-2-36\\\/\",\"name\":\"Highlights from Git 2.36 - The GitHub Blog\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/github.blog\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/github.blog\\\/open-source\\\/git\\\/highlights-from-git-2-36\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/github.blog\\\/open-source\\\/git\\\/highlights-from-git-2-36\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/github.blog\\\/wp-content\\\/uploads\\\/2022\\\/04\\\/git-2.36.png?fit=4800%2C2520\",\"datePublished\":\"2022-04-18T16:44:50+00:00\",\"dateModified\":\"2022-04-19T15:39:26+00:00\",\"author\":{\"@id\":\"https:\\\/\\\/github.blog\\\/#\\\/schema\\\/person\\\/f2a5dc09d09f41c8c731679cc07da524\"},\"description\":\"Another new release of Git is here! Take a look at some of our highlights on what's new in Git 2.36.\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/github.blog\\\/open-source\\\/git\\\/highlights-from-git-2-36\\\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/github.blog\\\/open-source\\\/git\\\/highlights-from-git-2-36\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/github.blog\\\/open-source\\\/git\\\/highlights-from-git-2-36\\\/#primaryimage\",\"url\":\"https:\\\/\\\/github.blog\\\/wp-content\\\/uploads\\\/2022\\\/04\\\/git-2.36.png?fit=4800%2C2520\",\"contentUrl\":\"https:\\\/\\\/github.blog\\\/wp-content\\\/uploads\\\/2022\\\/04\\\/git-2.36.png?fit=4800%2C2520\",\"width\":4800,\"height\":2520},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/github.blog\\\/open-source\\\/git\\\/highlights-from-git-2-36\\\/#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.36\"}]},{\"@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.36 - The GitHub Blog","description":"Another new release of Git is here! Take a look at some of our highlights on what's new in Git 2.36.","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-36\/","og_locale":"en_US","og_type":"article","og_title":"Highlights from Git 2.36","og_description":"Another new release of Git is here! Take a look at some of our highlights on what's new in Git 2.36.","og_url":"https:\/\/github.blog\/open-source\/git\/highlights-from-git-2-36\/","og_site_name":"The GitHub Blog","article_published_time":"2022-04-18T16:44:50+00:00","article_modified_time":"2022-04-19T15:39:26+00:00","og_image":[{"width":4800,"height":2520,"url":"https:\/\/github.blog\/wp-content\/uploads\/2022\/04\/git-2.36.png?fit=4800%2C2520","type":"image\/png"}],"author":"Taylor Blau","twitter_card":"summary_large_image","twitter_description":"Another new release of Git is here! Take a look at some of our highlights on what's new in Git 2.36.","twitter_misc":{"Written by":"Taylor Blau","Est. reading time":"16 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/github.blog\/open-source\/git\/highlights-from-git-2-36\/#article","isPartOf":{"@id":"https:\/\/github.blog\/open-source\/git\/highlights-from-git-2-36\/"},"author":{"name":"Taylor Blau","@id":"https:\/\/github.blog\/#\/schema\/person\/f2a5dc09d09f41c8c731679cc07da524"},"headline":"Highlights from Git 2.36","datePublished":"2022-04-18T16:44:50+00:00","dateModified":"2022-04-19T15:39:26+00:00","mainEntityOfPage":{"@id":"https:\/\/github.blog\/open-source\/git\/highlights-from-git-2-36\/"},"wordCount":2925,"image":{"@id":"https:\/\/github.blog\/open-source\/git\/highlights-from-git-2-36\/#primaryimage"},"thumbnailUrl":"https:\/\/github.blog\/wp-content\/uploads\/2022\/04\/git-2.36.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-36\/","url":"https:\/\/github.blog\/open-source\/git\/highlights-from-git-2-36\/","name":"Highlights from Git 2.36 - The GitHub Blog","isPartOf":{"@id":"https:\/\/github.blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/github.blog\/open-source\/git\/highlights-from-git-2-36\/#primaryimage"},"image":{"@id":"https:\/\/github.blog\/open-source\/git\/highlights-from-git-2-36\/#primaryimage"},"thumbnailUrl":"https:\/\/github.blog\/wp-content\/uploads\/2022\/04\/git-2.36.png?fit=4800%2C2520","datePublished":"2022-04-18T16:44:50+00:00","dateModified":"2022-04-19T15:39:26+00:00","author":{"@id":"https:\/\/github.blog\/#\/schema\/person\/f2a5dc09d09f41c8c731679cc07da524"},"description":"Another new release of Git is here! Take a look at some of our highlights on what's new in Git 2.36.","breadcrumb":{"@id":"https:\/\/github.blog\/open-source\/git\/highlights-from-git-2-36\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/github.blog\/open-source\/git\/highlights-from-git-2-36\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/github.blog\/open-source\/git\/highlights-from-git-2-36\/#primaryimage","url":"https:\/\/github.blog\/wp-content\/uploads\/2022\/04\/git-2.36.png?fit=4800%2C2520","contentUrl":"https:\/\/github.blog\/wp-content\/uploads\/2022\/04\/git-2.36.png?fit=4800%2C2520","width":4800,"height":2520},{"@type":"BreadcrumbList","@id":"https:\/\/github.blog\/open-source\/git\/highlights-from-git-2-36\/#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.36"}]},{"@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_featured_media_url":"https:\/\/github.blog\/wp-content\/uploads\/2022\/04\/git-2.36.png?fit=4800%2C2520","jetpack_shortlink":"https:\/\/wp.me\/pamS32-gHy","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/github.blog\/wp-json\/wp\/v2\/posts\/64204","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=64204"}],"version-history":[{"count":30,"href":"https:\/\/github.blog\/wp-json\/wp\/v2\/posts\/64204\/revisions"}],"predecessor-version":[{"id":64888,"href":"https:\/\/github.blog\/wp-json\/wp\/v2\/posts\/64204\/revisions\/64888"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/github.blog\/wp-json\/wp\/v2\/media\/64224"}],"wp:attachment":[{"href":"https:\/\/github.blog\/wp-json\/wp\/v2\/media?parent=64204"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/github.blog\/wp-json\/wp\/v2\/categories?post=64204"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/github.blog\/wp-json\/wp\/v2\/tags?post=64204"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/github.blog\/wp-json\/wp\/v2\/coauthors?post=64204"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}