- Is it within your control?
- Can you tell when you’re done?
- In SourceTree, the “Commit options…” dropdown list to the right of the commit dialog has an option to “Amend latest commit.” You’ll be asked if you want to replace the commit text in your current dialog with the message of the previous commit. Say yes, since you’re adding a file to the previous commit that you had meant to include all along.
- If you’re using the git gui tool that’s distributed with git, there are radio buttons above the commit message so that you can select “Amend Last Commit.”
- From the command line, accomplish the equivalent rewrite with
git commit --amend.
- If you’re cleaning up a bigger mess, use
git rebase -ito fix up any commits that haven’t been pushed.
- And my favorite, take a calm and measured stroll through this choose-your-own-adventure-style guide to fixing commits in git.
- Not a few
It’s New Year’s Resolution time, but this applies to Quarterly Objectives and other professional development goals, too. Set your goals around behaviors that are under your control. Sounds trivial, but it isn’t how most people write goals.
“Lose weight” isn’t something you can do. Not to say it isn’t something that can happen, but it’s an outcome, not a behavior you can modify. “Cook at home five days a week,” on the other hand, or “play outside with the kids three times a week,” those are things you can do—behaviors within your locus of control—that will propel you towards that desired outcome.
I remember one project where, during go-live, we deployed a quick fix that had to be quick un-fixed. The dev who’d written the problem code resolved to “be more careful in the future.” That makes it sound like carefulness is just a dial you could turn up. Just… think more. That doesn’t work. Carefulness, like health, is an outcome, not a behavior unto itself. We collaborated to come up with some behaviors he’d try that should result in carefulness, such as diff-ing files before committing them and having a quick assumption-vetting chat with a teammate before developing an on-the-fly fix.
One barometer I use to judge whether I’m targeting behaviors I can control is: Can someone else tell when I’m doing it? Can I tell when I’m done? Will I be able to check off that goal as accomplished? For example, with a goal like “learn Python,” it’s hard to say when you’re done learning it. There’s always more learning to do. But “build a Twitter-enabled temperature monitor for my barbecue smoker in Python on a Raspberry Pi”? That is a goal worth doing. And you get to learn Python.
All this hints at the M in SMART goals, but I find that mnemonic rather encumbered. When I’m writing goals with my mentees—or for myself—we get a lot of mileage from these two simple tests:
The best career advice I ever got, from my friend and former manager Rich Vosburgh, is “Trust in positive intentions.” Following this advice makes my days calmer, my co-workers easier to collaborate with, and the number of times I look like an ass kept down to a minimum.
What Rich means is, start a conversation with the assumption that the other person intends to do good. Or at least isn’t out to do you harm.
On the whole, the people in your workplace are decent, are honest enough, and want the team to succeed. I’ve worked with a few people I would say are selfish, or perhaps self-centered, but nobody who was truly malicious. Not really. Not even when they were driving me out of my tree with their irritating behavior.
How does trusting in positive intentions help me deal with irritating behavior? It lets me step back, outside of myself and my irritation, and ask, not “Why are they determined to annoy me?” but instead “What might be motivating their behavior?” This is what saves me from looking like an ass… when I remember to do it before I go off half-cocked.
Trust in positive intentions, and ignorance
Usually the answer is that I don’t have all the information. There are other factors that, were I aware of them, would make that behavior make sense. This is especially true when it seems like managers are making “dumb decisions.” I remember when I was working for Big Manufacturer, I asked (out loud, in a department meeting of course) why we would dull our edge by buying some vendor’s off-the-shelf supply chain management software, instead of letting my team build it, given that our company dominates supply chain management. The answer was: Haven’t you noticed? We used to dominate; at this point, becoming average would be an improvement. Oh.
If I had started by assuming that the directors who were deciding to buy the vendor’s software had positive intentions, and that perhaps I didn’t have the whole picture, I could have asked, using a tone that conveys I am actually interested in the answer, “I thought we were the leaders in supply chain management. How will this new software give us a competitive edge?”
Trust in positive intentions, and awkward interactions
Some team interactions are rough for no other reason than a bunch of awkward introverts are trying to get a job done. Together. While nerds are easier for me to talk with than regular people, they’re still people, which means I’m still awkward. So I grant the same benefit of doubt when a conversation goes south. As many times as you’ve put your foot in your mouth, where you hear your words sounding nothing like you intended, maybe that just happened to the person you’re talking with—they meant well, but social anxiety made their brain fritz out.
Trust in positive intentions, and Google Translate
I led a development team located in Brazil. Early in the project, I get an email that they have “some doubts about the technical design.” Doubts? Really??
Yes, really. Because by “doubts,” they meant “questions” and were seeking clarification. Being non-native speakers of English, they merely chose a word that happened to inflame my own doubts about my design.
The testers from India would conclude their requests for me to reboot a server or whatever with “Please do the needful.” As in, now that I’ve asked for the thing I need in order to deliver the thing you need, would you please do that thing? No condescension intended.
Especially when the medium is text, without any tone or body language, your best bet is to trust in positive intentions, and read that text in the most neutral tone you can.
Trust in positive intentions, and improv
Sometimes people have different goals than you do. Not bad ones, just different. I like the approach presented in Crucial Conversations that says, seek to understand, and then be open to finding a solution that meets the goals of both of you. When you look at a conversation as a debate to make your point win over theirs, you are headed for a needless argument. Why does it have to be one thing or the other (A XOR B), why not both? Like the improv people say, look for “Yes, and…” solutions.
Trust in positive intentions, and fear
And sometimes people are just afraid. Over the years, the most antagonistic workplace behavior I’ve seen could always be traced down to secret fears. Self doubt. Imposter syndrome. Even arrogance comes from fear; confident people don’t need to posture for your approval, but scared people will go through gymnastics to show you how good they are.
I remember when a colleague and I first undertook rolling out an agile project management style at Our Big Company. Because it was 2007, it was Scrum. I met a lot of resistance up and down the stack and had to do a lot of convincing—to managers, to the process team, to devs, to testers… The strongest pushback came from our project manager, the person I most needed to embrace this change and lead us to success. Why was he fighting me? He has the skills to be such a great scrum master. I need him to be our scrum master.
Suddenly it hit me: He thinks I want his job. He thinks I’m setting this up with me as the scrum master. Not to mention, the discourse around agile at the time had a lot of “ditch your project managers!” sentiment. He thinks I intend to freeze him out, make him irrelevant.
Heck no! I want to stay a developer. Once I had this epiphany, I was able to address it with him directly and clarify, first, I see him excelling at this role, and second, there’s no one better to be our scrum master. I highlighted for him the specific skills I saw in him that would make him great at this, and I asked him to take up the banner and join us in this campaign.
He turned out to be a fantastic scrum master and a champion for agile project leadership across the company. But to get there, I had to first see through the objections to spot the fear, which revealed itself after I asked myself, assuming he has positive intentions, why would he be acting this way.
Perhaps you’ve seen this in people in your organization. I mean, talk about positive intentions: They want so desperately to do a good job that they are going into fight-or-flight mode over it. How can you alleviate their fears?
Trust in positive intentions, and ask questions
I continue to learn from Rich’s advice. This blog post captures only some of the insights I’ve gained by applying it, or failing to. Asking questions is the recurring theme. Actually asking questions, where you actually want to understand more, starting from the position that your colleagues are competent and invested in the team’s success, will serve you well.
The book Crucial Accountability coaches us to abandon the story we’ve constructed about what the other person is thinking, and instead seek to genuinely understand what they are thinking. This will help you stay calmer, make you a more effective collaborator, and occasionally save you from looking like an ass.
The messy one, at any rate.
Looking at a team’s git repository, I see the following evidence of somebody having a bad day:
Those are three commits, in rapid succession, from the same developer, trying to mash files into a compiling state. But why can I see those commits? They should have been squashed or amended to neaten them up before being pushed to the remote repo for me to pull.
This presented an opportunity for coaching, but it’s also a good reminder: If you’re using a tool other than the command line, make sure the setting to automatically push commits is turned off.
This beastie. Don’t check it.
Instead, when you need to fix a mistake, use one of the following options before pushing to the remote repo.
A common theme in all of these strategies is don’t change commits you’ve pushed somewhere other developers might be using. Which is why you want to uncheck that “automatically push” setting.
Any harm in having multiple flailing attempts to fix a set of files? Not especially, but having a clean, intention-revealing history makes troubleshooting later easier, and I’ll be less likely to cluck my tongue at you.
End-of-the-year housecleaning time: Our team’s project has accumulated a few* git branches that are almost certainly stale. Some of them were last worked on by people who aren’t even on the project anymore. Still, I wanted to reassure myself before I summarily deleted them. Here are the git commands I was able to round up. What’ve you got?
git checkout master, since these work relative to the current branch and only make sense when that current branch is master.
git branch --merged
lists branches that have been merged to HEAD. (You’ve already made master the current branch, right?) If your branch is in that list, it’s in master and can be deleted.
git branch --contains my-branch-to-delete
lists branches that contain the branch you specified. If master shows up in the list, then master contains your branch.
git log my-branch-to-delete ^master --no-merges
lists commits that are in my-branch-to-delete but are not in master. The ^ means “exclude this branch”, so this is listing commits on my-branch-to-delete, excluding commits that are also on master. If there are no commits in this list, then master contains my-branch-to-delete.
After fruitless searches in electronics books, electrical engineering textbooks, even physics, trying to find a way to understand transistors (not just where to put one in a circuit), I stumbled upon the answer when I wasn’t looking for it.
Chemistry. The answer is in chemistry. Specifically, it is in The Joy of Chemistry by Cathy Cobb and Monty L. Fetterolf.
I draw pictures when I want to understand something, so here you go.
One way to imagine an atom looks like a solar system, with a positive nucleus at the center, orbited by negatively charged electrons in discrete shells, with rules about how many electrons can go in each shell. The periodic table is laid out according to this idea. As you march to the right, each atom has one more electron in its outermost shell, until you hit a big ol’ carriage return and start filling the next shell.
The outermost electron shell of an atom is called its valence shell, and how full it is determines the chemical properties of the atom.
An atom with a filled valence shell is stable and inert. The noble gases, the rightmost column of the periodic table, sit where they are and behave the way they do because their valence shells are filled. Atoms without a filled outer shell will swap and share electrons with other atoms to get to that state.
When atoms swap electrons and then stick to each other like oppositely charged magnets, that’s an ionic bond. When they share electrons, it’s called a covalent bond (as in, co-sharing valence electrons).
Copper is interesting.
For one thing, it’s a metal, so that means it’s shiny, bendy, and ready to make metallic bonds. (That’s the third kind of bond.) Metallic bonds are like covalent bonds, only a whole lot more so.
When many copper atoms get together, they share electrons so readily the electrons form a conduction band encompassing all the atoms. This makes copper a great conductor of electricity, since electricity is the flow of charged particles (such as electrons). So we make the wires in our houses out of copper. (Or aluminum, if your house was built in the 70s. Sigh.)
We make the transistors in our computers, on the other hand, out of silicon.
Silicon has four valence electrons, but its shell would be filled if it had eight. This lets silicon atoms bond with other silicon atoms in a complex lattice, fancier than what I could draw here in 2D.
Crystals don’t conduct. But if we swapped out one of those silicon atoms with something else, something that had an extra electron, or maybe something that had a spare spot to accept an electron, then we’d have something that could conduct. Some of the time, anyway. It would be a… _semi_conductor.
Adding impurities to silicon to change its electrical properties is called doping. Good choices for doping silicon are the atoms sitting on either side of it on the periodic table.
Aluminum is one spot to the left of silicon, because it has one fewer electron. Phosphorus is one spot to the right, because it has one more electron. Having extra electrons that are easy to knock free, plus “holes” where spare electrons can go, makes a material able to move those electrons along. In other words, conduct electricity.
Silicon doped with phosphorus makes an n-type semiconductor. Silicon doped with aluminum makes a p-type semiconductor. Side-by-side, they make a component called a diode.
Diodes are useful when you want to ensure current can flow through your circuit in only one direction. One practical application is circuits with electromagnets. Electromagnets when they’re shut off can kick current back and damage your microcontroller, so you put a diode between the two, letting the microcontroller send current to the electromagnet but protecting it from this flyback.
If a diode is an n plus a p, what do you get with n, p, and another n (or p, n, and p)?
Transistors are like two diodes stuck back-to-back. Since diodes let current flow in only one direction, this is like attaching a valve that lets liquid flow only from right to left to a valve that allows flow only from left to right; i.e., no flow at all. That sounds kind of useless.
Applying a current to the p-type semiconductor in the middle segment knocks some electrons free, switching it to behave like an n-type semiconductor. Now the transistor is N-N-N instead of N-P-N, and current can flow through it.
In this way, the transistor acts like an on/off switch. A small current can flip the switch, either allowing or blocking a big current. This is exactly what you need when you want your arduino microcontroller, which can only pump 5 volts out of its output pins, to decide when to switch on something with a bigger power draw, like a motor or a fountain pump.
Combining transistors into a computer is left as an exercise for the reader.
Check out The Joy of Chemistry. It makes not only transistors but a lot of other things make sense (like, how does your toilet actually flush?). It has illustrative experiments and then, because the authors know their audience are grown-ups, descriptions of what would have happened if you’d done the experiment. And I love that this book knows that science is fun all on its own and doesn’t need cutesy distractions or wisecracks to make the book “engaging.”
Now, can anybody tell me what it means—means-means, not just the effects you observe—when a microcontroller pin is “floating”?
UPDATE: Andy Philips explains “float” in the comments.
I’m not always using Git in an environment that supports pull requests. My preferred Git workflow, even within a team of co-workers who sit together, is to have features developed and tested within a feature branch, then reviewed and merged via pull request. I took a page from Vincent Driessen‘s playbook, A successful Git branching model, which gives a step-by-step explanation.
But easy-to-review pull requests are a feature of GitHub and BitBucket, not Git itself. (
git request-pull doesn’t cut it.) Here’s my current workflow to review a feature’s worth of changes.
The Goal: Get a list of all files changed for this feature and compare each one’s initial state against its final state, without any noise from merges from master.
The Approach: Pretend I’m going to merge the feature into master but don’t commit it. Diff the pending changes and send my recommendations. Then throw away the changes and clean everything up.
git checkout master git merge ‑‑no‑ff ‑‑no‑commit name_of_their_feature_branch
First I check out master as the branch I want to merge into. Then I run a merge with two important options. No-fast-forward (
‑‑no‑ff) makes the feature join into master with a single, explicit merge commit. This tells git, even if it could perform a fast-forward merge, where it applies each of the feature-branch commits as if they had been committed straight to master, please don’t. With the
‑‑no‑ff option, you’ll have the single, show-me-everything commit you wanted to review. The second,
‑‑no‑commit, is even more important: Stage them but don’t commit them. (Although, as long as you don’t push to a remote, even that is reversible. This choose-your-own-adventure git guide reassuringly walks you through revising history.)
Because you are taking a trial-run at merging the feature to master, you may need to resolve some merge conflicts. Go ahead and do so, since that will give you a realistic picture of the finished feature.
After the Review: You’ve finished with your review and are ready to clean up your working directory. Here are the commands to discard the changes.
This throws away your work, but you were just pretend-merging anyway, right?
git reset ‑‑hard git clean ‑fd
reset sets the current branch back to the most recent commit, and
‑‑hard says to discard changes to tracked files. This does not clean up new files that the feature branch added. That’s what
clean takes care of. The
‑f option is for “force,” since Git can be configured to not execute a clean unless you expressly specify force—a little safety net since
clean is so destructive. The
‑d option instructs Git to also remove newly created directories. (Some folks include
‑x, to throw away even files that would have been ignored by your
.gitignore, such as dlls in your bin folder. This is a little too thorough for me, so I don’t use it.)
So there you go. To review what will be changed by a feature branch, pretend to merge it and see what changed.
We have the neediest coffee maker. It’s great having free, freshly ground espresso at the office, but that machine is constantly yalping for one thing or another. Waiting for your espresso to brew gives you time to think about usability.
The coffee machine has a one-line, 10-character LED display, which it uses to cryptically beg you for attention. (The latest: “Descale machine.”) I found a co-worker one morning, exasperated with trying to guess its needs. “I’ve put coffee in! What is its problem?” The machine was alternating between two words, “grounds” and “empty.” Believing that the grounds were empty, my co-worker was adding more to the hopper. Turn the sentence around, though, and you realize the tray for catching used grounds needed to be emptied.
I recently read Microinteractions by Dan Saffer. He gives a great explanation of what a microinteraction is, a single use-case interaction with a device or application. Dismissing an alert on your phone, setting the target temperature on the oven, even turning on a lamp are all microinteractions. Getting these right is what makes an application “intuitive.”
The coffee maker could scroll the words or just use an LED display with two lines of text. At least it is consistent: all messages are imperative commands, rather than declarative statements. Having seen other, less ambiguous messages from it led me to parse “empty” “grounds” correctly. And error messages in applications should be instructions, telling us what to fix instead of just complaining that something is wrong.
The coffee machine’s not off the hook, though. There’s a button you press to select the strength of your coffee. One press means “mild,” two means “strong,” three means “stand the spoon up in it,” and I hope that’s the one you wanted, because there’s no cycling back to the beginning. Subsequent button presses do nothing.
What microinteractions are you designing into your applications?
My pharmacy upgraded their computer system. I can tell by the label on my most recent medicine bottle: the QR code is in a different spot, and the prescription identifier now sports a leading zero. (Only programmers think numbers can start with zeros.) The troubling thing, though, was the “Remaining Refills” part. Last month, I had “5” remaining; on this new label, “1.3.”
I stopped in at the pharmacy to ask about it. The answer made me laugh. It was such a nerd answer, showing where developer decisions were leaking out into the real world.
Any time I’ve tried to push a developer’s way of thinking onto the business, the result is a mess. True, the requirements they bring to us are often a mess, but getting non-developers to acknowledge the complexity and gaps in their request by drawing charts with boxes and cylinders makes for a tiring and fruitless day.
I’ll tell you about the (first) time I learned this lesson, by getting it quite wrong. I worked for a large manufacturer, building software to help buyers track and negotiate the costs of parts they were buying. Parts they buy directly are identified by a five-character part number. (As above, they’re surprisingly not interested in hearing that a number that contains letters is a string. Can’t imagine why not.) But they also negotiate the cost of components that manufacturers will use to build those parts. So one group is managing motherboards while another is negotiating for the CPU fans that go into those motherboards. (There’s also a line item for SLPs, which I learned stands for Sh…illy Little Parts. Screws and LEDs and stuff.)
Thinking database-y for a minute, imagine the rows in your NegotiatedCost table. For some of them, the value in the PartNumber column can be found in the Grand Uber Parts System of Our Fine Company. For others, that value is a part number our supplier uses to identify components in what they’re selling us. For yet others, it’s the part number the OEM uses to identify the part they’re selling to our suppliers.
PartNumber is a lousy primary key. But it becomes unique and usable if you also know whose part number it is. Part number + part-numbering system makes a composite key. (Psst. Please don’t tell me I should use a guid instead of a composite key. I still have to know in which system I’m looking up the part’s description.) What do you call that second column? It’s going to be seen by users, too. It’s not the same as the supplier of the part. Remember, the motherboard supplier is (indirectly) selling me the fan, using the fan manufacturer’s part number. How do I label the column that tells you whose part number it is?
Through a weird kind of linguistic inertia, “Whose Part Number” started to gain traction. (I’m sure this was totally my fault. I was young.) And because this was a Big Fancy Corporation, that got turned into an acronym, so the UI had a WPN column, which of course had no meaning at all to the users. Revel in my shame.
So what did the pharmacist say to me to explain the “1.3”? “Your doctor wrote the prescription for three months, but your insurance will pay for only one month at a time. So you have 1.3 three-month refills remaining.” In other words, one-and-a-third calendar quarters = the 4 months I was expecting.
Does your system have any “1.3 three-month refills” in it?
It was a perfect moment.
I’m at last year’s That Conference, sitting in the big dining hall, while people step up to a microphone at the other end of the room and announce the Open Spaces session they will convene over the next few days. I’ve got three brain cells listening, mostly I’m eating and cogitating (ha, applying both senses of the word “ruminating,” eh?).
A voice cuts across the din, silencing the room. Clear as a bell, Cori Drew’s daughter states that she will convene a session showing Scratch, the programming language, at 2:00 on Tuesday. Her voice is so young, yet her words so organized and self-possessed, that I get a chill (and write down the time of the session). The room bursts into applause.
So I went to that talk. Friends, you have no idea. Katelyn, then nine years old, showed a PowerPoint presentation, gave a demo, coded live, fielded questions from grown-ups and kids, and tried things on the fly in her IDE in response to those questions. I learned a lot, and had to try it out for myself when I got home. (See a proud mama’s pictures.)
What inspired me most was watching the interaction between Katelyn and another girl the same age, who was as enthusiastic about learning Scratch as Katelyn is. Questions and smiles and edge of her seat, she was leaning in so far. I saw them together for the rest of the conference, and I mused, “There it is. That’s the answer. They’re too young to know that girls don’t code.” I had to become a part of making a space where more of that could happen.
I’ve signed on with this year’s That Conference Family Track planning committee. I can’t wait. I’m putting together a hands-on workshop of electronics for small (supervised) fingers. Kids and parents and blinky LEDs! What more could I want?
Well. For one: you to be there. And if you have kiddos, to bring those kiddos; and if you don’t, to come hang out and code with other people’s kiddos. That Conference is held during summer vacation at an indoor waterpark. srsly.
That Conference and ones like it spur the minds of the next generation of developers. If you wanna get pragmatic about it, we’re mentoring our future employees. College and high school are too late. For our future talent pool to represent the full rainbow of human experience, we need to encourage geeklets in elementary school.
In addition to all that, the conference offers an engaging and useful professional track. Y’know, for grown-up developers. Submit a talk to That Conference when the call for speakers opens on 3/31. We are gonna have fun.
subscribe via RSS