<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="3.10.0">Jekyll</generator><link href="https://stolee.dev/feed.xml" rel="self" type="application/atom+xml" /><link href="https://stolee.dev/" rel="alternate" type="text/html" /><updated>2025-12-31T13:53:43-05:00</updated><id>https://stolee.dev/feed.xml</id><title type="html">Stolee’s Dev Blog</title><subtitle>The personal developer blog of Derrick Stolee</subtitle><entry><title type="html">Communicating in Pull Requests</title><link href="https://stolee.dev/2025/12/31/pr-communication.html" rel="alternate" type="text/html" title="Communicating in Pull Requests" /><published>2025-12-31T00:00:00-05:00</published><updated>2025-12-31T00:00:00-05:00</updated><id>https://stolee.dev/2025/12/31/pr-communication</id><content type="html" xml:base="https://stolee.dev/2025/12/31/pr-communication.html"><![CDATA[<p>Most software projects gate new contributions by a code review step, and
that’s normally done by pull requests (or equivalently, merge requests).</p>

<p>Projects may also set up additional technical requirements, such as
building and testing the code, performing static style checks, or
even scanning the diff with a generative AI code review bot.</p>

<p>With all of these automated processes, it’s more important than ever to
focus on the <em>primary purpose</em> of pull requests:</p>

<blockquote>
  <p><strong>The main purpose of pull requests is to communicate with the other
humans interacting with the project.</strong></p>
</blockquote>

<p>Many contributors erroneously assume that the purpose of pull requests
is to avoid bugs or regressions. While that’s important, we avoid
regressions by having a robust test suite that is checked before merging.
While sometimes humans can catch bugs, they are incredibly fallible. I
personally believe that <em>code is easier to write than it is to read</em>, so
how can I expect a reviewer to catch something that I didn’t while
writing, building, and running the code locally?</p>

<p>This is where it becomes critical to communicate clearly when presenting
a change to your project.</p>

<p><strong>Every code change has risk.</strong> Why is the expected reward worth that
risk? What have you done to minimize the risk and maximize the value?</p>

<p><strong>Every code change interrupts the mental model of other engineers.</strong> How
can you use your pull request as an opportunity to <em>improve</em> everyone’s
mental model of the project? What concepts and ideas were of utmost
importance, even if you think that most contributors already know it?</p>

<p><strong>Every line of code is technical debt.</strong> You are asking your team to take
ownership of this change into the future. Your new feature is something
that may cause maintenance burden or add complexity to future changes. How
can future contributors make sense of your change and why you made it?</p>

<p>With these things in mind, the most important thing to keep in mind is
that no one understands this section of the code as much as you do in this
moment, <em>including you in the future</em>. You already have a lot of valuable
information in your brain right now. Write it down before it’s too late!</p>

<p>Improving your communication has benefits in a few different directions:</p>

<ul>
  <li><strong>Most Obvious:</strong> You can help the reviewers jump into review with full
context and get to high quality feedback as soon as possible.</li>
  <li><strong>Less Obvious:</strong> You can do a self-review before sharing your change
with your team, helping to improve your own understanding of the problem
and avoiding costly asynchronous feedback loops with the team.</li>
  <li><strong>Most Obscure:</strong> Your future self may stumble on this change again and
will have lost the necessary context that you have right now. Make it
easy to reload that context out of your long-term memory by encoding it
in writing.</li>
</ul>

<p>While taking the time to communicate well may seem like friction to your
development process, this is a critical step to speed up your reviews and
to minimize maintenance costs in the future.</p>

<p>This guide will present some examples of how to communicate well that you
can take back to your team and project. Work with your community to
establish the standards you expect everyone to follow and point a way
forward to improved communication.</p>

<h2 id="opportunities-for-communication">Opportunities for communication</h2>

<p>When working with pull requests, the first thing reviewers see is an
opportunity to set the stage and prepare them to dig into your code change
with confidence.</p>

<p>Let’s review a few common opportunities in every pull request system.</p>

<p><img src="https://stolee.dev/img/pr-description.png" alt="Pull Request Communication Opportunities" /></p>

<center><b>Figure:</b> Opportunities to communicate in a pull request.</center>

<h3 id="use-helpful-titles">Use helpful titles</h3>

<p>When reviewers are perusing a list of pull requests to review, they are
likely drowning in a long list of possible changes. How can you catch the
eye of a reviewer to signal that your change is relevant and valuable?</p>

<p>It can help to start your title with a general area of the project or a
feature name. This can help catch the eye of experts in certain subareas.</p>

<p>Then, create a short descriptive name for the change. Be concise and get
to the core of the change. Think about how you can signal the type of
change:</p>

<ul>
  <li>User facing feature? Describe what a user will be able to do when done.</li>
  <li>Security issue? Start your title with “[URGENT: SECURITY]” or similar.</li>
  <li>Incremental change? Provide a numeral such as “[Feature 4/N]”.</li>
</ul>

<h3 id="link-to-related-work">Link to related work</h3>

<p>Outside of the context that you’ll provide in the description, it can be
helpful to link to work items, issues, or related pull requests. These
links can help unlock a network of related changes and other involved
engineers who have worked in this space before.</p>

<p>These links can be extremely important for leaving breadcrumbs. You can
see whether or not the feature is fully complete with this change or if it
is one of a sequence of changes in this direction. Did we need to rollback
a similar change in the past?</p>

<p>Linked work items can also fill in much of the context that you may not
want to repeat</p>

<h3 id="write-self-contained-descriptions">Write self-contained descriptions</h3>

<p>The bulk of your communication should be done in the pull request
description. This is particularly important as it will also be the basis
of the commit message when your change is merged.</p>

<blockquote>
  <p><strong>Note:</strong> GitHub doesn’t automatically copy your description into the
merge commit message, but you do have an opportunity to copy it yourself.
Azure DevOps does use the pull request title and description as the
commit message when you complete your pull request.</p>
</blockquote>

<p>Expect your reviewers to read the description from top to bottom. What is
the most important thing to say first? How can you <strong>tell a story</strong> that
will help them understand the change?</p>

<p>I’ve developed a structure that I like to use over and over again:</p>

<ol>
  <li>
    <p><strong>Start with “why”.</strong> What context has led to this change being
necessary or valuable? Are users complaining about a bug, or did you
happen to notice something when doing your own testing? Is this a
funded feature or are you volunteering to pay down tech debt?</p>
  </li>
  <li>
    <p><strong>Describe the change.</strong> What code was changed? Was it easy to find
the way forward or did it take digging?</p>
  </li>
  <li>
    <p><strong>Demonstrate the impact.</strong> What’s the proof that this does what you
say it does? What tests did you add that would fail before but pass
now? Did you do performance tests? Do you have screenshots of the
new behavior?</p>
  </li>
  <li>
    <p><strong>Consider alternatives.</strong> (Optional) Sometimes, there’s one clear way
to accomplish a task. Often, there are multiple ways a problem could
have been solved. Why did you pick this one? Did you try something
else before going down this road? Including these details could avoid
a costly round of async feedback recommending alternatives.</p>
  </li>
</ol>

<p>After this free-form description is a good time to fill out a pull request
template. These templates are specified by the repository owners and
frequently include checklists and questions that are important for every
change author to consider and demonstrate that they have understood the
requirements.</p>

<p>If you are in the privileged position to be designing a pull request
template, make sure that every item you put in that template has a real
purpose. If you are making a change and come across a pull request
template, fill it out with the perspective that every line is there for a
reason (and usually that reason is an incident due to a bad code change).</p>

<h4 id="a-brief-aside-about-templates">A brief aside about templates</h4>

<p>Sometimes templates and checklists can feel tedious or restrictive. They
don’t communicate <em>trust</em> in the engineers making changes in the repo.</p>

<p>I’d like to counter any concerns about trust with this idea:</p>

<center><i>Checklists are hard-earned wisdom, externalized.</i></center>
<p><br /></p>

<p>Every checklist is an opportunity to double-check yourself while you’re in
the thick of things. While working on a problem, you may be too close to
it to see the forest through the trees.</p>

<p>I know this due to hard experience. Please indulge me as I tell you a
story:</p>

<p>I was once tasked with creating templates for “production change records”
which were going to become a requirement to improve availability issues in
our product. I was interested in the idea and started writing down all of
the standard questions I would ask about safe deployment based on my own
experiences. <em>These were all things I already knew</em>. Once I had encoded
these concepts into a document for review, I decided to lead by example
and apply the checklist to a change I had already submitted for review.</p>

<p><strong>I was missing important details.</strong></p>

<p>That’s right: by using my own checklist, I caught myself missing an
important detail in my own change. This is why encoding best practices
into written form is critical to avoiding human error.</p>

<p>Humans are fallible. We have limited working memory in our brains. We
need strategies to externalize information to assist with recall from
long-term memory. I found that externalizing my own experiences into a
checklist of questions led to an improved outcome for changes I was
making. I’m confident that this will help most software engineers, too.</p>

