Rebinding Keys For Quickly Resolving Conflicts in GoLand

I’m dealing with a lot of conflicts today as I try to clear a backlog of Git rebases in my to-do pile. I’ve been using GoLand to do this, as my current Git “mergetool” is configured to Vimdiff for some reason1 and I’m not really bothered to find some other tool, at least not yet. GoLand does a pretty good job.

Unfortunately, the default key-bindings for resolving conflicts in GoLand is far from good. About the quarter of actions are bound to keys that make sense. Half the actions, like ignoring hunks, are not bound to anything, while the last quarter are bound to keys that result in a suboptimal experience. For example, the key to accept changes for a delta use the arrow keys, whereas the key to go to the next delta is F7. What a strange default. I’d have to constantly move my hand off the arrow keys over to the Fn row if I want to go through and fix each delta. This, plus moving over to the mouse to select an action not bound to a key, makes resolving conflicts really slow.

Fortunately GoLand allows remapping keys to pretty much anything, so I’d figured it’s time to fix this problem. I set about coming up with a nicer key-mapping scheme for resolving conflicts. I wanted to come up with one that adhered to these principals as best it can:

  1. My hands must not move from where they rest on the keyboard for almost the entire time a file is being worked upon. The only exception are actions that are invoked less frequently and have a large radius of change โ€” such as the accepting all changes from the left or the right. I’d figured it’s still okay to use the mouse for those.
  2. The arrow keys should be used for navigation (go here) and for addressing (this one).
  3. The modifier keys should be used for choosing the operation, such as going to the next delta, or choosing or ignoring a change.

Here’s the key-map I’ve come up with. The actions marked with an asterisk were the one’s that I needed to change. All these actions are within the “Version Control Systems > Diff & Merge” group within the “Keymap” section in preferences.

Action Key Binding
Previous Difference * ^โŒ˜โ†‘
Next Difference * ^โŒ˜โ†“
Previous Conflict * ^โŒฅโŒ˜โ†“
Next Conflict * ^โŒฅโŒ˜โ†“
Accept Left Side ^โŒ˜โ†’
Accept Right Side ^โŒ˜โ†
Ignore Left Side * โ‡งโŒ˜โ†
Ignore Right Side * โ‡งโŒ˜โ†’
Confirm Merge โŒ˜Enter

I’ve only tried this out as part of a single rebasing session, but already it feels so much faster. It’s taken me probably half the time to go through each file now, maybe even better. I also like the fact that most of the time I only need to hold down Ctrl and Cmd key, and use the arrows to move to and accept changes. Ignoring a change involves moving my left pinky to the Shift key, adding a bit of resistance to indicate an action that requires just that little bit more care.

We’ll see how this goes as I deal with future conflicts, and I may make a change or to. But this is looking really promising.

One last note: this was done in GoLand but I’d imagine it’s possible to set this key-mapping up in most, if not all, of JetBrain’s other IDEs.


  1. It was previously something else, and I have no idea how it got changed. ↩︎

Those “Accept Yours” & “Accept Theirs” buttons in GoLand’s conflicts dialog are a bit of a tease. Might be that I’m missing something (which is possible) but I though a file appearing here means that I manually need to review it. Would anyone blindly accept changes like this?

Accept Yours, Accept Theirs & Merge buttons in Conflict resolution dialog

Oof, spent all morning updating and rebasing out-of-date pull requests. Only got through half of them so far. This project is pretty fast pace at the moment, so conflicts are expected. But many of these are PRs I been neglecting until now, so it’s still mostly my own doing. ๐Ÿ˜ฎโ€๐Ÿ’จ

Here’s today’s instalment of Why Didn’t I Think of This Soonerโ„ข.

I’ve got into the habit of squashing commits before I push them as part of a pull request. In order to run the command I use to do this โ€” git rebase -i HEAD~n โ€” I need to know the number of commits I want to squash (this will be the value of n).

Fortunately, I’ve got into the habit of prefixing each commit message with the Jira task number. For example, I may write a commit message with the first line being ABC-123: fixed a bug in the thing, followed by a more detailed list of changes. I do for every commit, even for those “checkpoint commits” I make before changing branches.

So all I need to do to get the number of commits I need to squash is to simply count up all the commits that start with the Jira task number. For all this time, the way I do this is to run git log to open up the history in Vim, and manually count the number of commit messages that began with the particular Jira task number.

