
GitHub Copilot Chat beta now available for all individuals
All GitHub Copilot for Individuals users now have access to GitHub Copilot Chat beta, bringing natural language-powered coding to every developer in all languages.
The open source Git project just released Git 2.17.0, with features and bugfixes from over 60 contributors. Here’s our look at some of the most interesting new features from the last few versions of Git.
When you’re reviewing a commit that moves some code, its diff will show a big chunk of lines being deleted in one place and a big chunk of lines appearing elsewhere. The commit message may claim that this was pure code movement, but how can you verify that? And if some lines needed to be changed, how can you easily see which lines?
Git v2.15 offers a new --color-moved
option which colors groups of moved lines differently. Use this option for any command that generates a diff: git diff
, git log -p
, git show
, and so on.
The blue lines show the blocks that were moved verbatim, while the red and green lines show the corrected typo. Note that these aren’t the default colors; we’ve just used them to highlight this simple example. By default, old and new blocks get their own colors, and non-adjacent groups of lines are colored independently. This helps when there are several moved blocks in a single diff. You can configure the colors to match your preferences.
[source]
One reason that Git is fast is avoiding unnecessary disk reads. For example, when you run git status
, Git uses the stat()
system call to check whether each file’s size or timestamp has changed since the last time Git checked. If not, it assumes that its contents haven’t changed and avoids reading the file contents at all.
This helps a lot, but it still requires Git to call stat()
once for every file in your working copy. If you have a lot of files, that work adds up. This can be further exacerbated if you’re on an operating systems where stat()
is more expensive.
Git v2.16 adds a new fsmonitor
hook that relies on the operating system to tell us what has changed. Doing so allows us to avoid the repeated stat()
calls, making the work proportional to the number of changed files, not the total size of the repository.
The hook provides a generic interface into which you can plug any tool, but most people will want to use the watchman
tool, which runs on
Linux, macOS, and Windows. Git ships with a sample hook for using watchman
.
[source]
Have you ever gotten hold of an object hash for a blob or tree like c1626490c2
and had no idea what path it corresponds to, or in which commits it could be found? Perhaps somebody else mentioned the object, or a Git command lke fsck
complained about it.
There’s no single defined answer for these questions. Because Git commits are snapshots of the tree, an object may appear in many commits: it may get introduced in commit A
, then persist in commit B
that only touches another file, and then finally go away in commit C
. Likewise, an object may appear at multiple paths if it’s renamed or copied.
Getting this information used to require a pipeline of arcane commands. But now you can use --find-object
to select the commits you want and display them however you like.
Here we’ve used --raw
to easily show that these commits are the ones where the object comes and goes (and that Git omitted any in the middle which didn’t affect it). You might be more likely to use -p
to show the full diff.
[source]
When you search for a string with git grep
, it’s often helpful to see the surrounding context. You can use -C 2
to tell Git to show you two lines of context on either side, but it’s hard to know the right number in advance without ending up with too much or too little context.
For many years, git grep
has had a --function-context
option (and its shorter alias -W
) to show you the whole function surrounding each match. This uses language-specific patterns if you have the appropriate gitattributes defined, or it can fall back to some generic heuristics.
Since Git v2.16, it can now also find and show comments before the start of a function, which provides even more context for your matches.
Without -W
, we’re left with very little information about how the function is used. With it, we can see the whole function, including its accompanying comment.
[source]
--indent-heuristic
option we mentioned in our v2.11 post has now become the default. If you’ve never tried it, you may now see your diffs subtly improved. Automatically!
[source]
[source]
git grep -P
by up to 70%.
[source]
*.c
no longer require you to enter --
on the command line. That convenience has been extended to “magic” pathspecs, letting you more easily write exotic matches like git ls-files ':attr(filter=lfs)'
.
[source]
cat .git/rebase-apply/patch
? Or sometimes /rebase-merge/
, depending on how rebase was invoked? Now you can use git rebase --show-current-patch
, and even tab-complete it.
[source]
git log --format='%h%n%(trailers:only,unfold)'
to get just the key: value
trailers, with any whitespace normalized.
git add
on the files? Fixing that used to be a pain,git add --renormalize
.
[source]
git log
by setting the pager.log
config option. But this was useless for commands like git tag
, which sometimes generate a lot of output (when listing tags) but other times generate none (when creating a tag, in which case having to quit the pager is an irritation). The tag
, branch
, and config
commands have all learned only to invoke the pager in their “list” modes, and now default to paging in those modes.
That’s just a sampling of changes from the last few versions. Read the full release notes for 2.17, or find the release notes for previous versions in the Git repository.