<h3 id="use-draft-pull-requests">Use draft pull requests</h3>

<p>The state of the PR may also be important. Is it a draft that is looking
for high-level feedback and not a full review? Are there tags about
impacted areas? Is it urgent for deadlines, hotfixing, or security
reasons?</p>

<h3 id="use-the-pull-request-discussion">Use the pull request discussion</h3>

<p>Depending on what you’re trying to communicate, it may be helpful to add
comments into your pull request discussion that don’t make sense to keep
in the pull request description.</p>

<p>For example, you could pre-load discussion with requests for what
reviewers should focus on. These comments could even highlight the most
critical code paths as a good place to start before going through the rest
of the changes and test code.</p>

<p>Sometimes you’ll want to post a change for full review but also block the
change on your own comment regarding some final round of performance
testing.</p>

<p>During the review, you can use emoji to indicate “I’ve applied this advice
locally” while waiting to resolve a comment until you’ve pushed a change
that has the full reaction.</p>

<h3 id="other-communication">Other communication</h3>

<p>When you’re working on a team, there are many ways that you can communicate
your change. Email, teams, chatting in hallways, pairing sessions are all
informal outlets for communication and can provide valuable context such
as “I need early feedback on this direction; please ignore style issues”
or “This change is very low risk, can I get a quick look?”</p>

<p>Keep in mind that “if it’s not in the PR, then it didn’t happen” in terms
of the official record. The pull request review sequence itself is an
important historical record of its own that may need to be referenced in
the future. I’ve found myself inspecting a change and tracking down the
original pull request and reading the discussion to find out how they
landed on that direction (or worse: found that there was no discussion and
maybe the review wasn’t very careful).</p>

<h2 id="where-i-learned-these-things">Where I learned these things</h2>

<p>It’s important to show my work, so let me briefly describe how I came to
have strong opinions about communication here.</p>

<p>Before I was an engineer, I was an academic. My career was built around
sharing knowledge and teaching others. Even within that space, every
research paper or grant proposal I wrote had to justify why the
contribution was important and why it was worth the readers’ time.</p>

<p>The skills I learned there became valuable when I changed careers to
software engineering, starting on the Azure Repos backend team. Working on
a massive scale source control system had very high risk concerns around
protecting user data. Correctness, resiliency, and privacy were critical
for every change. That team already had high standards for reviews, which
taught me both how to review code critically and how to present my code in
a reviewable way.</p>

<p>My next career shift included moving from the Git server to the open-source
Git community, working on client side performance. While I thought that
the Azure Repos team had high standards, the Git community was a step
beyond that. There were two critical differences working with the Git
community:</p>

<ol>
  <li>
    <p>Every part of the change is up for review, including every commit
message and the organization of commits into small pieces.</p>
  </li>
  <li>
    <p>There is no agreed-upon backlog to lean on for why the changes should
happen. Every patch series is a request for the community to take
ownership of your change.</p>
  </li>
</ol>

<p>These two differences were an interesting challenge and have motivated
much of my philosophy around communicating code changes. While these
standards are on the more extreme side, it is worth considering which of
the requirements are worth keeping for your project and which are needed
only occasionally.</p>

<p>In my career since, I’ve had the opportunity to work with many teams and
many different sets of expectations. In my current role, I jump around
many different repositories and work with many different teams. I find
myself needing to understand new codebases constantly and am missing the
hints left by careful commit messages. When I make a change, I find myself
needing to justify why I’m in their space and providing an unexpected (or
even uninvited) change.</p>

<p>Sometimes, the most important thing I can say in a pull request is “Hi,
I’m new to this space. Here’s what I know for sure and what I am still
unsure about.”</p>

<h2 id="advanced-techniques">Advanced techniques</h2>

<p>The techniques that follow are more sophisticated and may not be necessary
for every project or every change. However, they can be powerful tools when
you need to communicate complex changes or work within specific project
requirements.</p>

<h3 id="advanced-technique-commit-by-commit-review">Advanced Technique: Commit-by-Commit Review</h3>

<p>Some projects, such as Git itself, do review on a commit-by-commit basis.
Git hosts that use pull requests don’t always make commit-by-commit review
easy or necessary, but it can be valuable to use it on occasion.</p>

<p>The trick here is that you need to carefully construct your commits to be
meaningful on their own and tell a story in finer detail than the full
pull request. This comes in handy in a few different cases:</p>

<ul>
  <li>
    <p>There is one very critical piece of logic that you want to highlight for
careful review while the rest of the changes are mostly boilerplate that
can be reviewed quickly.</p>
  </li>
  <li>
    <p>In order to make the change, some large refactoring was needed. Separating
the refactor as its own commit followed by a commit that does the important
logic can help reviewers read the changes with the right level of detail.</p>
  </li>
</ul>

<p>As an example, I wanted to share one of my favorite contributions to the
Git client: making topological sort extremely fast.</p>

<p><img src="https://stolee.dev/img/commit-by-commit.png" alt="Reviewing commit-by-commit" /></p>

<center><b>Figure:</b> Using a cover letter with careful commit messages.</center>

<p>In <a href="https://lore.kernel.org/git/pull.25.git.gitgitgadget@gmail.com/">the mailing list discussion</a>,
the cover letter for a patch series is like a pull
request description and can describe the high-level purpose of the patches.
The cover letter isn’t stored in the final
<a href="https://github.com/git/git/compare/2d3b1c576c85b7f5db1f418907af00ab88e0c303...561b583749b7428f1790f03164d0d0e75be71d7b">sequence of commits</a>.</p>

<p>But in this patch series, there was
<a href="https://github.com/git/git/commit/b45424181e9e8b2284a48c6db7b8db635bbfccc8">one commit that was larger than the rest</a>,
both in terms of the commit message and the code change. This was the
crucial step that essentially reimplemented the old algorithm using a new
structure. However, the commits leading up to that point were valuable to
create some shared code that could be used by both approaches. Doing it in
this way made it clear that this large change was purely new code and not
mutating the older path.</p>

<p>While this is one of my favorite contributions that I’ve ever made, I do
regret that I didn’t take the time to construct parts of the algorithm
across multiple commits, even though the first commits would need to
introduce methods that were not called by anything until the later commits
arrived.</p>

<h3 id="advanced-technique-stacked-pull-requests">Advanced Technique: Stacked Pull Requests</h3>

<p>Reading code is hard. Reading a lot of code is harder. Do your reviewers a
favor and break up large changes into a sequence of smaller changes. When
using pull requests as your quantum of change,
<a href="https://www.git-tower.com/blog/stacked-prs/">stacked pull requests</a> can
tell a multi-part story across several changes.</p>

<p>Showing a pull request stack can be great to help get an early change
merged while also showing that the change is contributing to a long-term
vision (even if that vision is only visible as some draft pull requests
that don’t have everything ready yet). This can avoid reworking an early
data structure or API by demonstrating the current definition is
sufficient for a later application.</p>

<p>I love using stacked pull requests to help me tell a story. It’s a great
way to get some of the benefits of commit-by-commit review while still
using the pull request as the minimum reviewable piece. It’s also easier
to track differences between versions using things like Azure Repos’
iterations.</p>

<p>Stacked pull requests are mostly an informal idea at the moment for most
Git hosts, so you need to do some work yourself to communicate the
existence of the stack and where each pull request fits within the stack.
See the figure below for how I’ve done this in the past.</p>

<p><img src="https://stolee.dev/img/pr-stack-example.png" alt="Describing stacked pull requests" /></p>

<center><b>Figure:</b> Describing a stack of pull requests.</center>

<p>To construct a pull request stack, you create the first layer as normal.
Each next layer is then a pull request into the <em>source</em> branch of the
previous layer, making the presented diff be only the change between those
two branches.</p>

<p>As lower layers complete, you may need to retarget the next layer to the
intended target branch. If you use squash merges, you’ll need to use
something like</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>git rebase --onto &lt;target&gt; &lt;old-branch&gt; &lt;tip-branch&gt;
</code></pre></div></div>

<p>to update your changes into the new target branch that includes the
squashed merge. Using <code class="language-plaintext highlighter-rouge">git rebase --update-refs</code> can help update all of
your local branches in the stack as you change things anywhere in the
stack.</p>

<p>If you’re intrigued by this idea, then you can read more in these places:</p>

<ul>
  <li><a href="https://www.awesomecodereviews.com/best-practices/stacked-prs/">Stacked Pull Requests - The Complete Guide for Developers</a></li>
  <li><a href="https://newsletter.pragmaticengineer.com/p/stacked-diffs">Stacked diffs (and why you should know about them)</a></li>
  <li><a href="https://andrewlock.net/working-with-stacked-branches-in-git-is-easier-with-update-refs/">Working with stacked branches in Git is easier with <code class="language-plaintext highlighter-rouge">--update-refs</code></a></li>