Today, I remembered that I could use a shell pipeline to do the same thing:

git log | grep ABC-123 | wc -l

which would save me stack-loads of time and potential mistakes.

Wish I thought of this sooner. ๐Ÿคฆ

I’m moving the posts I had on my wiki to this blog and I’m shutting the wiki down.

I never really used the wiki a lot โ€” in fact, the last two posts were the only pages that were on there (the rest were all links). This was partly because I never got around to setting up backups (this was a pretty big reason why I didn’t put anything I wanted to keep there), but also because I found other places to document things. Anything related to software development I found myself just posting it here. Things that related to projects that I wanted to keep private, I wrote in Day One. So nothing really went into the wiki at all.

I did use the wiki a lot to keep bookmarks to guides and resources I occasionally need to lookup. I think, going forward, I’ll just keep these links as a page on this site. I’m in Micro.blog almost every day so I imagine the amount of extra effort needed to keep this page up-to-date will be low. One less site to visit and maintain. ๐Ÿ™‚

๐Ÿ”— A delightful reference for HTML Symbols, Entities and ASCII Character Codes

A great reference site I stumbled along when I was trying to find the perfect arrow to include in a webpage. Nice, clean, and quite comprehensive. No awful ads either, which is a breath of fresh air.

Dynamo-Browse: Using The Back-Stack To Go Forward

More work on Audax toolset. Reengineered the entire back-stack in dynamo-browse to support going forward as well as backwards, much like going forward in a web-browser. Previously, when going back, the current “view snapshot” was being popped off the stack and lost forever (a “view snapshot” is information about the currently viewed table, including the current query and filter if any are set). But I’d need to maintain these view snapshot if I wanted to add going forward as well.

So this evening, I changed it this such that view snapshots were no longer being deleted. Instead, there is now a pointer to the current view snapshot that will go up or down the stack when the user wants to go backwards or forwards. This involved changing the back-stack from a single-linked list to a doubly-linked list, but that was pretty straightforward. The logic to pop snapshots from the stack hasn’t been removed: in fact, it has been augmented so that it can now remove the entire head up to the current view snapshot. This happens when the user goes backwards a few times, then runs a new query or sets a new filter, again much like a web-browser where going backwards a few times, then clicking a link, will remove any chance of going forward from that point.

Last thing I changed this evening was to restore the last viewed table, query or filter when relaunching dyanmo-browse using an existing workspace. This works quite nicely with the back-stack as it works now: it just needs to read the view snapshot at the head.

Second breakfast time.

Sulphur-crested cockatoos feeding outside a different house.

Breakfast time.

Sulphur-crested cockatoos feeding outside someones house.

One thing I miss about working in Java is that the JVM comes out of the box with an interactive debugger. With just a few switches, you can enable a remote debugging session without having to do anything special with your build.

As far as I can tell, such a thing is not possible in Go, at least by default. This means that if you need to debug something running in something like Kubernetes, you either need to bundle something like delve in your container โ€” which might not be possible if you don’t control the entire build pipeline โ€” or you’re out of luck and need to resort to print-level debugging.

I wonder if people who say they hate bagpipes are actually saying they don’t like the music traditionally played with bagpipes. I’m not one that likes that sort of music either. But Mike Oldfield is a favourite artist of mine, and he’s not afraid of using a fair bit of bagpipe.

Went to the Union Club Hotel, in Collingwood, with a few friends for dinner tonight. Apparently quite popular with footy fans, which I did not know: there was a group that was quite roudy when I arrived. Fortunately things settled down when we ate dinner, which was pretty good.

Off to breakfast this morning.

Track running through forest

Met some locals on the way.

Rainbow lorikeets and a galllah sitting on a fence

Day One needs a โ€œthis time one day agoโ€ section, where you look at the entries from yesterday, realised youโ€™ve made all these spelling and grammatical errors, and you go ahead and fix them. I sure know I can make use of such a feature.

Adding Copy-To-Clipboard And Layout Changes In Dynamo-Browse

Spent some more time on dynamo-browse this morning, just a little bit.

