In this post I describe one of the features I really like about the JetBrains' Rider IDE: its built-in Git support. I'm a bit fan of command-line Git for many things, but the Git integration in Rider is so good, that I do almost everything from the GUI now. But that doesn't mean I use the mouse—there's shortcuts for everything, so you can keep the efficient keyboard-based workflow command-line enthusiasts crave!
Rider is a paid-product, but as a Microsoft MVP, JetBrains provide a licence free-of charge. If that wasn't the case, I would absolutely purchase a personal license (as I did for Resharper), and they have lots of discounts available if you're a student for example.
Switching to JetBrains Rider
For years I was an avid Resharper (R#) user. I was (like every other R# user) in love with all the additional refactorings R# provided, but despised how slow it made Visual Studio. When JetBrains' Rider first came out, it seemed like the perfect solution—all the power without the lag—but in practice I initially found it lacking in features. Fast-forward, and now it's my daily driver.
It's kind of silly, but one of the things I always struggled with was the Java-based UI, that just didn't look as polished as Visual Studio, and the difference in code-highlighting/theming. If you're like me, just persist with it, I think it's worth the effort!
One of the selling points of Rider, is that it can leverage all the existing tech from JetBrains' other products. For example the database integration (Datagrip) is brilliant, making it easy to query and managed a wide variety of database types. Similarly, the web editor is excellent.
One such built-in feature I use daily is the git integration. Whether it's switching branches, committing, or rebasing, I typically use Rider's built-in Git support.
The command-line vs GUIs
One of the endless (mostly-pointless) debates in software is whether "real" programmers should always use the command line, or whether it's "fine" to use a GUI. As always, there are extreme views on both sides, and the reality likely lies somewhere in the middle.
Proponents of command-line Git advocate for the ability to script command-line interaction and the enhanced power that comes at the command line thanks to all the extra available commands and switches. The main drawback of the command line is that it's really hard to know where to start unless you already know Git.
If you've dabbled with Git, but don't feel like you understand a
rebase(for example), I strongly suggest reading Think like a Git. After reading this 10 years ago, something clicked, and I finally "got it". Maybe it will click for you too!
GUIs are, for the most part, far more discoverable than command-line Git. You're guided towards the common options, and it's harder to make "mistakes". Some features are also just easier to do with a GUI, such as selecting a subset of changed lines in a file to stage. On the other hand, GUIs are typically "slower", requiring UI interaction rather than just typing commands, and may not provide access to the full gamut of Git commands and options.
I like Rider's Git integration, because it lies somewhere in-between. For the most part, I use keyboard shortcuts to navigate the various Git features, falling back to the mouse for features for which it makes sense.
Another important reason to use the built-in Git feature is that Rider seems to prefer it if you do. While you can switch branches using the command line (e.g.
git switch main) this seems to cause Rider to do more work to figure out what's changed than if you switch branches using the IDE.
For the record, Visual Studio similarly has a fit if you change branches for a solution you have open!
Working with Git branches in Rider
In this section I'll describe how I typically work with Git branches using Rider.
Most of the shortcuts I describe are the defaults, but in some cases I've tweaked or added shortcuts.
You can view all the branches for a repository using the shortcut ctrl+shift+`. This opens a dialog box:
As you can see from the above screenshot, this dialog lists all your local (and remote) branches. From here, you can do lots of things:
- View the current checked-out branch (shown at the top of the local branches list, marked with a tag symbol 🏷)
- Create a new branch (more on that later)
- Checkout a specific tag/commit
- Star ⭐ a highlighted branch by pressing space, which keeps the branch at the top of the list
- Do a
git fetchby clicking the blue arrow ↙ at the top of the dialog
You can view individual actions for a specific branch by navigating up and down with the arrow keys and pressing ➡ or Enter on a branch. If you select the currently-checked out branch, as shown below, you'll get the options shown below:
The highlighted "Update" option here effectively does a
git fetch master:master, and fast-forwards or does a merge, depending on your settings.
If you view the options for a branch which is not currently checked out, you'll have many more options:
As before you can navigate these with the arrow keys and select using Enter. If you select the "New branch from 'branch'" option, a new dialog will pop up:
This dialog is pretty self explanatory. You can provide a new name for your branch, select whether or not to immediately switch/checkout to the branch. If you provide the name of a branch that already exists, you can opt to overwrite the existing branch (otherwise creating will be blocked.)
That covers some of the basic git branching operations. Lets move on to the most common Git command: committing your changes.
Committing changes using Rider
One of the most common actions when working with Git is to stage and commit your changes. In this section I show how it works in Rider.
Understanding the "staging" area for Git is often one of the most confusing aspects for newcomers, and often seems like extra unnecessary complexity. And when you're using a GUI, arguably, it is. Instead of having to do "stage" and "commit" as two separate steps (as you generally must from the command line), you can select a subset of files and commit them in one command using a GUI.
You certainly can use the staging are inside Rider, but personally I keep it disabled and use Rider's "changelists" support instead. You can find this setting in File > Settings > Version Control > Git > Enable Staging Area.
You can open the Git commit interface in Rider using ctrl+alt+k. This opens up an interface which shows the list of currently modified/created/deleted files, and a text box for your commit message:
The commit message box is automatically focused, so you can immediately start typing. If everything you want to commit is selected, you can hit the commit button (or use alt+i) to commit your changes.
I prefer to use the non-modal version of the commit interface, which is shown in the above screenshot. If you prefer the modal version, you can toggle it using File > Settings > Version Control > Commit > Use non-modal commit interface.
You can add or remove files from the commit be selecting the check marks from the file list in the commit pane (on the right in the above screen shot). When you highlight a file, the diff is shown in the main editor. There are lots of options for controlling how the diff is displayed. You can use the checkmark ✅ next to a changed section to choose whether it should be included in the commit, or you can use the chevrons ⏩ to the left to revert the change if you prefer.
Above the commit-message box is a checkbox for amending the previous commit:
When you check this box (alt+m) the commit message changes to the previous commit's message, and the file changelist above shows the files that were included in the previous commit (underneath the new changes). This lets you easily add extra files to a commit, and/or easily fix a typo in the previous commit message.
Rebasing commits with Rider
As well basic Git commands like creating branches and committing, you can also you some more advanced commands like
git rebase. I'm a big fan of Rider's rebase functionality, especially when using interactive rebase, as you'll see shortly.
I rebase branches a lot—I like to commit a lot and then tidy them up before creating a PR, to make reviewing easier. For that reason I added my own shortcut for the Git-Rebase command: ctrl+alt+r. This pops up the rebase branch dialog:
As you can see, this is a simple dialog that contains the name of the branch to rebase one. You get auto-complete for the branch name, and if you click "Rebase", effectively runs
git rebase <branch>. Where things get interesting are with the extra options you can select.
Choosing "Modify Options" (or hitting alt+m) opens a dropdown with lots of extra options:
The two options I use all the time are
--interactive. If you're comfortable rebasing, this won't surprise you, but where Rider really shines is the interactive-rebase dialog. If you select the
--interactive option (as I have above) and choose "Rebase" (or hit Enter), you get the interactive-rebase dialog.
This dialog is strongly analogous to the text-only version you get from running
git rebase --interactive from the command line, which opens a text editor containing something like the following:
edit a0f51b6 Update build to .NET 7 and update packages (#93) reword 26037e2 Reduce number of snapshots (#95) pick 3abb1cd Fix deserialization of nullable string IDs (#94) fixup ae5ad85 Use ForAttributeWithMetadataName APIs
But the power of the GUI really comes to the fore, as you can see in the following screenshot:
The commit list on the left of the dialog is analogous the list you see in your text editor when running from the command line. You can perform the usual pick/fixup/squash/edit commands using the actions above, or alternatively (my preference) use the following intuitive shortcuts:
- Pick: The default, but you can also use alt+p
- Edit: alt+e
- Reword: alt+r
- Fixup: alt+f
- Squash: alt+s
- Drop: alt+d
When you select an option that requires updating the commit message (reword/squash) then a text-box opens inline where you can immediately provide the new name (hit ctrl+enter to confirm). Rider won't update any message yet, but will use the new message when performing the rebase.
Another great feature is the ability to view the changes in a given commit. This is something I frequently need, as I try to figure out which commit I want to change😅 Double-clicking one of the files opens the diff-view for the file.
This is one area where I find keyboard-only experience isn't the best—I haven't figured out how to focus the file list using the keyboard to select a file to view! Luckily that's relatively rare, and everything else works with the keyboard only.
Once you're all set, hit Enter or choose "Start Rebasing", and Rider will perform the rebase, using the commit messages you specified, and stopping to let you resolve any merge conflicts or to perform edits as required!
There's loads of other Git features built into Rider I could talk about such as the Log view, but I'll leave it at that for this post. Obviously you can't do everything in Rider—you're not going to be doing a
git filter-branch from inside Rider, and there's only partial support for
--update-refs currently—but for day-to-day tasks, it has most-everything you need!
Hopefully I've whet your appetite, and shown that if you're a Rider user that loves the command-line, it's worth looking into Rider's Git integration and all its associated keyboard shortcuts!
In this post I discussed the Git integration in JetBrains' Rider IDE. One of the reasons some people like using the command-line with Git is the efficiency: you never have to move your hands off the keyboard to use a mouse. With Rider's first-class Git support and extensive shortcuts, you can get many of the same benefits with some really nice value-added by rich GUI features like the built-in diff viewer and interactive-rebase dialog.