</ul>

<h1 id="establishing-team-standards">Establishing team standards</h1>

<p>I’m done sharing my ideas around effective communication and my bag of
tricks. You can adopt or ignore these as you see fit.</p>

<p>Ultimately, <strong>it is up to you and your team to decide</strong> what standards you
expect of each other.</p>

<p>I challenge you to get together with your team or community and discuss
pull request communication in very clear terms. Discuss what is at stake
when you make changes and find the right level of rigor that you find
important for your context.</p>

<h2 id="communication-retrospective">Communication retrospective</h2>

<p>Meet with your team and do a <strong>blameless retrospective</strong> of review
process. Consider pull requests that were communicated well, or not well.
Do you have recent changes that caused issues as they deployed? What could
have been done in the pull request communication to avoid this? Create
guidelines for your minimum standards of communication. Create guidelines
for when you should go above and beyond.</p>

<p>Consider your project on a technical basis and discover where some common
patterns are repeated and thus could be externalized to runbooks that can
be referenced instead of repeated. When using these runbooks, what
questions are still important to be answered in each situation?</p>

<p>Consider the seniority of your team. How many engineers do you have of
differing levels of expertise? How often are you training newer engineers
in this space? Do you have an external operations team that is the first
line of support and may need to react to issues in your domain?</p>

<h2 id="create-templates">Create templates</h2>

<p>Take what you learned in the retrospective and encode the most important
bits into pull request templates.</p>

<p>Here are some ideas that could be valuable to include in a template:</p>

<ul>
  <li>What kind of change is this? A refactoring? A new feature? A bugfix?</li>
  <li>What kind of testing was done? Manual testing? New regression tests?
Or: is testing particularly difficult and our only known mechanism to
test is to deploy to production? (Keep an eye out for these to inform
your backlog of technical debt.)</li>
  <li>How will this impact production? What monitors or alerts would fire if
this goes poorly? What metrics will positively indicate that the
change is working as intended?</li>
  <li>When will this change be deployed, and how? Is it going out in the
next binary deployment with immediate effect? Is it waiting for the
next release branch? Is it a binary deployment change or is it gated
by a feature flag or special configuration?</li>
</ul>

<p>Here are some ideas for things to include, but I recommend to make it
clear that they can be deleted from the template when they don’t apply to
a change:</p>

<ul>
  <li>
    <p>What alternative approaches were considered? Do you have branches
that show those prototypes? Why were those approaches rejected and
this approach chosen?</p>
  </li>
  <li>
    <p>What was difficult about making this change? Is there technical debt
that made this more complicated than it should have been, and thus we
should track this as justification to pay down that debt?</p>
  </li>
  <li>
    <p>What was difficult about testing this change? Are there concerns
around special cases, operating at scale or under load? How does your
deployment plan include strategies to safely learn more as this change
rolls out to real use?</p>
  </li>
</ul>

<p>Keep in mind that some of these questions may be answered similarly in
many “regular” changes. Consider creating runbooks for certain types of
changes and then point to those runbooks if the change fits that
scenario perfectly. We don’t need to reinvent the wheel, but we do need
to know that there is prior art.</p>

<h2 id="make-everyone-better">Make everyone better</h2>

<p>Another main goal here is to help junior engineers or engineers who are
new to the project to understand these changes. I personally find it
extremely valuable to learn about a project by watching what others are
doing to change it. But if they don’t overcommunicate the context, then
I’m lost and need to work even harder (or interrupt the contributor with
questions) to find that context. If you just wrote the code, then you
already have this context in your head! Externalize it to help everyone
else catch up.</p>

<p>This concept of <em>overcommunicating the context</em> is important for
contributors of all levels. Newer contributors should overcommunicate
their understanding so more experienced contributors can double-check
that understanding against their experience. Experienced contributors
should overcommunicate their understanding as that will expand the
knowledge of the newer contributors.</p>

<h2 id="revisit-your-decisions">Revisit your decisions</h2>

<p>Schedule time to revisit all of these thoughts after experimenting with
the new standards for a while (1 month, 3 months, 1 year?). You will
always learn new things that can help expand or contract the templates.</p>

<p>Do you track statistics for your team? Consider tracking any change in
the following metrics:</p>

<ul>
  <li>Pull request dwell time.</li>
  <li>Feature delivery and backlog burndown rate.</li>
  <li>Incident rate.</li>
  <li>Incident response time.</li>
  <li>Do you have regular “engineer wellness” surveys?</li>
</ul>

<h1 id="long-term-benefits-and-considerations">Long-term benefits and considerations</h1>

<p>Here are some additional thoughts about the long-term impact of good
communication practices.</p>

<h2 id="future-you-thanks-you">Future you thanks you</h2>

<p>Software products are not static things, but are constantly changing.
Even projects that have little code change are impacted by a changing
environment, changing user behavior, or any number of external
variables. As things change, <em>things will go wrong</em>. How do you react
to these incidents?</p>

<p>In most cases, teams share the load of supporting a project by
rotating who is responsible for front-line support. This will frequently
mean that the person driving the investigation is not the person who
wrote the code that is misbehaving or needs updating. Even if the person
responding to the incident wrote the code that is misbehaving, memory is
fallible over time and the context of the change can be hard to
remember.</p>

<p>In this way, carefully communicating your change in the pull request can
help all engineers be better prepared to support an issue in this space,
<em>including your future self</em>!</p>

<p>Keep in mind that the pull request title and description will be stored
as the commit message, so if you are using <code class="language-plaintext highlighter-rouge">git log</code> to find recent
changes in a section of code, then you can automatically load that
necessary context. The title will frequently point to the pull request
by number, so you can load the discussion to see if there are any other
hints of what may have been tricky here.</p>

<p>Outside of the history, you may also need to look at the related work
items or issues to see if they had any other related work that is
involved. This linking process can help point to a different area that
was changed in reaction to this, or similar problems.</p>

<h2 id="the-robots-can-sometimes-help-but-also-need-help">The robots can sometimes help, but also need help</h2>

<p>Generative AI tools are getting really good at describing a code change.
It is natural to think that we could rely on those tools to do all of
this for us.</p>

<p>There are some limitations:</p>

<ul>
  <li>
    <p>AI summaries are frequently in the pull request metadata, but not
actually committed to the commit message.</p>
  </li>
  <li>
    <p>AI summaries are based on the diff presented, and can only describe
the change based on that context. They can’t talk about alternatives
that you tried and rejected. They typically can’t describe the larger
context of how this change will impact the larger project, especially
around when and how it will be deployed.</p>
  </li>
  <li>
    <p>With proper prompting, AI tools could look for risk factors or
improved test coverage. While these could be factored in via a custom
build policy that runs custom prompting, the best time to ask AI for
these types of things is during development and doing a careful
evaluation of those outputs while the change is in your working
memory.</p>
  </li>
</ul>

<p>In general, generative AI tools are doing pattern matching from previous
work done by humans. Consider that their generated descriptions could be
based on poor descriptions, leading to <em>garbage in, garbage out</em>.</p>

<p>As you do your work, you are naturallly creating the data set for the
next generation of generative AI tooling. Be part of improving those
tools!</p>

<h2 id="further-reading">Further reading</h2>

<p>Here are some valuable resources that I find myself revisiting time and
again.</p>

<h3 id="write-better-commits-create-better-projects"><a href="https://github.blog/developer-skills/github/write-better-commits-build-better-projects/">Write Better Commits, Create Better Projects</a></h3>

<p>This blog post by GitHub engineer Victoria Dye focuses on commits as a
method of communicating a larger change via small atomic changes. It goes
deep on methods for organizing and updating your commits via intereactive
rebase.</p>

<p>If you are focused on pull requests as your unit of change and always
squash-merge, then you don’t need the details around commit manipulation.
The advice around justifying your work in a commit message translates well
into communicating in a pull request description.</p>

<h3 id="git-is-about-communication"><a href="https://tomdebruijn.com/posts/git-is-about-communication/">Git is about communication</a></h3>

<p>This blog post focuses on how Git commits are an archive of important context
that you’ll be grateful to have later if you are diligent about discussing
the “why” of your changes in the present.</p>

<h3 id="pull-request-best-practices-a-complete-guide-for-modern-developers"><a href="https://articles.mergify.com/pull-request-best-practices-complete-guide-developers/">Pull Request Best Practices: A Complete Guide for Modern Developers</a></h3>

<p>This guide by Mergify focuses on why small pull requests are better. It
includes some discussion about PR metrics as well. There’s also some
discussion about automating parts of the review to free up time for the
humans reviewing things at a higher level.</p>

<h3 id="git-contribution-guidelines"><a href="https://github.com/git/git/blob/master/Documentation/SubmittingPatches#L234">Git contribution guidelines</a></h3>