Got one new feature built and merged to main, which is the ability to copy the displayed item to the pasteboard by pressing c. This is directly inspired by a feature in K9S, which allows you to copy the logs of a running pod to the pasteboard (I use this feature all the time). The package I’m using to access the pasteboard is github.com/golang-design/clipboard, which seems to offer a nice cross-platform approach to doing this.

The copied item is not meant for machine use. It’s exactly what’s displayed in the item viewport and is intended for tracking items that change over time. What I’ve found myself doing, when I need to track such an item, is to manually select it with Terminal and pasting it to an untitled textedit window. I do this again when the item changes until I’m ready to eye the changes manually. It’s not sophisticated, but it tends to work. And although this feature is not a full-blown item comparer, it will make this use case a little easier. Plus, it will copy the entire image, not just the lines displayed when a viewed item is too large for the viewport.

Speaking of which, the other thing I started working on today was on allowing the user to resize the item viewport to take up more of the screen. At the moment, the displayed item viewport takes up the bottom 14 lines of the screen, and is not resizable. Naturally, for large items, this is not large enough, and having the ability to resize this viewport would be a good thing to have.

I’ve been thinking about the best way to handle this, and I’ve decided that an approach similar to how Vim does this โ€” where you need to press a key-chord followed by a number to move the vertical split between two views โ€” would be a little to annoying here. Too much fine grain control for when you just need the viewport bigger. So, I’m opting for a more course-grain approach, where you simply press w and the viewport size will cycle amongst 5 different sizes:

  • 14 rows at the bottom of the screen (the default)
  • Half the screen
  • All but the top 6 rows of the screen, so you can still see a bit of the table view
  • The entire screen (i.e. hiding the table view)
  • Completely hidden (i.e. the table view takes up the entire screen).

Doing this will not necessarily steal focus from the table view: even if shown the entire screen, you can still go through each item by pressing Up or Down. But you’ll be able to see more of the selected item.

Anyway, that’s the theory. We’ll see how well this works in practice.

Turning Off Shared Command History in Oh My Zsh

TL,DR: add “unsetopt share_history” to your .zshrc file

I’ve been using Oh My Zsh at work for a few months. As far as terminal config managers go, this one works pretty well. But the default configuration does include something which I found quite annoying.

First, a few words on how I use the terminal. I’m in the terminal constantly in my day to day. At the start of the day, I’m creating terminal tabs and running commands to do things like build the project I’m working on, start a testing session, etc. This all starts very ad-hoc, but over time these tabs take on a particular role. I may run make and git in the left-most tab, run tests in the tab next to that, have logs tailing in the one after that, etc. As I start and stop commands in each tab, they all build up a different history, which is usually visible in the terminal output itself. Eventually it comes to the point where in order to run a particular tool, I simply need to switch to the particular tab and press โ†‘ one or two times to get to it.

Installing Oh My Zsh broke this workflow. Out of the box Oh My Zsh enables shared command history across each session, meaning that the commands recalled when pressing โ†‘ are the last commands executed in any tab. This meant that when going through the history, the recalled command would be different from the ones that I’ve entered in the tab I’m in. In addition to this resulting in pressing โ†‘ way more times than I used to โ€” sometimes to the point where I gave up and simply typed the command out again โ€” it also meant that the recalled commands differ from the ones I saw in the tab output itself. This was very jarring.

Fortunately, this feature can be turned off simply by adding the following to your .zshrc file.

unsetopt share_history

I did just this and my old workflow was restored.

I don’t know why shared command history was chosen as the default. Am I in the minority using the terminal this way? Maybe. But I know for certain that this group is larger than a single person. In either case, I’m glad that I was able to disable this “feature”.

The last hold-out.

Deciduous tree with yellow leaves

Discovered something cool on the ATP website. If you play old shows while logged in as a member, you actually get those from the members feed instead of the public one. Not sure if I’m the last person to find this out, but chalk me up as someone delighted by this little feature.

I started seeing job ads for โ€œBlockchain Engineerโ€ on LinkedIn recently. I have no interest in such roles. But I was curious, so I clicked into one to see what it actually entails. Now, LinkedIn is emailing me similar web3 roles, thinking that Iโ€™m interested.

Serves me right. ๐Ÿคฆ

๐Ÿ”— NYC Subway Track Map

Dad and I have been watching YouTube cab-rides of the NYC subway system recently. Part of the fun is trying to understand the various track configurations and how the system operates. The size of the network never ceases to amaze.