<p>Did you know that Git itself doesn’t use pull requests? This document
details much about the process for submitting patches to the Git mailing
list. One main aspect of code review on a mailing list is that every bit
of the change is up for review, including each and every commit message.</p>

<p>This document includes some very helpful ideas for being rigorous around
communicating a code change.</p>

<h3 id="git-code-review-guidelines"><a href="https://github.com/git/git/blob/master/Documentation/ReviewingGuidelines.adoc#reviewing-patches">Git code review guidelines</a></h3>

<p>This document details the Git community’s expectations for code <em>reviewers</em>,
not just authors. Consider creating something like this for your own team
so you can set standards that fit your group and hold each other accountable.</p>

<h3 id="the-programmers-brain"><a href="https://www.manning.com/books/the-programmers-brain">The Programmer’s Brain</a></h3>

<p>This book by Prof. Felienne Hermans goes deep to connect the science of human
brains to the realities faced by programmers dealing with large systems. Much of
the book focuses on our limited working memory and how mental models, architecture,
and tooling help us work through complex ideas while paging ideas in and out of
our long-term memory.</p>]]></content><author><name>Derrick Stolee</name></author><category term="software engineering" /><category term="git" /><category term="pull requests" /><category term="collaboration" /><summary type="html"><![CDATA[Most software projects gate new contributions by a code review step, and that’s normally done by pull requests (or equivalently, merge requests). Projects may also set up additional technical requirements, such as building and testing the code, performing static style checks, or even scanning the diff with a generative AI code review bot. With all of these automated processes, it’s more important than ever to focus on the primary purpose of pull requests: The main purpose of pull requests is to communicate with the other humans interacting with the project. Many contributors erroneously assume that the purpose of pull requests is to avoid bugs or regressions. While that’s important, we avoid regressions by having a robust test suite that is checked before merging. While sometimes humans can catch bugs, they are incredibly fallible. I personally believe that code is easier to write than it is to read, so how can I expect a reviewer to catch something that I didn’t while writing, building, and running the code locally? This is where it becomes critical to communicate clearly when presenting a change to your project. Every code change has risk. Why is the expected reward worth that risk? What have you done to minimize the risk and maximize the value? Every code change interrupts the mental model of other engineers. How can you use your pull request as an opportunity to improve everyone’s mental model of the project? What concepts and ideas were of utmost importance, even if you think that most contributors already know it? Every line of code is technical debt. You are asking your team to take ownership of this change into the future. Your new feature is something that may cause maintenance burden or add complexity to future changes. How can future contributors make sense of your change and why you made it? With these things in mind, the most important thing to keep in mind is that no one understands this section of the code as much as you do in this moment, including you in the future. You already have a lot of valuable information in your brain right now. Write it down before it’s too late! Improving your communication has benefits in a few different directions: Most Obvious: You can help the reviewers jump into review with full context and get to high quality feedback as soon as possible. Less Obvious: You can do a self-review before sharing your change with your team, helping to improve your own understanding of the problem and avoiding costly asynchronous feedback loops with the team. Most Obscure: Your future self may stumble on this change again and will have lost the necessary context that you have right now. Make it easy to reload that context out of your long-term memory by encoding it in writing. While taking the time to communicate well may seem like friction to your development process, this is a critical step to speed up your reviews and to minimize maintenance costs in the future. This guide will present some examples of how to communicate well that you can take back to your team and project. Work with your community to establish the standards you expect everyone to follow and point a way forward to improved communication. Opportunities for communication When working with pull requests, the first thing reviewers see is an opportunity to set the stage and prepare them to dig into your code change with confidence. Let’s review a few common opportunities in every pull request system. Figure: Opportunities to communicate in a pull request. Use helpful titles When reviewers are perusing a list of pull requests to review, they are likely drowning in a long list of possible changes. How can you catch the eye of a reviewer to signal that your change is relevant and valuable? It can help to start your title with a general area of the project or a feature name. This can help catch the eye of experts in certain subareas. Then, create a short descriptive name for the change. Be concise and get to the core of the change. Think about how you can signal the type of change: User facing feature? Describe what a user will be able to do when done. Security issue? Start your title with “[URGENT: SECURITY]” or similar. Incremental change? Provide a numeral such as “[Feature 4/N]”. Link to related work Outside of the context that you’ll provide in the description, it can be helpful to link to work items, issues, or related pull requests. These links can help unlock a network of related changes and other involved engineers who have worked in this space before. These links can be extremely important for leaving breadcrumbs. You can see whether or not the feature is fully complete with this change or if it is one of a sequence of changes in this direction. Did we need to rollback a similar change in the past? Linked work items can also fill in much of the context that you may not want to repeat Write self-contained descriptions The bulk of your communication should be done in the pull request description. This is particularly important as it will also be the basis of the commit message when your change is merged. Note: GitHub doesn’t automatically copy your description into the merge commit message, but you do have an opportunity to copy it yourself. Azure DevOps does use the pull request title and description as the commit message when you complete your pull request. Expect your reviewers to read the description from top to bottom. What is the most important thing to say first? How can you tell a story that will help them understand the change? I’ve developed a structure that I like to use over and over again: Start with “why”. What context has led to this change being necessary or valuable? Are users complaining about a bug, or did you happen to notice something when doing your own testing? Is this a funded feature or are you volunteering to pay down tech debt? Describe the change. What code was changed? Was it easy to find the way forward or did it take digging? Demonstrate the impact. What’s the proof that this does what you say it does? What tests did you add that would fail before but pass now? Did you do performance tests? Do you have screenshots of the new behavior? Consider alternatives. (Optional) Sometimes, there’s one clear way to accomplish a task. Often, there are multiple ways a problem could have been solved. Why did you pick this one? Did you try something else before going down this road? Including these details could avoid a costly round of async feedback recommending alternatives. After this free-form description is a good time to fill out a pull request template. These templates are specified by the repository owners and frequently include checklists and questions that are important for every change author to consider and demonstrate that they have understood the requirements. If you are in the privileged position to be designing a pull request template, make sure that every item you put in that template has a real purpose. If you are making a change and come across a pull request template, fill it out with the perspective that every line is there for a reason (and usually that reason is an incident due to a bad code change). A brief aside about templates Sometimes templates and checklists can feel tedious or restrictive. They don’t communicate trust in the engineers making changes in the repo. I’d like to counter any concerns about trust with this idea: Checklists are hard-earned wisdom, externalized. Every checklist is an opportunity to double-check yourself while you’re in the thick of things. While working on a problem, you may be too close to it to see the forest through the trees. I know this due to hard experience. Please indulge me as I tell you a story: I was once tasked with creating templates for “production change records” which were going to become a requirement to improve availability issues in our product. I was interested in the idea and started writing down all of the standard questions I would ask about safe deployment based on my own experiences. These were all things I already knew. Once I had encoded these concepts into a document for review, I decided to lead by example and apply the checklist to a change I had already submitted for review. I was missing important details. That’s right: by using my own checklist, I caught myself missing an important detail in my own change. This is why encoding best practices into written form is critical to avoiding human error. Humans are fallible. We have limited working memory in our brains. We need strategies to externalize information to assist with recall from long-term memory. I found that externalizing my own experiences into a checklist of questions led to an improved outcome for changes I was making. I’m confident that this will help most software engineers, too. Use draft pull requests The state of the PR may also be important. Is it a draft that is looking for high-level feedback and not a full review? Are there tags about impacted areas? Is it urgent for deadlines, hotfixing, or security reasons? Use the pull request discussion Depending on what you’re trying to communicate, it may be helpful to add comments into your pull request discussion that don’t make sense to keep in the pull request description. For example, you could pre-load discussion with requests for what reviewers should focus on. These comments could even highlight the most critical code paths as a good place to start before going through the rest of the changes and test code. Sometimes you’ll want to post a change for full review but also block the change on your own comment regarding some final round of performance testing. During the review, you can use emoji to indicate “I’ve applied this advice locally” while waiting to resolve a comment until you’ve pushed a change that has the full reaction. Other communication When you’re working on a team, there are many ways that you can communicate your change. Email, teams, chatting in hallways, pairing sessions are all informal outlets for communication and can provide valuable context such as “I need early feedback on this direction; please ignore style issues” or “This change is very low risk, can I get a quick look?” Keep in mind that “if it’s not in the PR, then it didn’t happen” in terms of the official record. The pull request review sequence itself is an important historical record of its own that may need to be referenced in the future. I’ve found myself inspecting a change and tracking down the original pull request and reading the discussion to find out how they landed on that direction (or worse: found that there was no discussion and maybe the review wasn’t very careful). Where I learned these things It’s important to show my work, so let me briefly describe how I came to have strong opinions about communication here. Before I was an engineer, I was an academic. My career was built around sharing knowledge and teaching others. Even within that space, every research paper or grant proposal I wrote had to justify why the contribution was important and why it was worth the readers’ time. The skills I learned there became valuable when I changed careers to software engineering, starting on the Azure Repos backend team. Working on a massive scale source control system had very high risk concerns around protecting user data. Correctness, resiliency, and privacy were critical for every change. That team already had high standards for reviews, which taught me both how to review code critically and how to present my code in a reviewable way. My next career shift included moving from the Git server to the open-source Git community, working on client side performance. While I thought that the Azure Repos team had high standards, the Git community was a step beyond that. There were two critical differences working with the Git community: Every part of the change is up for review, including every commit message and the organization of commits into small pieces. There is no agreed-upon backlog to lean on for why the changes should happen. Every patch series is a request for the community to take ownership of your change. These two differences were an interesting challenge and have motivated much of my philosophy around communicating code changes. While these standards are on the more extreme side, it is worth considering which of the requirements are worth keeping for your project and which are needed only occasionally. In my career since, I’ve had the opportunity to work with many teams and many different sets of expectations. In my current role, I jump around many different repositories and work with many different teams. I find myself needing to understand new codebases constantly and am missing the hints left by careful commit messages. When I make a change, I find myself needing to justify why I’m in their space and providing an unexpected (or even uninvited) change. Sometimes, the most important thing I can say in a pull request is “Hi, I’m new to this space. Here’s what I know for sure and what I am still unsure about.” Advanced techniques The techniques that follow are more sophisticated and may not be necessary for every project or every change. However, they can be powerful tools when you need to communicate complex changes or work within specific project requirements. Advanced Technique: Commit-by-Commit Review Some projects, such as Git itself, do review on a commit-by-commit basis. Git hosts that use pull requests don’t always make commit-by-commit review easy or necessary, but it can be valuable to use it on occasion. The trick here is that you need to carefully construct your commits to be meaningful on their own and tell a story in finer detail than the full pull request. This comes in handy in a few different cases: There is one very critical piece of logic that you want to highlight for careful review while the rest of the changes are mostly boilerplate that can be reviewed quickly. In order to make the change, some large refactoring was needed. Separating the refactor as its own commit followed by a commit that does the important logic can help reviewers read the changes with the right level of detail. As an example, I wanted to share one of my favorite contributions to the Git client: making topological sort extremely fast. Figure: Using a cover letter with careful commit messages. In the mailing list discussion, the cover letter for a patch series is like a pull request description and can describe the high-level purpose of the patches. The cover letter isn’t stored in the final sequence of commits. But in this patch series, there was one commit that was larger than the rest, both in terms of the commit message and the code change. This was the crucial step that essentially reimplemented the old algorithm using a new structure. However, the commits leading up to that point were valuable to create some shared code that could be used by both approaches. Doing it in this way made it clear that this large change was purely new code and not mutating the older path. While this is one of my favorite contributions that I’ve ever made, I do regret that I didn’t take the time to construct parts of the algorithm across multiple commits, even though the first commits would need to introduce methods that were not called by anything until the later commits arrived. Advanced Technique: Stacked Pull Requests Reading code is hard. Reading a lot of code is harder. Do your reviewers a favor and break up large changes into a sequence of smaller changes. When using pull requests as your quantum of change, stacked pull requests can tell a multi-part story across several changes. Showing a pull request stack can be great to help get an early change merged while also showing that the change is contributing to a long-term vision (even if that vision is only visible as some draft pull requests that don’t have everything ready yet). This can avoid reworking an early data structure or API by demonstrating the current definition is sufficient for a later application. I love using stacked pull requests to help me tell a story. It’s a great way to get some of the benefits of commit-by-commit review while still using the pull request as the minimum reviewable piece. It’s also easier to track differences between versions using things like Azure Repos’ iterations. Stacked pull requests are mostly an informal idea at the moment for most Git hosts, so you need to do some work yourself to communicate the existence of the stack and where each pull request fits within the stack. See the figure below for how I’ve done this in the past. Figure: Describing a stack of pull requests. To construct a pull request stack, you create the first layer as normal. Each next layer is then a pull request into the source branch of the previous layer, making the presented diff be only the change between those two branches. As lower layers complete, you may need to retarget the next layer to the intended target branch. If you use squash merges, you’ll need to use something like git rebase --onto &lt;target&gt; &lt;old-branch&gt; &lt;tip-branch&gt; to update your changes into the new target branch that includes the squashed merge. Using git rebase --update-refs can help update all of your local branches in the stack as you change things anywhere in the stack. If you’re intrigued by this idea, then you can read more in these places: Stacked Pull Requests - The Complete Guide for Developers Stacked diffs (and why you should know about them) Working with stacked branches in Git is easier with --update-refs Establishing team standards I’m done sharing my ideas around effective communication and my bag of tricks. You can adopt or ignore these as you see fit. Ultimately, it is up to you and your team to decide what standards you expect of each other. I challenge you to get together with your team or community and discuss pull request communication in very clear terms. Discuss what is at stake when you make changes and find the right level of rigor that you find important for your context. Communication retrospective Meet with your team and do a blameless retrospective of review process. Consider pull requests that were communicated well, or not well. Do you have recent changes that caused issues as they deployed? What could have been done in the pull request communication to avoid this? Create guidelines for your minimum standards of communication. Create guidelines for when you should go above and beyond. Consider your project on a technical basis and discover where some common patterns are repeated and thus could be externalized to runbooks that can be referenced instead of repeated. When using these runbooks, what questions are still important to be answered in each situation? Consider the seniority of your team. How many engineers do you have of differing levels of expertise? How often are you training newer engineers in this space? Do you have an external operations team that is the first line of support and may need to react to issues in your domain? Create templates Take what you learned in the retrospective and encode the most important bits into pull request templates. Here are some ideas that could be valuable to include in a template: What kind of change is this? A refactoring? A new feature? A bugfix? What kind of testing was done? Manual testing? New regression tests? Or: is testing particularly difficult and our only known mechanism to test is to deploy to production? (Keep an eye out for these to inform your backlog of technical debt.) How will this impact production? What monitors or alerts would fire if this goes poorly? What metrics will positively indicate that the change is working as intended? When will this change be deployed, and how? Is it going out in the next binary deployment with immediate effect? Is it waiting for the next release branch? Is it a binary deployment change or is it gated by a feature flag or special configuration? Here are some ideas for things to include, but I recommend to make it clear that they can be deleted from the template when they don’t apply to a change: What alternative approaches were considered? Do you have branches that show those prototypes? Why were those approaches rejected and this approach chosen? What was difficult about making this change? Is there technical debt that made this more complicated than it should have been, and thus we should track this as justification to pay down that debt? What was difficult about testing this change? Are there concerns around special cases, operating at scale or under load? How does your deployment plan include strategies to safely learn more as this change rolls out to real use? Keep in mind that some of these questions may be answered similarly in many “regular” changes. Consider creating runbooks for certain types of changes and then point to those runbooks if the change fits that scenario perfectly. We don’t need to reinvent the wheel, but we do need to know that there is prior art. Make everyone better Another main goal here is to help junior engineers or engineers who are new to the project to understand these changes. I personally find it extremely valuable to learn about a project by watching what others are doing to change it. But if they don’t overcommunicate the context, then I’m lost and need to work even harder (or interrupt the contributor with questions) to find that context. If you just wrote the code, then you already have this context in your head! Externalize it to help everyone else catch up. This concept of overcommunicating the context is important for contributors of all levels. Newer contributors should overcommunicate their understanding so more experienced contributors can double-check that understanding against their experience. Experienced contributors should overcommunicate their understanding as that will expand the knowledge of the newer contributors. Revisit your decisions Schedule time to revisit all of these thoughts after experimenting with the new standards for a while (1 month, 3 months, 1 year?). You will always learn new things that can help expand or contract the templates. Do you track statistics for your team? Consider tracking any change in the following metrics: Pull request dwell time. Feature delivery and backlog burndown rate. Incident rate. Incident response time. Do you have regular “engineer wellness” surveys? Long-term benefits and considerations Here are some additional thoughts about the long-term impact of good communication practices. Future you thanks you Software products are not static things, but are constantly changing. Even projects that have little code change are impacted by a changing environment, changing user behavior, or any number of external variables. As things change, things will go wrong. How do you react to these incidents? In most cases, teams share the load of supporting a project by rotating who is responsible for front-line support. This will frequently mean that the person driving the investigation is not the person who wrote the code that is misbehaving or needs updating. Even if the person responding to the incident wrote the code that is misbehaving, memory is fallible over time and the context of the change can be hard to remember. In this way, carefully communicating your change in the pull request can help all engineers be better prepared to support an issue in this space, including your future self! Keep in mind that the pull request title and description will be stored as the commit message, so if you are using git log to find recent changes in a section of code, then you can automatically load that necessary context. The title will frequently point to the pull request by number, so you can load the discussion to see if there are any other hints of what may have been tricky here. Outside of the history, you may also need to look at the related work items or issues to see if they had any other related work that is involved. This linking process can help point to a different area that was changed in reaction to this, or similar problems. The robots can sometimes help, but also need help Generative AI tools are getting really good at describing a code change. It is natural to think that we could rely on those tools to do all of this for us. There are some limitations: AI summaries are frequently in the pull request metadata, but not actually committed to the commit message. AI summaries are based on the diff presented, and can only describe the change based on that context. They can’t talk about alternatives that you tried and rejected. They typically can’t describe the larger context of how this change will impact the larger project, especially around when and how it will be deployed. With proper prompting, AI tools could look for risk factors or improved test coverage. While these could be factored in via a custom build policy that runs custom prompting, the best time to ask AI for these types of things is during development and doing a careful evaluation of those outputs while the change is in your working memory. In general, generative AI tools are doing pattern matching from previous work done by humans. Consider that their generated descriptions could be based on poor descriptions, leading to garbage in, garbage out. As you do your work, you are naturallly creating the data set for the next generation of generative AI tooling. Be part of improving those tools! Further reading Here are some valuable resources that I find myself revisiting time and again. Write Better Commits, Create Better Projects This blog post by GitHub engineer Victoria Dye focuses on commits as a method of communicating a larger change via small atomic changes. It goes deep on methods for organizing and updating your commits via intereactive rebase. If you are focused on pull requests as your unit of change and always squash-merge, then you don’t need the details around commit manipulation. The advice around justifying your work in a commit message translates well into communicating in a pull request description. Git is about communication This blog post focuses on how Git commits are an archive of important context that you’ll be grateful to have later if you are diligent about discussing the “why” of your changes in the present. Pull Request Best Practices: A Complete Guide for Modern Developers This guide by Mergify focuses on why small pull requests are better. It includes some discussion about PR metrics as well. There’s also some discussion about automating parts of the review to free up time for the humans reviewing things at a higher level. Git contribution guidelines Did you know that Git itself doesn’t use pull requests? This document details much about the process for submitting patches to the Git mailing list. One main aspect of code review on a mailing list is that every bit of the change is up for review, including each and every commit message. This document includes some very helpful ideas for being rigorous around communicating a code change. Git code review guidelines This document details the Git community’s expectations for code reviewers, not just authors. Consider creating something like this for your own team so you can set standards that fit your group and hold each other accountable. The Programmer’s Brain This book by Prof. Felienne Hermans goes deep to connect the science of human brains to the realities faced by programmers dealing with large systems. Much of the book focuses on our limited working memory and how mental models, architecture, and tooling help us work through complex ideas while paging ideas in and out of our long-term memory.]]></summary></entry><entry><title type="html">Learning about Guitar Making on YouTube</title><link href="https://stolee.dev/2022/12/25/luthiery-videos.html" rel="alternate" type="text/html" title="Learning about Guitar Making on YouTube" /><published>2022-12-25T00:00:00-05:00</published><updated>2022-12-25T00:00:00-05:00</updated><id>https://stolee.dev/2022/12/25/luthiery-videos</id><content type="html" xml:base="https://stolee.dev/2022/12/25/luthiery-videos.html"><![CDATA[<p>There comes a time in every software engineer’s lifetime where they need
to break out of their digital life and away from screens. I’ve already
done this in some ways when listening to vinyl records or playing Magic
the Gathering with friends in real life. However, one hobby has become so
common for software engineers that it’s practically a meme: woodworking.</p>

<p>Growing up, I learned several handy skills from building things with my
father. This includes helping to build and finish a lake cabin. In grad
school, I built a few pieces of furniture for our small home, but they
were very basic due to building things as quickly as possible without too
much attention to detail.</p>

<p>I’ve wanted to get back into it and learn real skills and build the focus
to do high-quality finishes. However, I’ve not found a project that
captivated me enough to want to invest the time, money, and effort into
the process.</p>

<p>Recently, I’ve been relearning the guitar and enjoy learning about what
makes an electric guitar really work. This led me to discover several
guitar YouTube channels, mostly about learning how to play better. This
did have a side effect: YouTube then recommended some <em>guitar maker</em>
channels. That led me down a rabbit hole so deep that I now “know” what it
takes to build a guitar and want to try it myself.</p>

<p>I haven’t even started trying to build a guitar, but I have watched many
videos to the point that I have a rough idea of how I want to get started
and level up from there. Here is an inventory of my favorite channels and
particularly helpful videos in case you are interested in getting started.</p>

<!--more-->

<h2 id="guitar-making-channels">Guitar Making Channels</h2>

<p>Here is a curated list of my favorite channels for learning about guitar
making. These creators make it look easy, but also film and edit it in a
way that is easy to get lost in their content for hours.</p>

<h3 id="tchiks-guitars"><a href="https://www.youtube.com/@tchiksguitars">tchiks guitars</a></h3>

<p><strong>tchiks guitars</strong> makes beautiful guitars that show the natural features
of wood grain. That is, unless they are making guitars from old Ikea
furniture or other odd restrictions. My favorite videos have no narration,
but demonstrate the creation in careful visual detail. They are relaxing
to watch as well as educational.</p>

<p>To get started, I recommend watching their
<a href="https://www.youtube.com/playlist?list=PL3DG0jde7mcR5fuIrA1yUsU3Jt_4W4ouB">How to make your first guitar at home</a>
guide. They build a Telecaster style guitar while explaining all of the
details step-by-step as well as the tools being used. It’s inspirational,
for sure, even though I don’t think I will start my <em>first</em> guitar with
such an ambitious project.</p>

<p>However, I want to highlight a different video,
<a href="https://youtu.be/yOO9QWr81eg">their Les Paul build</a>
has a lot of details that I aspire to eventually be able to replicate:
carved top on top of the body base, laminated neck, woodworked pick guard,
and many other careful details.</p>

<iframe width="560" height="315" src="https://www.youtube.com/embed/yOO9QWr81eg" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen=""></iframe>

<h3 id="crimson-custom-guitars"><a href="https://www.youtube.com/@CrimsonCustomGuitars">Crimson Custom Guitars</a></h3>

<p><strong>Crimson Custom Guitars</strong> is probably the biggest guitar making channel
out there. They run their own school and supply shop dedicated to supporting
hobbyists and professionals alike. Their videos include intricate, one-of-a-kind
builds. But also, they include shorter videos about upgrading or repairing
guitars they didn’t build.</p>

<p>They also run <a href="https://greatguitarbuildoff.com/">the Great Guitar Build Off</a>,
which is also a great way to find more guitar makers.</p>

<p>To highlight some of the craziest features Crimson Custom Guitars can make,
I recommend <a href="https://youtu.be/Z4J42JsBReo">the super cut of the Nebula 2.0 guitar</a>.
Most guitars can be described as “shaped like [famous guitar brand]”
but this one is in its own category. Take a look at what can be done when
every part of the guitar is rethought and created with precision. Also,
that color finish is unbelievable.</p>

<iframe width="560" height="315" src="https://www.youtube.com/embed/Z4J42JsBReo" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen=""></iframe>

<h3 id="magic-attic-guitars"><a href="https://www.youtube.com/@MagicAtticGuitars">Magic Attic Guitars</a></h3>

<p><strong>Magic Attic Guitars</strong> creates works of art. Every guitar has incredible
details, right down to the inlay logo in each headstock. Even with all of
those high-end flourishes, this channel also includes tips and tricks for
everyone to level up in very specific ways.</p>

<p>I’ve chosen to highlight <a href="https://youtu.be/QKemu6JxGos">Building guitar with wire inlay</a> because it demonstrates the attention to small details and
decorations.</p>

<iframe width="560" height="315" src="https://www.youtube.com/embed/QKemu6JxGos" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen=""></iframe>

<h3 id="daisy-tempest"><a href="https://www.youtube.com/@DaisyTempest">Daisy Tempest</a></h3>

<p><strong>Daisy Tempest</strong> is a more traditional <em>luthier</em> and builds beautiful
acoustic guitars. Her videos are educational and talk about the tools of
the trade in addition to the techniques required. While I’m not planning
to build an acoustic guitar until I’m satisfied with electric guitars.</p>

<p>I want to highlight one of her technique videos, especially
<a href="https://www.youtube.com/watch?v=uFqIJkhjgAw">this one about she does high-end fretwork</a>.
In particular, I’ve learned that she always applies binding to the sides
of her fretboard which requires <em>fret tang nippers</em> to cut the part of the
fret that inserts into the fret board so it doesn’t cut into the binding.
I’ve fallen in love with that look and want to build a fretboard that way
myself (just not at first).</p>

<iframe width="560" height="315" src="https://www.youtube.com/embed/uFqIJkhjgAw" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen=""></iframe>

<h3 id="noe-hervas"><a href="https://www.youtube.com/@NoeHervas">Noe Hervas</a></h3>

<p><strong>Noe Hervas</strong> is probably my most-recent discovery in this vein, but their
work looks really impressive from what I’ve explored so far. This is
another creator that focuses on high-quality wood and their skills bring
out the natural strengths of the wood.</p>

<p>I want to highlight their <a href="https://youtu.be/EZf9MJbijHo">“The Opal” full build</a>
as an example of showing all the steps but without words. It’s the kind of
video I can watch with a small child in my lap to help them calm down.</p>

<iframe width="560" height="315" src="https://www.youtube.com/embed/EZf9MJbijHo" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen=""></iframe>

<h2 id="getting-started-plan">Getting Started Plan</h2>

<p>The first thing I need to learn is how to adjust the settings on my own
guitars. I can change my strings just fine, but adjusting the string
height (the <em>action</em>) or the bend of the neck are all new concepts to me.
It would also be good to clean up the fretboard on one guitar I bought
used, and the finishing techniques would be helpful to try there.</p>

<p>To whet my woodworking appetite, I could build some helper tools for when
I get around to building a guitar, such as a <a href="https://www.crimsonguitars.com/collections/guitar-maintenance-tools/products/rockin-neck-rest">neck rest</a>
or a stand to hold multiple guitars.</p>

<p>For my first full guitar, I plan to start with a kit, such as one from
<a href="https://www.stewmac.com/kits-and-projects/instrument-kits/?gclid=CjwKCAiAhqCdBhB0EiwAH8M_GtAz_AnfZDvJDVEwg1fkQc03fbvPHU29DuqdZIY9QIMtUz8jAekjxRoCdIsQAvD_BwE">StewMac</a>,
which seems to be the place to go. The focus is to get to a complete
project as soon as possible, as well as to have a straight-forward way to
learn about wiring and finishing. This approach should be much cheaper
than starting from a body blank because of the materials and tools. Fret boards and neck seem like
the most complicated things and easiest to get wrong, so leaving that for
a future project would be best.</p>

<p>The next step would be to create a custom body while using a prebuilt neck.
This might be an optional one depending on if I want to make the leap to
a full build based on the kit experience.</p>

<h2 id="guitar-making-bucket-list">Guitar Making Bucket List</h2>

<p>After building from a kit and having a complete project under my belt, I
want to try going into more advanced concepts, such as hand-carving the
neck and fretboard. I’d like to consider laminating the guitar body for
interesting patterns along the edges, or creating a laminated neck for
lines up the neck and headstock. I’d like to create custom fretboard
inlays for the fret markers. Some guitar bodies require binding; the
simple start is to use a plastic binding, but more advanced would be to
bend a wood binding around the guitar. I’ve also mentioned that I like
the look of binding on a fretboard.</p>

<p>There are a variety of guitar styles that I think I’d like to try, and
from the videos I’ve seen have some variation in difficulty level. There
are some skills that are absolutely necessary for some (carved top for
Les Pauls) while not as much for others (Telecasters are pretty flat).</p>

<p>Here’s my mostly-ordered list of body styles that I’d like to try out:</p>

<ul>
  <li>Telecaster Style</li>
  <li>Stratocaster or Super-strat style</li>
  <li>Flying V Style</li>
  <li>Explorer Style</li>
  <li>Les Paul Style with curved top</li>
  <li>ES-335 Style with semi-hollow body (bonus for neck-through design)</li>
</ul>

<p>In some hypothetical future where I’ve built several electric guitars and
am happy with the results, I’ll do another deep dive into acoustic guitar
making and try that on for size. The few acoustic guitar video builds I’ve
seen show a dramatically different set of techniques that require even
more patience and attention to detail.</p>]]></content><author><name>Derrick Stolee</name></author><category term="luthiery" /><category term="guitars" /><category term="youtube" /><summary type="html"><![CDATA[There comes a time in every software engineer’s lifetime where they need to break out of their digital life and away from screens. I’ve already done this in some ways when listening to vinyl records or playing Magic the Gathering with friends in real life. However, one hobby has become so common for software engineers that it’s practically a meme: woodworking. Growing up, I learned several handy skills from building things with my father. This includes helping to build and finish a lake cabin. In grad school, I built a few pieces of furniture for our small home, but they were very basic due to building things as quickly as possible without too much attention to detail. I’ve wanted to get back into it and learn real skills and build the focus to do high-quality finishes. However, I’ve not found a project that captivated me enough to want to invest the time, money, and effort into the process. Recently, I’ve been relearning the guitar and enjoy learning about what makes an electric guitar really work. This led me to discover several guitar YouTube channels, mostly about learning how to play better. This did have a side effect: YouTube then recommended some guitar maker channels. That led me down a rabbit hole so deep that I now “know” what it takes to build a guitar and want to try it myself. I haven’t even started trying to build a guitar, but I have watched many videos to the point that I have a rough idea of how I want to get started and level up from there. Here is an inventory of my favorite channels and particularly helpful videos in case you are interested in getting started.]]></summary></entry><entry><title type="html">On Mental Toughness (for Software Engineers): How the Best of the Best Get Better And Better</title><link href="https://stolee.dev/2019/10/27/mental-toughness-1.html" rel="alternate" type="text/html" title="On Mental Toughness (for Software Engineers): How the Best of the Best Get Better And Better" /><published>2019-10-27T00:00:00-04:00</published><updated>2019-10-27T00:00:00-04:00</updated><id>https://stolee.dev/2019/10/27/mental-toughness-1</id><content type="html" xml:base="https://stolee.dev/2019/10/27/mental-toughness-1.html"><![CDATA[<p>I was recently gifted <em>On Mental Toughness</em>, a collection
of ten Harvard Business Review articles reprinted as a
paperback. The first article,
<a href="http://project12.circlespring.com/workshop1/R0806H-PDF-ENG.PDF">“How the Best of the Best Get Better and Better” by Graham Jones</a>,
takes advice
gathered from athletic achievement into business achievement.
Let’s explore some of the ideas as they relate to
building software.</p>

<!--more-->

<blockquote>
  <p>This post is part of a series where I try to take
generic business articles and view them through my
lens as an individual contributor software engineer.</p>

  <p>While the articles are usually focused on upper
management roles, I believe there are many parallels
with IC software engineers. Our profession is very
intellectually demanding, there are always trade-offs
in every choice we make, and our mistakes are likely
to affect many people (customers or others in our
organizations).</p>
</blockquote>

<h1 id="mental-barriers">Mental barriers</h1>

<p>The article begins using the example of the
<a href="https://en.wikipedia.org/wiki/Four-minute_mile">four-minute mile</a>.
For decades, everyone publicly declared that running
a four-minute mile was impossible, until someone did it.
(This is very similar to the recent advances towards
a <a href="https://en.wikipedia.org/wiki/Ineos_1:59_Challenge">two-hour marathon</a>.)
After one person ran that fast, others quickly followed
suit. These days, some of the most elite high-school
runners can run a four-minute mile.</p>

<p>Some limits are in your mind, or are ingrained by
those around you.</p>

<p>What problems are you facing but not trying to overcome
because others’ experience says it is impossible?</p>

<p>Don’t forget to know what is a real limitation, and what
is not. Feel free to assume that an NP-Hard problem will
not have a polynomial-time algorithm. Instead, see if
your specific version of the problem can be solved using
heuristics, or the “slow” algorithm is actually fast for
you due to some bounded parameter.</p>

<p><strong>Example:</strong> I remember working on counting the number
of perfect matchings in graphs. This is a well-known
P#-Complete problem (if you can solve this problem fast,
then you can count the number of solutions to 3-SAT fast,
too). Turns out that the reduction required to translate
3-SAT into a perfect matching problem requires an
exponential increase in the number of solutions. The
reason it is “hard” to count is because there are so
many! When focusing on graphs with a small number of
perfect matchings, the brute-force algorithm is quite
fast.</p>

<h1 id="focus-on-your-own-excellence">Focus on your own excellence</h1>

<p>To improve, you must focus on what you can control.</p>

<p>Don’t compare yourself to others. <strong>Their success is not
your failure.</strong> I had to remind myself of that frequently
in graduate school, when I was first getting my bearings
in how to publish scholarly work. Other students (usually
from higher-ranking institutions) would publish more
papers in higher venues, and I would find my rate
inadequate. This led to a very stressful point in my
life, where I overworked myself more than ever.</p>

<p>What I realized (eventually) was that there will <em>always</em>
be someone who achieves more than me (or you) and from
the outside it will look like it was easy for them. This
is especially true when looking at an international field
of people. In grad school, journals came in every month
with authors from all over the world. Now, I see fantastic
people sharing their expertise and professional adventures
on Twitter. It’s hard to avoid FOMO when presented with
the best view of someone’s life.</p>

<p>By focusing on yourself, you can think about what you
can control, and what steps you can take to advance your
goals. Instead of seeing what others are doing, do the
thing that shows your talents the best. Success will
follow.</p>

<h1 id="understand-your-own-success">Understand your own success</h1>

<p>In order to focus on your own success, you must also
reflect and discover what had led to your current
level of success.</p>

<p><em>If you are like me, then a lot of your success has
come from privilege. Recognize that, then find the
<strong>next</strong> reason for your success.</em></p>

<p>Jones mentions this in their section about celebrating
victories. While athletes spend time celebrating the
big wins, having a bit of fun is not the point of the
party. “The very best performers do not move on before
they have scrutinized and understood thoroughly the
factors underpinning their success,” Jones writes.</p>

<p>If you have a big win, then take the time and enjoy
that win! While you are relaxed and happy, think back
on what choices you made to influence that success.</p>

<p>When building software, our view of the future can
be murky. We don’t always know how difficult things
will be. Our code is exercised in situations we
never expected. We may be redirected from one
project to another, or the project changes significantly
one week to the next.</p>

<p>But we can always look back at what we have done.
Version control is great for this: you can literally
see everything you completed. With good commit
messages, you can remember the challenges you faced
and overcame. Can you also recall the different
options you could have pursued? The priorities you
could have set instead? What constellations aligned
this time to create your success? Hopefully, you
can look back to decisions you made based on
thoughtful preparation. You can repeat the success
by making those steps part of your daily process.</p>

<h1 id="working-with-the-best">Working with the best</h1>

<p>While focusing on yourself is good, it always helps
to have a little bit of competition. Jones mentions
how rivals sometimes train together as a way for
each athlete to improve. By learning from each other,
the athletes each grow more than they could by
themselves. At the end of the day, they compete
against each other – but also against a lot of others.</p>

<p>There are two things I gather from this idea:
have a great team, and work in the open.</p>

<p>Working with high-quality engineers makes everyone
on the team better. Code review spreads good habits
and spreads knowledge. Working with great people
is inspiring. This seems like an idea that is
widespread in the software industry.</p>

<p>This is the same when working on an open source
project, <em>especially with your competitors</em>. Git
is the backbone of most Git hosting providers:
GitHub, GitLab, BitBucket, etc. (NOT Azure Repos
or Gerrit). The Git client is used by all Git
users on their workstations, including most
engineers in Microsoft. The Git development
community is filled with engineers from all of
the companies that rely on Git, even though
they compete <em>directly</em> in the space. By coming
together and being open about our goals, the
community thrives and everyone benefits.</p>

<p>Also, I never thought I’d learn so much minutia
about shell scripts that I do after working on
Git.</p>

<h1 id="how-do-you-get-better-and-better">How do you get better and better?</h1>

<p><a href="https://twitter.com/stolee">Find me on Twitter</a> and
let me know!</p>]]></content><author><name>Derrick Stolee</name></author><category term="reading" /><summary type="html"><![CDATA[I was recently gifted On Mental Toughness, a collection of ten Harvard Business Review articles reprinted as a paperback. The first article, “How the Best of the Best Get Better and Better” by Graham Jones, takes advice gathered from athletic achievement into business achievement. Let’s explore some of the ideas as they relate to building software.]]></summary></entry><entry><title type="html">Building stolee.dev</title><link href="https://stolee.dev/2019/03/13/building-stolee-dev.html" rel="alternate" type="text/html" title="Building stolee.dev" /><published>2019-03-13T00:00:00-04:00</published><updated>2019-03-13T00:00:00-04:00</updated><id>https://stolee.dev/2019/03/13/building-stolee-dev</id><content type="html" xml:base="https://stolee.dev/2019/03/13/building-stolee-dev.html"><![CDATA[<p>Welcome to <a href="https://stolee.dev">stolee.dev</a>! This is my
personal blog, not to be confused with blog articles I
write for my job.</p>

<p>In this post, I’ll discuss some things I learned while
building this page, and share links to the sources I
used.</p>

<!--more-->

<h1 id="connecting-a-dev-domain-to-github-pages">Connecting a .dev domain to GitHub Pages</h1>

<p>I hadn’t purchased a domain in fifteen years, so when
<a href="https://www.blog.google/technology/developers/hello-dev/">Google announced the <code class="language-plaintext highlighter-rouge">.dev</code> domain</a>,
I thought it would be a good time to try it again. I’ve
been using GitHub Pages for some side projects, so I
wanted to use that for easy hosting. But I hadn’t set
up a custom domain yet.</p>

<p>To set up a custom domain, I used Luis L’s
<a href="https://medium.com/@Tnylnc/tnylnc-how-to-set-up-github-pages-with-google-domains-83bd5a4fbc5c">How to set up Github Pages with Google domains</a>.
Of course, I made some mistakes and was a bit impatient
waiting for the changes in Google Domains to propagate
to GitHub Page’s tools.</p>

<h1 id="mobile-friendly-rendering">Mobile-friendly rendering</h1>

<p>I got started with HTML in 2001, and gave up all desire
to make web pages by 2007, so I missed the mobile boom.
After desigining a simple layout using my desktop browser,
I tried looking at the page on my phone and it was <em>awful</em>.
Instead of nicely rendering the font at a readable size, it
was zoomed way out and tiny.</p>

<p>This turns out to be a trick phone browsers use to display
web pages that have <em>not</em> been optimized for mobile. The
simple way to get around this behavior is to add the
following tag to the <code class="language-plaintext highlighter-rouge">&lt;head&gt;</code> of your page:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>&lt;meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1"&gt;
</code></pre></div></div>

<p><a href="https://developer.mozilla.org/en-US/docs/Mozilla/Mobile/Viewport_meta_tag">You can learn more about the viewport on Mozilla’s web docs</a>.</p>

<h1 id="text-friendly-rendering">Text-friendly rendering</h1>

<p>Since I’m used to working with the Git mailing list,
I’ve grown fond of old-school approaches to things.
Making the page useful for text-based browsers was
one thing I really wanted to ensure was that
text-based browsers could read the page as close to
the original rendering as possible. Here is how it
looks:</p>

<p><img src="https://stolee.dev/img/text-render.png" alt="How it looks in lynx" /></p>

<p>Of course, the home page is super-simple, so this is
not a surprise. The entire page is mostly a collection
of unordered lists (<code class="language-plaintext highlighter-rouge">&lt;ul&gt;</code> tags) with some simple CSS
to style different parts. The most interesting part is
that the navigation menu for the different sections has
a horizontal list, even though it is a <code class="language-plaintext highlighter-rouge">&lt;ul&gt;</code> tag.</p>

<p>Hopefully, this focus on text-based visibility also
ensures anyone with a visual impairment can read the page.
Please let me know if you have any trouble!</p>

<h1 id="jekyll-enabled-blogging">Jekyll-enabled blogging</h1>

<p>Since this page is deployed and hosted by GitHub pages,
it is by necessity a static site. However, we can get
a bit creative to automatically generate a blog feed based
on a list of markdown files using Jekyll.</p>

<p>Here is my <code class="language-plaintext highlighter-rouge">_config.yml</code> file:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>name: Stolee's Dev Blog
description: The personal developer blog of Derrick Stolee
url: https://stolee.dev
plugins:
  - jekyll-feed
theme: minima
permalink: /posts/:year/:month/:title
feed_items: 10
feed_update_period: daily
feed_update_frequency: 1
collections:
  posts:
    output: true

permalink           : date
paginate_path       : /page:num
timezone: America/New_York

markdown            : kramdown
highlighter         : rouge
lsi                 : false
excerpt_separator   : "&lt;!--more--&gt;"
incremental         : false

</code></pre></div></div>

<p>Then, I have my posts written in markdown in the
<code class="language-plaintext highlighter-rouge">_posts</code> folder automatically generate HTML pages
for each article, an <a href="https://stolee.dev/feed.xml">RSS feed</a>,
and <a href="https://stolee.dev/blog/">an HTML index of posts</a>. The
index is generated by a simple <code class="language-plaintext highlighter-rouge">blog/index.md</code> file:</p>

<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>---
layout: home
title: Stolee's Dev Blog
---
</code></pre></div></div>

<p>One <strong>super important thing</strong> that tripped me up was that
the files in the <code class="language-plaintext highlighter-rouge">_posts</code> folder <strong>must</strong> have filenames
with the format <code class="language-plaintext highlighter-rouge">YYYY-MM-DD-name.md</code> or else Jekyll will
ignore them!</p>

<p>I’m sure there are ways to make this more fancy, but this
suits me for now.</p>]]></content><author><name>Derrick Stolee</name></author><category term="web" /><summary type="html"><![CDATA[Welcome to stolee.dev! This is my personal blog, not to be confused with blog articles I write for my job. In this post, I’ll discuss some things I learned while building this page, and share links to the sources I used.]]></summary></entry></feed>